pandoc 2.19.2 → 3.10
raw patch · 1373 files changed
Files
- AUTHORS.md +155/−3
- CONTRIBUTING.md +44/−34
- COPYING.md +5/−6
- COPYRIGHT +47/−21
- INSTALL.md +84/−54
- MANUAL.txt +8044/−7119
- README.md +57/−15
- Setup.hs +0/−2
- app/pandoc.hs +0/−33
- benchmark/benchmark-pandoc.hs +8/−6
- cabal.project +0/−4
- changelog.md +14642/−7921
- data/bash_completion.tpl +1/−1
- data/default.csl +3929/−678
- data/docx/word/document.xml +41/−109
- data/docx/word/fontTable.xml +50/−50
- data/docx/word/footnotes.xml +20/−6
- data/docx/word/settings.xml +4/−4
- data/docx/word/styles.xml +339/−93
- data/docx/word/theme/theme1.xml +293/−2
- data/epub.css +206/−21
- data/odt/Configurations2/accelerator/current.xml +0/−0
- data/odt/META-INF/manifest.xml +2/−6
- data/odt/Thumbnails/thumbnail.png binary
- data/odt/content.xml +81/−1
- data/odt/meta.xml +1/−1
- data/odt/settings.xml +0/−2
- data/odt/styles.xml +70/−7
- data/pptx/ppt/slides/slide3.xml +1/−1
- data/sample.lua +0/−363
- data/templates/after-header-includes.latex +10/−0
- data/templates/article.jats_publishing +17/−1
- data/templates/common.latex +263/−0
- data/templates/default.ansi +21/−0
- data/templates/default.asciidoc +6/−1
- data/templates/default.asciidoctor +0/−41
- data/templates/default.bbcode +1/−0
- data/templates/default.beamer +204/−0
- data/templates/default.chunkedhtml +103/−0
- data/templates/default.context +26/−5
- data/templates/default.djot +27/−0
- data/templates/default.epub2 +5/−2
- data/templates/default.epub3 +5/−2
- data/templates/default.html4 +1/−1
- data/templates/default.html5 +2/−5
- data/templates/default.icml +5/−0
- data/templates/default.jats_articleauthoring +6/−1
- data/templates/default.latex +35/−424
- data/templates/default.man +1/−20
- data/templates/default.ms +15/−13
- data/templates/default.opendocument +1/−1
- data/templates/default.openxml +65/−0
- data/templates/default.org +6/−0
- data/templates/default.revealjs +37/−5
- data/templates/default.texinfo +11/−1
- data/templates/default.typst +154/−0
- data/templates/default.vimdoc +16/−0
- data/templates/document-metadata.latex +20/−0
- data/templates/font-settings.latex +103/−0
- data/templates/fonts.latex +23/−0
- data/templates/hypersetup.latex +34/−0
- data/templates/passoptions.latex +9/−0
- data/templates/styles.citations.html +23/−0
- data/templates/styles.html +45/−36
- data/templates/template.typst +120/−0
- data/translations/af.yaml +20/−0
- data/translations/alt.yaml +5/−0
- data/translations/ar.yaml +21/−20
- data/translations/as.yaml +21/−0
- data/translations/ast.yaml +21/−0
- data/translations/az.yaml +21/−0
- data/translations/be.yaml +21/−0
- data/translations/bg.yaml +5/−3
- data/translations/bo.yaml +14/−0
- data/translations/br.yaml +21/−0
- data/translations/bs.yaml +21/−0
- data/translations/bua.yaml +17/−0
- data/translations/ckb-Arab.yaml +21/−0
- data/translations/ckb-Latn.yaml +21/−0
- data/translations/cs.yaml +4/−4
- data/translations/cu.yaml +21/−0
- data/translations/cy.yaml +21/−0
- data/translations/cz.yaml +21/−0
- data/translations/da.yaml +2/−2
- data/translations/dsb.yaml +21/−0
- data/translations/el.yaml +2/−2
- data/translations/en.yaml +2/−2
- data/translations/eo.yaml +2/−1
- data/translations/es-ES.yaml +21/−0
- data/translations/es-MX.yaml +21/−0
- data/translations/es.yaml +4/−4
- data/translations/et.yaml +3/−1
- data/translations/fa.yaml +21/−21
- data/translations/fi.yaml +1/−1
- data/translations/fil.yaml +18/−0
- data/translations/fur.yaml +21/−0
- data/translations/ga.yaml +21/−0
- data/translations/gd.yaml +21/−0
- data/translations/gl.yaml +21/−0
- data/translations/grc.yaml +21/−0
- data/translations/gu.yaml +9/−0
- data/translations/ha.yaml +21/−0
- data/translations/he.yaml +3/−4
- data/translations/hi.yaml +8/−10
- data/translations/hsb.yaml +21/−0
- data/translations/hu.yaml +1/−1
- data/translations/hy.yaml +20/−0
- data/translations/ia.yaml +21/−0
- data/translations/id.yaml +21/−0
- data/translations/is.yaml +1/−1
- data/translations/it.yaml +1/−1
- data/translations/ja.yaml +21/−0
- data/translations/ka.yaml +21/−0
- data/translations/kmr-Arab.yaml +21/−0
- data/translations/kmr-Latn.yaml +21/−0
- data/translations/kn.yaml +20/−0
- data/translations/ko.yaml +1/−1
- data/translations/la.yaml +20/−0
- data/translations/lb.yaml +21/−0
- data/translations/lv.yaml +3/−3
- data/translations/mk.yaml +21/−0
- data/translations/ml.yaml +12/−0
- data/translations/mn.yaml +19/−0
- data/translations/mr.yaml +21/−0
- data/translations/ms.yaml +21/−0
- data/translations/nb.yaml +21/−0
- data/translations/nko.yaml +21/−0
- data/translations/nl.yaml +6/−6
- data/translations/nn.yaml +21/−0
- data/translations/oc.yaml +21/−0
- data/translations/or.yaml +21/−0
- data/translations/pa.yaml +20/−0
- data/translations/pl.yaml +1/−1
- data/translations/pms.yaml +21/−0
- data/translations/pt-BR.yaml +21/−0
- data/translations/pt-PT.yaml +21/−0
- data/translations/ro.yaml +2/−2
- data/translations/ru.yaml +3/−2
- data/translations/se.yaml +21/−0
- data/translations/si.yaml +21/−0
- data/translations/sk.yaml +6/−6
- data/translations/sq.yaml +4/−1
- data/translations/sr-Cyrl.yaml +21/−0
- data/translations/sr-Latn.yaml +21/−0
- data/translations/sr-cyrl.yaml +0/−21
- data/translations/sr.yaml +21/−21
- data/translations/ta.yaml +11/−0
- data/translations/te.yaml +21/−0
- data/translations/th.yaml +1/−1
- data/translations/tk.yaml +21/−0
- data/translations/tr.yaml +0/−1
- data/translations/ua.yaml +22/−0
- data/translations/ug.yaml +21/−0
- data/translations/uk.yaml +1/−1
- data/translations/ur.yaml +21/−22
- data/translations/vi.yaml +6/−6
- man/manfilter.lua +0/−44
- man/pandoc.1 +0/−8040
- man/pandoc.1.after +0/−5
- man/pandoc.1.before +0/−2
- pandoc.cabal +240/−199
- src/Text/Pandoc.hs +11/−3
- src/Text/Pandoc/App.hs +181/−221
- src/Text/Pandoc/App/CommandLineOptions.hs +530/−320
- src/Text/Pandoc/App/FormatHeuristics.hs +0/−92
- src/Text/Pandoc/App/Input.hs +138/−0
- src/Text/Pandoc/App/Opt.hs +159/−58
- src/Text/Pandoc/App/OutputSettings.hs +154/−94
- src/Text/Pandoc/Asciify.hs +1/−1
- src/Text/Pandoc/CSS.hs +4/−3
- src/Text/Pandoc/CSV.hs +8/−4
- src/Text/Pandoc/Char.hs +59/−0
- src/Text/Pandoc/Chunks.hs +444/−0
- src/Text/Pandoc/Citeproc.hs +100/−62
- src/Text/Pandoc/Citeproc/BibTeX.hs +54/−155
- src/Text/Pandoc/Citeproc/CslJson.hs +10/−6
- src/Text/Pandoc/Citeproc/Locator.hs +44/−11
- src/Text/Pandoc/Citeproc/MetaValue.hs +2/−7
- src/Text/Pandoc/Citeproc/Name.hs +153/−0
- src/Text/Pandoc/Citeproc/Util.hs +1/−1
- src/Text/Pandoc/Class.hs +4/−2
- src/Text/Pandoc/Class/CommonState.hs +13/−1
- src/Text/Pandoc/Class/IO.hs +83/−27
- src/Text/Pandoc/Class/PandocMonad.hs +124/−296
- src/Text/Pandoc/Class/PandocPure.hs +20/−1
- src/Text/Pandoc/Class/Sandbox.hs +15/−4
- src/Text/Pandoc/Data.hs +232/−19
- src/Text/Pandoc/Data/BakedIn.hs +32/−0
- src/Text/Pandoc/Error.hs +50/−53
- src/Text/Pandoc/Extensions.hs +90/−56
- src/Text/Pandoc/Filter.hs +17/−7
- src/Text/Pandoc/Filter/Environment.hs +1/−1
- src/Text/Pandoc/Filter/JSON.hs +4/−3
- src/Text/Pandoc/Filter/Lua.hs +0/−51
- src/Text/Pandoc/Format.hs +251/−0
- src/Text/Pandoc/Highlighting.hs +57/−4
- src/Text/Pandoc/Image.hs +1/−1
- src/Text/Pandoc/ImageSize.hs +307/−35
- src/Text/Pandoc/Logging.hs +81/−5
- src/Text/Pandoc/Lua.hs +0/−23
- src/Text/Pandoc/Lua/ErrorConversion.hs +0/−40
- src/Text/Pandoc/Lua/Filter.hs +0/−46
- src/Text/Pandoc/Lua/Global.hs +0/−74
- src/Text/Pandoc/Lua/Init.hs +0/−153
- src/Text/Pandoc/Lua/Marshal/CommonState.hs +0/−68
- src/Text/Pandoc/Lua/Marshal/Context.hs +0/−28
- src/Text/Pandoc/Lua/Marshal/PandocError.hs +0/−50
- src/Text/Pandoc/Lua/Marshal/ReaderOptions.hs +0/−137
- src/Text/Pandoc/Lua/Marshal/Reference.hs +0/−96
- src/Text/Pandoc/Lua/Marshal/Sources.hs +0/−56
- src/Text/Pandoc/Lua/Marshal/Template.hs +0/−31
- src/Text/Pandoc/Lua/Marshal/WriterOptions.hs +0/−244
- src/Text/Pandoc/Lua/Module/MediaBag.hs +0/−143
- src/Text/Pandoc/Lua/Module/Pandoc.hs +0/−320
- src/Text/Pandoc/Lua/Module/System.hs +0/−41
- src/Text/Pandoc/Lua/Module/Template.hs +0/−61
- src/Text/Pandoc/Lua/Module/Types.hs +0/−42
- src/Text/Pandoc/Lua/Module/Utils.hs +0/−239
- src/Text/Pandoc/Lua/Orphans.hs +0/−116
- src/Text/Pandoc/Lua/PandocLua.hs +0/−113
- src/Text/Pandoc/Lua/Writer/Classic.hs +0/−250
- src/Text/Pandoc/MIME.hs +30/−300
- src/Text/Pandoc/MediaBag.hs +44/−27
- src/Text/Pandoc/Network/HTTP.hs +0/−18
- src/Text/Pandoc/Options.hs +94/−13
- src/Text/Pandoc/PDF.hs +296/−164
- src/Text/Pandoc/Parsing.hs +35/−13
- src/Text/Pandoc/Parsing/Capabilities.hs +12/−12
- src/Text/Pandoc/Parsing/Citations.hs +6/−6
- src/Text/Pandoc/Parsing/Future.hs +49/−0
- src/Text/Pandoc/Parsing/General.hs +148/−136
- src/Text/Pandoc/Parsing/GridTable.hs +93/−33
- src/Text/Pandoc/Parsing/Lists.hs +31/−27
- src/Text/Pandoc/Parsing/Math.hs +29/−23
- src/Text/Pandoc/Parsing/Smart.hs +22/−29
- src/Text/Pandoc/Parsing/State.hs +4/−6
- src/Text/Pandoc/Parsing/Types.hs +0/−58
- src/Text/Pandoc/Process.hs +1/−1
- src/Text/Pandoc/Readers.hs +42/−31
- src/Text/Pandoc/Readers/AsciiDoc.hs +416/−0
- src/Text/Pandoc/Readers/BibTeX.hs +3/−2
- src/Text/Pandoc/Readers/CSV.hs +6/−4
- src/Text/Pandoc/Readers/CommonMark.hs +44/−9
- src/Text/Pandoc/Readers/Creole.hs +4/−3
- src/Text/Pandoc/Readers/CslJson.hs +1/−1
- src/Text/Pandoc/Readers/Custom.hs +0/−83
- src/Text/Pandoc/Readers/Djot.hs +273/−0
- src/Text/Pandoc/Readers/DocBook.hs +207/−115
- src/Text/Pandoc/Readers/Docx.hs +161/−73
- src/Text/Pandoc/Readers/Docx/Combine.hs +9/−8
- src/Text/Pandoc/Readers/Docx/Fields.hs +72/−42
- src/Text/Pandoc/Readers/Docx/Lists.hs +50/−25
- src/Text/Pandoc/Readers/Docx/Parse.hs +432/−140
- src/Text/Pandoc/Readers/Docx/Parse/Styles.hs +7/−2
- src/Text/Pandoc/Readers/Docx/Symbols.hs +1085/−0
- src/Text/Pandoc/Readers/Docx/Util.hs +18/−43
- src/Text/Pandoc/Readers/DokuWiki.hs +61/−46
- src/Text/Pandoc/Readers/EPUB.hs +17/−8
- src/Text/Pandoc/Readers/EndNote.hs +14/−9
- src/Text/Pandoc/Readers/FB2.hs +4/−4
- src/Text/Pandoc/Readers/HTML.hs +191/−103
- src/Text/Pandoc/Readers/HTML/Parsing.hs +3/−1
- src/Text/Pandoc/Readers/HTML/Table.hs +34/−13
- src/Text/Pandoc/Readers/HTML/TagCategories.hs +2/−2
- src/Text/Pandoc/Readers/HTML/Types.hs +6/−5
- src/Text/Pandoc/Readers/Haddock.hs +3/−4
- src/Text/Pandoc/Readers/Ipynb.hs +20/−17
- src/Text/Pandoc/Readers/JATS.hs +341/−144
- src/Text/Pandoc/Readers/Jira.hs +19/−9
- src/Text/Pandoc/Readers/LaTeX.hs +200/−104
- src/Text/Pandoc/Readers/LaTeX/Citation.hs +1/−3
- src/Text/Pandoc/Readers/LaTeX/Inline.hs +67/−13
- src/Text/Pandoc/Readers/LaTeX/Lang.hs +5/−3
- src/Text/Pandoc/Readers/LaTeX/Macro.hs +1/−1
- src/Text/Pandoc/Readers/LaTeX/Math.hs +61/−30
- src/Text/Pandoc/Readers/LaTeX/Parsing.hs +133/−65
- src/Text/Pandoc/Readers/LaTeX/SIunitx.hs +6/−8
- src/Text/Pandoc/Readers/LaTeX/Table.hs +56/−55
- src/Text/Pandoc/Readers/LaTeX/Types.hs +0/−54
- src/Text/Pandoc/Readers/Man.hs +82/−41
- src/Text/Pandoc/Readers/Markdown.hs +367/−254
- src/Text/Pandoc/Readers/Mdoc.hs +1469/−0
- src/Text/Pandoc/Readers/Mdoc/Lex.hs +225/−0
- src/Text/Pandoc/Readers/Mdoc/Macros.hs +183/−0
- src/Text/Pandoc/Readers/Mdoc/Standards.hs +70/−0
- src/Text/Pandoc/Readers/MediaWiki.hs +222/−95
- src/Text/Pandoc/Readers/Metadata.hs +83/−40
- src/Text/Pandoc/Readers/Muse.hs +8/−6
- src/Text/Pandoc/Readers/Native.hs +1/−1
- src/Text/Pandoc/Readers/ODT.hs +114/−0
- src/Text/Pandoc/Readers/ODT/Arrows/State.hs +153/−0
- src/Text/Pandoc/Readers/ODT/Arrows/Utils.hs +241/−0
- src/Text/Pandoc/Readers/ODT/Base.hs +26/−0
- src/Text/Pandoc/Readers/ODT/ContentReader.hs +1054/−0
- src/Text/Pandoc/Readers/ODT/Generic/Fallible.hs +113/−0
- src/Text/Pandoc/Readers/ODT/Generic/Namespaces.hs +49/−0
- src/Text/Pandoc/Readers/ODT/Generic/SetMap.hs +36/−0
- src/Text/Pandoc/Readers/ODT/Generic/Utils.hs +116/−0
- src/Text/Pandoc/Readers/ODT/Generic/XMLConverter.hs +781/−0
- src/Text/Pandoc/Readers/ODT/Namespaces.hs +93/−0
- src/Text/Pandoc/Readers/ODT/StyleReader.hs +640/−0
- src/Text/Pandoc/Readers/OOXML/Shared.hs +95/−0
- src/Text/Pandoc/Readers/OPML.hs +1/−1
- src/Text/Pandoc/Readers/Odt.hs +0/−97
- src/Text/Pandoc/Readers/Odt/Arrows/State.hs +0/−139
- src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs +0/−214
- src/Text/Pandoc/Readers/Odt/Base.hs +0/−22
- src/Text/Pandoc/Readers/Odt/ContentReader.hs +0/−950
- src/Text/Pandoc/Readers/Odt/Generic/Fallible.hs +0/−104
- src/Text/Pandoc/Readers/Odt/Generic/Namespaces.hs +0/−45
- src/Text/Pandoc/Readers/Odt/Generic/SetMap.hs +0/−30
- src/Text/Pandoc/Readers/Odt/Generic/Utils.hs +0/−116
- src/Text/Pandoc/Readers/Odt/Generic/XMLConverter.hs +0/−785
- src/Text/Pandoc/Readers/Odt/Namespaces.hs +0/−93
- src/Text/Pandoc/Readers/Odt/StyleReader.hs +0/−640
- src/Text/Pandoc/Readers/Org.hs +2/−3
- src/Text/Pandoc/Readers/Org/BlockStarts.hs +30/−19
- src/Text/Pandoc/Readers/Org/Blocks.hs +145/−97
- src/Text/Pandoc/Readers/Org/DocumentTree.hs +7/−5
- src/Text/Pandoc/Readers/Org/ExportSettings.hs +2/−2
- src/Text/Pandoc/Readers/Org/Inlines.hs +90/−77
- src/Text/Pandoc/Readers/Org/Meta.hs +8/−4
- src/Text/Pandoc/Readers/Org/ParserState.hs +15/−7
- src/Text/Pandoc/Readers/Org/Parsing.hs +21/−5
- src/Text/Pandoc/Readers/Org/Shared.hs +4/−5
- src/Text/Pandoc/Readers/Pod.hs +446/−0
- src/Text/Pandoc/Readers/Pptx.hs +43/−0
- src/Text/Pandoc/Readers/Pptx/Parse.hs +216/−0
- src/Text/Pandoc/Readers/Pptx/Shapes.hs +330/−0
- src/Text/Pandoc/Readers/Pptx/Slides.hs +83/−0
- src/Text/Pandoc/Readers/Pptx/SmartArt.hs +220/−0
- src/Text/Pandoc/Readers/RIS.hs +8/−6
- src/Text/Pandoc/Readers/RST.hs +450/−236
- src/Text/Pandoc/Readers/RTF.hs +165/−96
- src/Text/Pandoc/Readers/Roff.hs +63/−226
- src/Text/Pandoc/Readers/Roff/Escape.hs +222/−0
- src/Text/Pandoc/Readers/TWiki.hs +27/−22
- src/Text/Pandoc/Readers/Textile.hs +155/−49
- src/Text/Pandoc/Readers/TikiWiki.hs +15/−26
- src/Text/Pandoc/Readers/Txt2Tags.hs +4/−3
- src/Text/Pandoc/Readers/Typst.hs +781/−0
- src/Text/Pandoc/Readers/Typst/Math.hs +421/−0
- src/Text/Pandoc/Readers/Typst/Parsing.hs +76/−0
- src/Text/Pandoc/Readers/Vimwiki.hs +43/−55
- src/Text/Pandoc/Readers/XML.hs +543/−0
- src/Text/Pandoc/Readers/Xlsx.hs +40/−0
- src/Text/Pandoc/Readers/Xlsx/Cells.hs +63/−0
- src/Text/Pandoc/Readers/Xlsx/Parse.hs +296/−0
- src/Text/Pandoc/Readers/Xlsx/Sheets.hs +112/−0
- src/Text/Pandoc/RoffChar.hs +17/−15
- src/Text/Pandoc/Scripting.hs +63/−0
- src/Text/Pandoc/SelfContained.hs +184/−30
- src/Text/Pandoc/Server.hs +0/−355
- src/Text/Pandoc/Shared.hs +171/−339
- src/Text/Pandoc/Slides.hs +2/−2
- src/Text/Pandoc/Sources.hs +12/−1
- src/Text/Pandoc/TeX.hs +54/−0
- src/Text/Pandoc/Templates.hs +35/−12
- src/Text/Pandoc/Transforms.hs +169/−0
- src/Text/Pandoc/Translations.hs +66/−72
- src/Text/Pandoc/Translations/Types.hs +88/−0
- src/Text/Pandoc/URI.hs +159/−0
- src/Text/Pandoc/UTF8.hs +3/−2
- src/Text/Pandoc/UUID.hs +1/−1
- src/Text/Pandoc/Version.hs +28/−0
- src/Text/Pandoc/Writers.hs +58/−35
- src/Text/Pandoc/Writers/ANSI.hs +394/−0
- src/Text/Pandoc/Writers/AnnotatedTable.hs +0/−1
- src/Text/Pandoc/Writers/AsciiDoc.hs +392/−109
- src/Text/Pandoc/Writers/BBCode.hs +1089/−0
- src/Text/Pandoc/Writers/BibTeX.hs +1/−3
- src/Text/Pandoc/Writers/Blaze.hs +1/−1
- src/Text/Pandoc/Writers/ChunkedHTML.hs +173/−0
- src/Text/Pandoc/Writers/CommonMark.hs +1/−2
- src/Text/Pandoc/Writers/ConTeXt.hs +159/−62
- src/Text/Pandoc/Writers/CslJson.hs +3/−2
- src/Text/Pandoc/Writers/Custom.hs +0/−58
- src/Text/Pandoc/Writers/Djot.hs +300/−0
- src/Text/Pandoc/Writers/DocBook.hs +525/−0
- src/Text/Pandoc/Writers/Docbook.hs +0/−498
- src/Text/Pandoc/Writers/Docx.hs +850/−1443
- src/Text/Pandoc/Writers/Docx/OpenXML.hs +1146/−0
- src/Text/Pandoc/Writers/Docx/StyleMap.hs +1/−1
- src/Text/Pandoc/Writers/Docx/Table.hs +84/−58
- src/Text/Pandoc/Writers/Docx/Types.hs +10/−1
- src/Text/Pandoc/Writers/DokuWiki.hs +110/−134
- src/Text/Pandoc/Writers/EPUB.hs +243/−273
- src/Text/Pandoc/Writers/FB2.hs +17/−12
- src/Text/Pandoc/Writers/GridTable.hs +11/−5
- src/Text/Pandoc/Writers/HTML.hs +415/−307
- src/Text/Pandoc/Writers/Haddock.hs +9/−9
- src/Text/Pandoc/Writers/ICML.hs +107/−50
- src/Text/Pandoc/Writers/Ipynb.hs +5/−3
- src/Text/Pandoc/Writers/JATS.hs +208/−77
- src/Text/Pandoc/Writers/JATS/References.hs +7/−9
- src/Text/Pandoc/Writers/JATS/Table.hs +8/−3
- src/Text/Pandoc/Writers/JATS/Types.hs +1/−1
- src/Text/Pandoc/Writers/Jira.hs +6/−16
- src/Text/Pandoc/Writers/LaTeX.hs +667/−186
- src/Text/Pandoc/Writers/LaTeX/Caption.hs +20/−9
- src/Text/Pandoc/Writers/LaTeX/Citation.hs +45/−18
- src/Text/Pandoc/Writers/LaTeX/Lang.hs +117/−110
- src/Text/Pandoc/Writers/LaTeX/Notes.hs +1/−1
- src/Text/Pandoc/Writers/LaTeX/Table.hs +139/−65
- src/Text/Pandoc/Writers/LaTeX/Types.hs +25/−0
- src/Text/Pandoc/Writers/LaTeX/Util.hs +46/−32
- src/Text/Pandoc/Writers/Man.hs +80/−32
- src/Text/Pandoc/Writers/Markdown.hs +284/−140
- src/Text/Pandoc/Writers/Markdown/Inline.hs +107/−89
- src/Text/Pandoc/Writers/Markdown/Table.hs +14/−7
- src/Text/Pandoc/Writers/Markdown/Types.hs +1/−4
- src/Text/Pandoc/Writers/MediaWiki.hs +213/−153
- src/Text/Pandoc/Writers/Ms.hs +106/−54
- src/Text/Pandoc/Writers/Muse.hs +19/−7
- src/Text/Pandoc/Writers/Native.hs +1/−2
- src/Text/Pandoc/Writers/ODT.hs +182/−39
- src/Text/Pandoc/Writers/OOXML.hs +2/−2
- src/Text/Pandoc/Writers/OPML.hs +9/−4
- src/Text/Pandoc/Writers/OpenDocument.hs +301/−230
- src/Text/Pandoc/Writers/Org.hs +133/−90
- src/Text/Pandoc/Writers/Powerpoint/Output.hs +76/−34
- src/Text/Pandoc/Writers/Powerpoint/Presentation.hs +53/−29
- src/Text/Pandoc/Writers/RST.hs +281/−98
- src/Text/Pandoc/Writers/RTF.hs +7/−5
- src/Text/Pandoc/Writers/Roff.hs +25/−23
- src/Text/Pandoc/Writers/Shared.hs +534/−163
- src/Text/Pandoc/Writers/TEI.hs +10/−20
- src/Text/Pandoc/Writers/Texinfo.hs +160/−84
- src/Text/Pandoc/Writers/Textile.hs +24/−21
- src/Text/Pandoc/Writers/Typst.hs +730/−0
- src/Text/Pandoc/Writers/Vimdoc.hs +615/−0
- src/Text/Pandoc/Writers/XML.hs +365/−0
- src/Text/Pandoc/Writers/XWiki.hs +24/−7
- src/Text/Pandoc/Writers/ZimWiki.hs +9/−15
- src/Text/Pandoc/XML.hs +10/−6
- src/Text/Pandoc/XML/Light.hs +0/−114
- src/Text/Pandoc/XML/Light/Output.hs +0/−234
- src/Text/Pandoc/XML/Light/Proc.hs +0/−139
- src/Text/Pandoc/XML/Light/Types.hs +0/−193
- src/Text/Pandoc/XMLFormat.hs +188/−0
- stack.yaml +0/−51
- test/Tests/Command.hs +2/−17
- test/Tests/Helpers.hs +19/−3
- test/Tests/Lua.hs +0/−247
- test/Tests/Lua/Module.hs +0/−41
- test/Tests/MediaBag.hs +56/−0
- test/Tests/Old.hs +68/−18
- test/Tests/Readers/Creole.hs +1/−1
- test/Tests/Readers/Docx.hs +56/−42
- test/Tests/Readers/DokuWiki.hs +9/−8
- test/Tests/Readers/EPUB.hs +1/−1
- test/Tests/Readers/HTML.hs +20/−8
- test/Tests/Readers/JATS.hs +36/−1
- test/Tests/Readers/Jira.hs +2/−2
- test/Tests/Readers/LaTeX.hs +1/−1
- test/Tests/Readers/Man.hs +1/−2
- test/Tests/Readers/Markdown.hs +49/−32
- test/Tests/Readers/Mdoc.hs +321/−0
- test/Tests/Readers/ODT.hs +196/−0
- test/Tests/Readers/Odt.hs +0/−187
- test/Tests/Readers/Org.hs +2/−2
- test/Tests/Readers/Org/Block.hs +19/−21
- test/Tests/Readers/Org/Block/CodeBlock.hs +5/−5
- test/Tests/Readers/Org/Block/Figure.hs +26/−16
- test/Tests/Readers/Org/Block/Header.hs +9/−2
- test/Tests/Readers/Org/Block/List.hs +2/−2
- test/Tests/Readers/Org/Block/Table.hs +2/−2
- test/Tests/Readers/Org/Directive.hs +13/−13
- test/Tests/Readers/Org/Inline.hs +30/−6
- test/Tests/Readers/Org/Inline/Citation.hs +3/−10
- test/Tests/Readers/Org/Inline/Note.hs +2/−2
- test/Tests/Readers/Org/Inline/Smart.hs +6/−2
- test/Tests/Readers/Org/Meta.hs +14/−7
- test/Tests/Readers/Org/Shared.hs +2/−2
- test/Tests/Readers/Pod.hs +187/−0
- test/Tests/Readers/Pptx.hs +48/−0
- test/Tests/Readers/RST.hs +13/−13
- test/Tests/Readers/RTF.hs +1/−2
- test/Tests/Readers/Txt2Tags.hs +1/−1
- test/Tests/Readers/Xlsx.hs +48/−0
- test/Tests/Shared.hs +5/−4
- test/Tests/Writers/AsciiDoc.hs +17/−5
- test/Tests/Writers/BBCode.hs +355/−0
- test/Tests/Writers/ConTeXt.hs +8/−6
- test/Tests/Writers/DocBook.hs +431/−0
- test/Tests/Writers/Docbook.hs +0/−420
- test/Tests/Writers/Docx.hs +174/−4
- test/Tests/Writers/HTML.hs +8/−3
- test/Tests/Writers/JATS.hs +5/−4
- test/Tests/Writers/LaTeX.hs +85/−7
- test/Tests/Writers/Markdown.hs +5/−2
- test/Tests/Writers/Muse.hs +0/−1
- test/Tests/Writers/OOXML.hs +6/−0
- test/Tests/Writers/Powerpoint.hs +24/−0
- test/Tests/Writers/RST.hs +2/−2
- test/Tests/XML.hs +28/−0
- test/ansi-test.ansi +122/−0
- test/ansi-test.txt +127/−0
- test/asciidoc-reader-include.adoc +4/−0
- test/asciidoc-reader-include.rb +4/−0
- test/asciidoc-reader.adoc +908/−0
- test/asciidoc-reader.native +4418/−0
- test/command/10002.md +203/−0
- test/command/10057.md +6/−0
- test/command/10062.md +10/−0
- test/command/10071.md +15/−0
- test/command/10093.md +53/−0
- test/command/10094.md +47/−0
- test/command/10105.md +8/−0
- test/command/10127.md +713/−0
- test/command/10145.md +24/−0
- test/command/10148.md +18/−0
- test/command/10149.md +296/−0
- test/command/10152.md +446/−0
- test/command/10160.md +15/−0
- test/command/10185.md +46/−0
- test/command/10236.md +80/−0
- test/command/10271.md +29/−0
- test/command/10279.md +9/−0
- test/command/10281.md +68/−0
- test/command/10318.md +84/−0
- test/command/10328.md +37/−0
- test/command/10338-rst-multiple-header-rows.md +155/−0
- test/command/10385.md +22/−0
- test/command/10390.md +23/−0
- test/command/10414.md +6/−0
- test/command/10459.md +11/−0
- test/command/10484.md +22/−0
- test/command/10490.md +50/−0
- test/command/10491.md +35/−0
- test/command/10497.md +13/−0
- test/command/10537.md +24/−0
- test/command/10594.md +28/−0
- test/command/10621.md +7/−0
- test/command/10631.md +8/−0
- test/command/10635.md +24/−0
- test/command/10643.md +11/−0
- test/command/10650.md +9/−0
- test/command/10659.md +45/−0
- test/command/10672.md +26/−0
- test/command/10708.md +24/−0
- test/command/10730.md +7/−0
- test/command/10747.md +6/−0
- test/command/10755.md +71/−0
- test/command/10758.md +21/−0
- test/command/10781.md +8/−0
- test/command/10791.md +15/−0
- test/command/10805.md +19/−0
- test/command/10812.md +41/−0
- test/command/10816.md +7/−0
- test/command/10825.md +39/−0
- test/command/10836.md +12/−0
- test/command/10848.md +82/−0
- test/command/10855.md +71/−0
- test/command/10862.md +6/−0
- test/command/10867.md +26/−0
- test/command/10884.md +17/−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/10942.md +97/−0
- test/command/10965.md +50/−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/11101.md +15/−0
- test/command/11113.docx binary
- test/command/11113.md +7/−0
- test/command/11124.md +10/−0
- test/command/11128.md +23/−0
- test/command/11140.md +71/−0
- test/command/11150.md +29/−0
- test/command/11162.md +19/−0
- test/command/11188.md +80/−0
- test/command/11210.md +13/−0
- test/command/11211.md +16/−0
- test/command/11253.md +27/−0
- test/command/11266.md +19/−0
- test/command/11270.md +25/−0
- test/command/11299.md +28/−0
- test/command/11300.md +67/−0
- test/command/11309.md +6/−0
- test/command/11312.md +21/−0
- test/command/11323.md +12/−0
- test/command/11341.md +9/−0
- test/command/11342.md +33/−0
- test/command/11348.md +61/−0
- test/command/11362.md +17/−0
- test/command/11364.md +75/−0
- test/command/11374.md +6/−0
- test/command/11384.md +17/−0
- test/command/11409.md +11/−0
- test/command/11420.md +15/−0
- test/command/11422.md +12/−0
- test/command/11450.md +62/−0
- test/command/11455.md +26/−0
- test/command/11463.md +13/−0
- test/command/11479.md +31/−0
- test/command/11486.md +82/−0
- test/command/11486/scroll.revealjs +15/−0
- test/command/11490.md +13/−0
- test/command/11494.md +73/−0
- test/command/11498.md +121/−0
- test/command/11498.png binary
- test/command/11511.md +6/−0
- test/command/11534.md +42/−0
- test/command/11542.md +47/−0
- test/command/11562.md +10/−0
- test/command/11571.md +18/−0
- test/command/11583.md +16/−0
- test/command/11588.md +10/−0
- test/command/11589.md +20/−0
- test/command/11598.md +16/−0
- test/command/11604.md +22/−0
- test/command/11608.md +54/−0
- test/command/11635.md +28/−0
- test/command/1166.md +8/−8
- test/command/11664.md +35/−0
- test/command/11668.md +42/−0
- test/command/11682.md +81/−0
- test/command/1608.md +1/−1
- test/command/1629.md +1/−1
- test/command/1710.md +4/−4
- test/command/1762.md +3/−6
- test/command/1881.md +6/−6
- test/command/2118.md +10/−5
- test/command/2337.md +6/−0
- test/command/2378.md +6/−5
- test/command/2434.md +19/−16
- test/command/2465.md +59/−0
- test/command/2606.md +3/−3
- test/command/2649.md +17/−17
- test/command/2834.md +7/−7
- test/command/2874.md +1/−1
- test/command/3113.md +1/−1
- test/command/3314.md +2/−2
- test/command/3422.md +1/−1
- test/command/3432.md +22/−22
- test/command/3450.md +1/−1
- test/command/3487.md +1/−1
- test/command/3494.md +4/−4
- test/command/3499.md +1/−1
- test/command/3516.md +2/−0
- test/command/3568.md +2/−2
- test/command/3577.md +10/−7
- test/command/3596.md +15/−15
- test/command/3667.md +1/−1
- test/command/3734.md +7/−7
- test/command/3958.md +1/−1
- test/command/4016.md +5/−5
- test/command/4164.md +2/−4
- test/command/4183.md +18/−7
- test/command/4186.md +5/−5
- test/command/4235.md +1/−1
- test/command/4420.md +3/−5
- test/command/4470.md +27/−0
- test/command/4545.md +1/−1
- test/command/4550.md +1/−1
- test/command/4564.md +58/−0
- test/command/4677.md +2/−2
- test/command/4690.md +3/−3
- test/command/4742.md +3/−3
- test/command/4746.md +56/−0
- test/command/4794.md +2/−1
- test/command/4805-beamer-columns-alignment.md +4/−4
- test/command/5071.md +68/−0
- test/command/5081.md +8/−0
- test/command/5116.md +107/−0
- test/command/512.md +1/−1
- test/command/5128.md +16/−16
- test/command/5321.md +17/−10
- test/command/5367.md +7/−6
- test/command/5368.md +20/−9
- test/command/5407.md +4/−4
- test/command/5420.md +1/−1
- test/command/5476.md +1/−1
- test/command/5529.md +2/−2
- test/command/5543.md +1/−1
- test/command/5574.md +1/−2
- test/command/5619.md +54/−25
- test/command/5620.md +2/−2
- test/command/5705.md +1/−1
- test/command/5793.md +13/−0
- test/command/5857.md +3/−3
- test/command/5876.md +2/−2
- test/command/5898.md +7/−7
- test/command/5899.md +11/−11
- test/command/5967.md +2/−2
- test/command/5986.md +2/−2
- test/command/6021.md +54/−0
- test/command/6030.md +4/−6
- test/command/6033.md +7/−12
- test/command/6034.md +8/−3
- test/command/6107.md +3/−4
- test/command/6137.md +87/−82
- test/command/6285.md +6/−0
- test/command/6288.md +1/−3
- test/command/6350.md +29/−0
- test/command/6360.md +1/−1
- test/command/6384.md +12/−0
- test/command/6424.md +6/−0
- test/command/6441.md +2/−2
- test/command/6481.md +2/−2
- test/command/6549.md +2/−2
- test/command/6588.md +10/−0
- test/command/6719.md +2/−2
- test/command/6723.md +2/−2
- test/command/6774.md +5/−5
- test/command/6783.md +1/−1
- test/command/6792.md +1/−1
- test/command/6821.md +80/−0
- test/command/6858.md +6/−6
- test/command/6890.md +6/−14
- test/command/6925.md +2/−2
- test/command/6948.md +3/−3
- test/command/6951.md +1/−1
- test/command/6959.md +12/−0
- test/command/6992.md +76/−0
- test/command/7016.md +1/−0
- test/command/7042.md +1/−0
- test/command/7064.md +2/−2
- test/command/7112.md +1/−1
- test/command/7172.md +17/−0
- test/command/7181.md +1/−1
- test/command/7201.md +47/−0
- test/command/7214.md +2/−2
- test/command/7219.md +25/−0
- test/command/7272.md +6/−3
- test/command/7278.md +4/−4
- test/command/7326.md +1227/−0
- test/command/7329.md +16/−11
- test/command/7473.md +39/−0
- test/command/7512.md +70/−0
- test/command/7521.md +1/−1
- test/command/7582.md +28/−0
- test/command/7678.md +62/−0
- test/command/7691.docx binary
- test/command/7691.md +5/−0
- test/command/7713.md +2/−2
- test/command/7743.md +56/−0
- test/command/7778.md +59/−0
- test/command/7847.md +11/−11
- test/command/7857.md +2/−3
- test/command/7861.md +1/−1
- test/command/7863.md +9/−2
- test/command/7871.md +1/−1
- test/command/7884.md +1/−1
- test/command/7919.md +12/−12
- test/command/8024.md +10/−0
- test/command/8024a.yaml +2/−0
- test/command/8024b.yaml +3/−0
- test/command/8070.md +3/−2
- test/command/8110.md +3/−3
- test/command/8131.md +41/−0
- test/command/8150.md +10/−17
- test/command/8155.md +0/−19
- test/command/8174.md +44/−0
- test/command/8204.md +12/−0
- test/command/8216.md +3/−3
- test/command/8219.md +4/−2
- test/command/8243.md +23/−0
- test/command/8251.md +13/−0
- test/command/8254.md +20/−0
- test/command/8256.md +33/−0
- test/command/8257.md +41/−0
- test/command/8281.md +15/−0
- test/command/8302.md +6/−0
- test/command/8307.md +49/−0
- test/command/8344.md +90/−0
- test/command/8354.md +38/−0
- test/command/8364.md +54/−0
- test/command/8365.md +50/−0
- test/command/8380.md +31/−0
- test/command/8402.md +52/−0
- test/command/8437.md +44/−0
- test/command/8486.md +55/−0
- test/command/8487.md +14/−0
- test/command/8504.md +90/−0
- test/command/8508.md +20/−0
- test/command/8511.md +16/−0
- test/command/8513.md +27/−0
- test/command/8534.md +11/−0
- test/command/8573.md +7/−0
- test/command/8611.md +34/−0
- test/command/8638.md +22/−0
- test/command/8652.md +28/−0
- test/command/8653.md +23/−0
- test/command/8659.md +54/−0
- test/command/8661.md +9/−0
- test/command/8665.md +29/−0
- test/command/8666.md +40/−0
- test/command/8681.md +14/−0
- test/command/8689.md +12/−0
- test/command/8711.md +118/−0
- test/command/8738.md +6/−0
- test/command/8745.md +52/−0
- test/command/8764.md +50/−0
- test/command/8770-block.md +75/−0
- test/command/8770-document.md +66/−0
- test/command/8770-section.md +72/−0
- test/command/8777.md +8/−0
- test/command/8783.md +33/−0
- test/command/8789.md +42/−0
- test/command/8852.md +43/−0
- test/command/8853.md +6/−0
- test/command/8863.md +11/−0
- test/command/8867.md +49/−0
- test/command/8869.md +20/−0
- test/command/8872.md +45/−0
- test/command/8880.md +42/−0
- test/command/8948.md +31/−0
- test/command/8956.md +48/−0
- test/command/8957.md +7/−0
- test/command/8966.md +9/−0
- test/command/8981.md +6/−0
- test/command/8984.md +122/−0
- test/command/8992.md +6/−0
- test/command/8997.md +77/−0
- test/command/9000.md +14/−0
- test/command/9002.docx binary
- test/command/9002.md +20/−0
- test/command/9017.md +54/−0
- test/command/9021.md +61/−0
- test/command/9038.md +6/−0
- test/command/9042.md +30/−0
- test/command/9043.md +13/−0
- test/command/9045.md +10/−0
- test/command/9047.md +47/−0
- test/command/9088.md +10/−0
- test/command/9090.md +15/−0
- test/command/9121.md +17/−0
- test/command/9136.md +89/−0
- test/command/9150.md +51/−0
- test/command/9159.md +15/−0
- test/command/9171.md +65/−0
- test/command/9193.md +7/−0
- test/command/9196.md +6/−0
- test/command/9201.md +18/−0
- test/command/9202.md +62/−0
- test/command/9209.md +6/−0
- test/command/9218.md +22/−0
- test/command/9236.md +34/−0
- test/command/9275.md +18/−0
- test/command/9279.md +131/−0
- test/command/9293.md +29/−0
- test/command/9346.md +8/−0
- test/command/9350.md +14/−0
- test/command/9358.docx binary
- test/command/9358.md +45/−0
- test/command/9366.md +34/−0
- test/command/9371.md +30/−0
- test/command/9386.md +17/−0
- test/command/9387.md +23/−0
- test/command/9388.md +21/−0
- test/command/9391.docx binary
- test/command/9391.md +9/−0
- test/command/9420.md +13/−0
- test/command/9420.svg +9/−0
- test/command/9445.md +6/−0
- test/command/9452.md +19/−0
- test/command/9467.md +7/−0
- test/command/9467.svg +56/−0
- test/command/9472.md +85/−0
- test/command/9475.md +102/−0
- test/command/9478.md +9/−0
- test/command/9481.md +7/−0
- test/command/9516.md +17/−0
- test/command/9517.md +34/−0
- test/command/9555.md +13/−0
- test/command/9569.md +19/−0
- test/command/9576.md +23/−0
- test/command/9579.md +46/−0
- test/command/9585.md +11/−0
- test/command/9586.md +7/−0
- test/command/9597.md +6/−0
- test/command/9603.docx binary
- test/command/9603.md +23/−0
- test/command/9616.md +16/−0
- test/command/9630.md +12/−0
- test/command/9632.md +7/−0
- test/command/9635.md +16/−0
- test/command/9639.md +11/−0
- test/command/9644.md +7/−0
- test/command/9652.md +9/−0
- test/command/9652.svg +3/−0
- test/command/9657.md +7/−0
- test/command/9676.md +9/−0
- test/command/9700.md +14/−0
- test/command/9716.md +13/−0
- test/command/9777-b.md +62/−0
- test/command/9777.md +58/−0
- test/command/9792.md +21/−0
- test/command/9797.md +39/−0
- test/command/9805.md +10/−0
- test/command/9807.md +13/−0
- test/command/9809.md +14/−0
- test/command/982.md +5/−1
- test/command/9865.md +53/−0
- test/command/9878.md +12/−0
- test/command/9902.md +6/−0
- test/command/9904.md +180/−0
- test/command/9905.md +20/−0
- test/command/9908.md +10/−0
- test/command/9943.md +24/−0
- test/command/9945.md +28/−0
- test/command/9953.md +29/−0
- test/command/9987.md +10/−0
- test/command/alerts.md +55/−0
- test/command/ascii.md +2/−2
- test/command/author-in-text-move-note.md +19/−0
- test/command/biblatex-angenendt.md +1/−1
- test/command/biblatex-crossref-nested.md +1/−1
- test/command/bits-book-meta.md +104/−0
- test/command/bits-book-part-wrapper-meta.md +95/−0
- test/command/bits-book-part-wrapper.md +149/−0
- test/command/bits-book.md +186/−0
- test/command/bits-index-elements.md +83/−0
- test/command/bits-legend.md +45/−0
- test/command/bits-named-boook-parts.md +68/−0
- test/command/bits-title-display-as.md +175/−0
- test/command/bits-title-supress.md +122/−0
- test/command/bits-toc-elements.md +69/−0
- test/command/citeproc-7a.md +2/−2
- test/command/citeproc-87.md +10/−6
- test/command/dokuwiki-quote.md +16/−0
- test/command/figures-context.md +48/−0
- test/command/figures-fb2.md +8/−0
- test/command/figures-haddock.md +7/−0
- test/command/figures-html.md +92/−0
- test/command/figures-jats.md +31/−0
- test/command/figures-jira.md +9/−0
- test/command/figures-latex.md +83/−0
- test/command/figures-markdown.md +12/−0
- test/command/figures-mediawiki.md +11/−0
- test/command/figures-org.md +16/−0
- test/command/figures-rst.md +13/−0
- test/command/figures-texinfo.md +115/−0
- test/command/figures-textile.md +31/−0
- test/command/figures-xwiki.md +10/−0
- test/command/figures-zimwiki.md +9/−0
- test/command/file1.txt +9/−0
- test/command/file2.txt +5/−0
- test/command/grid-table-indented.md +65/−0
- test/command/html-read-figure.md +32/−16
- test/command/html-writer-a-in-a.md +7/−0
- test/command/jabberwocky.md +22/−0
- test/command/jats-figure-alt-text.md +10/−6
- test/command/latex-color.md +12/−6
- test/command/latex-math-trailing-space.md +38/−0
- test/command/lists-inside-definition.md +5/−2
- test/command/lua-pandoc-state.lua +0/−11
- test/command/lua-pandoc-state.md +0/−14
- test/command/macros.md +2/−2
- test/command/man-defines.md +15/−0
- test/command/mdoc-An.md +17/−0
- test/command/mdoc-Bd-unfilled.md +24/−0
- test/command/mdoc-Bl-column.md +22/−0
- test/command/mdoc-Bl-tag.md +36/−0
- test/command/mediawiki_behavior_switches.md +16/−0
- test/command/minimal.svg +5/−0
- test/command/newif.md +7/−7
- test/command/pandoc-citeproc-118.md +3/−4
- test/command/pandoc-citeproc-119.md +2/−2
- test/command/pandoc-citeproc-13.md +2/−2
- test/command/pandoc-citeproc-136.md +2/−2
- test/command/pandoc-citeproc-14.md +12/−12
- test/command/pandoc-citeproc-152.md +2/−2
- test/command/pandoc-citeproc-160.md +2/−2
- test/command/pandoc-citeproc-175.md +3/−3
- test/command/pandoc-citeproc-197.md +2/−2
- test/command/pandoc-citeproc-213.md +2/−2
- test/command/pandoc-citeproc-25.md +3/−3
- test/command/pandoc-citeproc-250.md +3/−3
- test/command/pandoc-citeproc-27.md +2/−2
- test/command/pandoc-citeproc-292.md +2/−2
- test/command/pandoc-citeproc-301.md +6/−6
- test/command/pandoc-citeproc-307.md +2/−2
- test/command/pandoc-citeproc-31.md +2/−2
- test/command/pandoc-citeproc-312.md +2/−2
- test/command/pandoc-citeproc-320.md +2/−2
- test/command/pandoc-citeproc-320a.md +28/−35
- test/command/pandoc-citeproc-322.md +2/−2
- test/command/pandoc-citeproc-325.md +5/−5
- test/command/pandoc-citeproc-327.md +3/−3
- test/command/pandoc-citeproc-338.md +2/−2
- test/command/pandoc-citeproc-351.md +2/−2
- test/command/pandoc-citeproc-360.md +2/−2
- test/command/pandoc-citeproc-365.md +2/−2
- test/command/pandoc-citeproc-371.md +3/−3
- test/command/pandoc-citeproc-38.md +4/−4
- test/command/pandoc-citeproc-386.md +2/−2
- test/command/pandoc-citeproc-392.md +2/−2
- test/command/pandoc-citeproc-401.md +6/−6
- test/command/pandoc-citeproc-408.md +4/−4
- test/command/pandoc-citeproc-416.md +5/−5
- test/command/pandoc-citeproc-47.md +5/−5
- test/command/pandoc-citeproc-51.md +2/−2
- test/command/pandoc-citeproc-53.md +2/−2
- test/command/pandoc-citeproc-57.md +2/−2
- test/command/pandoc-citeproc-58.md +2/−2
- test/command/pandoc-citeproc-61.md +2/−2
- test/command/pandoc-citeproc-64.md +9/−9
- test/command/pandoc-citeproc-65.md +3/−4
- test/command/pandoc-citeproc-68.md +2/−2
- test/command/pandoc-citeproc-7.md +3/−3
- test/command/pandoc-citeproc-70.md +5/−5
- test/command/pandoc-citeproc-75.md +2/−2
- test/command/pandoc-citeproc-76.md +6/−6
- test/command/pandoc-citeproc-77.md +2/−2
- test/command/pandoc-citeproc-82.md +2/−2
- test/command/pandoc-citeproc-87.md +18/−18
- test/command/pandoc-citeproc-chicago-author-date.md +5/−5
- test/command/pandoc-citeproc-chicago-fullnote-bibliography.md +2/−2
- test/command/pandoc-citeproc-ieee.md +2/−2
- test/command/pandoc-citeproc-locators-delimited.md +1/−1
- test/command/pandoc-citeproc-no-author.md +8/−8
- test/command/pandoc-citeproc-number-of-volumes.md +3/−3
- test/command/pdfstandard.md +616/−0
- test/command/refs.md +28/−24
- test/command/reset-citation-positions.md +41/−0
- test/command/rst-writer-gridtable-if-rowspans.md +246/−0
- test/command/rst_block_subst.md +18/−0
- test/command/short-caption.md +42/−0
- test/command/table-with-column-span.md +2/−2
- test/command/tasklist.md +18/−16
- test/command/toc.md +6/−6
- test/command/translations.md +1/−1
- test/command/typst-hs-80.md +55/−0
- test/command/typst-image-alt.md +78/−0
- test/command/typst-images.md +32/−0
- test/command/typst-property-output.md +235/−0
- test/command/wikilinks_title_after_pipe.md +73/−0
- test/command/wikilinks_title_before_pipe.md +84/−0
- test/command/yaml-with-chomp.md +1/−7
- test/djot-reader.djot +749/−0
- test/djot-reader.native +2365/−0
- test/docbook-reader.docbook +146/−10
- test/docbook-reader.native +395/−20
- test/docbook-xref.docbook +34/−1
- test/docbook-xref.native +166/−14
- test/docx/0_level_headers.native +146/−52
- test/docx/anchor_header_after_anchor.docx binary
- test/docx/anchor_header_after_anchor.native +6/−0
- test/docx/block_quotes.docx binary
- test/docx/block_quotes.native +11/−0
- test/docx/block_quotes_parse_indent.native +0/−8
- test/docx/comments.native +1/−1
- test/docx/cross_reference.docx binary
- test/docx/cross_reference.native +7/−0
- test/docx/custom-style-reference.docx binary
- test/docx/deep_normalize.native +3/−3
- test/docx/definition_list.docx binary
- test/docx/definition_list.native +33/−7
- test/docx/empty_field.native +1/−1
- test/docx/german-reference.docx binary
- 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/custom_style_reference.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/docx/image_with_textbox_caption.docx binary
- test/docx/image_with_textbox_caption.native +44/−0
- test/docx/lists.native +1/−1
- test/docx/lists_9994.native +8/−0
- test/docx/lists_level_override.native +266/−37
- test/docx/mendeley_citations_plus.native +14/−9
- test/docx/normalize.docx binary
- test/docx/sdt_elements.native +60/−24
- test/docx/table_captions_no_field.docx binary
- test/docx/table_captions_no_field.native +81/−34
- test/docx/table_captions_with_field.native +145/−54
- test/docx/table_gridbefore.docx binary
- test/docx/table_gridbefore.native +823/−0
- test/docx/table_header_rowspan.native +542/−189
- test/docx/table_one_header_row.native +34/−18
- test/docx/table_one_row.native +37/−18
- test/docx/table_variable_width.native +78/−40
- test/docx/table_with_list_cell.native +72/−25
- test/docx/tables.native +238/−92
- test/docx/task_list.docx binary
- test/docx/task_list.native +40/−0
- test/docx/text_in_shape_format.docx binary
- test/docx/text_in_shape_format.native +33/−0
- test/docx/textbox_image.docx binary
- test/docx/textbox_image.native +30/−0
- test/docx/textbox_image_duplicate_encoding.docx binary
- test/docx/textbox_image_duplicate_encoding.native +30/−0
- test/docx/zotero_citations_plus.native +19/−22
- test/epub/features.native +1721/−1686
- test/epub/formatting.native +6020/−5989
- test/epub/wasteland.native +4602/−4551
- test/fb2/images-embedded.fb2 +1/−1
- test/html-reader.html +28/−0
- test/html-reader.native +100/−1
- test/ipynb/simple.out.native +1/−1
- test/jats-reader.native +3662/−2799
- test/jats-reader.xml +337/−38
- test/lhs-test.html +0/−231
- test/lhs-test.html+lhs +0/−231
- test/lhs-test.latex +1/−96
- test/lhs-test.latex+lhs +1/−63
- test/lua/attr-test.lua +0/−6
- test/lua/block-count.lua +0/−11
- test/lua/blocks-filter.lua +0/−8
- test/lua/hello-world-doc.lua +0/−10
- test/lua/implicit-doc-filter.lua +0/−6
- test/lua/inlines-filter.lua +0/−19
- test/lua/markdown-reader.lua +0/−12
- test/lua/math.lua +0/−10
- test/lua/meta.lua +0/−6
- test/lua/metatable-catch-all.lua +0/−20
- test/lua/module/globals.lua +0/−108
- test/lua/module/pandoc-list.lua +0/−160
- test/lua/module/pandoc-mediabag.lua +0/−72
- test/lua/module/pandoc-path.lua +0/−44
- test/lua/module/pandoc-template.lua +0/−65
- test/lua/module/pandoc-types.lua +0/−86
- test/lua/module/pandoc-utils.lua +0/−333
- test/lua/module/pandoc.lua +0/−356
- test/lua/module/partial.test +0/−0
- test/lua/module/tiny.epub binary
- test/lua/plain-to-para.lua +0/−6
- test/lua/require-file.lua +0/−2
- test/lua/script-name.lua +0/−3
- test/lua/single-to-double-quoted.lua +0/−10
- test/lua/smallcaps-title.lua +0/−12
- test/lua/smart-constructors.lua +0/−10
- test/lua/strmacro.lua +0/−11
- test/lua/undiv.lua +0/−3
- test/lua/uppercase-header.lua +0/−9
- test/man-reader.man +1/−1
- test/man-reader.native +25/−25
- test/markdown-reader-more.native +7/−11
- test/mediawiki-reader.native +94/−130
- test/odt/markdown/blockquote2.md +3/−0
- test/odt/native/imageIndex.native +28/−1
- test/odt/native/imageRelative.native +10/−0
- test/odt/native/imageWithCaption.native +28/−1
- test/odt/native/listContinueNumbering.native +89/−0
- test/odt/native/listContinueNumbering2.native +95/−0
- test/odt/native/preformattedText.native +4/−0
- test/odt/native/preformattedTextParentStyle.native +4/−0
- 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/sourceText.native +11/−0
- test/odt/native/tableWithContents.native +1/−1
- test/odt/native/tableWithSpans.native +134/−0
- test/odt/odt/blockquote2.odt binary
- test/odt/odt/imageRelative.odt binary
- test/odt/odt/listContinueNumbering.odt binary
- test/odt/odt/listContinueNumbering2.odt binary
- test/odt/odt/preformattedText.odt binary
- test/odt/odt/preformattedTextParentStyle.odt binary
- test/odt/odt/simpleTableWithHeader.odt binary
- test/odt/odt/simpleTableWithMultipleHeaderRows.odt binary
- test/odt/odt/sourceText.odt binary
- test/odt/odt/tableWithSpans.odt binary
- test/pod-reader.native +393/−0
- test/pod-reader.pod +155/−0
- test/pptx-reader/basic.native +149/−0
- test/pptx-reader/basic.pptx binary
- test/pptx/background-image/output.pptx binary
- test/pptx/background-image/templated.pptx binary
- test/pptx/comparison/both-columns/output.pptx binary
- test/pptx/comparison/both-columns/templated.pptx binary
- test/pptx/comparison/extra-image/output.pptx binary
- test/pptx/comparison/extra-image/templated.pptx binary
- test/pptx/comparison/extra-text/output.pptx binary
- test/pptx/comparison/extra-text/templated.pptx binary
- test/pptx/comparison/non-text-first/output.pptx binary
- test/pptx/comparison/non-text-first/templated.pptx binary
- test/pptx/comparison/one-column/templated.pptx binary
- test/pptx/content-with-caption/heading-text-image/output.pptx binary
- test/pptx/content-with-caption/heading-text-image/templated.pptx binary
- test/pptx/content-with-caption/image-text/output.pptx binary
- test/pptx/content-with-caption/image-text/templated.pptx binary
- test/pptx/content-with-caption/text-image/output.pptx binary
- test/pptx/content-with-caption/text-image/templated.pptx binary
- test/pptx/document-properties-short-desc/output.pptx binary
- test/pptx/document-properties-short-desc/templated.pptx binary
- test/pptx/footer/basic/output.pptx binary
- test/pptx/footer/fixed-date/output.pptx binary
- test/pptx/footer/higher-slide-number/output.pptx binary
- test/pptx/footer/no-title-slide/output.pptx binary
- test/pptx/images/output.pptx binary
- test/pptx/images/templated.pptx binary
- test/pptx/incremental-lists/with-flag/output.pptx binary
- test/pptx/incremental-lists/with-flag/templated.pptx binary
- test/pptx/incremental-lists/without-flag/output.pptx binary
- test/pptx/incremental-lists/without-flag/templated.pptx binary
- test/pptx/layouts/deleted.pptx binary
- test/pptx/layouts/moved.pptx binary
- test/pptx/metadata-speaker-notes/input.native +3/−0
- test/pptx/metadata-speaker-notes/output.pptx binary
- test/pptx/metadata-speaker-notes/templated.pptx binary
- test/pptx/reference-no-slides.pptx binary
- test/pptx/reference-no-slides/add-slides/input.native +14/−0
- test/pptx/reference-no-slides/add-slides/output.pptx binary
- test/pptx/reference-no-slides/with-notes/input.native +70/−0
- test/pptx/reference-no-slides/with-notes/output.pptx binary
- test/pptx/single-column/image/input.native +22/−0
- test/pptx/single-column/image/output.pptx binary
- test/pptx/single-column/image/templated.pptx binary
- test/pptx/single-column/text/input.native +13/−0
- test/pptx/single-column/text/output.pptx binary
- test/pptx/single-column/text/templated.pptx binary
- test/pptx/slide-level-0/h1-with-image/output.pptx binary
- test/pptx/slide-level-0/h1-with-image/templated.pptx binary
- test/pptx/slide-level-0/h2-with-image/output.pptx binary
- test/pptx/slide-level-0/h2-with-image/templated.pptx binary
- test/pptx/speaker-notes-after-metadata/output.pptx binary
- test/pptx/speaker-notes-after-metadata/templated.pptx binary
- test/pptx/speaker-notes-afterseps/output.pptx binary
- test/pptx/speaker-notes-afterseps/templated.pptx binary
- test/pptx/tables/output.pptx binary
- test/pptx/tables/templated.pptx binary
- test/pptx/two-column/text-and-image/output.pptx binary
- test/pptx/two-column/text-and-image/templated.pptx binary
- test/rst-reader.native +7/−7
- test/s5-basic.html +13/−4
- test/s5-fancy.html +15/−6
- test/s5-inserts.html +14/−5
- test/tables.asciidoc_legacy +67/−0
- test/tables.asciidoctor +0/−67
- test/tables.bbcode +60/−0
- test/tables.custom +0/−200
- test/tables.djot +56/−0
- test/tables.docbook4 +3/−9
- test/tables.docbook5 +3/−9
- test/tables.haddock +7/−7
- test/tables.html4 +23/−23
- test/tables.html5 +23/−23
- test/tables.latex +52/−37
- test/tables.man +4/−4
- test/tables.markua +8/−8
- test/tables.mediawiki +93/−86
- test/tables.ms +4/−4
- test/tables.muse +7/−1
- test/tables.texinfo +3/−3
- test/tables.textile +16/−16
- test/tables.typst +105/−0
- test/tables.vimdoc +65/−0
- test/tables/nordics.html4 +7/−7
- test/tables/nordics.html5 +7/−7
- test/tables/nordics.jats_archiving +2/−4
- test/tables/nordics.latex +14/−11
- test/tables/nordics.markdown +18/−0
- test/tables/nordics.mediawiki +40/−0
- test/tables/nordics.typst +21/−0
- test/tables/planets.html4 +10/−10
- test/tables/planets.html5 +10/−10
- test/tables/planets.latex +17/−15
- test/tables/planets.markdown +31/−0
- test/tables/planets.mediawiki +119/−0
- test/tables/planets.typst +33/−0
- test/tables/students.html4 +10/−10
- test/tables/students.html5 +10/−10
- test/tables/students.latex +11/−10
- test/tables/students.markdown +23/−0
- test/tables/students.mediawiki +30/−0
- test/tables/students.typst +26/−0
- test/test-pandoc.hs +26/−17
- test/testsuite.native +9/−5
- test/testsuite.txt +1/−2
- test/textile-reader.native +42/−12
- test/textile-reader.textile +7/−1
- test/twiki-reader.native +16/−0
- test/twiki-reader.twiki +6/−0
- test/typst-reader.native +5349/−0
- test/typst-reader.typ +28/−0
- test/undergradmath.typ +510/−0
- test/vimdoc/definition-lists.markdown +70/−0
- test/vimdoc/definition-lists.vimdoc +71/−0
- test/vimdoc/headers-numbered.vimdoc +108/−0
- test/vimdoc/headers.markdown +45/−0
- test/vimdoc/headers.vimdoc +94/−0
- test/vimdoc/vim-online-doc.markdown +42/−0
- test/vimdoc/vim-online-doc.vimdoc +53/−0
- test/vimwiki-reader.native +20/−20
- test/writer.asciidoc +40/−38
- test/writer.asciidoc_legacy +649/−0
- test/writer.asciidoctor +0/−649
- test/writer.bbcode +729/−0
- test/writer.context +8/−6
- test/writer.custom +0/−781
- test/writer.djot +749/−0
- test/writer.docbook4 +11/−8
- test/writer.docbook5 +11/−8
- test/writer.dokuwiki +58/−94
- test/writer.haddock +1/−0
- test/writer.html4 +29/−14
- test/writer.html5 +27/−15
- test/writer.jats_archiving +9/−26
- test/writer.jats_articleauthoring +9/−26
- test/writer.jats_publishing +9/−26
- test/writer.jira +1/−1
- test/writer.latex +69/−89
- test/writer.man +175/−194
- test/writer.markdown +102/−162
- test/writer.markua +9/−7
- test/writer.mediawiki +15/−36
- test/writer.ms +109/−106
- test/writer.muse +1/−1
- test/writer.native +9/−5
- test/writer.opendocument +957/−1907
- test/writer.opml +20/−20
- test/writer.org +8/−15
- test/writer.plain +79/−80
- test/writer.rst +54/−54
- test/writer.rtf +15/−14
- test/writer.tei +2/−1
- test/writer.texinfo +10/−39
- test/writer.textile +10/−1
- test/writer.typst +872/−0
- test/writer.vimdoc +669/−0
- test/writer.xwiki +3/−2
- test/writer.zimwiki +3/−1
- test/writers-lang-and-dir.context +1/−1
- test/writers-lang-and-dir.latex +35/−30
- test/xlsx-reader/basic.native +381/−0
- test/xlsx-reader/basic.xlsx binary
- trypandoc/index.html +0/−181
- trypandoc/trypandoc.js +0/−166
- xml-light/Text/Pandoc/XML/Light.hs +113/−0
- xml-light/Text/Pandoc/XML/Light/Output.hs +234/−0
- xml-light/Text/Pandoc/XML/Light/Proc.hs +137/−0
- xml-light/Text/Pandoc/XML/Light/Types.hs +191/−0
@@ -1,34 +1,49 @@ # Contributors - Aaron Wolen+- Adelar da Silva Queiróz+- Agriya Khetarpal - Agustín Martín Barbero+- Akash Patel+- Akos Marton - Albert Krewinkel+- Albert Lei - Alex Ivkin - Alex Toldaiev - Alex Vong+- Alexander Batischev - Alexander Kondratskiy - Alexander Krotov - Alexander Sulfrian - Alexander V Vershilov - Alexandre Franke - Alfred Wechselberger+- Amar Al-Zubaidi - Amir Dekel+- Amneesh Singh - Amogh Rathore+- Amy de Buitléir - Anabra - Anders Waldenborg+- Andreas Deininger - Andreas Lööw+- Andreas Scherer+- Andres Freund - Andrew Dunning - Andy Morris - Aner Lucero - Anti-Distinctlyminty - Antoine Latter+- Anton Antich+- Anton Melnikov - Antonio Terceiro - Arata Mizuki - Arata Mizuki - Arfon Smith-- Arfon Smith - Arlo O'Keeffe+- Artem Pelenitsyn - Artyom Kazak+- Asliddinbek Azizovich - B. Scott Michel - Bastien Dumont - Ben Firshman@@ -36,6 +51,7 @@ - Ben Steinberg - Beni Cherniavsky-Paskin - Benjamin Bray+- Benjamin Esham - Benjamin Wuethrich - Benoit Schweblin - Benson Muite@@ -49,26 +65,35 @@ - Caleb McDaniel - Caleb Mclennan - Calvin Beck+- Carlos Scheidegger - Carlos Sosa - Carsten Allefeld - Castedo Ellerman - Cécile Chemin - Cédric Couralet - Cezary Drożak+- Chandrahas77 - Charanjit Singh+- Charles Tapley Hoyt+- Charlotte Koch - Chris Black+- Chris Callison-Burch - Christian Conkle+- Christian Christiansen - Christian Despres - Christoffer Ackelman - Christoffer Sawicki - Christophe Dervieux+- Christopher Kenny - Clare Macrae - Clint Adams - Conal Elliott - Cormac Relf - Craig S. Bosma - Damien Clochard+- Dan Jacobson - Daniel Bergey+- Daniel Kessler - Daniel Maslowski - Daniel T. Staal - Daniele D'Orazio@@ -80,23 +105,28 @@ - Denis Maier - Derek Chen-Becker - Diego Balseiro+- Diogo Almiro - Dimitri Sabadie - Dimitris Apostolou - Dmitry Pogodin - Dmitry Volodin - Douglas Calvert+- Edwin Török - Eigil Rischel - Elliot Bobrow - Emanuel Evans+- Emmanuel Ferdman - Emerson Harkin - Emily Bourke - Emily Eisenberg - Eric Kow - Eric Schrijver - Eric Seidel+- Erik Post - Erik Rask - Ethan Riley - Étienne Bersac+- Evan Silberman - Even Brenden - Ezwal - Fabián Heredia Montiel@@ -106,9 +136,11 @@ - Florian Eitel - Florian Klink - Florian Kohrt+- FoxChillz - Francesco Mazzoli - Francesco Occhipinti - François Gannaz+- Frank Seifferth - Frederik Elwert - Freiric Barral - Freirich Raabe@@ -117,7 +149,11 @@ - Gabor Pali - Gabriel Lewertowski - Gavin Beatty+- George Stagg - Georgi Lyubenov+- GHyman83+- Gokul Rajiv+- Gordon Woodhull - Gottfried Haider - Greg Maslov - Greg Rundlett@@ -126,28 +162,38 @@ - Gwern Branwen - Hamish Mackenzie - Hans-Peter Deifel+- Hendrik Erz - Heiko Schlittermann - Henrik Tramberend - Henry de Valence - Herwig Stuetz+- Hikaru Ibayashi - Hos Es - Hubert Plociniczak+- Iacobus1983 - Ian Max Andolina - Igor Khorlo - Igor Pashev+- Ilona Silverwood - Ilya V. Portnov - Ivan Panchenko - Ivan Trubach - Ivar de Bruin - Ivo Clarysse - Jaap de Jong+- Jacob Larkin+- James J Balamuta - J. B. Rainsberger - J. Lewis Muir+- Jackson Schuster - Jaehwang Jung - Jaime Marquínez Ferrándiz - Jake Zimmerman - Jakob Voß - James Aspnes+- James P. Ascher+- James Barlow+- James Scott-Brown - Jamie F. Olson - Jan Larres - Jan Schulz@@ -160,53 +206,73 @@ - Jeff Runningen - Jens Getreu - Jens Petersen+- Jens Oehlschlägel - Jesse Hathaway+- Jeremie Knuesel - Jérémy Bobbio - Jeroen de Haas - Jerry Sky - Jesse Rosenthal+- Jez Cope - Joe Hermaszewski - Joe Hillenbrand+- Johan Larsson - John KetzerX - John Luke Bentley - John MacFarlane - John Muccigrosso+- John Purnell - Jonas Scholl - Jonas Smedegaard+- Jonathan - Jonathan Daugherty - Jonathan Dönszelmann - Jose Luis Duran - José de Mattos Neto - Josef Svenningsson - Joseph C. Sible+- Julia Diaz - Julien Cretel - Julien Dutant - Juliette Fourcot - Juliusz Gonera - Justin Bogner+- Justin Wood - Karl Pettersson+- Keenan Brock - Keiichiro Shikano - Kelsey Hightower+- Kevin Broch - Kolen Cheung - Konstantin Zudov - Kristof Bastiaensen - Krystof Beuermann - Lars-Dominik Braun - Laurent P. René de Cotret+- Lawrence Chonavel - Leif Metcalf+- Leo Heitmann Ruiz - Leonard Rosenthol - Lila+- Link Swanson - Loïc Grobol - Lorenzo - Lucas Escot - Lucas Viana - Lucas V. R+- Luis Rivera - Luke Plant+- Manolis Stamatogiannakis - Marc Schreiber+- Marcin Serwin - Mario Lang+- Mark Gardner - Mark Szepieniec - Mark Wright+- Martin Joerg - Martin Linn+- Martin Michlmayr+- Martín Pozo - Masataka Ogawa - Masayoshi Takahashi - Matej Kollar@@ -214,24 +280,33 @@ - Mathias Walter - Mathieu Boespflug - Mathieu Duponchelle+- Matt Dodson - Matthew Doty - Matthew Eddey - Matthew Pickering - Matthias C. M. Troffaes - Mauro Bieg - Max Bolingbroke+- Max Heller - Max Rydahl Andersen+- Meher Chaitanya - Merijn Verstraaten - Michael Beaumont - Michael Chladek - Michael Hoffmann+- Michael McClurg - Michael Peyton Jones - Michael Reed - Michael Snoyman+- Michael Stahl - Michael Thompson+- Mickaël Canouil - Mike Tzou+- Mikołaj Machowski - Milan Bracke - MinRK+- Mohamed Akram+- Morgan Willcock - Morton Fox - Nathan Gass - Naveen@@ -240,77 +315,121 @@ - Nick Berendsen - Nick Fleisher - Nicolas Kaiser+- Niklas Eicker - Nikolai Korobeinikov - Nikolay Yakimov - Nils Carlson - Nixon Enraght-Moony+- Noah Malmed - Nokome Bentley+- Norwid Behrnd - OCzarnecki - Ola Wolska - Ole Martin Ruud+- Oliver Fabel - Oliver Matthews+- Olivier Benz+- Olivier Dossmann - Ophir Lifshitz - Or Neeman - OvidiusCicero - Owen McGrath - Pablo Rodríguez - Pascal Wagler+- Pau RE - Paul Rivier - Paul Tilley - Paulo Tanimoto+- Pavol Otto+- Per Christian Gaustad - Pete Ryland+- Peter Briggs - Peter Fabinksi - Peter Wang - Philip Pesca - Philippe Ombredanne - Phillip Alday+- Pranesh Prakash+- Prat - Prayag Verma - Puneeth Chaganti - Quinn+- R. N. West - Ralf Stephan - Raniere Silva+- Raymond Berger - Raymond Ehlers - Recai Oktaş+- Repetitive+- Reuben Thomas - Rowan Rodrik van der Molen - Roland Hieber - Roman Beránek+- Ruqi - RyanGlScott+- Ryan Gibb - S.P.H+- Sai Asish Y - Salim B+- Sam S. Almahri+- Sam May - Samuel Tardieu - Saumel Lemmenmeier+- Santiago Zarate - Sascha Wilde - Scott Morrison+- Sean Soon - Sebastian Talmon+- Sebbones+- Sen-wen Deng - Sergei Trofimovich - Sergey Astanin+- Seth Speaks - Shahbaz Youssefi - Shaun Attfield - Shim Myeongseob - Shin Sang-jae - Sidarth Kapur+- Sidney Mau - Sidharth Kapur - Simon Hengel - Simon Schuster+- Siphalor - Stefan Dresselhaus+- Stephan Daus+- Stephan Meijer+- Stephen Altamirano+- Stephen Huan+- Stephen Reindl+- Stéphane Guillou - Sukil Etxenike - Sukka - Sumit Sahrawat+- Suraj Patil+- Sven Wick - TEC - Tarik Graba - Tatiana Porras+- Terence Eden - Thenaesh Elango - Thomas Hodgson+- Thomas Soeiro - Thomas Weißschuh+- Tiago-Manzato - Tim Lin+- Tim Stewart - Tim Wisotzki - Timm Albers - Timothy Humphries - Tiziano Müller - Todd Sifleet+- Tomas Dahlqvist+- TomBen - Tom Leese+- Toni Dietze - Tristan Stenner - Tristan de Cacqueray+- Tristano Ajmone - Tuong Nguyen Manh - Uli Köhler - Urs Liska@@ -323,66 +442,99 @@ - Viktor Kronvall - Vincent - Vlad Hanciuta+- Vladimir Alexiev - Waldir Pimenta - Wandmalfarbe - Wentao Han - Wikiwide - William Lupton+- William Rusnack - Winnie Hellmann+- Wout Gevaert - Xavier Olive - Yan Pashkovsky+- Yann Trividic+- Yehuda Katz - YI - Yoan Blanc+- You Jiangbin - Yuchen Pei - Zihang Chen+- 3w36zj6+- arcnmx - a-vrma - andrebauer-- argent0-- badumont+- benniekiss - black-desk - blmage - bucklereed - bumper314 - chinapedia - cholonam+- closeobserve - csforste - d-dorazio - damon-sava-stanley - dbecher-ito - ebiim+- ech0+- etclub - favonia+- guqicun+- har7an+- harabat - hseg - infinity0x - jeongminkim-islab+- josch - kaizshang91+- lawcho+- lifeunleaded - lux-lth - luz paz - lwolfsonkin+- massifrg+- mbracke - mbrackeantidot+- mh4ckt3mh4ckt1c4s - mjfs - mt_caret+- nbehrnd+- nibras shami - niszet - nkalvi - nuew - obcat - oltolm - oquechy+- pacien+- perro tuerto+- piq9117+- priiduonu - qerub - quasicomputational+- reptee - ricnorr - robabla - roblabla - rodja.trappe - rski+- samuel-weinhardt+- sdhoward - shreevatsa.public - takahashim - taotieren - tecosaur - tgkokk - the-solipsist+- thomjur - thsutton+- thron7 - timo-a - vijayphoenix+- vkraven+- wgevaert - wiefling - willj-dev - wuffi+- λx.x
@@ -12,16 +12,15 @@ There are many ways in which you can support pandoc. Here are a few ideas: - * Participate in online discussions. The [pandoc-discuss] mailing- list is a good place for this. This gives valuable input and- makes it easier to improve the program.+ * Participate in online discussions. The [discussion+ forum] is a good place for this. * Help with questions. Every request that is answered by the wider community frees time for programming contributors. This will speed up development of new features and issue fixes. Don't underestimate your knowledge, please share it! - Good places to help are the [pandoc-discuss] mailing list, Q/A+ Good places to help are the [discussion forum], Q/A sites like StackOverflow, community forums (e.g. [RStudio][RStudio Community], [Zettlr][Zettlr Forum]), and, for technical questions, the GitHub [issue tracker].@@ -62,7 +61,7 @@ Have a question? ---------------- -Ask on [pandoc-discuss].+Ask on the [discussion forum]. Found a bug?@@ -119,7 +118,7 @@ So before submitting a bug report, consider whether it might be "out of scope." If it concerns a feature of documents that isn't representable in pandoc's Markdown, then it very likely is.-(If in doubt, you can always ask on [pandoc-discuss].)+(If in doubt, you can always ask on the [discussion forum].) Fixing bugs from the issue tracker ----------------------------------@@ -133,8 +132,8 @@ issue is generic and can be resolved without deep knowledge of the code base. * [enhancement] — A feature which would be desirable. We recommend- you discuss any proposed enhancement on pandoc-discuss before- writing code.+ you discuss any proposed enhancement on the [discussion forum]+ before writing code. * [bug] — A problem which needs to be fixed. * [complexity:low] — The fix should only be a couple of lines. * [complexity:high] — The fix might require structural changes or in depth@@ -156,7 +155,8 @@ Have an idea for a new feature? ------------------------------- -First, search [pandoc-discuss] and the issue tracker (both [open issues] *and*+First, search the [discussion forum]+and the issue tracker (both [open issues] *and* [closed issues]) to make sure that the idea has not been discussed before. Explain the rationale for the feature you're requesting. Why would this@@ -168,15 +168,16 @@ contributions. It is helpful to be sympathetic to that fact, and to communicate future plans and availability clearly. -Any potential new feature is best discussed on [pandoc-discuss]-before opening an issue.+Any potential new feature is best discussed on the [discussion+forum] before opening an issue. Patches and pull requests ------------------------- Patches and pull requests are welcome. Before you put time into a nontrivial-patch, it is a good idea to discuss it on [pandoc-discuss], especially if it is-for a new feature (rather than fixing a bug).+patch, it is a good idea to discuss it on the+[discussion forum], especially if it is for a new feature (rather+than fixing a bug). Please follow these guidelines: @@ -213,9 +214,10 @@ 9. It is better not to introduce new dependencies. Dependencies on external C libraries should especially be avoided. -10. We aim for compatibility with ghc versions from 8.0 to the- latest release. All pull requests and commits are tested- automatically on GitHub Actions.+10. We aim for compatibility with at least the last three+ released ghc versions, and sometimes more. Currently we+ support ghc versions 9.6 and higher. All pull requests+ and commits are tested automatically on GitHub Actions. Tests -----@@ -355,23 +357,6 @@ pandoc +RTS -p -RTS [file]... less pandoc.prof -Templates------------The default templates live in `data/templates`, which is a git-subtree linked to <https://github.com/jgm/pandoc-templates.git>.-The purpose of maintaining a separate repository is to allow-people to maintain variant templates as a fork.--You can modify the templates and submit patches without worrying-much about this: when these patches are merged, we will-push them to the main templates repository by doing-- git subtree push --prefix=data/templates templates master--where `templates` is a remote pointing to the templates-repository.- The code -------- @@ -437,10 +422,33 @@ - `Text.Pandoc.UUID` contains functions for generating UUIDs. - `Text.Pandoc.XML` contains functions for formatting XML. +Adding a new command-line option+--------------------------------++To add a new command-line option, you'll need to make changes in several+places:++- `MANUAL.txt` -- documentation for new option, both in the list+ of options and in the section on defaults files.+- `Text.Pandoc.App.Opt` -- new constructor for Opt and default+ value+- `Text.Pandoc.App.CommandLineOptions` -- the option parser+- `Text.Pandoc.App` or `Text.Pandoc.App.OutputSettings` --+ handle the new option+- possibly in pandoc-server: `Text.Pandoc.Server` -- handle the+ new option++If your change requires a new field for ReaderOptions or+WriterOptions, you'll also need to++- `Text.Pandoc.Options` -- type change and default value+- in pandoc-lua-engine: Text.Pandoc.Lua.Marshal.WriterOptions+ and/or Text.Pandoc.Lua.Marshal.ReaderOptions+ Lua filters ----------- -If you've written a useful pandoc [lua filter](lua-filters.html),+If you've written a useful pandoc [lua filter](./doc/lua-filters.md), you may want to consider submitting a pull request to the [lua-filters repository](https://github.com/pandoc/lua-filters). @@ -473,3 +481,5 @@ [status:more-discussion-needed]: https://github.com/jgm/pandoc/labels/status:more-discussion-needed [status:more-info-needed]: https://github.com/jgm/pandoc/labels/status:more-info-needed [stack]: https://github.com/commercialhaskell/stack+[discussion forum]: https://github.com/jgm/pandoc/discussions+
@@ -3,8 +3,8 @@ Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA-+ <https://fsf.org/>+ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -317,10 +317,9 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.-- You should have received a copy of the GNU General Public License- along with this program; if not, write to the Free Software- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.+ + You should have received a copy of the GNU General Public License along+ with this program; if not, see <https://www.gnu.org/licenses/>. Also add information on how to contact you by electronic and paper mail.
@@ -1,5 +1,5 @@ Pandoc-Copyright (C) 2006-2022 John MacFarlane <jgm at berkeley dot edu>+Copyright (C) 2006-2024 John MacFarlane <jgm at berkeley dot edu> With the exceptions noted below, this code is released under the [GPL], version 2 or later:@@ -14,9 +14,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License- along with this program; if not, write to the Free Software- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+ You should have received a copy of the GNU General Public License along+ with this program; if not, see <https://www.gnu.org/licenses/>. The GNU General Public License is available in the file COPYING.md in the source distribution. On Debian systems, the complete text of the@@ -24,9 +23,9 @@ [GPL]: https://www.gnu.org/copyleft/gpl.html -Pandoc's complete source code is available from the [Pandoc home page].--[Pandoc home page]: https://pandoc.org+The complete source code for pandoc version X.Y.Z is available at+<https://hackage.haskell.org/package/pandoc-X.Y.Z/pandoc-X.Y.Z.tar.gz>+and at <https://github.com/jgm/pandoc/tree/X.Y.Z>. Pandoc includes some code with different copyrights, or subject to different licenses. The copyright and license statements for these sources are included@@ -37,7 +36,7 @@ Text.Pandoc.Builder, Text.Pandoc.Generics, Text.Pandoc.JSON, Text.Pandoc.Walk) are licensed under the BSD 3-clause license: -Copyright (c) 2006-2021, John MacFarlane+Copyright (c) 2006-2024, John MacFarlane All rights reserved. @@ -73,7 +72,7 @@ GPL (v2 or higher, same as pandoc) or (at your option) the BSD 3-clause license. -Copyright (c) 2014--2021, John MacFarlane+Copyright (c) 2014--2024, John MacFarlane ---------------------------------------------------------------------- src/Text/Pandoc/Writers/Muse.hs@@ -83,19 +82,19 @@ ---------------------------------------------------------------------- src/Text/Pandoc/Writers/Texinfo.hs-Copyright (C) 2008-2022 John MacFarlane and Peter Wang+Copyright (C) 2008-2024 John MacFarlane and Peter Wang Released under the GNU General Public License version 2 or later. ---------------------------------------------------------------------- src/Text/Pandoc/Writers/OpenDocument.hs-Copyright (C) 2008-2022 Andrea Rossato and John MacFarlane+Copyright (C) 2008-2024 Andrea Rossato and John MacFarlane Released under the GNU General Public License version 2 or later. ---------------------------------------------------------------------- src/Text/Pandoc/Writers/Org.hs-Copyright (C) 2010-2022 Puneeth Chaganti, John MacFarlane, and+Copyright (C) 2010-2024 Puneeth Chaganti, John MacFarlane, and Albert Krewinkel Released under the GNU General Public License version 2 or later.@@ -115,7 +114,7 @@ ---------------------------------------------------------------------- src/Text/Pandoc/Readers/Textile.hs-Copyright (C) 2010-2022 Paul Rivier and John MacFarlane+Copyright (C) 2010-2024 Paul Rivier and John MacFarlane Released under the GNU General Public License version 2 or later. @@ -133,7 +132,7 @@ ---------------------------------------------------------------------- src/Text/Pandoc/Readers/EPUB.hs-Copyright (C) 2014-2022 Matthew Pickering and John MacFarlane+Copyright (C) 2014-2024 Matthew Pickering and John MacFarlane Released under the GNU General Public License version 2 or later. @@ -141,15 +140,15 @@ src/Text/Pandoc/Readers/Org.hs src/Text/Pandoc/Readers/Org/* test/Tests/Readers/Org/*-Copyright (C) 2014-2022 Albert Krewinkel+Copyright (C) 2014-2024 Albert Krewinkel Released under the GNU General Public License version 2 or later. -----------------------------------------------------------------------src/Text/Pandoc/Lua.hs-src/Text/Pandoc/Lua/*-test/lua/*-Copyright (C) 2017--2022 Albert Krewinkel and John MacFarlane+pandoc-lua-engine/src/Text/Pandoc/Lua.hs+pandoc-lua-engine/src/Text/Pandoc/Lua/*+pandoc-lua-engine/test/lua/*+Copyright (C) 2017--2024 Albert Krewinkel and John MacFarlane Released under the GNU General Public License version 2 or later. @@ -157,7 +156,7 @@ src/Text/Pandoc/Readers/Jira.hs src/Text/Pandoc/Writers/Jira.hs test/Tests/Readers/Jira.hs-Copyright (C) 2019--2022 Albert Krewinkel+Copyright (C) 2019--2024 Albert Krewinkel Released under the GNU General Public License version 2 or later. @@ -177,7 +176,7 @@ ------------------------------------------------------------------------ Pandoc embeds a Lua interpreter (via hslua). -Copyright © 1994–2020 Lua.org, PUC-Rio.+Copyright © 1994--2023 Lua.org, PUC-Rio. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the@@ -197,3 +196,30 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.++------------------------------------------------------------------------+Some of the code in wasm/pandoc.js and the patches in wasm/patches is+from https://github.com/haskell-wasm/pandoc-wasm. It is released under+this license:++MIT License++Copyright (c) Tweag I/O Limited.++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
@@ -7,9 +7,15 @@ Download the latest installer </a> -For alternative ways to install pandoc, see below-under the heading for your operating system.+For alternative ways to install pandoc, see below under the heading for+your operating system. +**Note**: the statically linked Pandoc binaries provided by us (or those+available on Conda Forge) have a limitation. They are unable to utilise Lua+filters that rely on Lua modules written in C. If you require the+functionality offered by these filters, please consider an alternative+method of installation.+ ## Windows There is a package installer at pandoc's [download page].@@ -33,18 +39,21 @@ [MiKTeX] (to typeset PDFs with [LaTeX]): choco install rsvg-convert python miktex- + Or, you can install pandoc using [winget](https://github.com/microsoft/winget-pkgs): - winget install pandoc+ winget install --source winget --exact --id JohnMacFarlane.Pandoc +Or, you can install Pandoc using [Conda forge].+ Using multiple installation methods can result in two separate installations of pandoc; it is recommended to properly uninstall pandoc before switching to an alternative installation method. -By default, Pandoc creates PDFs using LaTeX.-We recommend installing it via [MiKTeX].+By default, Pandoc creates PDFs using LaTeX. We recommend+installing it via [MiKTeX]. With the option `--pdf-engine`,+you however can specify other programs for this task. ## macOS @@ -69,6 +78,12 @@ Homebrew installs from source, which takes additional time and disk space for the `ghc` compiler and dependent Haskell libraries. +You can also install pandoc using [MacPorts]:++ port install pandoc++Or, you can install Pandoc using [Conda forge].+ We also provide a zip file containing the binaries and man pages, for those who prefer not to use the installer. Simply unzip the file and move the binaries and man pages to@@ -82,20 +97,21 @@ tlmgr install collection-fontsrecommended +With the option `--pdf-engine`, you however can specify other programs+for this task.+ ## Linux Check whether the pandoc version in your package manager is not outdated. Pandoc is in the [Debian], [Ubuntu], [Slackware],-[Arch], [Fedora], [NiXOS], [openSUSE], [gentoo] and [Void] repositories.+[Arch], [Fedora], [NixOS], [openSUSE], [gentoo] and [Void] repositories. To get the latest release, we provide a binary package for amd64 architecture on the **[download page]**. The executable is statically linked and has no dynamic dependencies or dependencies on external-data files. Note: because of the static-linking, the pandoc binary from this package cannot use lua-filters that require external lua modules written in C.+data files. Both a tarball and a deb installer are provided. To install the deb: @@ -118,15 +134,15 @@ ar p $DEB data.tar.gz | tar xvz --strip-components 2 -C $DEST +Or, you can install Pandoc using [Conda forge].+ You can also install from source, using the instructions below under [Compiling from source].-Note that most distros have the Haskell platform in their-package repositories. For example, on Debian/Ubuntu,-you can install it with `apt-get install haskell-platform`. -For PDF output, you'll need LaTeX. We recommend installing+By default, Pandoc creates PDFs using LaTeX. We recommend installing [TeX Live](https://www.tug.org/texlive/) via your package-manager. (On Debian/Ubuntu, `apt-get install texlive`.)+manager. (On Debian/Ubuntu, `apt-get install texlive`.) With the option+`--pdf-engine`, you however can specify other programs for this task. ## Chrome OS @@ -143,8 +159,23 @@ ## BSD -Pandoc is in the [NetBSD] and [FreeBSD ports] repositories.+Pandoc is in the [NetBSD], [FreeBSD], and [OpenBSD ports] repositories. +## Conda Forge++You can install Pandoc using a [Conda+Forge](https://anaconda.org/conda-forge/pandoc) tool, like+[Conda](https://conda.pydata.org/docs/intro.html),+[[Micro]Mamba](https://mamba.readthedocs.io/en/latest/index.html) or+[Pixi](https://prefix.dev). Conda forge also includes multiple LaTeX and+other relevant packages for Pandoc (including `pandoc-citeproc`,+`pandoc-plot`, `rsvg-convert` via `librsvg` etc.). **Note:** conda forge+installs a statically-linked executable.++ conda install -c conda-forge pandoc+ pixi global install pandoc+ micromamba install pandoc+ ## Docker The official Docker images for pandoc can be found at@@ -205,18 +236,15 @@ 1. Install [stack][stack]. Note that Pandoc requires stack >= 1.7.0. -2. Change to the pandoc source directory and issue the following commands:-+2. stack setup- stack install+ stack install pandoc-cli `stack setup` will automatically download the ghc compiler if you don't have it. `stack install` will install the `pandoc` executable into `~/.local/bin`, which you should add to your `PATH`. This process will take a while, and will consume a considerable amount of disk space.- If you also want the `pandoc-server` executable, add- `--flag pandoc:server` to the above command. ### Quick cabal method@@ -230,22 +258,21 @@ 3. Use `cabal` to install pandoc and its dependencies: - cabal install pandoc+ cabal install pandoc-cli This procedure will install the released version of pandoc, which will be downloaded automatically from HackageDB.- The `pandoc` executable will be placed in `$HOME/.cabal/bin`+ The `pandoc` executable will be symlinked in`$HOME/.cabal/bin` on linux/unix/macOS and in `%APPDATA%\cabal\bin` on Windows.- Make sure this directory is in your path.-- If you also want the `pandoc-server` executable, add- `-fserver` to the above command.-- If you want to install a modified or development version- of pandoc instead, switch to the source directory and do- as above, but without the 'pandoc':+ Make sure this directory is in your path. To specify a+ custom install directory, use `--installdir`. To have+ the executable copied instead of symlinked, use+ `--install-method=copy`. - cabal install+ If you want to install a modified or development version of+ pandoc instead, switch to the source directory before running+ the above command -- cabal will use the local code for all+ projects mentioned in the `cabal.project`. 4. You should now be able to run `pandoc`: @@ -266,12 +293,10 @@ assume that the pandoc source directory is your working directory. You will need cabal version 2.0 or higher. -1. Install dependencies: in addition to the [Haskell platform],- you will need a number of additional libraries. You can install- them all with+1. Install dependencies: cabal update- cabal install --only-dependencies+ cabal build --only-dependencies 2. Configure: @@ -285,15 +310,20 @@ `FLAGSPEC` is a list of Cabal configuration flags, optionally preceded by a `-` (to force the flag to `false`), and separated- by spaces. Pandoc's flags include:+ by spaces. `pandoc`'s flags include: - `embed_data_files`: embed all data files into the binary (default no). This is helpful if you want to create a relocatable binary. - - `lua53`: embed support for Lua 5.3 instead of 5.4.+ `pandoc-cli`'s flags include: - - `server`: build the `pandoc-server` executable.+ - `lua`: compile in support for Lua filters and custom+ writers. + - `server`: compile in support for running in HTTP server+ mode when the executable is renamed (or symlinked as)+ `pandoc-server`.+ 3. Build: cabal build@@ -303,19 +333,20 @@ cabal haddock --html-location=URL --hyperlink-source +5. Install + cabal install pandoc-cli+ ### Creating a relocatable binary It is possible to compile pandoc such that the data files pandoc uses are embedded in the binary. The resulting binary can be run from any directory and is completely self-contained. With cabal, add `-fembed_data_files` to the `cabal configure`-or `cabal install` commands.+or `cabal build` commands. With stack, use `--flag pandoc:embed_data_files`. -- ### Running tests Pandoc comes with an automated test suite.@@ -325,7 +356,6 @@ To run particular tests (pattern-matching on their names), use the `-p` option: - cabal install pandoc --enable-tests cabal test --test-options='-p markdown' Or with stack:@@ -364,25 +394,25 @@ cabal bench --benchmark-options='markdown' -[Arch]: https://www.archlinux.org/packages/community/x86_64/pandoc/+[Arch]: https://archlinux.org/packages/?q=pandoc [Cabal User's Guide]: https://cabal.readthedocs.io/-[Debian]: https://packages.debian.org/pandoc-[Fedora]: https://apps.fedoraproject.org/packages/pandoc-[FreeBSD ports]: https://www.freshports.org/textproc/hs-pandoc/+[Debian]: https://packages.debian.org/search?keywords=pandoc+[Fedora]: https://packages.fedoraproject.org/pkgs/pandoc/pandoc/+[FreeBSD]: https://www.freshports.org/textproc/hs-pandoc/ [GHC]: https://www.haskell.org/ghc/ [GitLab CI/CD]: https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/-[Haskell platform]: https://hackage.haskell.org/platform/-[MacPorts]: https://trac.macports.org/browser/trunk/dports/textproc/pandoc/Portfile+[MacPorts]: https://ports.macports.org/port/pandoc/ [MacTeX]: https://tug.org/mactex/+[OpenBSD ports]: https://cvsweb.openbsd.org/ports/textproc/pandoc/ [BasicTeX]: https://www.tug.org/mactex/morepackages.html [LaTeX]: https://www.latex-project.org [MiKTeX]: https://miktex.org/ [librsvg]: https://wiki.gnome.org/Projects/LibRsvg [Python]: https://www.python.org-[NetBSD]: https://pkgsrc.se/wip/pandoc-[NixOS]: https://nixos.org/nixos/packages.html+[NetBSD]: https://pkgsrc.se/converters/pandoc+[NixOS]: https://search.nixos.org/packages?query=pandoc [Slackware]: https://www.slackbuilds.org/result/?search=pandoc&sv=-[Ubuntu]: https://packages.ubuntu.com/pandoc+[Ubuntu]: https://packages.ubuntu.com/search?keywords=pandoc [download page]: https://github.com/jgm/pandoc/releases/latest [gentoo]: https://packages.gentoo.org/package/app-text/pandoc [haskell repository]: https://wiki.archlinux.org/index.php/Haskell_Package_Guidelines#.5Bhaskell.5D@@ -390,5 +420,5 @@ [source tarball]: https://hackage.haskell.org/package/pandoc [stack]: https://docs.haskellstack.org/en/stable/install_and_upgrade.html [cabal-install]: https://hackage.haskell.org/package/cabal-install-[Void]: https://voidlinux.org/-[uninstaller]: https://raw.githubusercontent.com/jgm/pandoc/master/macos/uninstall-pandoc.pl+[Void]: https://voidlinux.org/packages/?arch=x86_64&q=pandoc+[uninstaller]: https://raw.githubusercontent.com/jgm/pandoc/main/macos/uninstall-pandoc.pl
@@ -1,7125 +1,8050 @@ --- title: Pandoc User's Guide author: John MacFarlane-date: August 22, 2022------# Synopsis--`pandoc` [*options*] [*input-file*]...--# Description--Pandoc is a [Haskell] library for converting from one markup format to-another, and a command-line tool that uses this library.--Pandoc can convert between numerous markup and word processing formats,-including, but not limited to, various flavors of [Markdown], [HTML],-[LaTeX] and [Word docx]. For the full lists of input and output formats,-see the `--from` and `--to` [options below][General options].-Pandoc can also produce [PDF] output: see [creating a PDF], below.--Pandoc's enhanced version of Markdown includes syntax for [tables],-[definition lists], [metadata blocks], [footnotes], [citations], [math],-and much more. See below under [Pandoc's Markdown].--Pandoc has a modular design: it consists of a set of readers, which parse-text in a given format and produce a native representation of the document-(an _abstract syntax tree_ or AST), and a set of writers, which convert-this native representation into a target format. Thus, adding an input-or output format requires only adding a reader or writer. Users can also-run custom [pandoc filters] to modify the intermediate AST.--Because pandoc's intermediate representation of a document is less-expressive than many of the formats it converts between, one should-not expect perfect conversions between every format and every other.-Pandoc attempts to preserve the structural elements of a document, but-not formatting details such as margin size. And some document elements,-such as complex tables, may not fit into pandoc's simple document-model. While conversions from pandoc's Markdown to all formats aspire-to be perfect, conversions from formats more expressive than pandoc's-Markdown can be expected to be lossy.--## Using pandoc--If no *input-files* are specified, input is read from *stdin*.-Output goes to *stdout* by default. For output to a file,-use the `-o` option:-- pandoc -o output.html input.txt--By default, pandoc produces a document fragment. To produce a standalone-document (e.g. a valid HTML file including `<head>` and `<body>`),-use the `-s` or `--standalone` flag:-- pandoc -s -o output.html input.txt--For more information on how standalone documents are produced, see-[Templates] below.--If multiple input files are given, pandoc will concatenate them all (with-blank lines between them) before parsing. (Use `--file-scope` to parse files-individually.)--## Specifying formats--The format of the input and output can be specified explicitly using-command-line options. The input format can be specified using the-`-f/--from` option, the output format using the `-t/--to` option.-Thus, to convert `hello.txt` from Markdown to LaTeX, you could type:-- pandoc -f markdown -t latex hello.txt--To convert `hello.html` from HTML to Markdown:-- pandoc -f html -t markdown hello.html--Supported input and output formats are listed below under [Options]-(see `-f` for input formats and `-t` for output formats). You-can also use `pandoc --list-input-formats` and-`pandoc --list-output-formats` to print lists of supported-formats.--If the input or output format is not specified explicitly, pandoc-will attempt to guess it from the extensions of the filenames.-Thus, for example,-- pandoc -o hello.tex hello.txt--will convert `hello.txt` from Markdown to LaTeX. If no output file-is specified (so that output goes to *stdout*), or if the output file's-extension is unknown, the output format will default to HTML.-If no input file is specified (so that input comes from *stdin*), or-if the input files' extensions are unknown, the input format will-be assumed to be Markdown.--## Character encoding--Pandoc uses the UTF-8 character encoding for both input and output.-If your local character encoding is not UTF-8, you-should pipe input and output through [`iconv`]:-- iconv -t utf-8 input.txt | pandoc | iconv -f utf-8--Note that in some output formats (such as HTML, LaTeX, ConTeXt,-RTF, OPML, DocBook, and Texinfo), information about-the character encoding is included in the document header, which-will only be included if you use the `-s/--standalone` option.--[`iconv`]: https://www.gnu.org/software/libiconv/--## Creating a PDF--To produce a PDF, specify an output file with a `.pdf` extension:-- pandoc test.txt -o test.pdf--By default, pandoc will use LaTeX to create the PDF, which requires-that a LaTeX engine be installed (see `--pdf-engine` below).-Alternatively, pandoc can use ConTeXt, roff ms, or HTML as an-intermediate format. To do this, specify an output file with a-`.pdf` extension, as before, but add the `--pdf-engine` option-or `-t context`, `-t html`, or `-t ms` to the command line.-The tool used to generate the PDF from the intermediate format-may be specified using `--pdf-engine`.--You can control the PDF style using variables, depending on-the intermediate format used: see [variables for LaTeX],-[variables for ConTeXt], [variables for `wkhtmltopdf`],-[variables for ms]. When HTML is used as an intermediate-format, the output can be styled using `--css`.--To debug the PDF creation, it can be useful to look at the intermediate-representation: instead of `-o test.pdf`, use for example `-s -o test.tex`-to output the generated LaTeX. You can then test it with `pdflatex test.tex`.--When using LaTeX, the following packages need to be available-(they are included with all recent versions of [TeX Live]):-[`amsfonts`], [`amsmath`], [`lm`], [`unicode-math`],-[`iftex`], [`listings`] (if the-`--listings` option is used), [`fancyvrb`], [`longtable`],-[`booktabs`], [`graphicx`] (if the document-contains images), [`hyperref`], [`xcolor`],-[`ulem`], [`geometry`] (with the `geometry` variable set),-[`setspace`] (with `linestretch`), and-[`babel`] (with `lang`). If `CJKmainfont` is set, [`xeCJK`]-is needed. The use of `xelatex` or `lualatex` as-the PDF engine requires [`fontspec`]. `lualatex` uses-[`selnolig`]. `xelatex` uses [`bidi`] (with the `dir` variable set).-If the `mathspec` variable is set, `xelatex` will use [`mathspec`]-instead of [`unicode-math`]. The [`upquote`] and [`microtype`]-packages are used if available, and [`csquotes`] will be used-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-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),-[`parskip`] (for better inter-paragraph spaces), [`xurl`] (for-better line breaks in URLs), [`bookmark`] (for better PDF-bookmarks), and [`footnotehyper`] or [`footnote`] (to allow-footnotes in tables).--[TeX Live]: https://www.tug.org/texlive/-[`amsfonts`]: https://ctan.org/pkg/amsfonts-[`amsmath`]: https://ctan.org/pkg/amsmath-[`babel`]: https://ctan.org/pkg/babel-[`biber`]: https://ctan.org/pkg/biber-[`biblatex`]: https://ctan.org/pkg/biblatex-[`bibtex`]: https://ctan.org/pkg/bibtex-[`bidi`]: https://ctan.org/pkg/bidi-[`bookmark`]: https://ctan.org/pkg/bookmark-[`booktabs`]: https://ctan.org/pkg/booktabs-[`csquotes`]: https://ctan.org/pkg/csquotes-[`fancyvrb`]: https://ctan.org/pkg/fancyvrb-[`fontspec`]: https://ctan.org/pkg/fontspec-[`footnote`]: https://ctan.org/pkg/footnote-[`footnotehyper`]: https://ctan.org/pkg/footnotehyper-[`geometry`]: https://ctan.org/pkg/geometry-[`graphicx`]: https://ctan.org/pkg/graphicx-[`grffile`]: https://ctan.org/pkg/grffile-[`hyperref`]: https://ctan.org/pkg/hyperref-[`iftex`]: https://ctan.org/pkg/iftex-[`listings`]: https://ctan.org/pkg/listings-[`lm`]: https://ctan.org/pkg/lm-[`longtable`]: https://ctan.org/pkg/longtable-[`mathspec`]: https://ctan.org/pkg/mathspec-[`microtype`]: https://ctan.org/pkg/microtype-[`natbib`]: https://ctan.org/pkg/natbib-[`parskip`]: https://ctan.org/pkg/parskip-[`polyglossia`]: https://ctan.org/pkg/polyglossia-[`prince`]: https://www.princexml.com/-[`setspace`]: https://ctan.org/pkg/setspace-[`ulem`]: https://ctan.org/pkg/ulem-[`unicode-math`]: https://ctan.org/pkg/unicode-math-[`upquote`]: https://ctan.org/pkg/upquote-[`weasyprint`]: https://weasyprint.org-[`wkhtmltopdf`]: https://wkhtmltopdf.org-[`xcolor`]: https://ctan.org/pkg/xcolor-[`xeCJK`]: https://ctan.org/pkg/xecjk-[`xurl`]: https://ctan.org/pkg/xurl-[`selnolig`]: https://ctan.org/pkg/selnolig----## Reading from the Web--Instead of an input file, an absolute URI may be given. In this case-pandoc will fetch the content using HTTP:-- pandoc -f html -t markdown https://www.fsf.org--It is possible to supply a custom User-Agent string or other-header when requesting a document from a URL:-- pandoc -f html -t markdown --request-header User-Agent:"Mozilla/5.0" \- https://www.fsf.org--# Options--## General options {.options}--`-f` *FORMAT*, `-r` *FORMAT*, `--from=`*FORMAT*, `--read=`*FORMAT*--: Specify input format. *FORMAT* can be:-- ::: {#input-formats}- - `bibtex` ([BibTeX] bibliography)- - `biblatex` ([BibLaTeX] bibliography)- - `commonmark` ([CommonMark] Markdown)- - `commonmark_x` ([CommonMark] Markdown with extensions)- - `creole` ([Creole 1.0])- - `csljson` ([CSL JSON] bibliography)- - `csv` ([CSV] table)- - `tsv` ([TSV] table)- - `docbook` ([DocBook])- - `docx` ([Word docx])- - `dokuwiki` ([DokuWiki markup])- - `endnotexml` ([EndNote XML bibliography])- - `epub` ([EPUB])- - `fb2` ([FictionBook2] e-book)- - `gfm` ([GitHub-Flavored Markdown]),- or the deprecated and less accurate `markdown_github`;- use [`markdown_github`](#markdown-variants) only- if you need extensions not supported in [`gfm`](#markdown-variants).- - `haddock` ([Haddock markup])- - `html` ([HTML])- - `ipynb` ([Jupyter notebook])- - `jats` ([JATS] XML)- - `jira` ([Jira]/Confluence wiki markup)- - `json` (JSON version of native AST)- - `latex` ([LaTeX])- - `markdown` ([Pandoc's Markdown])- - `markdown_mmd` ([MultiMarkdown])- - `markdown_phpextra` ([PHP Markdown Extra])- - `markdown_strict` (original unextended [Markdown])- - `mediawiki` ([MediaWiki markup])- - `man` ([roff man])- - `muse` ([Muse])- - `native` (native Haskell)- - `odt` ([ODT])- - `opml` ([OPML])- - `org` ([Emacs Org mode])- - `ris` ([RIS] bibliography)- - `rtf` ([Rich Text Format])- - `rst` ([reStructuredText])- - `t2t` ([txt2tags])- - `textile` ([Textile])- - `tikiwiki` ([TikiWiki markup])- - `twiki` ([TWiki markup])- - `vimwiki` ([Vimwiki])- - the path of a custom Lua reader, see [Custom readers and writers] below- :::-- Extensions can be individually enabled or disabled by- appending `+EXTENSION` or `-EXTENSION` to the format name.- See [Extensions] below, for a list of extensions and- their names. See `--list-input-formats` and `--list-extensions`,- below.--`-t` *FORMAT*, `-w` *FORMAT*, `--to=`*FORMAT*, `--write=`*FORMAT*--: Specify output format. *FORMAT* can be:-- ::: {#output-formats}- - `asciidoc` ([AsciiDoc]) or `asciidoctor` ([AsciiDoctor])- - `beamer` ([LaTeX beamer][`beamer`] slide show)- - `bibtex` ([BibTeX] bibliography)- - `biblatex` ([BibLaTeX] bibliography)- - `commonmark` ([CommonMark] Markdown)- - `commonmark_x` ([CommonMark] Markdown with extensions)- - `context` ([ConTeXt])- - `csljson` ([CSL JSON] bibliography)- - `docbook` or `docbook4` ([DocBook] 4)- - `docbook5` (DocBook 5)- - `docx` ([Word docx])- - `dokuwiki` ([DokuWiki markup])- - `epub` or `epub3` ([EPUB] v3 book)- - `epub2` (EPUB v2)- - `fb2` ([FictionBook2] e-book)- - `gfm` ([GitHub-Flavored Markdown]),- or the deprecated and less accurate `markdown_github`;- use [`markdown_github`](#markdown-variants) only- if you need extensions not supported in [`gfm`](#markdown-variants).- - `haddock` ([Haddock markup])- - `html` or `html5` ([HTML], i.e. [HTML5]/XHTML [polyglot markup])- - `html4` ([XHTML] 1.0 Transitional)- - `icml` ([InDesign ICML])- - `ipynb` ([Jupyter notebook])- - `jats_archiving` ([JATS] XML, Archiving and Interchange Tag Set)- - `jats_articleauthoring` ([JATS] XML, Article Authoring Tag Set)- - `jats_publishing` ([JATS] XML, Journal Publishing Tag Set)- - `jats` (alias for `jats_archiving`)- - `jira` ([Jira]/Confluence wiki markup)- - `json` (JSON version of native AST)- - `latex` ([LaTeX])- - `man` ([roff man])- - `markdown` ([Pandoc's Markdown])- - `markdown_mmd` ([MultiMarkdown])- - `markdown_phpextra` ([PHP Markdown Extra])- - `markdown_strict` (original unextended [Markdown])- - `markua` ([Markua])- - `mediawiki` ([MediaWiki markup])- - `ms` ([roff ms])- - `muse` ([Muse])- - `native` (native Haskell)- - `odt` ([OpenOffice text document][ODT])- - `opml` ([OPML])- - `opendocument` ([OpenDocument])- - `org` ([Emacs Org mode])- - `pdf` ([PDF])- - `plain` (plain text)- - `pptx` ([PowerPoint] slide show)- - `rst` ([reStructuredText])- - `rtf` ([Rich Text Format])- - `texinfo` ([GNU Texinfo])- - `textile` ([Textile])- - `slideous` ([Slideous] HTML and JavaScript slide show)- - `slidy` ([Slidy] HTML and JavaScript slide show)- - `dzslides` ([DZSlides] HTML5 + JavaScript slide show)- - `revealjs` ([reveal.js] HTML5 + JavaScript slide show)- - `s5` ([S5] HTML and JavaScript slide show)- - `tei` ([TEI Simple])- - `xwiki` ([XWiki markup])- - `zimwiki` ([ZimWiki markup])- - the path of a custom Lua writer, see [Custom readers and writers] below- :::-- Note that `odt`, `docx`, `epub`, and `pdf` output will not be directed- to *stdout* unless forced with `-o -`.-- Extensions can be individually enabled or- disabled by appending `+EXTENSION` or `-EXTENSION` to the format- name. See [Extensions] below, for a list of extensions and their- names. See `--list-output-formats` and `--list-extensions`, below.--`-o` *FILE*, `--output=`*FILE*--: Write output to *FILE* instead of *stdout*. If *FILE* is- `-`, output will go to *stdout*, even if a non-textual format- (`docx`, `odt`, `epub2`, `epub3`) is specified.--`--data-dir=`*DIRECTORY*--: Specify the user data directory to search for pandoc data files.- If this option is not specified, the default user data directory- will be used. On \*nix and macOS systems this will be the `pandoc`- subdirectory of the XDG data directory (by default,- `$HOME/.local/share`, overridable by setting the `XDG_DATA_HOME`- environment variable). If that directory does not exist and- `$HOME/.pandoc` exists, it will be used (for backwards compatibility).- On Windows the default user data directory is- `C:\Users\USERNAME\AppData\Roaming\pandoc`.- You can find the default user data directory on your system by- looking at the output of `pandoc --version`.- Data files placed in this directory (for example, `reference.odt`,- `reference.docx`, `epub.css`, `templates`) will override- pandoc's normal defaults.--`-d` *FILE*, `--defaults=`*FILE*--: Specify a set of default option settings. *FILE* is a YAML- file whose fields correspond to command-line option- settings. All options for document conversion, including input- and output files, can be set using a defaults file. The file will- be searched for first in the working directory, and then in- the `defaults` subdirectory of the user data directory- (see `--data-dir`). The `.yaml` extension may be omitted.- See the section [Defaults files] for more information on the- file format. Settings from the defaults file may be- overridden or extended by subsequent options on the command- line.--`--bash-completion`--: Generate a bash completion script. To enable bash completion- with pandoc, add this to your `.bashrc`:-- eval "$(pandoc --bash-completion)"--`--verbose`--: Give verbose debugging output.--`--quiet`--: Suppress warning messages.--`--fail-if-warnings`--: Exit with error status if there are any warnings.--`--log=`*FILE*--: Write log messages in machine-readable JSON format to- *FILE*. All messages above DEBUG level will be written,- regardless of verbosity settings (`--verbose`, `--quiet`).--`--list-input-formats`--: List supported input formats, one per line.--`--list-output-formats`--: List supported output formats, one per line.--`--list-extensions`[`=`*FORMAT*]--: List supported extensions for *FORMAT*, one per line, preceded- by a `+` or `-` indicating whether it is enabled by default- in *FORMAT*. If *FORMAT* is not specified, defaults for- pandoc's Markdown are given.--`--list-highlight-languages`--: List supported languages for syntax highlighting, one per- line.--`--list-highlight-styles`--: List supported styles for syntax highlighting, one per line.- See `--highlight-style`.--`-v`, `--version`--: Print version.--`-h`, `--help`--: Show usage message.--[Markdown]: https://daringfireball.net/projects/markdown/-[CommonMark]: https://commonmark.org-[PHP Markdown Extra]: https://michelf.ca/projects/php-markdown/extra/-[GitHub-Flavored Markdown]: https://help.github.com/articles/github-flavored-markdown/-[MultiMarkdown]: https://fletcherpenney.net/multimarkdown/-[reStructuredText]: https://docutils.sourceforge.io/docs/ref/rst/introduction.html-[S5]: https://meyerweb.com/eric/tools/s5/-[Slidy]: https://www.w3.org/Talks/Tools/Slidy2/-[Slideous]: https://goessner.net/articles/slideous/-[HTML]: https://www.w3.org/html/-[HTML5]: https://html.spec.whatwg.org/-[polyglot markup]: https://www.w3.org/TR/html-polyglot/-[XHTML]: https://www.w3.org/TR/xhtml1/-[LaTeX]: https://www.latex-project.org/-[`beamer`]: https://ctan.org/pkg/beamer-[Beamer User's Guide]: http://mirrors.ctan.org/macros/latex/contrib/beamer/doc/beameruserguide.pdf-[ConTeXt]: https://www.contextgarden.net/-[Rich Text Format]: https://en.wikipedia.org/wiki/Rich_Text_Format-[DocBook]: https://docbook.org-[JATS]: https://jats.nlm.nih.gov-[Jira]: https://jira.atlassian.com/secure/WikiRendererHelpAction.jspa?section=all-[txt2tags]: https://txt2tags.org-[EPUB]: http://idpf.org/epub-[OPML]: http://dev.opml.org/spec2.html-[OpenDocument]: http://opendocument.xml.org-[ODT]: https://en.wikipedia.org/wiki/OpenDocument-[Textile]: https://www.promptworks.com/textile-[MediaWiki markup]: https://www.mediawiki.org/wiki/Help:Formatting-[DokuWiki markup]: https://www.dokuwiki.org/dokuwiki-[ZimWiki markup]: https://zim-wiki.org/manual/Help/Wiki_Syntax.html-[XWiki markup]: https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/XWikiSyntax/-[TWiki markup]: https://twiki.org/cgi-bin/view/TWiki/TextFormattingRules-[TikiWiki markup]: https://doc.tiki.org/Wiki-Syntax-Text#The_Markup_Language_Wiki-Syntax-[Haddock markup]: https://www.haskell.org/haddock/doc/html/ch03s08.html-[Creole 1.0]: http://www.wikicreole.org/wiki/Creole1.0-[CSV]: https://tools.ietf.org/html/rfc4180-[TSV]: https://www.iana.org/assignments/media-types/text/tab-separated-values-[roff man]: https://man.cx/groff_man(7)-[roff ms]: https://man.cx/groff_ms(7)-[Haskell]: https://www.haskell.org-[GNU Texinfo]: https://www.gnu.org/software/texinfo/-[RIS]: https://en.wikipedia.org/wiki/RIS_(file_format)-[Emacs Org mode]: https://orgmode.org-[AsciiDoc]: https://www.methods.co.nz/asciidoc/-[AsciiDoctor]: https://asciidoctor.org/-[DZSlides]: https://paulrouget.com/dzslides/-[Word docx]: https://en.wikipedia.org/wiki/Office_Open_XML-[PDF]: https://www.adobe.com/pdf/-[reveal.js]: https://revealjs.com/-[FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1-[Jupyter notebook]: https://nbformat.readthedocs.io/en/latest/-[InDesign ICML]: https://wwwimages.adobe.com/www.adobe.com/content/dam/acom/en/devnet/indesign/sdk/cs6/idml/idml-cookbook.pdf-[TEI Simple]: https://github.com/TEIC/TEI-Simple-[Muse]: https://amusewiki.org/library/manual-[PowerPoint]: https://en.wikipedia.org/wiki/Microsoft_PowerPoint-[Vimwiki]: https://vimwiki.github.io-[CSL JSON]: https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html-[BibTeX]: https://ctan.org/pkg/bibtex-[BibLaTeX]: https://ctan.org/pkg/biblatex-[Markua]: https://leanpub.com/markua/read-[EndNote XML bibliography]: https://support.clarivate.com/Endnote/s/article/EndNote-XML-Document-Type-Definition--## Reader options {.options}--`--shift-heading-level-by=`*NUMBER*--: Shift heading levels by a positive or negative integer.- For example, with `--shift-heading-level-by=-1`, level 2- headings become level 1 headings, and level 3 headings- become level 2 headings. Headings cannot have a level- less than 1, so a heading that would be shifted below level 1- becomes a regular paragraph. Exception: with a shift of -N,- a level-N heading at the beginning of the document- replaces the metadata title. `--shift-heading-level-by=-1`- is a good choice when converting HTML or Markdown documents that- use an initial level-1 heading for the document title and- level-2+ headings for sections. `--shift-heading-level-by=1`- may be a good choice for converting Markdown documents that- use level-1 headings for sections to HTML, since pandoc uses- a level-1 heading to render the document title.--`--base-header-level=`*NUMBER*--: *Deprecated. Use `--shift-heading-level-by`=X instead,- where X = NUMBER - 1.* Specify the base level for headings- (defaults to 1).--`--strip-empty-paragraphs`--: *Deprecated. Use the `+empty_paragraphs` extension instead.*- Ignore paragraphs with no content. This option is useful- for converting word processing documents where users have- used empty paragraphs to create inter-paragraph space.--`--indented-code-classes=`*CLASSES*--: Specify classes to use for indented code blocks--for example,- `perl,numberLines` or `haskell`. Multiple classes may be separated- by spaces or commas.--`--default-image-extension=`*EXTENSION*--: Specify a default extension to use when image paths/URLs have no- extension. This allows you to use the same source for formats that- require different kinds of images. Currently this option only affects- the Markdown and LaTeX readers.--`--file-scope`--: Parse each file individually before combining for multifile- documents. This will allow footnotes in different files with the- same identifiers to work as expected. If this option is set,- footnotes and links will not work across files. Reading binary- files (docx, odt, epub) implies `--file-scope`.--`-F` *PROGRAM*, `--filter=`*PROGRAM*--: Specify an executable to be used as a filter transforming the- pandoc AST after the input is parsed and before the output is- written. The executable should read JSON from stdin and write- JSON to stdout. The JSON must be formatted like pandoc's own- JSON input and output. The name of the output format will be- passed to the filter as the first argument. Hence,-- pandoc --filter ./caps.py -t latex-- is equivalent to-- pandoc -t json | ./caps.py latex | pandoc -f json -t latex-- The latter form may be useful for debugging filters.-- Filters may be written in any language. `Text.Pandoc.JSON`- exports `toJSONFilter` to facilitate writing filters in Haskell.- Those who would prefer to write filters in python can use the- module [`pandocfilters`], installable from PyPI. There are also- pandoc filter libraries in [PHP], [perl], and- [JavaScript/node.js].-- In order of preference, pandoc will look for filters in-- 1. a specified full or relative path (executable or- non-executable),-- 2. `$DATADIR/filters` (executable or non-executable)- where `$DATADIR` is the user data directory (see- `--data-dir`, above),-- 3. `$PATH` (executable only).-- Filters, Lua-filters, and citeproc processing are applied in- the order specified on the command line.--`-L` *SCRIPT*, `--lua-filter=`*SCRIPT*--: Transform the document in a similar fashion as JSON filters (see- `--filter`), but use pandoc's built-in Lua filtering system. The given- Lua script is expected to return a list of Lua filters which will be- applied in order. Each Lua filter must contain element-transforming- functions indexed by the name of the AST element on which the filter- function should be applied.-- The `pandoc` Lua module provides helper functions for element- creation. It is always loaded into the script's Lua environment.-- See the [Lua filters documentation] for further details.-- In order of preference, pandoc will look for Lua filters in-- 1. a specified full or relative path,-- 2. `$DATADIR/filters` where `$DATADIR` is the user data- directory (see `--data-dir`, above).-- Filters, Lua filters, and citeproc processing are applied in- the order specified on the command line.--`-M` *KEY*[`=`*VAL*], `--metadata=`*KEY*[`:`*VAL*]--: Set the metadata field *KEY* to the value *VAL*. A value specified- on the command line overrides a value specified in the document- using [YAML metadata blocks][Extension: `yaml_metadata_block`].- Values will be parsed as YAML boolean or string values. If no value is- specified, the value will be treated as Boolean true. Like- `--variable`, `--metadata` causes template variables to be set.- But unlike `--variable`, `--metadata` affects the metadata of the- underlying document (which is accessible from filters and may be- printed in some output formats) and metadata values will be escaped- when inserted into the template.--`--metadata-file=`*FILE*--: Read metadata from the supplied YAML (or JSON) file. This- option can be used with every input format, but string scalars- in the YAML file will always be parsed as Markdown. (If the- input format is Markdown or a Markdown variant, then the- same variant will be used to parse the metadata file;- if it is a non-Markdown format, pandoc's default Markdown- extensions will be used.) This option can be used- repeatedly to include multiple metadata files; values in- files specified later on the command line will be preferred- over those specified in earlier files. Metadata values- specified inside the document, or by using `-M`, overwrite- values specified with this option. The file will be searched- for first in the working directory, and then in the `metadata`- subdirectory of the user data directory (see `--data-dir`).--`-p`, `--preserve-tabs`--: Preserve tabs instead of converting them to spaces. (By default, pandoc- converts tabs to spaces before parsing its input.) Note that this will- only affect tabs in literal code spans and code blocks. Tabs in regular- text are always treated as spaces.--`--tab-stop=`*NUMBER*--: Specify the number of spaces per tab (default is 4).--`--track-changes=accept`|`reject`|`all`--: Specifies what to do with insertions, deletions, and comments- produced by the MS Word "Track Changes" feature. `accept` (the- default) processes all the insertions and deletions.- `reject` ignores them. Both `accept` and `reject` ignore comments.- `all` includes all insertions, deletions, and comments, wrapped- in spans with `insertion`, `deletion`, `comment-start`, and- `comment-end` classes, respectively. The author and time of- change is included. `all` is useful for scripting: only- accepting changes from a certain reviewer, say, or before a- certain date. If a paragraph is inserted or deleted,- `track-changes=all` produces a span with the class- `paragraph-insertion`/`paragraph-deletion` before the- affected paragraph break. This option only affects the docx- reader.--`--extract-media=`*DIR*--: Extract images and other media contained in or linked from- the source document to the path *DIR*, creating it if- necessary, and adjust the images references in the document- so they point to the extracted files. Media are downloaded,- read from the file system, or extracted from a binary- container (e.g. docx), as needed. The original file paths- are used if they are relative paths not containing `..`.- Otherwise filenames are constructed from the SHA1 hash of- the contents.--`--abbreviations=`*FILE*--: Specifies a custom abbreviations file, with abbreviations- one to a line. If this option is not specified, pandoc will- read the data file `abbreviations` from the user data- directory or fall back on a system default. To see the- system default, use- `pandoc --print-default-data-file=abbreviations`. The only- use pandoc makes of this list is in the Markdown reader.- Strings found in this list will be followed by a nonbreaking- space, and the period will not produce sentence-ending space- in formats like LaTeX. The strings may not contain spaces.--`--trace`--: Print diagnostic output tracing parser progress to stderr.- This option is intended for use by developers in diagnosing- performance issues.--[`pandocfilters`]: https://github.com/jgm/pandocfilters-[PHP]: https://github.com/vinai/pandocfilters-php-[perl]: https://metacpan.org/pod/Pandoc::Filter-[JavaScript/node.js]: https://github.com/mvhenderson/pandoc-filter-node-[Lua filters documentation]: https://pandoc.org/lua-filters.html--## General writer options {.options}--`-s`, `--standalone`--: Produce output with an appropriate header and footer (e.g. a- standalone HTML, LaTeX, TEI, or RTF file, not a fragment). This option- is set automatically for `pdf`, `epub`, `epub3`, `fb2`, `docx`, and `odt`- output. For `native` output, this option causes metadata to- be included; otherwise, metadata is suppressed.--`--template=`*FILE*|*URL*--: Use the specified file as a custom template for the generated document.- Implies `--standalone`. See [Templates], below, for a description- of template syntax. If no extension is specified, an extension- corresponding to the writer will be added, so that `--template=special`- looks for `special.html` for HTML output. If the template is not- found, pandoc will search for it in the `templates` subdirectory of- the user data directory (see `--data-dir`). If this option is not used,- a default template appropriate for the output format will be used (see- `-D/--print-default-template`).--`-V` *KEY*[`=`*VAL*], `--variable=`*KEY*[`:`*VAL*]--: Set the template variable *KEY* to the value *VAL* when rendering the- document in standalone mode. If no *VAL* is specified, the- key will be given the value `true`.--`--sandbox`--: Run pandoc in a sandbox, limiting IO operations in readers- and writers to reading the files specified on the command line.- Note that this option does not limit IO operations by- filters or in the production of PDF documents. But it does- offer security against, for example, disclosure of files- through the use of `include` directives. Anyone using- pandoc on untrusted user input should use this option.-- Note: some readers and writers (e.g., `docx`) need access to data- files. If these are stored on the file system, then pandoc- will not be able to find them when run in `--sandbox` mode- and will raise an error. For these applications, we- recommend using a pandoc binary compiled with the `embed_data_files`- option, which causes the data files to be baked into the binary- instead of being stored on the file system.--`-D` *FORMAT*, `--print-default-template=`*FORMAT*--: Print the system default template for an output *FORMAT*. (See `-t`- for a list of possible *FORMAT*s.) Templates in the user data- directory are ignored. This option may be used with- `-o`/`--output` to redirect output to a file, but- `-o`/`--output` must come before `--print-default-template`- on the command line.-- Note that some of the default templates use partials, for- example `styles.html`. To print the partials, use- `--print-default-data-file`: for example,- `--print-default-data-file=templates/styles.html`.--`--print-default-data-file=`*FILE*--: Print a system default data file. Files in the user data directory- are ignored. This option may be used with `-o`/`--output` to- redirect output to a file, but `-o`/`--output` must come before- `--print-default-data-file` on the command line.--`--eol=crlf`|`lf`|`native`--: Manually specify line endings: `crlf` (Windows), `lf`- (macOS/Linux/UNIX), or `native` (line endings appropriate- to the OS on which pandoc is being run). The default is- `native`.--`--dpi`=*NUMBER*--: Specify the default dpi (dots per inch) value for conversion- from pixels to inch/centimeters and vice versa. (Technically,- the correct term would be ppi: pixels per inch.) The default- is 96dpi. When images contain information about dpi- internally, the encoded value is used instead of the default- specified by this option.--`--wrap=auto`|`none`|`preserve`--: Determine how text is wrapped in the output (the source- code, not the rendered version). With `auto` (the default),- pandoc will attempt to wrap lines to the column width specified by- `--columns` (default 72). With `none`, pandoc will not wrap- lines at all. With `preserve`, pandoc will attempt to- preserve the wrapping from the source document (that is,- where there are nonsemantic newlines in the source, there- will be nonsemantic newlines in the output as well).- In `ipynb` output, this option affects wrapping of the- contents of markdown cells.--`--columns=`*NUMBER*--: Specify length of lines in characters. This affects text wrapping- in the generated source code (see `--wrap`). It also affects- calculation of column widths for plain text tables (see [Tables] below).--`--toc`, `--table-of-contents`--: Include an automatically generated table of contents (or, in- the case of `latex`, `context`, `docx`, `odt`,- `opendocument`, `rst`, or `ms`, an instruction to create- one) in the output document. This option has no effect- unless `-s/--standalone` is used, and it has no effect- on `man`, `docbook4`, `docbook5`, or `jats` output.-- Note that if you are producing a PDF via `ms`, the table- of contents will appear at the beginning of the- document, before the title. If you would prefer it to- be at the end of the document, use the option- `--pdf-engine-opt=--no-toc-relocation`.--`--toc-depth=`*NUMBER*--: Specify the number of section levels to include in the table- of contents. The default is 3 (which means that level-1, 2, and 3- headings will be listed in the contents).--`--strip-comments`--: Strip out HTML comments in the Markdown or Textile source,- rather than passing them on to Markdown, Textile or HTML- output as raw HTML. This does not apply to HTML comments- inside raw HTML blocks when the `markdown_in_html_blocks`- extension is not set.--`--no-highlight`--: Disables syntax highlighting for code blocks and inlines, even when- a language attribute is given.--`--highlight-style=`*STYLE*|*FILE*--: 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- `--list-highlight-styles`.-- Instead of a *STYLE* name, a JSON file with extension- `.theme` may be supplied. This will be parsed as a KDE- syntax highlighting theme and (if valid) used as the- highlighting style.-- To generate the JSON version of an existing style,- use `--print-highlight-style`.--`--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- `-o`/`--output` to redirect output to a file, but- `-o`/`--output` must come before `--print-highlight-style`- on the command line.--`--syntax-definition=`*FILE*--: Instructs pandoc to load a KDE XML syntax definition file,- which will be used for syntax highlighting of appropriately- marked code blocks. This can be used to add support for- new languages or to use altered syntax definitions for- existing languages. This option may be repeated to add- multiple syntax definitions.--`-H` *FILE*, `--include-in-header=`*FILE*|*URL*--: Include contents of *FILE*, verbatim, at the end of the header.- This can be used, for example, to include special- CSS or JavaScript in HTML documents. This option can be used- repeatedly to include multiple files in the header. They will be- included in the order specified. Implies `--standalone`.--`-B` *FILE*, `--include-before-body=`*FILE*|*URL*--: Include contents of *FILE*, verbatim, at the beginning of the- document body (e.g. after the `<body>` tag in HTML, or the- `\begin{document}` command in LaTeX). This can be used to include- navigation bars or banners in HTML documents. This option can be- used repeatedly to include multiple files. They will be included in- the order specified. Implies `--standalone`.--`-A` *FILE*, `--include-after-body=`*FILE*|*URL*--: Include contents of *FILE*, verbatim, at the end of the document- body (before the `</body>` tag in HTML, or the- `\end{document}` command in LaTeX). This option can be used- repeatedly to include multiple files. They will be included in the- order specified. Implies `--standalone`.--`--resource-path=`*SEARCHPATH*--: List of paths to search for images and other resources.- The paths should be separated by `:` on Linux, UNIX, and- macOS systems, and by `;` on Windows. If `--resource-path`- is not specified, the default resource path is the working- directory. Note that, if `--resource-path` is specified,- the working directory must be explicitly listed or it- will not be searched. For example:- `--resource-path=.:test` will search the working directory- and the `test` subdirectory, in that order.- This option can be used repeatedly. Search path components- that come later on the command line will be searched before- those that come earlier, so- `--resource-path foo:bar --resource-path baz:bim` is- equivalent to `--resource-path baz:bim:foo:bar`.--`--request-header=`*NAME*`:`*VAL*--: Set the request header *NAME* to the value *VAL* when making- HTTP requests (for example, when a URL is given on the- command line, or when resources used in a document must be- downloaded). If you're behind a proxy, you also need to set- the environment variable `http_proxy` to `http://...`.--`--no-check-certificate`--: Disable the certificate verification to allow access to- unsecure HTTP resources (for example when the certificate- is no longer valid or self signed).--## Options affecting specific writers {.options}--`--self-contained`--: *Deprecated synonym for `--embed-resources --standalone`.*--`--embed-resources`--: Produce a standalone HTML file with no external dependencies, using- `data:` URIs to incorporate the contents of linked scripts, stylesheets,- images, and videos. The resulting file should be "self-contained," in the- sense that it needs no external files and no net access to be displayed- properly by a browser. This option works only with HTML output formats,- including `html4`, `html5`, `html+lhs`, `html5+lhs`, `s5`, `slidy`,- `slideous`, `dzslides`, and `revealjs`. Scripts, images, and stylesheets at- absolute URLs will be downloaded; those at relative URLs will be sought- relative to the working directory (if the first source- file is local) or relative to the base URL (if the first source- file is remote). Elements with the attribute- `data-external="1"` will be left alone; the documents they- link to will not be incorporated in the document.- Limitation: resources that are loaded dynamically through- JavaScript cannot be incorporated; as a result, some- advanced features (e.g. zoom or speaker notes) may not work- in an offline "self-contained" `reveal.js` slide show.--`--html-q-tags`--: Use `<q>` tags for quotes in HTML. (This option only has an- effect if the `smart` extension is enabled for the input- format used.)--`--ascii`--: Use only ASCII characters in output. Currently supported for XML- and HTML formats (which use entities instead of UTF-8 when this- option is selected), CommonMark, gfm, and Markdown (which use- entities), roff ms (which use hexadecimal escapes), and to a- limited degree LaTeX (which uses standard commands for accented- characters when possible). roff man output uses ASCII by default.--`--reference-links`--: Use reference-style links, rather than inline links, in writing Markdown- or reStructuredText. By default inline links are used. The- placement of link references is affected by the- `--reference-location` option.--`--reference-location=block`|`section`|`document`--: Specify whether footnotes (and references, if `reference-links` is- set) are placed at the end of the current (top-level) block, the- current section, or the document. The default is- `document`. Currently this option only affects the- `markdown`, `muse`, `html`, `epub`, `slidy`, `s5`, `slideous`,- `dzslides`, and `revealjs` writers.--`--markdown-headings=setext`|`atx`--: Specify whether to use ATX-style (`#`-prefixed) or- Setext-style (underlined) headings for level 1 and 2- headings in Markdown output. (The default is `atx`.)- ATX-style headings are always used for levels 3+.- This option also affects Markdown cells in `ipynb` output.--`--atx-headers`--: *Deprecated synonym for `--markdown-headings=atx`.*--`--top-level-division=default`|`section`|`chapter`|`part`--: Treat top-level headings as the given division type in- LaTeX, ConTeXt, DocBook, and TEI output. The hierarchy- order is part, chapter, then section; all headings are- shifted such that the top-level heading becomes the- specified type. The default behavior is to determine the- best division type via heuristics: unless other conditions- apply, `section` is chosen. When the `documentclass`- variable is set to `report`, `book`, or `memoir` (unless the- `article` option is specified), `chapter` is implied as the- setting for this option. If `beamer` is the output format,- specifying either `chapter` or `part` will cause top-level- headings to become `\part{..}`, while second-level headings- remain as their default type.--`-N`, `--number-sections`--: Number section headings in LaTeX, ConTeXt, HTML, Docx, ms, or EPUB- output. By default, sections are not numbered. Sections with class- `unnumbered` will never be numbered, even if `--number-sections`- is specified.--`--number-offset=`*NUMBER*[`,`*NUMBER*`,`*...*]--: Offset for section headings in HTML output (ignored in other- output formats). The first number is added to the section number for- top-level headings, the second for second-level headings, and so on.- So, for example, if you want the first top-level heading in your- document to be numbered "6", specify `--number-offset=5`.- If your document starts with a level-2 heading which you want to- be numbered "1.5", specify `--number-offset=1,4`.- Offsets are 0 by default. Implies `--number-sections`.--`--listings`--: 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].--`-i`, `--incremental`--: Make list items in slide shows display incrementally (one by one).- The default is for lists to be displayed all at once.--`--slide-level=`*NUMBER*--: Specifies that headings with the specified level create- slides (for `beamer`, `s5`, `slidy`, `slideous`, `dzslides`). Headings- above this level in the hierarchy are used to divide the slide show- into sections; headings below this level create subheads within a slide.- Valid values are 0-6. If a slide level of 0 is specified, slides will- not be split automatically on headings, and horizontal rules must be used- to indicate slide boundaries. If a slide level is not specified- explicitly, the slide level will be set automatically based on- the contents of the document; see [Structuring the slide show].--`--section-divs`--: Wrap sections in `<section>` tags (or `<div>` tags for `html4`),- and attach identifiers to the enclosing `<section>` (or `<div>`)- rather than the heading itself. See- [Heading identifiers], below.--`--email-obfuscation=none`|`javascript`|`references`--: Specify a method for obfuscating `mailto:` links in HTML documents.- `none` leaves `mailto:` links as they are. `javascript` obfuscates- them using JavaScript. `references` obfuscates them by printing their- letters as decimal or hexadecimal character references. The default- is `none`.--`--id-prefix=`*STRING*--: Specify a prefix to be added to all identifiers and internal links- in HTML and DocBook output, and to footnote numbers in Markdown- and Haddock output. This is useful for preventing duplicate- identifiers when generating fragments to be included in other pages.--`-T` *STRING*, `--title-prefix=`*STRING*--: Specify *STRING* as a prefix at the beginning of the title- that appears in the HTML header (but not in the title as it- appears at the beginning of the HTML body). Implies `--standalone`.--`-c` *URL*, `--css=`*URL*--: Link to a CSS style sheet. This option can be used repeatedly to- include multiple files. They will be included in the order specified.-- A stylesheet is required for generating EPUB. If none is- provided using this option (or the `css` or `stylesheet`- metadata fields), pandoc will look for a file `epub.css` in the- user data directory (see `--data-dir`). If it is not- found there, sensible defaults will be used.--`--reference-doc=`*FILE*--: Use the specified file as a style reference in producing a- docx or ODT file.-- Docx-- : For best results, the reference docx should be a modified- version of a docx file produced using pandoc. The contents- of the reference docx are ignored, but its stylesheets and- document properties (including margins, page size, header,- and footer) are used in the new docx. If no reference docx- is specified on the command line, pandoc will look for a- file `reference.docx` in the user data directory (see- `--data-dir`). If this is not found either, sensible- defaults will be used.-- To produce a custom `reference.docx`, first get a copy of- the default `reference.docx`: `pandoc- -o custom-reference.docx --print-default-data-file reference.docx`.- Then open `custom-reference.docx` in Word, modify the- styles as you wish, and save the file. For best- results, do not make changes to this file other than- modifying the styles used by pandoc:-- Paragraph styles:-- - Normal- - Body Text- - First Paragraph- - Compact- - Title- - Subtitle- - Author- - Date- - Abstract- - Bibliography- - Heading 1- - Heading 2- - Heading 3- - Heading 4- - Heading 5- - Heading 6- - Heading 7- - Heading 8- - Heading 9- - Block Text- - Source Code- - Footnote Text- - Definition Term- - Definition- - Caption- - Table Caption- - Image Caption- - Figure- - Captioned Figure- - TOC Heading-- Character styles:-- - Default Paragraph Font- - Body Text Char- - Verbatim Char- - Footnote Reference- - Hyperlink- - Section Number-- Table style:-- - Table-- ODT-- : For best results, the reference ODT should be a modified- version of an ODT produced using pandoc. The contents of- the reference ODT are ignored, but its stylesheets are used- in the new ODT. If no reference ODT is specified on the- command line, pandoc will look for a file `reference.odt` in- the user data directory (see `--data-dir`). If this is not- found either, sensible defaults will be used.-- To produce a custom `reference.odt`, first get a copy of- the default `reference.odt`: `pandoc- -o custom-reference.odt --print-default-data-file reference.odt`.- Then open `custom-reference.odt` in LibreOffice, modify- the styles as you wish, and save the file.-- PowerPoint-- : Templates included with Microsoft PowerPoint 2013 (either with- `.pptx` or `.potx` extension) are known to work, as are most- templates derived from these.-- The specific requirement is that the template should contain layouts- with the following names (as seen within PowerPoint):-- - Title Slide- - Title and Content- - Section Header- - Two Content- - Comparison- - Content with Caption- - Blank-- For each name, the first layout found with that name will be used.- If no layout is found with one of the names, pandoc will output a- warning and use the layout with that name from the default reference- doc instead. (How these layouts are used is described in [PowerPoint- layout choice](#powerpoint-layout-choice).)-- All templates included with a recent version of MS PowerPoint- will fit these criteria. (You can click on `Layout` under the- `Home` menu to check.)-- You can also modify the default `reference.pptx`: first run- `pandoc -o custom-reference.pptx --print-default-data-file- reference.pptx`, and then modify `custom-reference.pptx`- in MS PowerPoint (pandoc will use the layouts with the names- listed above).--`--epub-cover-image=`*FILE*--: Use the specified image as the EPUB cover. It is recommended- that the image be less than 1000px in width and height. Note that- in a Markdown source document you can also specify `cover-image`- in a YAML metadata block (see [EPUB Metadata], below).--`--epub-metadata=`*FILE*--: Look in the specified XML file for metadata for the EPUB.- The file should contain a series of [Dublin Core elements].- For example:-- <dc:rights>Creative Commons</dc:rights>- <dc:language>es-AR</dc:language>-- By default, pandoc will include the following metadata elements:- `<dc:title>` (from the document title), `<dc:creator>` (from the- document authors), `<dc:date>` (from the document date, which should- be in [ISO 8601 format]), `<dc:language>` (from the `lang`- variable, or, if is not set, the locale), and `<dc:identifier- id="BookId">` (a randomly generated UUID). Any of these may be- overridden by elements in the metadata file.-- Note: if the source document is Markdown, a YAML metadata block- in the document can be used instead. See below under- [EPUB Metadata].--`--epub-embed-font=`*FILE*--: Embed the specified font in the EPUB. This option can be repeated- to embed multiple fonts. Wildcards can also be used: for example,- `DejaVuSans-*.ttf`. However, if you use wildcards on the command- line, be sure to escape them or put the whole filename in single quotes,- to prevent them from being interpreted by the shell. To use the- embedded fonts, you will need to add declarations like the following- to your CSS (see `--css`):-- @font-face {- font-family: DejaVuSans;- font-style: normal;- font-weight: normal;- src:url("DejaVuSans-Regular.ttf");- }- @font-face {- font-family: DejaVuSans;- font-style: normal;- font-weight: bold;- src:url("DejaVuSans-Bold.ttf");- }- @font-face {- font-family: DejaVuSans;- font-style: italic;- font-weight: normal;- src:url("DejaVuSans-Oblique.ttf");- }- @font-face {- font-family: DejaVuSans;- font-style: italic;- font-weight: bold;- src:url("DejaVuSans-BoldOblique.ttf");- }- body { font-family: "DejaVuSans"; }--`--epub-chapter-level=`*NUMBER*--: Specify the heading level at which to split the EPUB into separate- "chapter" files. The default is to split into chapters at level-1- headings. This option only affects the internal composition of the- EPUB, not the way chapters and sections are displayed to users. Some- readers may be slow if the chapter files are too large, so for large- documents with few level-1 headings, one might want to use a chapter- level of 2 or 3.--`--epub-subdirectory=`*DIRNAME*--: Specify the subdirectory in the OCF container that is to hold- the EPUB-specific contents. The default is `EPUB`. To put- the EPUB contents in the top level, use an empty string.--`--ipynb-output=all|none|best`--: Determines how ipynb output cells are treated. `all` means- that all of the data formats included in the original are- preserved. `none` means that the contents of data cells- are omitted. `best` causes pandoc to try to pick the- richest data block in each output cell that is compatible- with the output format. The default is `best`.--`--pdf-engine=`*PROGRAM*--: Use the specified engine when producing PDF output.- Valid values are `pdflatex`, `lualatex`, `xelatex`, `latexmk`,- `tectonic`, `wkhtmltopdf`, `weasyprint`, `pagedjs-cli`,- `prince`, `context`, and `pdfroff`. If the engine is not in- your PATH, the full path of the engine may be specified here.- If this option is not specified, pandoc uses the following- defaults depending on the output format specified using- `-t/--to`:-- - `-t latex` or none: `pdflatex` (other options: `xelatex`, `lualatex`,- `tectonic`, `latexmk`)- - `-t context`: `context`- - `-t html`: `wkhtmltopdf` (other options: `prince`, `weasyprint`,- `pagedjs-cli`;- see [print-css.rocks](https://print-css.rocks) for a good- introduction to PDF generation from HTML/CSS)- - `-t ms`: `pdfroff`--`--pdf-engine-opt=`*STRING*--: Use the given string as a command-line argument to the `pdf-engine`.- For example, to use a persistent directory `foo` for `latexmk`'s- auxiliary files, use `--pdf-engine-opt=-outdir=foo`.- Note that no check for duplicate options is done.--[Dublin Core elements]: https://www.dublincore.org/specifications/dublin-core/dces/-[ISO 8601 format]: https://www.w3.org/TR/NOTE-datetime-[Encoding issue with the listings package]:- https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings#Encoding_issue--## Citation rendering {.options}--`-C`, `--citeproc`--: Process the citations in the file, replacing them with- rendered citations and adding a bibliography.- Citation processing will not take place unless bibliographic- data is supplied, either through an external file specified- using the `--bibliography` option or the `bibliography`- field in metadata, or via a `references` section in metadata- containing a list of citations in CSL YAML format with- Markdown formatting. The style is controlled by a [CSL]- stylesheet specified using the `--csl` option or the `csl`- field in metadata. (If no stylesheet is specified,- the `chicago-author-date` style will be used by default.)- The citation processing transformation may be applied before- or after filters or Lua filters (see `--filter`,- `--lua-filter`): these transformations are applied in the- order they appear on the command line. For more- information, see the section on [Citations].--`--bibliography=`*FILE*--: Set the `bibliography` field in the document's metadata to *FILE*,- overriding any value set in the metadata. If you supply- this argument multiple times, each *FILE* will be added to- bibliography. If *FILE* is a URL, it will be fetched- via HTTP. If *FILE* is not found relative to the- working directory, it will be sought in the resource path- (see `--resource-path`).--`--csl=`*FILE*--: Set the `csl` field in the document's metadata to *FILE*,- overriding any value set in the metadata. (This is equivalent to- `--metadata csl=FILE`.) If *FILE* is a URL, it will be- fetched via HTTP. If *FILE* is not found relative to the- working directory, it will be sought in the resource path- (see `--resource-path`) and finally in the `csl`- subdirectory of the pandoc user data directory.--`--citation-abbreviations=`*FILE*--: Set the `citation-abbreviations` field in the document's metadata to- *FILE*, overriding any value set in the metadata. (This is equivalent to- `--metadata citation-abbreviations=FILE`.)- If *FILE* is a URL, it will be fetched via HTTP. If *FILE* is not- found relative to the working directory, it will be sought- in the resource path (see `--resource-path`) and finally in- the `csl` subdirectory of the pandoc user data directory.--`--natbib`--: Use [`natbib`] for citations in LaTeX output. This option- is not for use with the `--citeproc` option or with PDF- output. It is intended for use in producing a LaTeX file- that can be processed with [`bibtex`].--`--biblatex`--: Use [`biblatex`] for citations in LaTeX output. This option- is not for use with the `--citeproc` option or with PDF- output. It is intended for use in producing a LaTeX file- that can be processed with [`bibtex`] or [`biber`].--## Math rendering in HTML {.options}--The default is to render TeX math as far as possible using-Unicode characters. Formulas are put inside a `span` with-`class="math"`, so that they may be styled differently from the-surrounding text if needed. However, this gives acceptable-results only for basic math, usually you will want to use-`--mathjax` or another of the following options.--`--mathjax`[`=`*URL*]--: Use [MathJax] to display embedded TeX math in HTML output.- TeX math will be put between `\(...\)` (for inline math)- or `\[...\]` (for display math) and wrapped in `<span>` tags- with class `math`. Then the MathJax JavaScript will render it.- The *URL* should point to the `MathJax.js` load script.- If a *URL* is not provided, a link to the Cloudflare CDN will- be inserted.--`--mathml`--: Convert TeX math to [MathML] (in `epub3`, `docbook4`,- `docbook5`, `jats`, `html4` and `html5`). This is the- default in `odt` output. Note that currently only Firefox- and Safari (and select e-book readers) natively support- MathML.--`--webtex`[`=`*URL*]--: Convert TeX formulas to `<img>` tags that link to an external script- that converts formulas to images. The formula will be URL-encoded- and concatenated with the URL provided. For SVG images you can for- example use `--webtex https://latex.codecogs.com/svg.latex?`.- If no URL is specified, the CodeCogs URL generating PNGs- will be used (`https://latex.codecogs.com/png.latex?`).- Note: the `--webtex` option will affect Markdown output- as well as HTML, which is useful if you're targeting a- version of Markdown without native math support.--`--katex`[`=`*URL*]--: Use [KaTeX] to display embedded TeX math in HTML output.- The *URL* is the base URL for the KaTeX library. That directory- should contain a `katex.min.js` and a `katex.min.css` file.- If a *URL* is not provided, a link to the KaTeX CDN will be inserted.--`--gladtex`--: Enclose TeX math in `<eq>` tags in HTML output. The resulting HTML- can then be processed by [GladTeX] to produce SVG images of the typeset- formulas and an HTML file with these images embedded.-- pandoc -s --gladtex input.md -o myfile.htex- gladtex -d image_dir myfile.htex- # produces myfile.html and images in image_dir--[MathML]: https://www.w3.org/Math/-[MathJax]: https://www.mathjax.org-[KaTeX]: https://github.com/Khan/KaTeX-[GladTeX]: https://humenda.github.io/GladTeX/--## Options for wrapper scripts {.options}--`--dump-args`--: Print information about command-line arguments to *stdout*, then exit.- This option is intended primarily for use in wrapper scripts.- The first line of output contains the name of the output file specified- with the `-o` option, or `-` (for *stdout*) if no output file was- specified. The remaining lines contain the command-line arguments,- one per line, in the order they appear. These do not include regular- pandoc options and their arguments, but do include any options appearing- after a `--` separator at the end of the line.--`--ignore-args`--: Ignore command-line arguments (for use in wrapper scripts).- Regular pandoc options are not ignored. Thus, for example,-- pandoc --ignore-args -o foo.html -s foo.txt -- -e latin1-- is equivalent to-- pandoc -o foo.html -s--# Exit codes--If pandoc completes successfully, it will return exit code 0.-Nonzero exit codes have the following meanings:-- Code Error------ ------------------------------------- 1 PandocIOError- 3 PandocFailOnWarningError- 4 PandocAppError- 5 PandocTemplateError- 6 PandocOptionError- 21 PandocUnknownReaderError- 22 PandocUnknownWriterError- 23 PandocUnsupportedExtensionError- 24 PandocCiteprocError- 25 PandocBibliographyError- 31 PandocEpubSubdirectoryError- 43 PandocPDFError- 44 PandocXMLError- 47 PandocPDFProgramNotFoundError- 61 PandocHttpError- 62 PandocShouldNeverHappenError- 63 PandocSomeError- 64 PandocParseError- 65 PandocParsecError- 66 PandocMakePDFError- 67 PandocSyntaxMapError- 83 PandocFilterError- 84 PandocLuaError- 91 PandocMacroLoop- 92 PandocUTF8DecodingError- 93 PandocIpynbDecodingError- 94 PandocUnsupportedCharsetError- 97 PandocCouldNotFindDataFileError- 98 PandocCouldNotFindMetadataFileError- 99 PandocResourceNotFound------ --------------------------------------# Defaults files--The `--defaults` option may be used to specify a package-of options, in the form of a YAML file.--Fields that are omitted will just have their regular-default values. So a defaults file can be as simple as-one line:--``` yaml-verbosity: INFO-```--In fields that expect a file path (or list of file paths), the-following syntax may be used to interpolate environment variables:--``` yaml-csl: ${HOME}/mycsldir/special.csl-```--`${USERDATA}` may also be used; this will always resolve to the-user data directory that is current when the defaults file is-parsed, regardless of the setting of the environment-variable `USERDATA`.--`${.}` will resolve to the directory containing the defaults-file itself. This allows you to refer to resources contained-in that directory:--``` yaml-epub-cover-image: ${.}/cover.jpg-epub-metadata: ${.}/meta.xml-resource-path:-- . # the working directory from which pandoc is run-- ${.}/images # the images subdirectory of the directory- # containing this defaults file-```--This environment variable interpolation syntax *only* works in-fields that expect file paths.--Defaults files can be placed in the `defaults` subdirectory of-the user data directory and used from any directory. For-example, one could create a file specifying defaults for writing-letters, save it as `letter.yaml` in the `defaults` subdirectory-of the user data directory, and then invoke these defaults-from any directory using `pandoc --defaults letter`-or `pandoc -dletter`.--When multiple defaults are used, their contents will be combined.--Note that, where command-line arguments may be repeated-(`--metadata-file`, `--css`, `--include-in-header`,-`--include-before-body`, `--include-after-body`, `--variable`,-`--metadata`, `--syntax-definition`), the values specified on-the command line will combine with values specified in the-defaults file, rather than replacing them.--The following tables show the mapping between the command line and-defaults file entries.--+----------------------------------+-----------------------------------+-| command line | defaults file |-+:=================================+:==================================+-| ``` | ``` yaml |-| foo.md | input-file: foo.md |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| foo.md bar.md | input-files: |-| | - foo.md |-| | - bar.md |-| ``` | ``` |-+----------------------------------+-----------------------------------+--The value of `input-files` may be left empty to indicate input from-stdin, and it can be an empty sequence `[]` for no input.--## General options--+----------------------------------+-----------------------------------+-| command line | defaults file |-+:=================================+:==================================+-| ``` | ``` yaml |-| --from markdown+emoji | from: markdown+emoji |-| ``` | ``` |-| | ``` yaml |-| | reader: markdown+emoji |-| | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --to markdown+hard_line_breaks | to: markdown+hard_line_breaks |-| ``` | ``` |-| | ``` yaml |-| | writer: markdown+hard_line_breaks |-| | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --output foo.pdf | output-file: foo.pdf |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --output - | output-file: |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --data-dir dir | data-dir: dir |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --defaults file | defaults: |-| ``` | - file |-| | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --verbose | verbosity: INFO |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --quiet | verbosity: ERROR |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --fail-if-warnings | fail-if-warnings: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --sandbox | sandbox: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --log=FILE | log-file: FILE |-| ``` | ``` |-+----------------------------------+-----------------------------------+--Options specified in a defaults file itself always have priority over-those in another file included with a `defaults:` entry.--`verbosity` can have the values `ERROR`, `WARNING`, or `INFO`.--## Reader options--+----------------------------------+-----------------------------------+-| command line | defaults file |-+:=================================+:==================================+-| ``` | ``` yaml |-| --shift-heading-level-by -1 | shift-heading-level-by: -1 |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --indented-code-classes python | indented-code-classes: |-| | - python |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --default-image-extension ".jpg" | default-image-extension: '.jpg' |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --file-scope | file-scope: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --filter pandoc-citeproc \ | filters: |-| --lua-filter count-words.lua \ | - pandoc-citeproc |-| --filter special.lua | - count-words.lua |-| | - type: json |-| | path: special.lua |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --metadata key=value \ | metadata: |-| --metadata key2 | key: value |-| | key2: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --metadata-file meta.yaml | metadata-files: |-| | - meta.yaml |-| ``` | ``` |-| | ``` yaml |-| | metadata-file: meta.yaml |-| | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --preserve-tabs | preserve-tabs: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --tab-stop 8 | tab-stop: 8 |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --track-changes accept | track-changes: accept |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --extract-media dir | extract-media: dir |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --abbreviations abbrevs.txt | abbreviations: abbrevs.txt |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --trace | trace: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+--Metadata values specified in a defaults file are parsed as literal-string text, not Markdown.--Filters will be assumed to be Lua filters if they have the `.lua`-extension, and JSON filters otherwise. But the filter type can also be-specified explicitly, as shown. Filters are run in the order specified.-To include the built-in citeproc filter, use either `citeproc` or-`{type: citeproc}`.--## General writer options--+----------------------------------+-----------------------------------+-| command line | defaults file |-+:=================================+:==================================+-| ``` | ``` yaml |-| --standalone | standalone: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --template letter | template: letter |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --variable key=val \ | variables: |-| --variable key2 | key: val |-| | key2: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --eol nl | eol: nl |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --dpi 300 | dpi: 300 |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --wrap 60 | wrap: 60 |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --columns 72 | columns: 72 |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --table-of-contents | table-of-contents: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --toc | toc: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --toc-depth 3 | toc-depth: 3 |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --strip-comments | strip-comments: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --no-highlight | highlight-style: null |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --highlight-style kate | highlight-style: kate |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --syntax-definition mylang.xml | syntax-definitions: |-| | - mylang.xml |-| ``` | ``` |-| | ``` yaml |-| | syntax-definition: mylang.xml |-| | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --include-in-header inc.tex | include-in-header: |-| | - inc.tex |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --include-before-body inc.tex | include-before-body: |-| | - inc.tex |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --include-after-body inc.tex | include-after-body: |-| | - inc.tex |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --resource-path .:foo | resource-path: ['.','foo'] |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --request-header foo:bar | request-headers: |-| | - ["User-Agent", "Mozilla/5.0"] |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --no-check-certificate | no-check-certificate: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+---## Options affecting specific writers--+----------------------------------+-----------------------------------+-| command line | defaults file |-+:=================================+:==================================+-| ``` | ``` yaml |-| --self-contained | self-contained: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --html-q-tags | html-q-tags: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --ascii | ascii: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --reference-links | reference-links: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --reference-location block | reference-location: block |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --markdown-headings atx | markdown-headings: atx |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --top-level-division chapter | top-level-division: chapter |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --number-sections | number-sections: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --number-offset=1,4 | number-offset: \[1,4\] |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --listings | listings: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --incremental | incremental: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --slide-level 2 | slide-level: 2 |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --section-divs | section-divs: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --email-obfuscation references | email-obfuscation: references |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --id-prefix ch1 | identifier-prefix: ch1 |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --title-prefix MySite | title-prefix: MySite |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --css styles/screen.css \ | css: |-| --css styles/special.css | - styles/screen.css |-| | - styles/special.css |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --reference-doc my.docx | reference-doc: my.docx |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --epub-cover-image cover.jpg | epub-cover-image: cover.jpg |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --epub-metadata meta.xml | epub-metadata: meta.xml |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --epub-embed-font special.otf \ | epub-fonts: |-| --epub-embed-font headline.otf | - special.otf |-| | - headline.otf |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --epub-chapter-level 2 | epub-chapter-level: 2 |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --epub-subdirectory="" | epub-subdirectory: '' |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --ipynb-output best | ipynb-output: best |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --pdf-engine xelatex | pdf-engine: xelatex |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --pdf-engine-opt=--shell-escape | pdf-engine-opts: |-| | - '-shell-escape' |-| ``` | ``` |-| | ``` yaml |-| | pdf-engine-opt: '-shell-escape' |-| | ``` |-+----------------------------------+-----------------------------------+--## Citation rendering--+----------------------------------+-----------------------------------+-| command line | defaults file |-+:=================================+:==================================+-| ``` | ``` yaml |-| --citeproc | citeproc: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --bibliography logic.bib | metadata: |-| | bibliography: logic.bib |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --csl ieee.csl | metadata: |-| | csl: ieee.csl |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --citation-abbreviations ab.json | metadata: |-| | citation-abbreviations: ab.json |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --natbib | cite-method: natbib |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --biblatex | cite-method: biblatex |-| ``` | ``` |-+----------------------------------+-----------------------------------+--`cite-method` can be `citeproc`, `natbib`, or `biblatex`. This only-affects LaTeX output. If you want to use citeproc to format citations,-you should also set 'citeproc: true'.--If you need control over when the citeproc processing is done relative-to other filters, you should instead use `citeproc` in the list-of `filters` (see above).--## Math rendering in HTML--+----------------------------------+-----------------------------------+-| command line | defaults file |-+:=================================+:==================================+-| ``` | ``` yaml |-| --mathjax | html-math-method: |-| | method: mathjax |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --mathml | html-math-method: |-| | method: mathml |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --webtex | html-math-method: |-| | method: webtex |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --katex | html-math-method: |-| | method: katex |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --gladtex | html-math-method: |-| | method: gladtex |-| ``` | ``` |-+----------------------------------+-----------------------------------+--In addition to the values listed above, `method` can have the-value `plain`.--If the command line option accepts a URL argument, an `url:` field can-be added to `html-math-method:`.--## Options for wrapper scripts--+----------------------------------+-----------------------------------+-| command line | defaults file |-+:=================================+:==================================+-| ``` | ``` yaml |-| --dump-args | dump-args: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+-| ``` | ``` yaml |-| --ignore-args | ignore-args: true |-| ``` | ``` |-+----------------------------------+-----------------------------------+--# Templates--When the `-s/--standalone` option is used, pandoc uses a template to-add header and footer material that is needed for a self-standing-document. To see the default template that is used, just type-- pandoc -D *FORMAT*--where *FORMAT* is the name of the output format. A custom template-can be specified using the `--template` option. You can also override-the system default templates for a given output format *FORMAT*-by putting a file `templates/default.*FORMAT*` in the user data-directory (see `--data-dir`, above). *Exceptions:*--- For `odt` output, customize the `default.opendocument`- template.-- For `pdf` output, customize the `default.latex` template- (or the `default.context` template, if you use `-t context`,- or the `default.ms` template, if you use `-t ms`, or the- `default.html` template, if you use `-t html`).-- `docx` and `pptx` have no template (however, you can use- `--reference-doc` to customize the output).--Templates contain *variables*, which allow for the inclusion of-arbitrary information at any point in the file. They may be set at the-command line using the `-V/--variable` option. If a variable is not set,-pandoc will look for the key in the document's metadata, which can be set-using either [YAML metadata blocks][Extension: `yaml_metadata_block`]-or with the `-M/--metadata` option. In addition, some variables-are given default values by pandoc. See [Variables] below for-a list of variables used in pandoc's default templates.--If you use custom templates, you may need to revise them as pandoc-changes. We recommend tracking the changes in the default templates,-and modifying your custom templates accordingly. An easy way to do this-is to fork the [pandoc-templates] repository and merge in-changes after each pandoc release.-- [pandoc-templates]: https://github.com/jgm/pandoc-templates--## Template syntax--### Comments--Anything between the sequence `$--` and the end of the-line will be treated as a comment and omitted from the output.--### Delimiters--To mark variables and control structures in the template,-either `$`...`$` or `${`...`}` may be used as delimiters.-The styles may also be mixed in the same template, but the-opening and closing delimiter must match in each case. The-opening delimiter may be followed by one or more spaces-or tabs, which will be ignored. The closing delimiter may-be followed by one or more spaces or tabs, which will be-ignored.--To include a literal `$` in the document, use `$$`.--### Interpolated variables--A slot for an interpolated variable is a variable name surrounded-by matched delimiters. Variable names must begin with a letter-and can contain letters, numbers, `_`, `-`, and `.`. The-keywords `it`, `if`, `else`, `endif`, `for`, `sep`, and `endfor` may-not be used as variable names. Examples:--```-$foo$-$foo.bar.baz$-$foo_bar.baz-bim$-$ foo $-${foo}-${foo.bar.baz}-${foo_bar.baz-bim}-${ foo }-```--Variable names with periods are used to get at structured-variable values. So, for example, `employee.salary` will return the-value of the `salary` field of the object that is the value of-the `employee` field.--- If the value of the variable is a simple value, it will be- rendered verbatim. (Note that no escaping is done;- the assumption is that the calling program will escape- the strings appropriately for the output format.)-- If the value is a list, the values will be concatenated.-- If the value is a map, the string `true` will be rendered.-- Every other value will be rendered as the empty string.--### Conditionals--A conditional begins with `if(variable)` (enclosed in-matched delimiters) and ends with `endif` (enclosed in matched-delimiters). It may optionally contain an `else` (enclosed in-matched delimiters). The `if` section is used if-`variable` has a non-empty value, otherwise the `else`-section is used (if present). Examples:--```-$if(foo)$bar$endif$--$if(foo)$- $foo$-$endif$--$if(foo)$-part one-$else$-part two-$endif$--${if(foo)}bar${endif}--${if(foo)}- ${foo}-${endif}--${if(foo)}-${ foo.bar }-${else}-no foo!-${endif}-```--The keyword `elseif` may be used to simplify complex nested-conditionals:--```-$if(foo)$-XXX-$elseif(bar)$-YYY-$else$-ZZZ-$endif$-```--### For loops--A for loop begins with `for(variable)` (enclosed in-matched delimiters) and ends with `endfor` (enclosed in matched-delimiters).--- If `variable` is an array, the material inside the loop will- be evaluated repeatedly, with `variable` being set to each- value of the array in turn, and concatenated.-- If `variable` is a map, the material inside will be set to- the map.-- If the value of the associated variable is not an array or- a map, a single iteration will be performed on its value.--Examples:--```-$for(foo)$$foo$$sep$, $endfor$--$for(foo)$- - $foo.last$, $foo.first$-$endfor$--${ for(foo.bar) }- - ${ foo.bar.last }, ${ foo.bar.first }-${ endfor }--$for(mymap)$-$it.name$: $it.office$-$endfor$-```--You may optionally specify a separator between consecutive-values using `sep` (enclosed in matched delimiters). The-material between `sep` and the `endfor` is the separator.--```-${ for(foo) }${ foo }${ sep }, ${ endfor }-```--Instead of using `variable` inside the loop, the special-anaphoric keyword `it` may be used.--```-${ for(foo.bar) }- - ${ it.last }, ${ it.first }-${ endfor }-```--### Partials--Partials (subtemplates stored in different files) may be-included by using the name of the partial, followed-by `()`, for example:--```-${ styles() }-```--Partials will be sought in the directory containing-the main template. The file name will be assumed to-have the same extension as the main template if it-lacks an extension. When calling the partial, the-full name including file extension can also be used:--```-${ styles.html() }-```--(If a partial is not found in the directory of the-template and the template path is given as a relative-path, it will also be sought in the `templates`-subdirectory of the user data directory.)--Partials may optionally be applied to variables using-a colon:--```-${ date:fancy() }--${ articles:bibentry() }-```--If `articles` is an array, this will iterate over its-values, applying the partial `bibentry()` to each one. So the-second example above is equivalent to--```-${ for(articles) }-${ it:bibentry() }-${ endfor }-```--Note that the anaphoric keyword `it` must be used when-iterating over partials. In the above examples,-the `bibentry` partial should contain `it.title`-(and so on) instead of `articles.title`.--Final newlines are omitted from included partials.--Partials may include other partials.--A separator between values of an array may be specified-in square brackets, immediately after the variable name-or partial:--```-${months[, ]}$--${articles:bibentry()[; ]$-```--The separator in this case is literal and (unlike with `sep`-in an explicit `for` loop) cannot contain interpolated-variables or other template directives.--### Nesting--To ensure that content is "nested," that is, subsequent lines-indented, use the `^` directive:--```-$item.number$ $^$$item.description$ ($item.price$)-```--In this example, if `item.description` has multiple lines,-they will all be indented to line up with the first line:--```-00123 A fine bottle of 18-year old- Oban whiskey. ($148)-```--To nest multiple lines to the same level, align them-with the `^` directive in the template. For example:--```-$item.number$ $^$$item.description$ ($item.price$)- (Available til $item.sellby$.)-```--will produce--```-00123 A fine bottle of 18-year old- Oban whiskey. ($148)- (Available til March 30, 2020.)-```--If a variable occurs by itself on a line, preceded by whitespace-and not followed by further text or directives on the same line,-and the variable's value contains multiple lines, it will be-nested automatically.--### Breakable spaces--Normally, spaces in the template itself (as opposed to values of-the interpolated variables) are not breakable, but they can be-made breakable in part of the template by using the `~` keyword-(ended with another `~`).--```-$~$This long line may break if the document is rendered-with a short line length.$~$-```--### Pipes--A pipe transforms the value of a variable or partial. Pipes are-specified using a slash (`/`) between the variable name (or partial)-and the pipe name. Example:--```-$for(name)$-$name/uppercase$-$endfor$--$for(metadata/pairs)$-- $it.key$: $it.value$-$endfor$--$employee:name()/uppercase$-```--Pipes may be chained:--```-$for(employees/pairs)$-$it.key/alpha/uppercase$. $it.name$-$endfor$-```--Some pipes take parameters:--```-|----------------------|------------|-$for(employee)$-$it.name.first/uppercase/left 20 "| "$$it.name.salary/right 10 " | " " |"$-$endfor$-|----------------------|------------|-```--Currently the following pipes are predefined:--- `pairs`: Converts a map or array to an array of maps,- each with `key` and `value` fields. If the original- value was an array, the `key` will be the array index,- starting with 1.--- `uppercase`: Converts text to uppercase.--- `lowercase`: Converts text to lowercase.--- `length`: Returns the length of the value: number- of characters for a textual value, number of elements- for a map or array.--- `reverse`: Reverses a textual value or array,- and has no effect on other values.--- `first`: Returns the first value of an array, if- applied to a non-empty array; otherwise returns- the original value.--- `last`: Returns the last value of an array, if- applied to a non-empty array; otherwise returns- the original value.--- `rest`: Returns all but the first value of an array, if- applied to a non-empty array; otherwise returns- the original value.--- `allbutlast`: Returns all but the last value of an array, if- applied to a non-empty array; otherwise returns- the original value.--- `chomp`: Removes trailing newlines (and breakable space).--- `nowrap`: Disables line wrapping on breakable spaces.--- `alpha`: Converts textual values that can be- read as an integer into lowercase alphabetic- characters `a..z` (mod 26). This can be used to get lettered- enumeration from array indices. To get uppercase- letters, chain with `uppercase`.--- `roman`: Converts textual values that can be- read as an integer into lowercase roman numerals.- This can be used to get lettered enumeration from array indices.- To get uppercase roman, chain with `uppercase`.--- `left n "leftborder" "rightborder"`: Renders a textual value- in a block of width `n`, aligned to the left, with an optional- left and right border. Has no effect on other values. This- can be used to align material in tables. Widths are positive- integers indicating the number of characters. Borders- are strings inside double quotes; literal `"` and `\` characters- must be backslash-escaped.--- `right n "leftborder" "rightborder"`: Renders a textual value- in a block of width `n`, aligned to the right, and has no- effect on other values.--- `center n "leftborder" "rightborder"`: Renders a textual- value in a block of width `n`, aligned to the center, and has- no effect on other values.---## Variables--### Metadata variables--`title`, `author`, `date`-: allow identification of basic aspects of the document. Included- in PDF metadata through LaTeX and ConTeXt. These can be set- through a [pandoc title block][Extension: `pandoc_title_block`],- which allows for multiple authors, or through a- [YAML metadata block][Extension: `yaml_metadata_block`]:-- ---- author:- - Aristotle- - Peter Abelard- ...-- Note that if you just want to set PDF or HTML metadata, without- including a title block in the document itself, you can- set the `title-meta`, `author-meta`, and `date-meta`- variables. (By default these are set automatically, based- on `title`, `author`, and `date`.) The page title in HTML- is set by `pagetitle`, which is equal to `title` by default.--`subtitle`-: document subtitle, included in HTML, EPUB, LaTeX, ConTeXt, and docx- documents--`abstract`-: document summary, included in HTML, LaTeX, ConTeXt, AsciiDoc, and docx- documents--`abstract-title`-: title of abstract, currently used only in HTML and EPUB.- This will be set automatically to a localized value,- depending on `lang`, but can be manually overridden.--`keywords`-: list of keywords to be included in HTML, PDF, ODT, pptx, docx- and AsciiDoc metadata; repeat as for `author`, above--`subject`-: document subject, included in ODT, PDF, docx, EPUB, and pptx metadata--`description`-: document description, included in ODT, docx and pptx metadata. Some- applications show this as `Comments` metadata.--`category`-: document category, included in docx and pptx metadata--Additionally,-any root-level string metadata, not included in ODT, docx-or pptx metadata is added as a *custom property*.-The following [YAML] metadata block for instance:-- ---- title: 'This is the title'- subtitle: "This is the subtitle"- author:- - Author One- - Author Two- description: |- This is a long- description.-- It consists of two paragraphs- ...--will include `title`, `author` and `description` as standard document-properties and `subtitle` as a custom property when converting to docx,-ODT or pptx.--### Language variables--`lang`-: identifies the main language of the document using IETF language- tags (following the [BCP 47] standard), such as `en` or `en-GB`.- The [Language subtag lookup] tool can look up or verify these tags.- This affects most formats, and controls hyphenation in PDF output- when using LaTeX (through [`babel`] and [`polyglossia`]) or ConTeXt.-- Use native pandoc [Divs and Spans] with the `lang` attribute to- switch the language:-- ---- lang: en-GB- ...-- Text in the main document language (British English).-- ::: {lang=fr-CA}- > Cette citation est écrite en français canadien.- :::-- More text in English. ['Zitat auf Deutsch.']{lang=de}--`dir`-: the base script direction, either `rtl` (right-to-left)- or `ltr` (left-to-right).-- For bidirectional documents, native pandoc `span`s and- `div`s with the `dir` attribute (value `rtl` or `ltr`) can- be used to override the base direction in some output- formats. This may not always be necessary if the final- renderer (e.g. the browser, when generating HTML) supports- the [Unicode Bidirectional Algorithm].-- When using LaTeX for bidirectional documents, only the- `xelatex` engine is fully supported (use- `--pdf-engine=xelatex`).--[BCP 47]: https://tools.ietf.org/html/bcp47-[Unicode Bidirectional Algorithm]: https://www.w3.org/International/articles/inline-bidi-markup/uba-basics-[Language subtag lookup]: https://r12a.github.io/app-subtags/--### Variables for HTML--`document-css`-: Enables inclusion of most of the [CSS] in the `styles.html`- [partial](#partials) (have a look with- `pandoc --print-default-data-file=templates/styles.html`).- Unless you use [`--css`](#option--css), this variable- is set to `true` by default. You can disable it with- e.g. `pandoc -M document-css=false`.--`mainfont`-: sets the CSS `font-family` property on the `html` element.--`fontsize`-: sets the base CSS `font-size`, which you'd usually set- to e.g. `20px`, but it also accepts `pt`- (12pt = 16px in most browsers).--`fontcolor`-: sets the CSS `color` property on the `html` element.--`linkcolor`-: sets the CSS `color` property on all links.--`monofont`-: sets the CSS `font-family` property on `code` elements.--`monobackgroundcolor`-: sets the CSS `background-color` property on `code` elements- and adds extra padding.--`linestretch`-: sets the CSS `line-height` property on the `html` element,- which is preferred to be unitless.--`backgroundcolor`-: sets the CSS `background-color` property on the `html` element.--`margin-left`, `margin-right`, `margin-top`, `margin-bottom`-: sets the corresponding CSS `padding` properties on the `body` element.--To override or extend some [CSS] for just one document, include for example:-- ---- header-includes: |- <style>- blockquote {- font-style: italic;- }- tr.even {- background-color: #f0f0f0;- }- td, th {- padding: 0.5em 2em 0.5em 0.5em;- }- tbody {- border-bottom: none;- }- </style>- -----[CSS]: https://developer.mozilla.org/en-US/docs/Learn/CSS--### Variables for HTML math--`classoption`-: when using [KaTeX](#option--katex), you can render display-math equations flush left using [YAML metadata](#layout) or with-`-M classoption=fleqn`.--### Variables for HTML slides--These affect HTML output when [producing slide shows with-pandoc](#slide-shows).--`institute`-: author affiliations: can be a list when there are multiple authors--`revealjs-url`-: base URL for reveal.js documents (defaults to- `https://unpkg.com/reveal.js@^4/`)--`s5-url`-: base URL for S5 documents (defaults to `s5/default`)--`slidy-url`-: base URL for Slidy documents (defaults to- `https://www.w3.org/Talks/Tools/Slidy2`)--`slideous-url`-: base URL for Slideous documents (defaults to `slideous`)--`title-slide-attributes`-: additional attributes for the title slide of reveal.js slide shows.- See [background in reveal.js, beamer, and pptx] for an example.--All [reveal.js configuration options] are available as variables.-To turn off boolean flags that default to true in reveal.js, use `0`.--[reveal.js configuration options]: https://revealjs.com/config/--### Variables for Beamer slides--These variables change the appearance of PDF slides using [`beamer`].--`aspectratio`-: slide aspect ratio (`43` for 4:3 [default], `169` for 16:9,- `1610` for 16:10, `149` for 14:9, `141` for 1.41:1, `54` for 5:4,- `32` for 3:2)--`beameroption`-: add extra beamer option with `\setbeameroption{}`--`institute`-: author affiliations: can be a list when there are multiple authors--`logo`-: logo image for slides--`navigation`-: controls navigation symbols (default is `empty` for no navigation- symbols; other valid values are `frame`, `vertical`, and `horizontal`)--`section-titles`-: enables "title pages" for new sections (default is true)--`theme`, `colortheme`, `fonttheme`, `innertheme`, `outertheme`-: beamer themes--`themeoptions`-: options for LaTeX beamer themes (a list).--`titlegraphic`-: image for title slide--### Variables for PowerPoint--These variables control the visual aspects of a slide show that-are not easily controlled via templates.--`monofont`-: font to use for code.--### Variables for LaTeX--Pandoc uses these variables when [creating a PDF] with a LaTeX engine.--#### Layout--`block-headings`-: make `\paragraph` and `\subparagraph` (fourth- and- fifth-level headings, or fifth- and sixth-level with book- classes) free-standing rather than run-in; requires further- formatting to distinguish from `\subsubsection` (third- or- fourth-level headings). Instead of using this option,- [KOMA-Script] can adjust headings more extensively:-- ---- documentclass: scrartcl- header-includes: |- \RedeclareSectionCommand[- beforeskip=-10pt plus -2pt minus -1pt,- afterskip=1sp plus -1sp minus 1sp,- font=\normalfont\itshape]{paragraph}- \RedeclareSectionCommand[- beforeskip=-10pt plus -2pt minus -1pt,- afterskip=1sp plus -1sp minus 1sp,- font=\normalfont\scshape,- indent=0pt]{subparagraph}- ...--`classoption`-: option for document class, e.g. `oneside`; repeat for multiple options:-- ---- classoption:- - twocolumn- - landscape- ...--`documentclass`-: document class: usually one of the standard classes,- [`article`], [`book`], and [`report`]; the [KOMA-Script]- equivalents, `scrartcl`, `scrbook`, and `scrreprt`, which- default to smaller margins; or [`memoir`]--`geometry`-: option for [`geometry`] package, e.g. `margin=1in`;- repeat for multiple options:-- ---- geometry:- - top=30mm- - left=20mm- - heightrounded- ...--`hyperrefoptions`-: option for [`hyperref`] package, e.g. `linktoc=all`;- repeat for multiple options:-- ---- hyperrefoptions:- - linktoc=all- - pdfwindowui- - pdfpagemode=FullScreen- ...--`indent`-: if true, pandoc will use document class settings for- indentation (the default LaTeX template otherwise removes- indentation and adds space between paragraphs)--`linestretch`-: adjusts line spacing using the [`setspace`]- package, e.g. `1.25`, `1.5`--`margin-left`, `margin-right`, `margin-top`, `margin-bottom`-: sets margins if `geometry` is not used (otherwise `geometry`- overrides these)--`pagestyle`-: control `\pagestyle{}`: the default article class- supports `plain` (default), `empty` (no running heads or page numbers),- and `headings` (section titles in running heads)--`papersize`-: paper size, e.g. `letter`, `a4`--`secnumdepth`-: numbering depth for sections (with `--number-sections` option- or `numbersections` variable)--`beamerarticle`-: produce an article from Beamer slides--#### Fonts--`fontenc`-: allows font encoding to be specified through `fontenc` package (with- `pdflatex`); default is `T1` (see [LaTeX font encodings guide])--`fontfamily`-: font package for use with `pdflatex`:- [TeX Live] includes many options, documented in the [LaTeX Font Catalogue].- The default is [Latin Modern][`lm`].--`fontfamilyoptions`-: options for package used as `fontfamily`; repeat for multiple options.- For example, to use the Libertine font with proportional lowercase- (old-style) figures through the [`libertinus`] package:-- ---- fontfamily: libertinus- fontfamilyoptions:- - osf- - p- ...--`fontsize`-: font size for body text. The standard classes allow 10pt, 11pt, and- 12pt. To use another size, set `documentclass` to one of- the [KOMA-Script] classes, such as `scrartcl` or `scrbook`.--`mainfont`, `sansfont`, `monofont`, `mathfont`, `CJKmainfont`-: font families for use with `xelatex` or- `lualatex`: take the name of any system font, using the- [`fontspec`] package. `CJKmainfont` uses the [`xecjk`] package.--`mainfontoptions`, `sansfontoptions`, `monofontoptions`, `mathfontoptions`, `CJKoptions`-: options to use with `mainfont`, `sansfont`, `monofont`, `mathfont`,- `CJKmainfont` in `xelatex` and `lualatex`. Allow for any- choices available through [`fontspec`]; repeat for multiple- options. For example, to use the [TeX Gyre] version of- Palatino with lowercase figures:-- ---- mainfont: TeX Gyre Pagella- mainfontoptions:- - Numbers=Lowercase- - Numbers=Proportional- ...--`microtypeoptions`-: options to pass to the microtype package--#### Links--`colorlinks`-: add color to link text; automatically enabled if any of- `linkcolor`, `filecolor`, `citecolor`, `urlcolor`, or `toccolor` are set--`boxlinks`-: add visible box around links (has no effect if `colorlinks` is set)--`linkcolor`, `filecolor`, `citecolor`, `urlcolor`, `toccolor`-: color for internal links, external links, citation links, linked- URLs, and links in table of contents, respectively: uses options- allowed by [`xcolor`], including the `dvipsnames`, `svgnames`, and- `x11names` lists--`links-as-notes`-: causes links to be printed as footnotes--#### Front matter--`lof`, `lot`-: include list of figures, list of tables--`thanks`-: contents of acknowledgments footnote after document title--`toc`-: include table of contents (can also be set using- `--toc/--table-of-contents`)--`toc-depth`-: level of section to include in table of contents--#### BibLaTeX Bibliographies--These variables function when using BibLaTeX for [citation rendering].--`biblatexoptions`-: list of options for biblatex--`biblio-style`-: bibliography style, when used with `--natbib` and `--biblatex`--`biblio-title`-: bibliography title, when used with `--natbib` and `--biblatex`--`bibliography`-: bibliography to use for resolving references--`natbiboptions`-: list of options for natbib--[KOMA-Script]: https://ctan.org/pkg/koma-script-[LaTeX Font Catalogue]: https://tug.org/FontCatalogue/-[LaTeX font encodings guide]: https://ctan.org/pkg/encguide-[TeX Gyre]: http://www.gust.org.pl/projects/e-foundry/tex-gyre-[`article`]: https://ctan.org/pkg/article-[`book`]: https://ctan.org/pkg/book-[`libertinus`]: https://ctan.org/pkg/libertinus-[`memoir`]: https://ctan.org/pkg/memoir-[`report`]: https://ctan.org/pkg/report--### Variables for ConTeXt--Pandoc uses these variables when [creating a PDF] with ConTeXt.--`fontsize`-: font size for body text (e.g. `10pt`, `12pt`)--`headertext`, `footertext`-: text to be placed in running header or footer (see [ConTeXt Headers and- Footers]); repeat up to four times for different placement--`indenting`-: controls indentation of paragraphs, e.g. `yes,small,next` (see- [ConTeXt Indentation]); repeat for multiple options--`interlinespace`-: adjusts line spacing, e.g. `4ex` (using [`setupinterlinespace`]);- repeat for multiple options--`layout`-: options for page margins and text arrangement (see [ConTeXt Layout]);- repeat for multiple options--`linkcolor`, `contrastcolor`-: color for links outside and inside a page, e.g. `red`, `blue` (see- [ConTeXt Color])--`linkstyle`-: typeface style for links, e.g. `normal`, `bold`, `slanted`, `boldslanted`,- `type`, `cap`, `small`--`lof`, `lot`-: include list of figures, list of tables--`mainfont`, `sansfont`, `monofont`, `mathfont`-: font families: take the name of any system font (see- [ConTeXt Font Switching])--`margin-left`, `margin-right`, `margin-top`, `margin-bottom`-: sets margins, if `layout` is not used (otherwise `layout`- overrides these)--`pagenumbering`-: page number style and location (using [`setuppagenumbering`]);- repeat for multiple options--`papersize`-: paper size, e.g. `letter`, `A4`, `landscape` (see [ConTeXt Paper Setup]);- repeat for multiple options--`pdfa`-: adds to the preamble the setup necessary to generate PDF/A- of the type specified, e.g. `1a:2005`, `2a`. If no type is- specified (i.e. the value is set to True, by e.g.- `--metadata=pdfa` or `pdfa: true` in a YAML metadata block),- `1b:2005` will be used as default, for reasons of backwards- compatibility. Using `--variable=pdfa` without specified value- is not supported. To successfully generate PDF/A the required- ICC color profiles have to be available and the content and all- included files (such as images) have to be standard-conforming.- The ICC profiles and output intent may be specified using the- variables `pdfaiccprofile` and `pdfaintent`. See also [ConTeXt- PDFA] for more details.--`pdfaiccprofile`-: when used in conjunction with `pdfa`, specifies the ICC profile to use- in the PDF, e.g. `default.cmyk`. If left unspecified, `sRGB.icc` is- used as default. May be repeated to include multiple profiles. Note that- the profiles have to be available on the system. They can be obtained- from [ConTeXt ICC Profiles].--`pdfaintent`-: when used in conjunction with `pdfa`, specifies the output intent for- the colors, e.g. `ISO coated v2 300\letterpercent\space (ECI)`- If left unspecified, `sRGB IEC61966-2.1` is used as default.--`toc`-: include table of contents (can also be set using- `--toc/--table-of-contents`)--`whitespace`-: spacing between paragraphs, e.g. `none`, `small` (using- [`setupwhitespace`])--`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 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-[`setupwhitespace`]: https://wiki.contextgarden.net/Command/setupwhitespace-[`setupinterlinespace`]: https://wiki.contextgarden.net/Command/setupinterlinespace-[`setuppagenumbering`]: https://wiki.contextgarden.net/Command/setuppagenumbering--### Variables for `wkhtmltopdf`--Pandoc uses these variables when [creating a PDF] with [`wkhtmltopdf`].-The `--css` option also affects the output.--`footer-html`, `header-html`-: add information to the header and footer--`margin-left`, `margin-right`, `margin-top`, `margin-bottom`-: set the page margins--`papersize`-: sets the PDF paper size--### Variables for man pages--`adjusting`-: adjusts text to left (`l`), right (`r`), center (`c`),- or both (`b`) margins--`footer`-: footer in man pages--`header`-: header in man pages--`hyphenate`-: if `true` (the default), hyphenation will be used--`section`-: section number in man pages--### Variables for ms--`fontfamily`-: font family (e.g. `T` or `P`)--`indent`-: paragraph indent (e.g. `2m`)--`lineheight`-: line height (e.g. `12p`)--`pointsize`-: point size (e.g. `10p`)--### Variables set automatically--Pandoc sets these variables automatically in response to [options] or-document contents; users can also modify them. These vary depending-on the output format, and include the following:--`body`-: body of document--`date-meta`-: the `date` variable converted to ISO 8601 YYYY-MM-DD,- included in all HTML based formats (dzslides, epub,- html, html4, html5, revealjs, s5, slideous, slidy).- The recognized formats for `date` are: `mm/dd/yyyy`,- `mm/dd/yy`, `yyyy-mm-dd` (ISO 8601), `dd MM yyyy`- (e.g. either `02 Apr 2018` or `02 April 2018`),- `MM dd, yyyy` (e.g. `Apr. 02, 2018` or `April 02, 2018),- `yyyy[mm[dd]]` (e.g. `20180402, `201804` or `2018`).--`header-includes`-: contents specified by `-H/--include-in-header` (may have multiple- values)--`include-before`-: contents specified by `-B/--include-before-body` (may have- multiple values)--`include-after`-: contents specified by `-A/--include-after-body` (may have- multiple values)--`meta-json`-: JSON representation of all of the document's metadata. Field- values are transformed to the selected output format.--`numbersections`-: non-null value if `-N/--number-sections` was specified--`sourcefile`, `outputfile`-: source and destination filenames, as given on the command line.- `sourcefile` can also be a list if input comes from multiple files,- or empty if input is from stdin. You can use the following snippet in- your template to distinguish them:-- $if(sourcefile)$- $for(sourcefile)$- $sourcefile$- $endfor$- $else$- (stdin)- $endif$-- Similarly, `outputfile` can be `-` if output goes to the terminal.-- If you need absolute paths, use e.g. `$curdir$/$sourcefile$`.--`curdir`-: working directory from which pandoc is run.--`toc`-: non-null value if `--toc/--table-of-contents` was specified--`toc-title`-: title of table of contents (works only with EPUB,- HTML, revealjs, opendocument, odt, docx, pptx, beamer, LaTeX)--[pandoc-templates]: https://github.com/jgm/pandoc-templates--# Extensions--The behavior of some of the readers and writers can be adjusted by-enabling or disabling various extensions.--An extension can be enabled by adding `+EXTENSION`-to the format name and disabled by adding `-EXTENSION`. For example,-`--from markdown_strict+footnotes` is strict Markdown with footnotes-enabled, while `--from markdown-footnotes-pipe_tables` is pandoc's-Markdown without footnotes or pipe tables.--The markdown reader and writer make by far the most use of extensions.-Extensions only used by them are therefore covered in the-section [Pandoc's Markdown] below (see [Markdown variants] for-`commonmark` and `gfm`). In the following, extensions that also work-for other formats are covered.--Note that markdown extensions added to the `ipynb` format-affect Markdown cells in Jupyter notebooks (as do command-line-options like `--atx-headers`).--## Typography--#### Extension: `smart` ####--Interpret straight quotes as curly quotes, `---` as em-dashes,-`--` as en-dashes, and `...` as ellipses. Nonbreaking spaces are-inserted after certain abbreviations, such as "Mr."--This extension can be enabled/disabled for the following formats:--input formats-: `markdown`, `commonmark`, `latex`, `mediawiki`, `org`, `rst`, `twiki`,- `html`--output formats-: `markdown`, `latex`, `context`, `rst`--enabled by default in-: `markdown`, `latex`, `context` (both input and output)--Note: If you are *writing* Markdown, then the `smart` extension-has the reverse effect: what would have been curly quotes comes-out straight.--In LaTeX, `smart` means to use the standard TeX ligatures-for quotation marks (` `` ` and ` '' ` for double quotes,-`` ` `` and `` ' `` for single quotes) and dashes (`--` for-en-dash and `---` for em-dash). If `smart` is disabled,-then in reading LaTeX pandoc will parse these characters-literally. In writing LaTeX, enabling `smart` tells pandoc-to use the ligatures when possible; if `smart` is disabled-pandoc will use unicode quotation mark and dash characters.--## Headings and sections--#### Extension: `auto_identifiers` ####--A heading without an explicitly specified identifier will be-automatically assigned a unique identifier based on the heading text.--This extension can be enabled/disabled for the following formats:--input formats-: `markdown`, `latex`, `rst`, `mediawiki`, `textile`--output formats-: `markdown`, `muse`--enabled by default in-: `markdown`, `muse`--The default algorithm used to derive the identifier from the-heading text is:-- - Remove all formatting, links, etc.- - Remove all footnotes.- - Remove all non-alphanumeric characters,- except underscores, hyphens, and periods.- - Replace all spaces and newlines with hyphens.- - Convert all alphabetic characters to lowercase.- - Remove everything up to the first letter (identifiers may- not begin with a number or punctuation mark).- - If nothing is left after this, use the identifier `section`.--Thus, for example,-- Heading Identifier- ------------------------------- ----------------------------- `Heading identifiers in HTML` `heading-identifiers-in-html`- `Maître d'hôtel` `maître-dhôtel`- `*Dogs*?--in *my* house?` `dogs--in-my-house`- `[HTML], [S5], or [RTF]?` `html-s5-or-rtf`- `3. Applications` `applications`- `33` `section`--These rules should, in most cases, allow one to determine the identifier-from the heading text. The exception is when several headings have the-same text; in this case, the first will get an identifier as described-above; the second will get the same identifier with `-1` appended; the-third with `-2`; and so on.--(However, a different algorithm is used if-`gfm_auto_identifiers` is enabled; see below.)--These identifiers are used to provide link targets in the table of-contents generated by the `--toc|--table-of-contents` option. They-also make it easy to provide links from one section of a document to-another. A link to this section, for example, might look like this:-- See the section on- [heading identifiers](#heading-identifiers-in-html-latex-and-context).--Note, however, that this method of providing links to sections works-only in HTML, LaTeX, and ConTeXt formats.--If the `--section-divs` option is specified, then each section will-be wrapped in a `section` (or a `div`, if `html4` was specified),-and the identifier will be attached to the enclosing `<section>`-(or `<div>`) tag rather than the heading itself. This allows entire-sections to be manipulated using JavaScript or treated differently in-CSS.--#### Extension: `ascii_identifiers` ####--Causes the identifiers produced by `auto_identifiers` to be pure ASCII.-Accents are stripped off of accented Latin letters, and non-Latin-letters are omitted.--#### Extension: `gfm_auto_identifiers` ####--Changes the algorithm used by `auto_identifiers` to conform to-GitHub's method. Spaces are converted to dashes (`-`),-uppercase characters to lowercase characters, and punctuation-characters other than `-` and `_` are removed.-Emojis are replaced by their names.--## Math Input--The extensions [`tex_math_dollars`](#extension-tex_math_dollars),-[`tex_math_single_backslash`](#extension-tex_math_single_backslash), and-[`tex_math_double_backslash`](#extension-tex_math_double_backslash)-are described in the section about Pandoc's Markdown.--However, they can also be used with HTML input. This is handy for-reading web pages formatted using MathJax, for example.--## Raw HTML/TeX--The following extensions are described in more detail in-their respective sections of [Pandoc's Markdown]:--- [`raw_html`](#extension-raw_html) allows HTML elements which- are not representable in pandoc's AST to be parsed as raw HTML.- By default, this is disabled for HTML input.--- [`raw_tex`](#extension-raw_tex) allows raw LaTeX, TeX, and ConTeXt- to be included in a document. This extension can be enabled/disabled- for the following formats (in addition to `markdown`):-- input formats- : `latex`, `textile`, `html` (environments, `\ref`, and- `\eqref` only), `ipynb`-- output formats- : `textile`, `commonmark`-- Note: as applied to `ipynb`, `raw_html` and `raw_tex` affect not- only raw TeX in markdown cells, but data with mime type- `text/html` in output cells. Since the `ipynb` reader attempts- to preserve the richest possible outputs when several options- are given, you will get best results if you disable `raw_html`- and `raw_tex` when converting to formats like `docx` which don't- allow raw `html` or `tex`.--- [`native_divs`](#extension-native_divs) causes HTML `div`- elements to be parsed as native pandoc Div blocks.- If you want them to be parsed as raw HTML, use- `-f html-native_divs+raw_html`.--- [`native_spans`](#extension-native_spans) causes HTML `span`- elements to be parsed as native pandoc Span inlines.- If you want them to be parsed as raw HTML, use- `-f html-native_spans+raw_html`. If you want to drop all- `div`s and `span`s when converting HTML to Markdown, you- can use `pandoc -f html-native_divs-native_spans -t markdown`.--## Literate Haskell support--#### Extension: `literate_haskell` ####--Treat the document as literate Haskell source.--This extension can be enabled/disabled for the following formats:--input formats-: `markdown`, `rst`, `latex`--output formats-: `markdown`, `rst`, `latex`, `html`--If you append `+lhs` (or `+literate_haskell`) to one of the formats-above, pandoc will treat the document as literate Haskell source.-This means that-- - In Markdown input, "bird track" sections will be parsed as Haskell- code rather than block quotations. Text between `\begin{code}`- and `\end{code}` will also be treated as Haskell code. For- ATX-style headings the character '=' will be used instead of '#'.-- - In Markdown output, code blocks with classes `haskell` and `literate`- will be rendered using bird tracks, and block quotations will be- indented one space, so they will not be treated as Haskell code.- In addition, headings will be rendered setext-style (with underlines)- rather than ATX-style (with '#' characters). (This is because ghc- treats '#' characters in column 1 as introducing line numbers.)-- - In restructured text input, "bird track" sections will be parsed- as Haskell code.-- - In restructured text output, code blocks with class `haskell` will- be rendered using bird tracks.-- - In LaTeX input, text in `code` environments will be parsed as- Haskell code.-- - In LaTeX output, code blocks with class `haskell` will be rendered- inside `code` environments.-- - In HTML output, code blocks with class `haskell` will be rendered- with class `literatehaskell` and bird tracks.--Examples:-- pandoc -f markdown+lhs -t html--reads literate Haskell source formatted with Markdown conventions and writes-ordinary HTML (without bird tracks).-- pandoc -f markdown+lhs -t html+lhs--writes HTML with the Haskell code in bird tracks, so it can be copied-and pasted as literate Haskell source.--Note that GHC expects the bird tracks in the first column, so indented-literate code blocks (e.g. inside an itemized environment) will not be-picked up by the Haskell compiler.--## Other extensions--#### Extension: `empty_paragraphs` ####--Allows empty paragraphs. By default empty paragraphs are-omitted.--This extension can be enabled/disabled for the following formats:--input formats-: `docx`, `html`--output formats-: `docx`, `odt`, `opendocument`, `html`--#### Extension: `native_numbering` ####--Enables native numbering of figures and tables. Enumeration-starts at 1.--This extension can be enabled/disabled for the following formats:--output formats-: `odt`, `opendocument`, `docx`--#### Extension: `xrefs_name` ####--Links to headings, figures and tables inside the document are-substituted with cross-references that will use the name or caption-of the referenced item. The original link text is replaced once-the generated document is refreshed. This extension can be combined-with `xrefs_number` in which case numbers will appear before the-name.--Text in cross-references is only made consistent with the referenced-item once the document has been refreshed.--This extension can be enabled/disabled for the following formats:--output formats-: `odt`, `opendocument`--#### Extension: `xrefs_number` ####--Links to headings, figures and tables inside the document are-substituted with cross-references that will use the number-of the referenced item. The original link text is discarded.-This extension can be combined with `xrefs_name` in which case-the name or caption numbers will appear after the number.--For the `xrefs_number` to be useful heading numbers must be enabled-in the generated document, also table and figure captions must be enabled-using for example the `native_numbering` extension.--Numbers in cross-references are only visible in the final document once-it has been refreshed.--This extension can be enabled/disabled for the following formats:--output formats-: `odt`, `opendocument`--#### Extension: `styles` #### {#ext-styles}--When converting from docx, read all docx styles as divs (for-paragraph styles) and spans (for character styles) regardless-of whether pandoc understands the meaning of these styles.-This can be used with [docx custom styles](#custom-styles).-Disabled by default.--input formats-: `docx`--#### Extension: `amuse` ####--In the `muse` input format, this enables Text::Amuse-extensions to Emacs Muse markup.--#### Extension: `raw_markdown` ####--In the `ipynb` input format, this causes Markdown cells-to be included as raw Markdown blocks (allowing lossless-round-tripping) rather than being parsed. Use this only-when you are targeting `ipynb` or a markdown-based-output format.--#### Extension: `citations` {#org-citations}--When the `citations` extension is enabled in `org`,-org-cite and org-ref style citations will be parsed as-native pandoc citations.-- [org-cite]: https://orgmode.org/manual/Citations.html- [org-ref]: https://github.com/jkitchin/org-ref--When `citations` is enabled in `docx`, citations inserted-by Zotero or Mendeley or EndNote plugins will be parsed as native-pandoc citations. (Otherwise, the formatted citations generated-by the bibliographic software will be parsed as regular text.)--#### Extension: `fancy_lists` {#org-fancy-lists}--Some aspects of [Pandoc's Markdown fancy lists](#extension-fancy_lists) are also-accepted in `org` input, mimicking the option `org-list-allow-alphabetical` in-Emacs. As in Org Mode, enabling this extension allows lowercase and uppercase-alphabetical markers for ordered lists to be parsed in addition to arabic ones.-Note that for Org, this does not include roman numerals or the `#` placeholder-that are enabled by the extension in Pandoc's Markdown.--#### Extension: `element_citations` ####--In the `jats` output formats, this causes reference items to-be replaced with `<element-citation>` elements. These-elements are not influenced by CSL styles, but all information-on the item is included in tags.--#### Extension: `ntb` ####--In the `context` output format this enables the use of [Natural Tables-(TABLE)](https://wiki.contextgarden.net/TABLE) instead of the default-[Extreme Tables (xtables)](https://wiki.contextgarden.net/xtables).-Natural tables allow more fine-grained global customization but come-at a performance penalty compared to extreme tables.---# Pandoc's Markdown--Pandoc understands an extended and slightly revised version of-John Gruber's [Markdown] syntax. This document explains the syntax,-noting differences from original Markdown. Except where noted, these-differences can be suppressed by using the `markdown_strict` format instead-of `markdown`. Extensions can be enabled or disabled to specify the-behavior more granularly. They are described in the following. See also-[Extensions] above, for extensions that work also on other formats.--## Philosophy--Markdown is designed to be easy to write, and, even more importantly,-easy to read:--> A Markdown-formatted document should be publishable as-is, as plain-> text, without looking like it's been marked up with tags or formatting-> instructions.-> -- [John Gruber](https://daringfireball.net/projects/markdown/syntax#philosophy)--This principle has guided pandoc's decisions in finding syntax for-tables, footnotes, and other extensions.--There is, however, one respect in which pandoc's aims are different-from the original aims of Markdown. Whereas Markdown was originally-designed with HTML generation in mind, pandoc is designed for multiple-output formats. Thus, while pandoc allows the embedding of raw HTML,-it discourages it, and provides other, non-HTMLish ways of representing-important document elements like definition lists, tables, mathematics, and-footnotes.--## Paragraphs--A paragraph is one or more lines of text followed by one or more blank lines.-Newlines are treated as spaces, so you can reflow your paragraphs as you like.-If you need a hard line break, put two or more spaces at the end of a line.--#### Extension: `escaped_line_breaks` ####--A backslash followed by a newline is also a hard line break.-Note: in multiline and grid table cells, this is the only way-to create a hard line break, since trailing spaces in the cells-are ignored.--## Headings--There are two kinds of headings: Setext and ATX.--### Setext-style headings ###--A setext-style heading is a line of text "underlined" with a row of `=` signs-(for a level-one heading) or `-` signs (for a level-two heading):-- A level-one heading- ===================-- A level-two heading- ---------------------The heading text can contain inline formatting, such as emphasis (see-[Inline formatting], below).---### ATX-style headings ###--An ATX-style heading consists of one to six `#` signs and a line of-text, optionally followed by any number of `#` signs. The number of-`#` signs at the beginning of the line is the heading level:-- ## A level-two heading-- ### A level-three heading ###--As with setext-style headings, the heading text can contain formatting:-- # A level-one heading with a [link](/url) and *emphasis*--#### Extension: `blank_before_header` ####--Original Markdown syntax does not require a blank line before a heading.-Pandoc does require this (except, of course, at the beginning of the-document). The reason for the requirement is that it is all too easy for a-`#` to end up at the beginning of a line by accident (perhaps through line-wrapping). Consider, for example:-- I like several of their flavors of ice cream:- #22, for example, and #5.--#### Extension: `space_in_atx_header` ####--Many Markdown implementations do not require a space between the-opening `#`s of an ATX heading and the heading text, so that-`#5 bolt` and `#hashtag` count as headings. With this extension,-pandoc does require the space.--### Heading identifiers ###--See also the [`auto_identifiers`-extension](#extension-auto_identifiers) above.--#### Extension: `header_attributes` ####--Headings can be assigned attributes using this syntax at the end-of the line containing the heading text:-- {#identifier .class .class key=value key=value}--Thus, for example, the following headings will all be assigned the identifier-`foo`:-- # My heading {#foo}-- ## My heading ## {#foo}-- My other heading {#foo}- -----------------(This syntax is compatible with [PHP Markdown Extra].)--Note that although this syntax allows assignment of classes and key/value-attributes, writers generally don't use all of this information. Identifiers,-classes, and key/value attributes are used in HTML and HTML-based formats such-as EPUB and slidy. Identifiers are used for labels and link anchors in the-LaTeX, ConTeXt, Textile, Jira markup, and AsciiDoc writers.--Headings with the class `unnumbered` will not be numbered, even if-`--number-sections` is specified. A single hyphen (`-`) in an attribute-context is equivalent to `.unnumbered`, and preferable in non-English-documents. So,-- # My heading {-}--is just the same as-- # My heading {.unnumbered}--If the `unlisted` class is present in addition to `unnumbered`,-the heading will not be included in a table of contents.-(Currently this feature is only implemented for certain-formats: those based on LaTeX and HTML, PowerPoint, and RTF.)--#### Extension: `implicit_header_references` ####--Pandoc behaves as if reference links have been defined for each heading.-So, to link to a heading-- # Heading identifiers in HTML--you can simply write-- [Heading identifiers in HTML]--or-- [Heading identifiers in HTML][]--or-- [the section on heading identifiers][heading identifiers in- HTML]--instead of giving the identifier explicitly:-- [Heading identifiers in HTML](#heading-identifiers-in-html)--If there are multiple headings with identical text, the corresponding-reference will link to the first one only, and you will need to use explicit-links to link to the others, as described above.--Like regular reference links, these references are case-insensitive.--Explicit link reference definitions always take priority over-implicit heading references. So, in the following example, the-link will point to `bar`, not to `#foo`:-- # Foo-- [foo]: bar-- See [foo]--## Block quotations--Markdown uses email conventions for quoting blocks of text.-A block quotation is one or more paragraphs or other block elements-(such as lists or headings), with each line preceded by a `>` character-and an optional space. (The `>` need not start at the left margin, but-it should not be indented more than three spaces.)-- > This is a block quote. This- > paragraph has two lines.- >- > 1. This is a list inside a block quote.- > 2. Second item.--A "lazy" form, which requires the `>` character only on the first-line of each block, is also allowed:-- > This is a block quote. This- paragraph has two lines.-- > 1. This is a list inside a block quote.- 2. Second item.--Among the block elements that can be contained in a block quote are-other block quotes. That is, block quotes can be nested:-- > This is a block quote.- >- > > A block quote within a block quote.--If the `>` character is followed by an optional space, that space-will be considered part of the block quote marker and not part of-the indentation of the contents. Thus, to put an indented code-block in a block quote, you need five spaces after the `>`:-- > code--#### Extension: `blank_before_blockquote` ####--Original Markdown syntax does not require a blank line before a-block quote. Pandoc does require this (except, of course, at-the beginning of the document). The reason for the requirement-is that it is all too easy for a `>` to end up at the beginning-of a line by accident (perhaps through line wrapping). So,-unless the `markdown_strict` format is used, the following does-not produce a nested block quote in pandoc:-- > This is a block quote.- >> Nested.---## Verbatim (code) blocks--### Indented code blocks ###--A block of text indented four spaces (or one tab) is treated as verbatim-text: that is, special characters do not trigger special formatting,-and all spaces and line breaks are preserved. For example,-- if (a > 3) {- moveShip(5 * gravity, DOWN);- }--The initial (four space or one tab) indentation is not considered part-of the verbatim text, and is removed in the output.--Note: blank lines in the verbatim text need not begin with four spaces.---### Fenced code blocks ###--#### Extension: `fenced_code_blocks` ####--In addition to standard indented code blocks, pandoc supports-*fenced* code blocks. These begin with a row of three or more-tildes (`~`) and end with a row of tildes that must be at least as long as-the starting row. Everything between these lines is treated as code. No-indentation is necessary:-- ~~~~~~~- if (a > 3) {- moveShip(5 * gravity, DOWN);- }- ~~~~~~~--Like regular code blocks, fenced code blocks must be separated-from surrounding text by blank lines.--If the code itself contains a row of tildes or backticks, just use a longer-row of tildes or backticks at the start and end:-- ~~~~~~~~~~~~~~~~- ~~~~~~~~~~- code including tildes- ~~~~~~~~~~- ~~~~~~~~~~~~~~~~--#### Extension: `backtick_code_blocks` ####--Same as `fenced_code_blocks`, but uses backticks (`` ` ``) instead of tildes-(`~`).--#### Extension: `fenced_code_attributes` ####--Optionally, you may attach attributes to fenced or backtick code block using-this syntax:-- ~~~~ {#mycode .haskell .numberLines startFrom="100"}- qsort [] = []- qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++- qsort (filter (>= x) xs)- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--Here `mycode` is an identifier, `haskell` and `numberLines` are-classes, and `startFrom` is an attribute with value `100`. Some-output formats can use this information to do syntax-highlighting. Currently, the only output formats that use this-information are HTML, LaTeX, Docx, Ms, and PowerPoint. If-highlighting is supported for your output format and language,-then the code block above will appear highlighted, with numbered-lines. (To see which languages are supported, type `pandoc---list-highlight-languages`.) Otherwise, the code block above-will appear as follows:-- <pre id="mycode" class="haskell numberLines" startFrom="100">- <code>- ...- </code>- </pre>--The `numberLines` (or `number-lines`) class will cause the lines-of the code block to be numbered, starting with `1` or the value-of the `startFrom` attribute. The `lineAnchors` (or-`line-anchors`) class will cause the lines to be clickable-anchors in HTML output.--A shortcut form can also be used for specifying the language of-the code block:-- ```haskell- qsort [] = []- ```--This is equivalent to:-- ``` {.haskell}- qsort [] = []- ```--If the `fenced_code_attributes` extension is disabled, but-input contains class attribute(s) for the code block, the first-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.--## Line blocks--#### Extension: `line_blocks` ####--A line block is a sequence of lines beginning with a vertical bar (`|`)-followed by a space. The division into lines will be preserved in-the output, as will any leading spaces; otherwise, the lines will-be formatted as Markdown. This is useful for verse and addresses:-- | The limerick packs laughs anatomical- | In space that is quite economical.- | But the good ones I've seen- | So seldom are clean- | And the clean ones so seldom are comical-- | 200 Main St.- | Berkeley, CA 94718--The lines can be hard-wrapped if needed, but the continuation-line must begin with a space.-- | The Right Honorable Most Venerable and Righteous Samuel L.- Constable, Jr.- | 200 Main St.- | Berkeley, CA 94718--Inline formatting (such as emphasis) is allowed in the content,-but not block-level formatting (such as block quotes or lists).--This syntax is borrowed from [reStructuredText].--## Lists--### Bullet lists ###--A bullet list is a list of bulleted list items. A bulleted list-item begins with a bullet (`*`, `+`, or `-`). Here is a simple-example:-- * one- * two- * three--This will produce a "compact" list. If you want a "loose" list, in which-each item is formatted as a paragraph, put spaces between the items:-- * one-- * two-- * three--The bullets need not be flush with the left margin; they may be-indented one, two, or three spaces. The bullet must be followed-by whitespace.--List items look best if subsequent lines are flush with the first-line (after the bullet):-- * here is my first- list item.- * and my second.--But Markdown also allows a "lazy" format:-- * here is my first- list item.- * and my second.--### Block content in list items ###--A list item may contain multiple paragraphs and other block-level-content. However, subsequent paragraphs must be preceded by a blank line-and indented to line up with the first non-space content after-the list marker.-- * First paragraph.-- Continued.-- * Second paragraph. With a code block, which must be indented- eight spaces:-- { code }--Exception: if the list marker is followed by an indented code-block, which must begin 5 spaces after the list marker, then-subsequent paragraphs must begin two columns after the last-character of the list marker:-- * code-- continuation paragraph--List items may include other lists. In this case the preceding blank-line is optional. The nested list must be indented to line up with-the first non-space character after the list marker of the-containing list item.-- * fruits- + apples- - macintosh- - red delicious- + pears- + peaches- * vegetables- + broccoli- + chard--As noted above, Markdown allows you to write list items "lazily," instead of-indenting continuation lines. However, if there are multiple paragraphs or-other blocks in a list item, the first line of each must be indented.-- + A lazy, lazy, list- item.-- + Another one; this looks- bad but is legal.-- Second paragraph of second- list item.--### Ordered lists ###--Ordered lists work just like bulleted lists, except that the items-begin with enumerators rather than bullets.--In original Markdown, enumerators are decimal numbers followed-by a period and a space. The numbers themselves are ignored, so-there is no difference between this list:-- 1. one- 2. two- 3. three--and this one:-- 5. one- 7. two- 1. three--#### Extension: `fancy_lists` ####--Unlike original Markdown, pandoc allows ordered list items to be marked-with uppercase and lowercase letters and roman numerals, in addition to-Arabic numerals. List markers may be enclosed in parentheses or followed by a-single right-parenthesis or period. They must be separated from the-text that follows by at least one space, and, if the list marker is a-capital letter with a period, by at least two spaces.[^2]--[^2]: The point of this rule is to ensure that normal paragraphs- starting with people's initials, like-- B. Russell was an English philosopher.-- do not get treated as list items.-- This rule will not prevent-- (C) 2007 Joe Smith-- from being interpreted as a list item. In this case, a backslash- escape can be used:-- (C\) 2007 Joe Smith--The `fancy_lists` extension also allows '`#`' to be used as an-ordered list marker in place of a numeral:-- #. one- #. two--#### Extension: `startnum` ####--Pandoc also pays attention to the type of list marker used, and to the-starting number, and both of these are preserved where possible in the-output format. Thus, the following yields a list with numbers followed-by a single parenthesis, starting with 9, and a sublist with lowercase-roman numerals:-- 9) Ninth- 10) Tenth- 11) Eleventh- i. subone- ii. subtwo- iii. subthree--Pandoc will start a new list each time a different type of list-marker is used. So, the following will create three lists:-- (2) Two- (5) Three- 1. Four- * Five--If default list markers are desired, use `#.`:-- #. one- #. two- #. three--#### Extension: `task_lists` ####--Pandoc supports task lists, using the syntax of GitHub-Flavored Markdown.-- - [ ] an unchecked task list item- - [x] checked item--### Definition lists ###--#### Extension: `definition_lists` ####--Pandoc supports definition lists, using the syntax of-[PHP Markdown Extra] with some extensions.[^3]-- Term 1-- : Definition 1-- Term 2 with *inline markup*-- : Definition 2-- { some code, part of Definition 2 }-- Third paragraph of definition 2.--Each term must fit on one line, which may optionally be followed by-a blank line, and must be followed by one or more definitions.-A definition begins with a colon or tilde, which may be indented one-or two spaces.--A term may have multiple definitions, and each definition may-consist of one or more block elements (paragraph, code block,-list, etc.), each indented four spaces or one tab stop. The-body of the definition (not including the first line)-should be indented four spaces. However, as with-other Markdown lists, you can "lazily" omit indentation except-at the beginning of a paragraph or other block element:-- Term 1-- : Definition- with lazy continuation.-- Second paragraph of the definition.--If you leave space before the definition (as in the example above),-the text of the definition will be treated as a paragraph. In some-output formats, this will mean greater spacing between term/definition-pairs. For a more compact definition list, omit the space before the-definition:-- Term 1- ~ Definition 1-- Term 2- ~ Definition 2a- ~ 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 `compact_definition_lists`: see-[Non-default extensions], below.)--[^3]: I have been influenced by the suggestions of [David- Wheeler](https://justatheory.com/2009/02/modest-markdown-proposal/).--### Numbered example lists ###--#### Extension: `example_lists` ####--The special list marker `@` can be used for sequentially numbered-examples. The first list item with a `@` marker will be numbered '1',-the next '2', and so on, throughout the document. The numbered examples-need not occur in a single list; each new list using `@` will take up-where the last stopped. So, for example:-- (@) My first example will be numbered (1).- (@) My second example will be numbered (2).-- Explanation of examples.-- (@) My third example will be numbered (3).--Numbered examples can be labeled and referred to elsewhere in the-document:-- (@good) This is a good example.-- As (@good) illustrates, ...--The label can be any string of alphanumeric characters, underscores,-or hyphens.--Note: continuation paragraphs in example lists must always-be indented four spaces, regardless of the length of the-list marker. That is, example lists always behave as if the-`four_space_rule` extension is set. This is because example-labels tend to be long, and indenting content to the-first non-space character after the label would be awkward.---### Ending a list ###--What if you want to put an indented code block after a list?-- - item one- - item two-- { my code block }--Trouble! Here pandoc (like other Markdown implementations) will treat-`{ my code block }` as the second paragraph of item two, and not as-a code block.--To "cut off" the list after item two, you can insert some non-indented-content, like an HTML comment, which won't produce visible output in-any format:-- - item one- - item two-- <!-- end of list -->-- { my code block }--You can use the same trick if you want two consecutive lists instead-of one big list:-- 1. one- 2. two- 3. three-- <!-- -->-- 1. uno- 2. dos- 3. tres--## Horizontal rules--A line containing a row of three or more `*`, `-`, or `_` characters-(optionally separated by spaces) produces a horizontal rule:-- * * * *-- -----------------We strongly recommend that horizontal rules be separated from-surrounding text by blank lines. If a horizontal rule is not-followed by a blank line, pandoc may try to interpret the-lines that follow as a YAML metadata block or a table.--## Tables--Four kinds of tables may be used. The first three kinds presuppose the use of-a fixed-width font, such as Courier. The fourth kind can be used with-proportionally spaced fonts, as it does not require lining up columns.--#### Extension: `table_captions` ####--A caption may optionally be provided with all 4 kinds of tables (as-illustrated in the examples below). A caption is a paragraph beginning-with the string `Table:` (or just `:`), which will be stripped off.-It may appear either before or after the table.--#### Extension: `simple_tables` ####--Simple tables look like this:-- Right Left Center Default- ------- ------ ---------- -------- 12 12 12 12- 123 123 123 123- 1 1 1 1-- Table: Demonstration of simple table syntax.--The header and table rows must each fit on one line. Column-alignments are determined by the position of the header text relative-to the dashed line below it:[^4]-- - If the dashed line is flush with the header text on the right side- but extends beyond it on the left, the column is right-aligned.- - If the dashed line is flush with the header text on the left side- but extends beyond it on the right, the column is left-aligned.- - If the dashed line extends beyond the header text on both sides,- the column is centered.- - If the dashed line is flush with the header text on both sides,- the default alignment is used (in most cases, this will be left).--[^4]: This scheme is due to Michel Fortin, who proposed it on the- [Markdown discussion list](http://six.pairlist.net/pipermail/markdown-discuss/2005-March/001097.html).--The table must end with a blank line, or a line of dashes followed by-a blank line.--The column header row may be omitted, provided a dashed line is used-to end the table. For example:-- ------- ------ ---------- -------- 12 12 12 12- 123 123 123 123- 1 1 1 1- ------- ------ ---------- ---------When the header row is omitted, column alignments are determined on the basis-of the first line of the table body. So, in the tables above, the columns-would be right, left, center, and right aligned, respectively.--#### Extension: `multiline_tables` ####--Multiline tables allow header and table rows to span multiple lines-of text (but cells that span multiple columns or rows of the table are-not supported). Here is an example:-- -------------------------------------------------------------- Centered Default Right Left- Header Aligned Aligned Aligned- ----------- ------- --------------- -------------------------- First row 12.0 Example of a row that- spans multiple lines.-- Second row 5.0 Here's another one. Note- the blank line between- rows.- --------------------------------------------------------------- Table: Here's the caption. It, too, may span- multiple lines.--These work like simple tables, but with the following differences:-- - They must begin with a row of dashes, before the header text- (unless the header row is omitted).- - They must end with a row of dashes, then a blank line.- - The rows must be separated by blank lines.--In multiline tables, the table parser pays attention to the widths of-the columns, and the writers try to reproduce these relative widths in-the output. So, if you find that one of the columns is too narrow in the-output, try widening it in the Markdown source.--The header may be omitted in multiline tables as well as simple tables:-- ----------- ------- --------------- -------------------------- First row 12.0 Example of a row that- spans multiple lines.-- Second row 5.0 Here's another one. Note- the blank line between- rows.- ----------- ------- --------------- --------------------------- : Here's a multiline table without a header.--It is possible for a multiline table to have just one row, but the row-should be followed by a blank line (and then the row of dashes that ends-the table), or the table may be interpreted as a simple table.--#### Extension: `grid_tables` ####--Grid tables look like this:-- : Sample grid table.-- +---------------+---------------+--------------------+- | Fruit | Price | Advantages |- +===============+===============+====================+- | Bananas | $1.34 | - built-in wrapper |- | | | - bright color |- +---------------+---------------+--------------------+- | Oranges | $2.10 | - cures scurvy |- | | | - tasty |- +---------------+---------------+--------------------+--The row of `=`s separates the header from the table body, and can be-omitted for a headerless table. The cells of grid tables may contain-arbitrary block elements (multiple paragraphs, code blocks, lists,-etc.). Cells that span multiple columns or rows are not-supported. Grid tables can be created easily using Emacs' table-mode-(`M-x table-insert`).--Alignments can be specified as with pipe tables, by putting-colons at the boundaries of the separator line after the-header:-- +---------------+---------------+--------------------+- | Right | Left | Centered |- +==============:+:==============+:==================:+- | Bananas | $1.34 | built-in wrapper |- +---------------+---------------+--------------------+--For headerless tables, the colons go on the top line instead:-- +--------------:+:--------------+:------------------:+- | Right | Left | Centered |- +---------------+---------------+--------------------+--##### Grid Table Limitations #####--Pandoc does not support grid tables with row spans or column spans.-This means that neither variable numbers of columns across rows nor-variable numbers of rows across columns are supported by Pandoc.-All grid tables must have the same number of columns in each row,-and the same number of rows in each column. For example, the-Docutils [sample grid tables] will not render as expected with-Pandoc.--[sample grid tables]: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#grid-tables---#### Extension: `pipe_tables` ####--Pipe tables look like this:-- | Right | Left | Default | Center |- |------:|:-----|---------|:------:|- | 12 | 12 | 12 | 12 |- | 123 | 123 | 123 | 123 |- | 1 | 1 | 1 | 1 |-- : Demonstration of pipe table syntax.--The syntax is identical to [PHP Markdown Extra tables]. The beginning and-ending pipe characters are optional, but pipes are required between all-columns. The colons indicate column alignment as shown. The header-cannot be omitted. To simulate a headerless table, include a header-with blank cells.--Since the pipes indicate column boundaries, columns need not be vertically-aligned, as they are in the above example. So, this is a perfectly-legal (though ugly) pipe table:-- fruit| price- -----|-----:- apple|2.05- pear|1.37- orange|3.09--The cells of pipe tables cannot contain block elements like paragraphs-and lists, and cannot span multiple lines. If any line of the-markdown source is longer than the column width (see `--columns`),-then the table will take up the full text width and the cell-contents will wrap, with the relative cell widths determined by-the number of dashes in the line separating the table header-from the table body. (For example `---|-` would make the first column 3/4-and the second column 1/4 of the full text width.)-On the other hand, if no lines are wider than column width, then-cell contents will not be wrapped, and the cells will be sized-to their contents.--Note: pandoc also recognizes pipe tables of the following-form, as can be produced by Emacs' orgtbl-mode:-- | One | Two |- |-----+-------|- | my | table |- | is | nice |--The difference is that `+` is used instead of `|`. Other orgtbl features-are not supported. In particular, to get non-default column alignment,-you'll need to add colons as above.--[PHP Markdown Extra tables]: https://michelf.ca/projects/php-markdown/extra/#table--## Metadata blocks--#### Extension: `pandoc_title_block` ####--If the file begins with a title block-- % title- % author(s) (separated by semicolons)- % date--it will be parsed as bibliographic information, not regular text. (It-will be used, for example, in the title of standalone LaTeX or HTML-output.) The block may contain just a title, a title and an author,-or all three elements. If you want to include an author but no-title, or a title and a date but no author, you need a blank line:--```-%-% Author-```--```-% My title-%-% June 15, 2006-```--The title may occupy multiple lines, but continuation lines must-begin with leading space, thus:--```-% My title- on multiple lines-```--If a document has multiple authors, the authors may be put on-separate lines with leading space, or separated by semicolons, or-both. So, all of the following are equivalent:--```-% Author One- Author Two-```--```-% Author One; Author Two-```--```-% Author One;- Author Two-```--The date must fit on one line.--All three metadata fields may contain standard inline formatting-(italics, links, footnotes, etc.).--Title blocks will always be parsed, but they will affect the output only-when the `--standalone` (`-s`) option is chosen. In HTML output, titles-will appear twice: once in the document head -- this is the title that-will appear at the top of the window in a browser -- and once at the-beginning of the document body. The title in the document head can have-an optional prefix attached (`--title-prefix` or `-T` option). The title-in the body appears as an H1 element with class "title", so it can be-suppressed or reformatted with CSS. If a title prefix is specified with-`-T` and no title block appears in the document, the title prefix will-be used by itself as the HTML title.--The man page writer extracts a title, man page section number, and-other header and footer information from the title line. The title-is assumed to be the first word on the title line, which may optionally-end with a (single-digit) section number in parentheses. (There should-be no space between the title and the parentheses.) Anything after-this is assumed to be additional footer and header text. A single pipe-character (`|`) should be used to separate the footer text from the header-text. Thus,-- % PANDOC(1)--will yield a man page with the title `PANDOC` and section 1.-- % PANDOC(1) Pandoc User Manuals--will also have "Pandoc User Manuals" in the footer.-- % PANDOC(1) Pandoc User Manuals | Version 4.0--will also have "Version 4.0" in the header.--#### Extension: `yaml_metadata_block` ####--A [YAML] metadata block is a valid YAML object, delimited by a line of three-hyphens (`---`) at the top and a line of three hyphens (`---`) or three dots-(`...`) at the bottom. The initial line `---` must not be followed by a blank-line. A YAML metadata block may occur anywhere in the document, but if-it is not at the beginning, it must be preceded by a blank line.--Note that, because of the way pandoc concatenates input files-when several are provided, you may also keep the metadata in a-separate YAML file and pass it to pandoc as an argument, along-with your Markdown files:-- pandoc chap1.md chap2.md chap3.md metadata.yaml -s -o book.html--Just be sure that the YAML file begins with `---` and ends with `---` or-`...`. Alternatively, you can use the `--metadata-file` option. Using-that approach however, you cannot reference content (like footnotes)-from the main markdown input document.--Metadata will be taken from the fields of the YAML object and added to any-existing document metadata. Metadata can contain lists and objects (nested-arbitrarily), but all string scalars will be interpreted as Markdown. Fields-with names ending in an underscore will be ignored by pandoc. (They may be-given a role by external processors.) Field names must not be-interpretable as YAML numbers or boolean values (so, for-example, `yes`, `True`, and `15` cannot be used as field names).--A document may contain multiple metadata blocks. If two-metadata blocks attempt to set the same field, the value from-the second block will be taken.--Each metadata block is handled internally as an independent YAML document.-This means, for example, that any YAML anchors defined in a block cannot be-referenced in another block.--When pandoc is used with `-t markdown` to create a Markdown document,-a YAML metadata block will be produced only if the `-s/--standalone`-option is used. All of the metadata will appear in a single block-at the beginning of the document.--Note that [YAML] escaping rules must be followed. Thus, for example,-if a title contains a colon, it must be quoted, and if it contains a-backslash escape, then it must be ensured that it is not treated as a-[YAML escape sequence]. The pipe character (`|`) can be used to begin-an indented block that will be interpreted literally, without need for-escaping. This form is necessary when the field contains blank lines-or block-level formatting:-- ---- title: 'This is the title: it contains a colon'- author:- - Author One- - Author Two- keywords: [nothing, nothingness]- abstract: |- This is the abstract.-- It consists of two paragraphs.- ...--The literal block after the `|` must be indented relative to the-line containing the `|`. If it is not, the YAML will be invalid-and pandoc will not interpret it as metadata. For an overview-of the complex rules governing YAML, see the [Wikipedia entry on-YAML syntax].--Template variables will be set automatically from the metadata. Thus, for-example, in writing HTML, the variable `abstract` will be set to the HTML-equivalent of the Markdown in the `abstract` field:-- <p>This is the abstract.</p>- <p>It consists of two paragraphs.</p>--Variables can contain arbitrary YAML structures, but the template must match-this structure. The `author` variable in the default templates expects a-simple list or string, but can be changed to support more complicated-structures. The following combination, for example, would add an affiliation-to the author if one is given:-- ---- title: The document title- author:- - name: Author One- affiliation: University of Somewhere- - name: Author Two- affiliation: University of Nowhere- ...--To use the structured authors in the example above, you would need a custom-template:-- $for(author)$- $if(author.name)$- $author.name$$if(author.affiliation)$ ($author.affiliation$)$endif$- $else$- $author$- $endif$- $endfor$--Raw content to include in the document's header may be specified-using `header-includes`; however, it is important to mark up-this content as raw code for a particular output format, using-the [`raw_attribute` extension](#extension-raw_attribute), or it-will be interpreted as markdown. For example:-- header-includes:- - |- ```{=latex}- \let\oldsection\section- \renewcommand{\section}[1]{\clearpage\oldsection{#1}}- ```--Note: the `yaml_metadata_block` extension works with-`commonmark` as well as `markdown` (and it is enabled by default-in `gfm` and `commonmark_x`). However, in these formats the-following restrictions apply:--- The YAML metadata block must occur at the beginning of the- document (and there can be only one). If multiple files are- given as arguments to pandoc, only the first can be a YAML- metadata block.--- The leaf nodes of the YAML structure are parsed in isolation from- each other and from the rest of the document. So, for- example, you can't use a reference link in these contexts- if the link definition is somewhere else in the document.--[YAML escape sequence]: https://yaml.org/spec/1.2/spec.html#id2776092-[Wikipedia entry on YAML syntax]: https://en.wikipedia.org/wiki/YAML#Syntax--## Backslash escapes--#### Extension: `all_symbols_escapable` ####--Except inside a code block or inline code, any punctuation or space-character preceded by a backslash will be treated literally, even if it-would normally indicate formatting. Thus, for example, if one writes-- *\*hello\**--one will get-- <em>*hello*</em>--instead of-- <strong>hello</strong>--This rule is easier to remember than original Markdown's rule,-which allows only the following characters to be backslash-escaped:-- \`*_{}[]()>#+-.!--(However, if the `markdown_strict` format is used, the original Markdown rule-will be used.)--A backslash-escaped space is parsed as a nonbreaking space. In TeX output,-it will appear as `~`. In HTML and XML output, it will appear as a-literal unicode nonbreaking space character (note that it will thus-actually look "invisible" in the generated HTML source; you can still-use the `--ascii` command-line option to make it appear as an explicit-entity).--A backslash-escaped newline (i.e. a backslash occurring at the end of-a line) is parsed as a hard line break. It will appear in TeX output as-`\\` and in HTML as `<br />`. This is a nice alternative to-Markdown's "invisible" way of indicating hard line breaks using-two trailing spaces on a line.--Backslash escapes do not work in verbatim contexts.--## Inline formatting--### Emphasis ###--To *emphasize* some text, surround it with `*`s or `_`, like this:-- This text is _emphasized with underscores_, and this- is *emphasized with asterisks*.--Double `*` or `_` produces **strong emphasis**:-- This is **strong emphasis** and __with underscores__.--A `*` or `_` character surrounded by spaces, or backslash-escaped,-will not trigger emphasis:-- This is * not emphasized *, and \*neither is this\*.--#### Extension: `intraword_underscores` ####--Because `_` is sometimes used inside words and identifiers,-pandoc does not interpret a `_` surrounded by alphanumeric-characters as an emphasis marker. If you want to emphasize-just part of a word, use `*`:-- feas*ible*, not feas*able*.--### Highlighting ###--To highlight text, use the `mark` class:-- [Mark]{.mark}--Or, without the `bracketed_spans` extension (but with `native_spans`):-- <span class="mark">Mark</span>--This will work in html output.--### Strikeout ###--#### Extension: `strikeout` ####--To strike out a section of text with a horizontal line, begin and end it-with `~~`. Thus, for example,-- This ~~is deleted text.~~---### Superscripts and subscripts ###--#### Extension: `superscript`, `subscript` ####--Superscripts may be written by surrounding the superscripted text by `^`-characters; subscripts may be written by surrounding the subscripted-text by `~` characters. Thus, for example,-- H~2~O is a liquid. 2^10^ is 1024.--The text between `^...^` or `~...~` may not contain spaces or-newlines. If the superscripted or subscripted text contains-spaces, these spaces must be escaped with backslashes. (This is-to prevent accidental superscripting and subscripting through-the ordinary use of `~` and `^`, and also bad interactions with-footnotes.) Thus, if you want the letter P with 'a cat' in-subscripts, use `P~a\ cat~`, not `P~a cat~`.--### Verbatim ###--To make a short span of text verbatim, put it inside backticks:-- What is the difference between `>>=` and `>>`?--If the verbatim text includes a backtick, use double backticks:-- Here is a literal backtick `` ` ``.--(The spaces after the opening backticks and before the closing-backticks will be ignored.)--The general rule is that a verbatim span starts with a string-of consecutive backticks (optionally followed by a space)-and ends with a string of the same number of backticks (optionally-preceded by a space).--Note that backslash-escapes (and other Markdown constructs) do not-work in verbatim contexts:-- This is a backslash followed by an asterisk: `\*`.--#### Extension: `inline_code_attributes` ####--Attributes can be attached to verbatim text, just as with-[fenced code blocks]:-- `<$>`{.haskell}--### Underline ###--To underline text, use the `underline` class:-- [Underline]{.underline}--Or, without the `bracketed_spans` extension (but with `native_spans`):-- <span class="underline">Underline</span>--This will work in all output formats that support underline.--### Small caps ###--To write small caps, use the `smallcaps` class:-- [Small caps]{.smallcaps}--Or, without the `bracketed_spans` extension:-- <span class="smallcaps">Small caps</span>--For compatibility with other Markdown flavors, CSS is also supported:-- <span style="font-variant:small-caps;">Small caps</span>--This will work in all output formats that support small caps.---## Math--#### Extension: `tex_math_dollars` ####--Anything between two `$` characters will be treated as TeX math. The-opening `$` must have a non-space character immediately to its right,-while the closing `$` must have a non-space character immediately to its-left, and must not be followed immediately by a digit. Thus,-`$20,000 and $30,000` won't parse as math. If for some reason-you need to enclose text in literal `$` characters, backslash-escape-them and they won't be treated as math delimiters.--For display math, use `$$` delimiters. (In this case, the delimiters-may be separated from the formula by whitespace. However, there can be-no blank lines between the opening and closing `$$` delimiters.)--TeX math will be printed in all output formats. How it is rendered-depends on the output format:--LaTeX- ~ It will appear verbatim surrounded by `\(...\)` (for inline- math) or `\[...\]` (for display math).--Markdown, Emacs Org mode, ConTeXt, ZimWiki- ~ It will appear verbatim surrounded by `$...$` (for inline- math) or `$$...$$` (for display math).--XWiki- ~ It will appear verbatim surrounded by `{{formula}}..{{/formula}}`.--reStructuredText- ~ It will be rendered using an [interpreted text role `:math:`].--AsciiDoc- ~ For AsciiDoc output format (`-t asciidoc`) it will appear verbatim- surrounded by `latexmath:[$...$]` (for inline math) or- `[latexmath]++++\[...\]+++` (for display math).- For AsciiDoctor output format (`-t asciidoctor`) the LaTeX delimiters- (`$..$` and `\[..\]`) are omitted.--Texinfo- ~ It will be rendered inside a `@math` command.--roff man, Jira markup- ~ It will be rendered verbatim without `$`'s.--MediaWiki, DokuWiki- ~ It will be rendered inside `<math>` tags.--Textile- ~ It will be rendered inside `<span class="math">` tags.--RTF, OpenDocument- ~ It will be rendered, if possible, using Unicode characters,- and will otherwise appear verbatim.--ODT- ~ It will be rendered, if possible, using MathML.--DocBook- ~ If the `--mathml` flag is used, it will be rendered using MathML- in an `inlineequation` or `informalequation` tag. Otherwise it- will be rendered, if possible, using Unicode characters.--Docx and PowerPoint- ~ It will be rendered using OMML math markup.--FictionBook2- ~ If the `--webtex` option is used, formulas are rendered as images- using CodeCogs or other compatible web service, downloaded- and embedded in the e-book. Otherwise, they will appear verbatim.--HTML, Slidy, DZSlides, S5, EPUB- ~ The way math is rendered in HTML will depend on the- command-line options selected. Therefore see [Math rendering in HTML]- above.--[interpreted text role `:math:`]: https://docutils.sourceforge.io/docs/ref/rst/roles.html#math--## Raw HTML--#### Extension: `raw_html` ####--Markdown allows you to insert raw HTML (or DocBook) anywhere in a document-(except verbatim contexts, where `<`, `>`, and `&` are interpreted-literally). (Technically this is not an extension, since standard-Markdown allows it, but it has been made an extension so that it can-be disabled if desired.)--The raw HTML is passed through unchanged in HTML, S5, Slidy, Slideous,-DZSlides, EPUB, Markdown, CommonMark, Emacs Org mode, and Textile-output, and suppressed in other formats.--For a more explicit way of including raw HTML in a Markdown-document, see the [`raw_attribute` extension][Extension: `raw_attribute`].--In the CommonMark format, if `raw_html` is enabled, superscripts,-subscripts, strikeouts and small capitals will be represented as HTML.-Otherwise, plain-text fallbacks will be used. Note that even if-`raw_html` is disabled, tables will be rendered with HTML syntax if-they cannot use pipe syntax.--#### Extension: `markdown_in_html_blocks` ####--Original Markdown allows you to include HTML "blocks": blocks-of HTML between balanced tags that are separated from the surrounding text-with blank lines, and start and end at the left margin. Within-these blocks, everything is interpreted as HTML, not Markdown;-so (for example), `*` does not signify emphasis.--Pandoc behaves this way when the `markdown_strict` format is used; but-by default, pandoc interprets material between HTML block tags as Markdown.-Thus, for example, pandoc will turn-- <table>- <tr>- <td>*one*</td>- <td>[a link](https://google.com)</td>- </tr>- </table>--into-- <table>- <tr>- <td><em>one</em></td>- <td><a href="https://google.com">a link</a></td>- </tr>- </table>--whereas `Markdown.pl` will preserve it as is.--There is one exception to this rule: text between `<script>`,-`<style>`, and `<textarea>` tags is not interpreted as Markdown.--This departure from original Markdown should make it easier to mix-Markdown with HTML block elements. For example, one can surround-a block of Markdown text with `<div>` tags without preventing it-from being interpreted as Markdown.--#### Extension: `native_divs` ####--Use native pandoc `Div` blocks for content inside `<div>` tags.-For the most part this should give the same output as-`markdown_in_html_blocks`, but it makes it easier to write pandoc-filters to manipulate groups of blocks.--#### Extension: `native_spans` ####--Use native pandoc `Span` blocks for content inside `<span>` tags.-For the most part this should give the same output as `raw_html`,-but it makes it easier to write pandoc filters to manipulate groups-of inlines.--#### Extension: `raw_tex` ####--In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be-included in a document. Inline TeX commands will be preserved and passed-unchanged to the LaTeX and ConTeXt writers. Thus, for example, you can use-LaTeX to include BibTeX citations:-- This result was proved in \cite{jones.1967}.--Note that in LaTeX environments, like-- \begin{tabular}{|l|l|}\hline- Age & Frequency \\ \hline- 18--25 & 15 \\- 26--35 & 33 \\- 36--45 & 22 \\ \hline- \end{tabular}--the material between the begin and end tags will be interpreted as raw-LaTeX, not as Markdown.--For a more explicit and flexible way of including raw TeX in a-Markdown document, see the [`raw_attribute`-extension][Extension: `raw_attribute`].--Inline LaTeX is ignored in output formats other than Markdown, LaTeX,-Emacs Org mode, and ConTeXt.--### Generic raw attribute ###--#### Extension: `raw_attribute` ####--Inline spans and fenced code blocks with a special-kind of attribute will be parsed as raw content with the-designated format. For example, the following produces a raw-roff `ms` block:-- ```{=ms}- .MYMACRO- blah blah- ```-And the following produces a raw `html` inline element:-- This is `<a>html</a>`{=html}--This can be useful to insert raw xml into `docx` documents, e.g.-a pagebreak:-- ```{=openxml}- <w:p>- <w:r>- <w:br w:type="page"/>- </w:r>- </w:p>- ```--The format name should match the target format name (see-`-t/--to`, above, for a list, or use `pandoc---list-output-formats`). Use `openxml` for `docx` output,-`opendocument` for `odt` output, `html5` for `epub3` output,-`html4` for `epub2` output, and `latex`, `beamer`,-`ms`, or `html5` for `pdf` output (depending on what you-use for `--pdf-engine`).--This extension presupposes that the relevant kind of-inline code or fenced code block is enabled. Thus, for-example, to use a raw attribute with a backtick code block,-`backtick_code_blocks` must be enabled.--The raw attribute cannot be combined with regular attributes.--## LaTeX macros--#### Extension: `latex_macros` ####--When this extension is enabled, pandoc will parse LaTeX-macro definitions and apply the resulting macros to all LaTeX-math and raw LaTeX. So, for example, the following will work in-all output formats, not just LaTeX:-- \newcommand{\tuple}[1]{\langle #1 \rangle}-- $\tuple{a, b, c}$--Note that LaTeX macros will not be applied if they occur-inside a raw span or block marked with the-[`raw_attribute` extension](#extension-raw_attribute).--When `latex_macros` is disabled, the raw LaTeX and math will-not have macros applied. This is usually a better approach when-you are targeting LaTeX or PDF.--Macro definitions in LaTeX will be passed through as raw LaTeX-only if `latex_macros` is not enabled. Macro definitions in-Markdown source (or other formats allowing `raw_tex`) will-be passed through regardless of whether `latex_macros` is-enabled.--## Links--Markdown allows links to be specified in several ways.--### Automatic links ###--If you enclose a URL or email address in pointy brackets, it-will become a link:-- <https://google.com>- <sam@green.eggs.ham>--### Inline links ###--An inline link consists of the link text in square brackets,-followed by the URL in parentheses. (Optionally, the URL can-be followed by a link title, in quotes.)-- This is an [inline link](/url), and here's [one with- a title](https://fsf.org "click here for a good time!").--There can be no space between the bracketed part and the parenthesized part.-The link text can contain formatting (such as emphasis), but the title cannot.--Email addresses in inline links are not autodetected, so they have to be-prefixed with `mailto`:-- [Write me!](mailto:sam@green.eggs.ham)--### Reference links ###--An *explicit* reference link has two parts, the link itself and the link-definition, which may occur elsewhere in the document (either-before or after the link).--The link consists of link text in square brackets, followed by a label in-square brackets. (There cannot be space between the two unless the-`spaced_reference_links` extension is enabled.) The link definition-consists of the bracketed label, followed by a colon and a space, followed by-the URL, and optionally (after a space) a link title either in quotes or in-parentheses. The label must not be parseable as a citation (assuming-the `citations` extension is enabled): citations take precedence over-link labels.--Here are some examples:-- [my label 1]: /foo/bar.html "My title, optional"- [my label 2]: /foo- [my label 3]: https://fsf.org (The Free Software Foundation)- [my label 4]: /bar#special 'A title in single quotes'--The URL may optionally be surrounded by angle brackets:-- [my label 5]: <http://foo.bar.baz>--The title may go on the next line:-- [my label 3]: https://fsf.org- "The Free Software Foundation"--Note that link labels are not case sensitive. So, this will work:-- Here is [my link][FOO]-- [Foo]: /bar/baz--In an *implicit* reference link, the second pair of brackets is-empty:-- See [my website][].-- [my website]: http://foo.bar.baz--Note: In `Markdown.pl` and most other Markdown implementations,-reference link definitions cannot occur in nested constructions-such as list items or block quotes. Pandoc lifts this-arbitrary-seeming restriction. So the following is fine in pandoc,-though not in most other implementations:-- > My block [quote].- >- > [quote]: /foo--#### Extension: `shortcut_reference_links` ####--In a *shortcut* reference link, the second pair of brackets may-be omitted entirely:-- See [my website].-- [my website]: http://foo.bar.baz--### Internal links ###--To link to another section of the same document, use the automatically-generated identifier (see [Heading identifiers]). For example:-- See the [Introduction](#introduction).--or-- See the [Introduction].-- [Introduction]: #introduction--Internal links are currently supported for HTML formats (including-HTML slide shows and EPUB), LaTeX, and ConTeXt.--## Images--A link immediately preceded by a `!` will be treated as an image.-The link text will be used as the image's alt text:-- -- ![movie reel]-- [movie reel]: movie.gif--#### Extension: `implicit_figures` ####--An image with nonempty alt text, occurring by itself in a-paragraph, will be rendered as a figure with a caption. The-image's alt text will be used as the caption.-- --How this is rendered depends on the output format. Some output-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.--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:-- \--Note that in reveal.js slide shows, an image in a paragraph-by itself that has the `r-stretch` class will fill the screen,-and the caption and figure tags will be omitted.--#### Extension: `link_attributes` ####--Attributes can be set on links and images:-- An inline {#id .class width=30 height=20px}- and a reference ![image][ref] with attributes.-- [ref]: foo.jpg "optional title" {#id .class key=val key2="val 2"}--(This syntax is compatible with [PHP Markdown Extra] when only `#id`-and `.class` are used.)--For HTML and EPUB, all known HTML5 attributes except `width` and-`height` (but including `srcset` and `sizes`) are passed through-as is. Unknown attributes are passed through as custom-attributes, with `data-` prepended. The other writers ignore-attributes that are not specifically supported by their output format.--The `width` and `height` attributes on images are treated specially. When-used without a unit, the unit is assumed to be pixels. However, any of-the following unit identifiers can be used: `px`, `cm`, `mm`, `in`, `inch`-and `%`. There must not be any spaces between the number and the unit.-For example:--```-{ width=50% }-```--- Dimensions may be converted to a form that is compatible with- the output format (for example, dimensions given in pixels will- be converted to inches when converting HTML to LaTeX). Conversion- between pixels and physical measurements is affected by the- `--dpi` option (by default, 96 dpi is assumed, unless the image- itself contains dpi information).-- The `%` unit is generally relative to some available space.- For example the above example will render to the following.- - HTML: `<img href="file.jpg" style="width: 50%;" />`- - LaTeX: `\includegraphics[width=0.5\textwidth,height=\textheight]{file.jpg}`- (If you're using a custom template, you need to configure `graphicx`- as in the default template.)- - ConTeXt: `\externalfigure[file.jpg][width=0.5\textwidth]`-- Some output formats have a notion of a class- ([ConTeXt](https://wiki.contextgarden.net/Using_Graphics#Multiple_Image_Settings))- or a unique identifier (LaTeX `\caption`), or both (HTML).-- When no `width` or `height` attributes are specified, the fallback- is to look at the image resolution and the dpi metadata embedded in- the image file.--## Divs and Spans--Using the `native_divs` and `native_spans` extensions-(see [above][Extension: `native_divs`]), HTML syntax can-be used as part of markdown to create native `Div` and `Span`-elements in the pandoc AST (as opposed to raw HTML).-However, there is also nicer syntax available:--#### Extension: `fenced_divs` ####--Allow special fenced syntax for native `Div` blocks. A Div-starts with a fence containing at least three consecutive-colons plus some attributes. The attributes may optionally-be followed by another string of consecutive colons.-The attribute syntax is exactly as in fenced code blocks (see-[Extension: `fenced_code_attributes`]). As with fenced-code blocks, one can use either attributes in curly braces-or a single unbraced word, which will be treated as a class-name. The Div ends with another line containing a string of at-least three consecutive colons. The fenced Div should be-separated by blank lines from preceding and following blocks.--Example:-- ::::: {#special .sidebar}- Here is a paragraph.-- And another.- :::::--Fenced divs can be nested. Opening fences are distinguished-because they *must* have attributes:-- ::: Warning ::::::- This is a warning.-- ::: Danger- This is a warning within a warning.- :::- ::::::::::::::::::--Fences without attributes are always closing fences. Unlike-with fenced code blocks, the number of colons in the closing-fence need not match the number in the opening fence. However,-it can be helpful for visual clarity to use fences of different-lengths to distinguish nested divs from their parents.---#### Extension: `bracketed_spans` ####--A bracketed sequence of inlines, as one would use to begin-a link, will be treated as a `Span` with attributes if it is-followed immediately by attributes:-- [This is *some text*]{.class key="val"}--## Footnotes--#### Extension: `footnotes` ####--Pandoc's Markdown allows footnotes, using the following syntax:-- Here is a footnote reference,[^1] and another.[^longnote]-- [^1]: Here is the footnote.-- [^longnote]: Here's one with multiple blocks.-- Subsequent paragraphs are indented to show that they- belong to the previous footnote.-- { some.code }-- The whole paragraph can be indented, or just the first- line. In this way, multi-paragraph footnotes work like- multi-paragraph list items.-- This paragraph won't be part of the note, because it- isn't indented.--The identifiers in footnote references may not contain spaces, tabs,-or newlines. These identifiers are used only to correlate the-footnote reference with the note itself; in the output, footnotes-will be numbered sequentially.--The footnotes themselves need not be placed at the end of the-document. They may appear anywhere except inside other block elements-(lists, block quotes, tables, etc.). Each footnote should be-separated from surrounding content (including other footnotes)-by blank lines.--#### Extension: `inline_notes` ####--Inline footnotes are also allowed (though, unlike regular notes,-they cannot contain multiple paragraphs). The syntax is as follows:-- Here is an inline note.^[Inline notes are easier to write, since- you don't have to pick an identifier and move down to type the- note.]--Inline and regular footnotes may be mixed freely.--## Citation syntax--#### Extension: `citations` ####--To cite a bibliographic item with an identifier foo, use the-syntax `@foo`. Normal citations should be included in square-brackets, with semicolons separating distinct items:-- Blah blah [@doe99; @smith2000; @smith2004].--How this is rendered depends on the citation style. In an-author-date style, it might render as-- Blah blah (Doe 1999, Smith 2000, 2004).--In a footnote style, it might render as-- Blah blah.[^1]-- [^1]: John Doe, "Frogs," *Journal of Amphibians* 44 (1999);- Susan Smith, "Flies," *Journal of Insects* (2000);- Susan Smith, "Bees," *Journal of Insects* (2004).--See the [CSL user documentation] for more information about CSL-styles and how they affect rendering.--Unless a citation key starts with a letter, digit, or `_`,-and contains only alphanumerics and single internal punctuation-characters (`:.#$%&-+?<>~/`), it must be surrounded-by curly braces, which are not considered part of the key.-In `@Foo_bar.baz.`, the key is `Foo_bar.baz` because the final-period is not *internal* punctuation, so it is not included in-the key. In `@{Foo_bar.baz.}`, the key is `Foo_bar.baz.`, including-the final period.-In `@Foo_bar--baz`, the key is `Foo_bar` because the repeated internal-punctuation characters terminate the key.-The curly braces are recommended if you use URLs as-keys: `[@{https://example.com/bib?name=foobar&date=2000}, p. 33]`.--Citation items may optionally include a prefix, a locator, and-a suffix. In-- Blah blah [see @doe99, pp. 33-35 and *passim*; @smith04, chap. 1].--the first item (`doe99`) has prefix `see `, locator `pp. 33-35`,-and suffix `and *passim*`. The second item (`smith04`) has-locator `chap. 1` and no prefix or suffix.--Pandoc uses some heuristics to separate the locator from the-rest of the subject. It is sensitive to the locator terms-defined in the [CSL locale files]. Either abbreviated or-unabbreviated forms are accepted. In the `en-US` locale, locator-terms can be written in either singular or plural forms, as-`book`, `bk.`/`bks.`; `chapter`, `chap.`/`chaps.`; `column`,-`col.`/`cols.`; `figure`, `fig.`/`figs.`; `folio`,-`fol.`/`fols.`; `number`, `no.`/`nos.`; `line`, `l.`/`ll.`;-`note`, `n.`/`nn.`; `opus`, `op.`/`opp.`; `page`, `p.`/`pp.`;-`paragraph`, `para.`/`paras.`; `part`, `pt.`/`pts.`; `section`,-`sec.`/`secs.`; `sub verbo`, `s.v.`/`s.vv.`; `verse`,-`v.`/`vv.`; `volume`, `vol.`/`vols.`; `¶`/`¶¶`; `§`/`§§`. If no-locator term is used, "page" is assumed.--In complex cases, you can force something to be treated as-a locator by enclosing it in curly braces or prevent parsing-the suffix as locator by prepending curly braces:-- [@smith{ii, A, D-Z}, with a suffix]- [@smith, {pp. iv, vi-xi, (xv)-(xvii)} with suffix here]- [@smith{}, 99 years later]--A minus sign (`-`) before the `@` will suppress mention of-the author in the citation. This can be useful when the-author is already mentioned in the text:-- Smith says blah [-@smith04].--You can also write an author-in-text citation, by omitting the-square brackets:-- @smith04 says blah.-- @smith04 [p. 33] says blah.--This will cause the author's name to be rendered, followed by-the bibliographical details. Use this form when you want to-make the citation the subject of a sentence.--When you are using a note style, it is usually better to let-citeproc create the footnotes from citations rather than writing-an explicit note. If you do write an explicit note that-contains a citation, note that normal citations will be put in-parentheses, while author-in-text citations will not. For-this reason, it is sometimes preferable to use the-author-in-text style inside notes when using a note style.--[CSL user documentation]: https://citationstyles.org/authors/-[CSL]: https://docs.citationstyles.org/en/stable/specification.html-[CSL markup specs]: https://docs.citationstyles.org/en/1.0/release-notes.html#rich-text-markup-within-fields-[Chicago Manual of Style]: https://chicagomanualofstyle.org-[Citation Style Language]: https://citationstyles.org-[Zotero Style Repository]: https://www.zotero.org/styles-[finding and editing styles]: https://citationstyles.org/authors/-[CSL locale files]: https://github.com/citation-style-language/locales--## Non-default extensions--The following Markdown syntax extensions are not enabled by default-in pandoc, but may be enabled by adding `+EXTENSION` to the format-name, where `EXTENSION` is the name of the extension. Thus, for-example, `markdown+hard_line_breaks` is Markdown with hard line breaks.--#### Extension: `rebase_relative_paths` ####--Rewrite relative paths for Markdown links and images, depending-on the path of the file containing the link or image link. For-each link or image, pandoc will compute the directory of the-containing file, relative to the working directory, and prepend-the resulting path to the link or image path.--The use of this extension is best understood by example.-Suppose you have a subdirectory for each chapter of a book,-`chap1`, `chap2`, `chap3`. Each contains a file `text.md` and a-number of images used in the chapter. You would like to have-`` in `chap1/text.md` refer to-`chap1/spider.jpg` and `` in `chap2/text.md`-refer to `chap2/spider.jpg`. To do this, use-- pandoc chap*/*.md -f markdown+rebase_relative_paths--Without this extension, you would have to use-`` in `chap1/text.md` and-`` in `chap2/text.md`. Links with-relative paths will be rewritten in the same way as images.--Absolute paths and URLs are not changed. Neither are empty-paths or paths consisting entirely of a fragment, e.g., `#foo`.--Note that relative paths in reference links and images will-be rewritten relative to the file containing the link-reference definition, not the file containing the reference link-or image itself, if these differ.--#### Extension: `attributes` ####--Allows attributes to be attached to any inline or block-level-element when parsing `commonmark`.-The syntax for the attributes is the same as that-used in [`header_attributes`][Extension: `header_attributes`].--- Attributes that occur immediately after an inline- element affect that element. If they follow a space, then they- belong to the space. (Hence, this option subsumes- `inline_code_attributes` and `link_attributes`.)-- Attributes that occur immediately before a block- element, on a line by themselves, affect that- element.-- Consecutive attribute specifiers may be used,- either for blocks or for inlines. Their attributes- will be combined.-- Attributes that occur at the end of the text of- a Setext or ATX heading (separated by whitespace- from the text) affect the heading element. (Hence, this- option subsumes `header_attributes`.)-- Attributes that occur after the opening fence- in a fenced code block affect the code block element. (Hence,- this option subsumes `fenced_code_attributes`.)-- Attributes that occur at the end of a reference- link definition affect links that refer to that- definition.--Note that pandoc's AST does not currently allow attributes-to be attached to arbitrary elements. Hence a Span or Div-container will be added if needed.--#### Extension: `old_dashes` ####--Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes:-`-` before a numeral is an en-dash, and `--` is an em-dash.-This option only has an effect if `smart` is enabled. It is-selected automatically for `textile` input.--#### Extension: `angle_brackets_escapable` ####--Allow `<` and `>` to be backslash-escaped, as they can be in-GitHub flavored Markdown but not original Markdown. This is-implied by pandoc's default `all_symbols_escapable`.--#### Extension: `lists_without_preceding_blankline` ####--Allow a list to occur right after a paragraph, with no intervening-blank space.--#### Extension: `four_space_rule` ####--Selects the pandoc <= 2.0 behavior for parsing lists, so that-four spaces indent are needed for list item continuation-paragraphs.--#### Extension: `spaced_reference_links` ####--Allow whitespace between the two components of a reference link,-for example,-- [foo] [bar].--#### Extension: `hard_line_breaks` ####--Causes all newlines within a paragraph to be interpreted as hard line-breaks instead of spaces.--#### Extension: `ignore_line_breaks` ####--Causes newlines within a paragraph to be ignored, rather than being-treated as spaces or as hard line breaks. This option is intended for-use with East Asian languages where spaces are not used between words,-but text is divided into lines for readability.--#### Extension: `east_asian_line_breaks` ####--Causes newlines within a paragraph to be ignored, rather than-being treated as spaces or as hard line breaks, when they occur-between two East Asian wide characters. This is a better choice-than `ignore_line_breaks` for texts that include a mix of East-Asian wide characters and other characters.--#### Extension: `emoji` ####--Parses textual emojis like `:smile:` as Unicode emoticons.--#### Extension: `tex_math_single_backslash` ####--Causes anything between `\(` and `\)` to be interpreted as inline-TeX math, and anything between `\[` and `\]` to be interpreted-as display TeX math. Note: a drawback of this extension is that-it precludes escaping `(` and `[`.--#### Extension: `tex_math_double_backslash` ####--Causes anything between `\\(` and `\\)` to be interpreted as inline-TeX math, and anything between `\\[` and `\\]` to be interpreted-as display TeX math.--#### Extension: `markdown_attribute` ####--By default, pandoc interprets material inside block-level tags as Markdown.-This extension changes the behavior so that Markdown is only parsed-inside block-level tags if the tags have the attribute `markdown=1`.--#### Extension: `mmd_title_block` ####--Enables a [MultiMarkdown] style title block at the top of-the document, for example:-- Title: My title- Author: John Doe- Date: September 1, 2008- Comment: This is a sample mmd title block, with- a field spanning multiple lines.--See the MultiMarkdown documentation for details. If `pandoc_title_block` or-`yaml_metadata_block` is enabled, it will take precedence over-`mmd_title_block`.--#### Extension: `abbreviations` ####--Parses PHP Markdown Extra abbreviation keys, like-- *[HTML]: Hypertext Markup Language--Note that the pandoc document model does not support-abbreviations, so if this extension is enabled, abbreviation keys are-simply skipped (as opposed to being parsed as paragraphs).--#### Extension: `autolink_bare_uris` ####--Makes all absolute URIs into links, even when not surrounded by-pointy braces `<...>`.--#### Extension: `mmd_link_attributes` ####--Parses multimarkdown style key-value attributes on link-and image references. This extension should not be confused with the-[`link_attributes`](#extension-link_attributes) extension.-- This is a reference ![image][ref] with multimarkdown attributes.-- [ref]: https://path.to/image "Image title" width=20px height=30px- id=myId class="myClass1 myClass2"--#### Extension: `mmd_header_identifiers` ####--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:-all-caps for strong emphasis, surround by underscores-for regular emphasis, add extra blank space around headings.-- [Project Gutenberg]: https://www.gutenberg.org--#### Extension: `sourcepos` ####--Include source position attributes when parsing `commonmark`.-For elements that accept attributes, a `data-pos` attribute-is added; other elements are placed in a surrounding-Div or Span element with a `data-pos` attribute.--#### Extension: `short_subsuperscripts` ####--Parse multimarkdown style subscripts and superscripts, which start with-a '~' or '^' character, respectively, and include the alphanumeric sequence-that follows. For example:-- x^2 = 4--or-- Oxygen is O~2.--## Markdown variants--In addition to pandoc's extended Markdown, the following Markdown-variants are supported:--- `markdown_phpextra` (PHP Markdown Extra)-- `markdown_github` (deprecated GitHub-Flavored Markdown)-- `markdown_mmd` (MultiMarkdown)-- `markdown_strict` (Markdown.pl)-- `commonmark` (CommonMark)-- `gfm` (Github-Flavored Markdown)-- `commonmark_x` (CommonMark with many pandoc extensions)--To see which extensions are supported for a given format,-and which are enabled by default, you can use the command-- pandoc --list-extensions=FORMAT--where `FORMAT` is replaced with the name of the format.--Note that the list of extensions for `commonmark`,-`gfm`, and `commonmark_x` are defined relative to default-commonmark. So, for example, `backtick_code_blocks`-does not appear as an extension, since it is enabled by-default and cannot be disabled.--# Citations--When the `--citeproc` option is used, pandoc can automatically generate-citations and a bibliography in a number of styles. Basic usage is-- pandoc --citeproc myinput.txt--To use this feature, you will need to have--- a document containing citations (see [Extension: `citations`]);-- a source of bibliographic data: either an external bibliography- file or a list of `references` in the document's YAML metadata;-- optionally, a [CSL] citation style.--## Specifying bibliographic data--You can specify an external bibliography using the-`bibliography` metadata field in a YAML metadata section or the-`--bibliography` command line argument. If you want to use-multiple bibliography files, you can supply multiple-`--bibliography` arguments or set `bibliography` metadata field-to YAML array. A bibliography may have any of these formats:-- Format File extension- ------------ --------------- BibLaTeX .bib- BibTeX .bibtex- CSL JSON .json- CSL YAML .yaml- RIS .ris--Note that `.bib` can be used with both BibTeX and BibLaTeX files;-use the extension `.bibtex` to force interpretation as BibTeX.--In BibTeX and BibLaTeX databases, pandoc parses LaTeX markup-inside fields such as `title`; in CSL YAML databases, pandoc-Markdown; and in CSL JSON databases, an [HTML-like markup][CSL-markup specs]:--`<i>...</i>`-: italics--`<b>...</b>`-: bold--`<span style="font-variant:small-caps;">...</span>` or `<sc>...</sc>`-: small capitals--`<sub>...</sub>`-: subscript--`<sup>...</sup>`-: superscript--`<span class="nocase">...</span>`-: prevent a phrase from being capitalized as title case--As an alternative to specifying a bibliography file using-`--bibliography` or the YAML metadata field `bibliography`, you-can include the citation data directly in the `references` field-of the document's YAML metadata. The field should contain an-array of YAML-encoded references, for example:-- ---- references:- - type: article-journal- id: WatsonCrick1953- author:- - family: Watson- given: J. D.- - family: Crick- given: F. H. C.- issued:- date-parts:- - - 1953- - 4- - 25- title: 'Molecular structure of nucleic acids: a structure for- deoxyribose nucleic acid'- title-short: Molecular structure of nucleic acids- container-title: Nature- volume: 171- issue: 4356- page: 737-738- DOI: 10.1038/171737a0- URL: https://www.nature.com/articles/171737a0- language: en-GB- ...--If both an external bibliography and inline (YAML metadata)-references are provided, both will be used. In case of-conflicting `id`s, the inline references will take precedence.--Note that pandoc can be used to produce such a YAML metadata-section from a BibTeX, BibLaTeX, or CSL JSON bibliography:-- pandoc chem.bib -s -f biblatex -t markdown- pandoc chem.json -s -f csljson -t markdown--Indeed, pandoc can convert between any of these-citation formats:-- pandoc chem.bib -s -f biblatex -t csljson- pandoc chem.yaml -s -f markdown -t biblatex--Running pandoc on a bibliography file with the `--citeproc`-option will create a formatted bibliography in the format-of your choice:-- pandoc chem.bib -s --citeproc -o chem.html- pandoc chem.bib -s --citeproc -o chem.pdf--### Capitalization in titles--If you are using a bibtex or biblatex bibliography, then observe-the following rules:-- - English titles should be in title case. Non-English titles should- be in sentence case, and the `langid` field in biblatex should be- set to the relevant language. (The following values are treated- as English: `american`, `british`, `canadian`, `english`,- `australian`, `newzealand`, `USenglish`, or `UKenglish`.)-- - As is standard with bibtex/biblatex, proper names should be- protected with curly braces so that they won't be lowercased- in styles that call for sentence case. For example:-- title = {My Dinner with {Andre}}-- - In addition, words that should remain lowercase (or camelCase)- should be protected:-- title = {Spin Wave Dispersion on the {nm} Scale}-- Though this is not necessary in bibtex/biblatex, it is necessary- with citeproc, which stores titles internally in sentence case,- and converts to title case in styles that require it. Here we- protect "nm" so that it doesn't get converted to "Nm" at this stage.--If you are using a CSL bibliography (either JSON or YAML), then observe-the following rules:-- - All titles should be in sentence case.-- - Use the `language` field for non-English titles to prevent their- conversion to title case in styles that call for this. (Conversion- happens only if `language` begins with `en` or is left empty.)-- - Protect words that should not be converted to title case using- this syntax:-- Spin wave dispersion on the <span class="nocase">nm</span> scale--### Conference Papers, Published vs. Unpublished--For a formally published conference paper, use the biblatex entry type-`inproceedings` (which will be mapped to CSL `paper-conference`).--For an unpublished manuscript, use the biblatex entry type-`unpublished` without an `eventtitle` field (this entry type-will be mapped to CSL `manuscript`).--For a talk, an unpublished conference paper, or a poster-presentation, use the biblatex entry type `unpublished` with an-`eventtitle` field (this entry type will be mapped to CSL-`speech`). Use the biblatex `type` field to indicate the type,-e.g. "Paper", or "Poster". `venue` and `eventdate` may be useful-too, though `eventdate` will not be rendered by most CSL styles.-Note that `venue` is for the event's venue, unlike `location`-which describes the publisher's location; do not use the latter-for an unpublished conference paper.---## Specifying a citation style--Citations and references can be formatted using any style supported by the-[Citation Style Language], listed in the [Zotero Style Repository].-These files are specified using the `--csl` option or the `csl`-(or `citation-style`) metadata field. By default, pandoc will-use the [Chicago Manual of Style] author-date format. (You can-override this default by copying a CSL style of your choice-to `default.csl` in your user data directory.)-The CSL project provides further information on [finding and-editing styles].--The `--citation-abbreviations` option (or the-`citation-abbreviations` metadata field) may be used to specify-a JSON file containing abbreviations of journals that should be-used in formatted bibliographies when `form="short"` is-specified. The format of the file can be illustrated with an-example:--- { "default": {- "container-title": {- "Lloyd's Law Reports": "Lloyd's Rep",- "Estates Gazette": "EG",- "Scots Law Times": "SLT"- }- }- }---## Citations in note styles--Pandoc's citation processing is designed to allow you to-move between author-date, numerical, and note styles without-modifying the markdown source. When you're using a note-style, avoid inserting footnotes manually. Instead, insert-citations just as you would in an author-date style---for-example,-- Blah blah [@foo, p. 33].--The footnote will be created automatically. Pandoc will take-care of removing the space and moving the note before or-after the period, depending on the setting of-`notes-after-punctuation`, as described below in [Other relevant-metadata fields].--In some cases you may need to put a citation inside a regular-footnote. Normal citations in footnotes (such as `[@foo, p.-33]`) will be rendered in parentheses. In-text citations (such-as `@foo [p. 33]`) will be rendered without parentheses. (A-comma will be added if appropriate.) Thus:-- [^1]: Some studies [@foo; @bar, p. 33] show that- frubulicious zoosnaps are quantical. For a survey- of the literature, see @baz [chap. 1].--## Raw content in a style--To include raw content in a prefix, suffix, delimiter, or term,-surround it with these tags indicating the format:-- {{jats}}<ref>{{/jats}}--Without the tags, the string will be interpreted as a string-and escaped in the output, rather than being passed through raw.--This feature allows stylesheets to be customized to give-different output for different output formats. However,-stylesheets customized in this way will not be usable-by other CSL implementations.----## 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:-- ::: {#refs}- :::--Otherwise, it will be placed at the end of the document.-Generation of the bibliography can be suppressed by setting-`suppress-bibliography: true` in the YAML metadata.--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)-or at the end of your document:-- last paragraph...-- # References--The bibliography will be inserted after this heading. Note that-the `unnumbered` class will be added to this heading, so that the-section will not be numbered.--If you want to put the bibliography into a variable in your-template, one way to do that is to put the div with id `refs`-into a metadata field, e.g.-- ---- refs: |- ::: {#refs}- :::- ...--You can then put the variable `$refs$` into your template where-you want the bibliography to be placed.--## Including uncited items in the bibliography--If you want to include items in the bibliography without actually-citing them in the body text, you can define a dummy `nocite` metadata-field and put the citations there:-- ---- nocite: |- @item1, @item2- ...-- @item3--In this example, the document will contain a citation for `item3`-only, but the bibliography will contain entries for `item1`, `item2`, and-`item3`.--It is possible to create a bibliography with all the citations,-whether or not they appear in the document, by using a wildcard:-- ---- nocite: |- @*- ...--For LaTeX output, you can also use [`natbib`] or [`biblatex`] to-render the bibliography. In order to do so, specify bibliography-files as outlined above, and add `--natbib` or `--biblatex`-argument to pandoc invocation. Bear in mind that bibliography-files have to be in either BibTeX (for `--natbib`)-or BibLaTeX (for `--biblatex`) format.--## Other relevant metadata fields--A few other metadata fields affect bibliography formatting:--`link-citations`-: If true, citations will be hyperlinked to the- corresponding bibliography entries (for author-date and- numerical styles only). Defaults to false.--`link-bibliography`-: If true, DOIs, PMCIDs, PMID, and URLs in bibliographies will- be rendered as hyperlinks. (If an entry contains a DOI, PMCID,- PMID, or URL, but none of these fields are rendered by the style,- then the title, or in the absence of a title the whole entry, will- be hyperlinked.) Defaults to true.--`lang`-: The `lang` field will affect how the style is localized,- for example in the translation of labels, the use- of quotation marks, and the way items are sorted.- (For backwards compatibility, `locale` may be used instead- of `lang`, but this use is deprecated.)-- A BCP 47 language tag is expected: for example, `en`,- `de`, `en-US`, `fr-CA`, `ug-Cyrl`. The unicode extension- syntax (after `-u-`) may be used to specify options for- collation (sorting) more precisely. Here are some examples:-- - `zh-u-co-pinyin` -- Chinese with the Pinyin collation.- - `es-u-co-trad` -- Spanish with the traditional collation- (with `Ch` sorting after `C`).- - `fr-u-kb` -- French with "backwards" accent sorting- (with `coté` sorting after `côte`).- - `en-US-u-kf-upper` -- English with uppercase letters sorting- before lower (default is lower before upper).--`notes-after-punctuation`-: If true (the default for note styles), pandoc will put- footnote references or superscripted numerical citations- after following punctuation. For example, if the source- contains `blah blah [@jones99].`, the result will look like- `blah blah.[^1]`, with the note moved after the period and- the space collapsed. If false, the space will still be- collapsed, but the footnote will not be moved after the- punctuation. The option may also be used in numerical styles- that use superscripts for citation numbers (but for these- styles the default is not to move the citation).---# Slide shows--You can use pandoc to produce an HTML + JavaScript slide presentation-that can be viewed via a web browser. There are five ways to do this,-using [S5], [DZSlides], [Slidy], [Slideous], or [reveal.js].-You can also produce a PDF slide show using LaTeX [`beamer`], or-slide shows in Microsoft [PowerPoint] format.--Here's the Markdown source for a simple slide show, `habits.txt`:-- % Habits- % John Doe- % March 22, 2005-- # In the morning-- ## Getting up-- - Turn off alarm- - Get out of bed-- ## Breakfast-- - Eat eggs- - Drink coffee-- # In the evening-- ## Dinner-- - Eat spaghetti- - Drink wine-- -------------------- -- ## Going to sleep-- - Get in bed- - Count sheep--To produce an HTML/JavaScript slide show, simply type-- pandoc -t FORMAT -s habits.txt -o habits.html--where `FORMAT` is either `s5`, `slidy`, `slideous`, `dzslides`, or `revealjs`.--For Slidy, Slideous, reveal.js, and S5, the file produced by-pandoc with the `-s/--standalone` option embeds a link to-JavaScript and CSS files, which are assumed to be available at-the relative path `s5/default` (for S5), `slideous` (for-Slideous), `reveal.js` (for reveal.js), or at the Slidy website-at `w3.org` (for Slidy). (These paths can be changed by setting-the `slidy-url`, `slideous-url`, `revealjs-url`, or `s5-url`-variables; see [Variables for HTML slides], above.) For-DZSlides, the (relatively short) JavaScript and CSS are included-in the file by default.--With all HTML slide formats, the `--self-contained` option can-be used to produce a single file that contains all of the data-necessary to display the slide show, including linked scripts,-stylesheets, images, and videos.--To produce a PDF slide show using beamer, type-- pandoc -t beamer habits.txt -o habits.pdf--Note that a reveal.js slide show can also be converted to a PDF-by printing it to a file from the browser.--To produce a PowerPoint slide show, type-- pandoc habits.txt -o habits.pptx--## Structuring the slide show--By default, the *slide level* is the highest heading level in-the hierarchy that is followed immediately by content, and not another-heading, somewhere in the document. In the example above, level-1 headings-are always followed by level-2 headings, which are followed by content,-so the slide level is 2. This default can be overridden using the-`--slide-level` option.--The document is carved up into slides according to the following-rules:-- * A horizontal rule always starts a new slide.-- * A heading at the slide level always starts a new slide.-- * Headings *below* the slide level in the hierarchy create- headings *within* a slide. (In beamer, a "block" will be- created. If the heading has the class `example`, an- `exampleblock` environment will be used; if it has the class- `alert`, an `alertblock` will be used; otherwise a regular- `block` will be used.)-- * Headings *above* the slide level in the hierarchy create- "title slides," which just contain the section title- and help to break the slide show into sections.- Non-slide content under these headings will be included- on the title slide (for HTML slide shows) or in a- subsequent slide with the same title (for beamer).-- * A title page is constructed automatically from the document's title- block, if present. (In the case of beamer, this can be disabled- by commenting out some lines in the default template.)--These rules are designed to support many different styles of slide show. If-you don't care about structuring your slides into sections and subsections,-you can either just use level-1 headings for all slides (in that case, level 1-will be the slide level) or you can set `--slide-level=0`.--Note: in reveal.js slide shows, if slide level is 2, a two-dimensional-layout will be produced, with level-1 headings building horizontally-and level-2 headings building vertically. It is not recommended that-you use deeper nesting of section levels with reveal.js unless you set-`--slide-level=0` (which lets reveal.js produce a one-dimensional layout-and only interprets horizontal rules as slide boundaries).--### PowerPoint layout choice--When creating slides, the pptx writer chooses from a number of pre-defined-layouts, based on the content of the slide:--Title Slide-: This layout is used for the initial slide, which is generated and- filled from the metadata fields `date`, `author`, and `title`, if- they are present.--Section Header-: This layout is used for what pandoc calls “title slides”, i.e.- slides which start with a header which is above the slide level in- the hierarchy.--Two Content-: This layout is used for two-column slides, i.e. slides containing a- div with class `columns` which contains at least two divs with class- `column`.--Comparison-: This layout is used instead of “Two Content” for any two-column- slides in which at least one column contains text followed by- non-text (e.g. an image or a table).--Content with Caption-: This layout is used for any non-two-column slides which contain text- followed by non-text (e.g. an image or a table).--Blank-: This layout is used for any slides which only contain blank content,- e.g. a slide containing only speaker notes, or a slide containing- only a non-breaking space.--Title and Content-: This layout is used for all slides which do not match the criteria- for another layout.--These layouts are chosen from the default pptx reference doc included with-pandoc, unless an alternative reference doc is specified using-`--reference-doc`.--## Incremental lists--By default, these writers produce lists that display "all at once."-If you want your lists to display incrementally (one item at a time),-use the `-i` option. If you want a particular list to depart from the-default, put it in a `div` block with class `incremental` or-`nonincremental`. So, for example, using the `fenced div` syntax, the-following would be incremental regardless of the document default:-- ::: incremental-- - Eat spaghetti- - Drink wine-- :::--or-- ::: nonincremental-- - Eat spaghetti- - Drink wine-- :::--While using `incremental` and `nonincremental` divs is the-recommended method of setting incremental lists on a per-case basis,-an older method is also supported: putting lists inside a blockquote-will depart from the document default (that is, it will display-incrementally without the `-i` option and all at once with the `-i`-option):-- > - Eat spaghetti- > - Drink wine--Both methods allow incremental and nonincremental lists to be mixed-in a single document.--If you want to include a block-quoted list, you can work around-this behavior by putting the list inside a fenced div, so that-it is not the direct child of the block quote:-- > ::: wrapper- > - a- > - list in a quote- > :::--## Inserting pauses--You can add "pauses" within a slide by including a paragraph containing-three dots, separated by spaces:-- # Slide with a pause-- content before the pause-- . . .-- content after the pause--Note: this feature is not yet implemented for PowerPoint output.--## Styling the slides--You can change the style of HTML slides by putting customized CSS files-in `$DATADIR/s5/default` (for S5), `$DATADIR/slidy` (for Slidy),-or `$DATADIR/slideous` (for Slideous),-where `$DATADIR` is the user data directory (see `--data-dir`, above).-The originals may be found in pandoc's system data directory (generally-`$CABALDIR/pandoc-VERSION/s5/default`). Pandoc will look there for any-files it does not find in the user data directory.--For dzslides, the CSS is included in the HTML file itself, and may-be modified there.--All [reveal.js configuration options] can be set through variables.-For example, themes can be used by setting the `theme` variable:-- -V theme=moon--Or you can specify a custom stylesheet using the `--css` option.--To style beamer slides, you can specify a `theme`, `colortheme`,-`fonttheme`, `innertheme`, and `outertheme`, using the `-V` option:-- pandoc -t beamer habits.txt -V theme:Warsaw -o habits.pdf--Note that heading attributes will turn into slide attributes-(on a `<div>` or `<section>`) in HTML slide formats, allowing you-to style individual slides. In beamer, a number of heading-classes and attributes are recognized as frame options and-will be passed through as options to the frame: see-[Frame attributes in beamer], below.--## Speaker notes--Speaker notes are supported in reveal.js, PowerPoint (pptx),-and beamer output. You can add notes to your Markdown document thus:-- ::: notes-- This is my note.-- - It can contain Markdown- - like this list-- :::--To show the notes window in reveal.js, press `s` while viewing the-presentation. Speaker notes in PowerPoint will be available, as usual,-in handouts and presenter view.--Notes are not yet supported for other slide formats, but the notes-will not appear on the slides themselves.--## Columns--To put material in side by side columns, you can use a native-div container with class `columns`, containing two or more div-containers with class `column` and a `width` attribute:-- :::::::::::::: {.columns}- ::: {.column width="40%"}- contents...- :::- ::: {.column width="60%"}- contents...- :::- ::::::::::::::--### Additional columns attributes in beamer--The div containers with classes `columns` and `column` can optionally have-an `align` attribute.-The class `columns` can optionally have a `totalwidth` attribute or an-`onlytextwidth` class.-- :::::::::::::: {.columns align=center totalwidth=8em}- ::: {.column width="40%"}- contents...- :::- ::: {.column width="60%" align=bottom}- contents...- :::- ::::::::::::::--The `align` attributes on `columns` and `column` can be used with the-values `top`, `top-baseline`, `center` and `bottom` to vertically align-the columns. It defaults to `top` in `columns`.--The `totalwidth` attribute limits the width of the columns to the given value.-- :::::::::::::: {.columns align=top .onlytextwidth}- ::: {.column width="40%" align=center}- contents...- :::- ::: {.column width="60%"}- contents...- :::- ::::::::::::::--The class `onlytextwidth` sets the `totalwidth` to `\textwidth`.--See Section 12.7 of the [Beamer User's Guide] for more details.--## Frame attributes in beamer--Sometimes it is necessary to add the LaTeX `[fragile]` option to-a frame in beamer (for example, when using the `minted` environment).-This can be forced by adding the `fragile` class to the heading-introducing the slide:-- # Fragile slide {.fragile}--All of the other frame attributes described in Section 8.1 of-the [Beamer User's Guide] may also be used: `allowdisplaybreaks`,-`allowframebreaks`, `b`, `c`, `s`, `t`, `environment`, `label`, `plain`,-`shrink`, `standout`, `noframenumbering`, `squeeze`.-`allowframebreaks` is recommended especially for bibliographies, as-it allows multiple slides to be created if the content overfills the-frame:-- # References {.allowframebreaks}--In addition, the `frameoptions` attribute may be used to-pass arbitrary frame options to a beamer slide:-- # Heading {frameoptions="squeeze,shrink,customoption=foobar"}--## Background in reveal.js, beamer, and pptx--Background images can be added to self-contained reveal.js slide shows,-beamer slide shows, and pptx slide shows.--### On all slides (beamer, reveal.js, pptx)--With beamer and reveal.js, the configuration option `background-image` can be-used either in the YAML metadata block or as a command-line variable to get the-same image on every slide.--For pptx, you can use a [reference doc](#option--reference-doc) in which-background images have been set on the [relevant-layouts](#powerpoint-layout-choice).--#### `parallaxBackgroundImage` (reveal.js)--For reveal.js, there is also the reveal.js-native option-`parallaxBackgroundImage`, which can be used instead of `background-image` to-produce a parallax scrolling background. You must also set-`parallaxBackgroundSize`, and can optionally set `parallaxBackgroundHorizontal`-and `parallaxBackgroundVertical` to configure the scrolling behaviour. See the-[reveal.js documentation](https://revealjs.com/backgrounds/#parallax-background)-for more details about the meaning of these options.--In reveal.js's overview mode, the parallaxBackgroundImage will show up-only on the first slide.--### On individual slides (reveal.js, pptx)--To set an image for a particular reveal.js or pptx slide, add-`{background-image="/path/to/image"}` to the first slide-level heading on the-slide (which may even be empty).--As the [HTML writers pass unknown attributes-through](#extension-link_attributes), other reveal.js background settings also-work on individual slides, including `background-size`, `background-repeat`,-`background-color`, `transition`, and `transition-speed`. (The `data-` prefix-will automatically be added.)--Note: `data-background-image` is also supported in pptx for consistency with-reveal.js – if `background-image` isn’t found, `data-background-image` will be-checked.--### On the title slide (reveal.js, pptx)--To add a background image to the automatically generated title slide for-reveal.js, use the `title-slide-attributes` variable in the YAML metadata block.-It must contain a map of attribute names and values. (Note that the `data-`-prefix is required here, as it isn’t added automatically.)--For pptx, pass a [reference doc](#option--reference-doc) with the background-image set on the “Title Slide” layout.--### Example (reveal.js)--```-----title: My Slide Show-parallaxBackgroundImage: /path/to/my/background_image.png-title-slide-attributes:- data-background-image: /path/to/title_image.png- data-background-size: contain------## Slide One--Slide 1 has background_image.png as its background.--## {background-image="/path/to/special_image.jpg"}--Slide 2 has a special image for its background, even though the heading has no content.-```--# EPUBs--## EPUB Metadata--EPUB metadata may be specified using the `--epub-metadata` option, but-if the source document is Markdown, it is better to use a [YAML metadata-block][Extension: `yaml_metadata_block`]. Here is an example:-- ---- title:- - type: main- text: My Book- - type: subtitle- text: An investigation of metadata- creator:- - role: author- text: John Smith- - role: editor- text: Sarah Jones- identifier:- - scheme: DOI- text: doi:10.234234.234/33- publisher: My Press- rights: © 2007 John Smith, CC BY-NC- ibooks:- version: 1.3.4- ...--The following fields are recognized:--`identifier`- ~ Either a string value or an object with fields `text` and- `scheme`. Valid values for `scheme` are `ISBN-10`,- `GTIN-13`, `UPC`, `ISMN-10`, `DOI`, `LCCN`, `GTIN-14`,- `ISBN-13`, `Legal deposit number`, `URN`, `OCLC`,- `ISMN-13`, `ISBN-A`, `JP`, `OLCC`.--`title`- ~ Either a string value, or an object with fields `file-as` and- `type`, or a list of such objects. Valid values for `type` are- `main`, `subtitle`, `short`, `collection`, `edition`, `extended`.--`creator`- ~ Either a string value, or an object with fields `role`, `file-as`,- and `text`, or a list of such objects. Valid values for `role` are- [MARC relators], but- pandoc will attempt to translate the human-readable versions- (like "author" and "editor") to the appropriate marc relators.--`contributor`- ~ Same format as `creator`.--`date`- ~ A string value in `YYYY-MM-DD` format. (Only the year is necessary.)- Pandoc will attempt to convert other common date formats.--`lang` (or legacy: `language`)- ~ A string value in [BCP 47] format. Pandoc will default to the local- language if nothing is specified.--`subject`- ~ Either a string value, or an object with fields `text`, `authority`,- and `term`, or a list of such objects. Valid values for `authority`- are either a [reserved authority value] (currently `AAT`, `BIC`,- `BISAC`, `CLC`, `DDC`, `CLIL`, `EuroVoc`, `MEDTOP`, `LCSH`, `NDC`,- `Thema`, `UDC`, and `WGS`) or an absolute IRI identifying a custom- scheme. Valid values for `term` are defined by the scheme.--`description`- ~ A string value.--`type`- ~ A string value.--`format`- ~ A string value.--`relation`- ~ A string value.--`coverage`- ~ A string value.--`rights`- ~ A string value.--`belongs-to-collection`- ~ A string value. Identifies the name of a collection to which- the EPUB Publication belongs.--`group-position`- ~ The `group-position` field indicates the numeric position in which- the EPUB Publication belongs relative to other works belonging to- the same `belongs-to-collection` field.--`cover-image`- ~ A string value (path to cover image).--`css` (or legacy: `stylesheet`)- ~ A string value (path to CSS stylesheet).--`page-progression-direction`- ~ Either `ltr` or `rtl`. Specifies the `page-progression-direction`- attribute for the [`spine` element].--`ibooks`- ~ iBooks-specific metadata, with the following fields:-- - `version`: (string)- - `specified-fonts`: `true`|`false` (default `false`)- - `ipad-orientation-lock`: `portrait-only`|`landscape-only`- - `iphone-orientation-lock`: `portrait-only`|`landscape-only`- - `binding`: `true`|`false` (default `true`)- - `scroll-axis`: `vertical`|`horizontal`|`default`--[MARC relators]: https://loc.gov/marc/relators/relaterm.html-[reserved authority value]: https://idpf.github.io/epub-registries/authorities/-[`spine` element]: http://idpf.org/epub/301/spec/epub-publications.html#sec-spine-elem--## The `epub:type` attribute--For `epub3` output, you can mark up the heading that corresponds to an EPUB-chapter using the [`epub:type` attribute][epub-type]. For example, to set-the attribute to the value `prologue`, use this markdown:-- # My chapter {epub:type=prologue}--Which will result in:-- <body epub:type="frontmatter">- <section epub:type="prologue">- <h1>My chapter</h1>--Pandoc will output `<body epub:type="bodymatter">`, unless-you use one of the following values, in which case either-`frontmatter` or `backmatter` will be output.--`epub:type` of first section `epub:type` of body----------------------------- -------------------prologue frontmatter-abstract frontmatter-acknowledgments frontmatter-copyright-page frontmatter-dedication frontmatter-credits frontmatter-keywords frontmatter-imprint frontmatter-contributors frontmatter-other-credits frontmatter-errata frontmatter-revision-history frontmatter-titlepage frontmatter-halftitlepage frontmatter-seriespage frontmatter-foreword frontmatter-preface frontmatter-frontispiece frontmatter-appendix backmatter-colophon backmatter-bibliography backmatter-index backmatter--[epub-type]: http://www.idpf.org/epub/31/spec/epub-contentdocs.html#sec-epub-type-attribute--## Linked media--By default, pandoc will download media referenced from any `<img>`, `<audio>`,-`<video>` or `<source>` element present in the generated EPUB,-and include it in the EPUB container, yielding a completely-self-contained EPUB. If you want to link to external media resources-instead, use raw HTML in your source and add `data-external="1"` to the tag-with the `src` attribute. For example:-- <audio controls="1">- <source src="https://example.com/music/toccata.mp3"- data-external="1" type="audio/mpeg">- </source>- </audio>--If the input format already is HTML then `data-external="1"` will work-as expected for `<img>` elements. Similarly, for Markdown, external-images can be declared with `{external=1}`. Note that this-only works for images; the other media elements have no native-representation in pandoc's AST and require the use of raw HTML.--## EPUB styling--By default, pandoc will include some basic styling-contained in its `epub.css` data file. (To see this,-use `pandoc --print-default-data-file epub.css`.)-To use a different CSS file, just use the `--css` command-line option. A few inline styles are defined in addition; these-are essential for correct formatting of pandoc's HTML output.--The `document-css` variable may be set if the more opinionated-styling of pandoc's default HTML templates is desired (and-in that case the variables defined in [Variables for HTML] may-be used to fine-tune the style).--# Jupyter notebooks--When creating a [Jupyter notebook], pandoc will try to infer the-notebook structure. Code blocks with the class `code` will be-taken as code cells, and intervening content will be taken as-Markdown cells. Attachments will automatically be created for-images in Markdown cells. Metadata will be taken from the-`jupyter` metadata field. For example:--````-----title: My notebook-jupyter:- nbformat: 4- nbformat_minor: 5- kernelspec:- display_name: Python 2- language: python- name: python2- language_info:- codemirror_mode:- name: ipython- version: 2- file_extension: ".py"- mimetype: "text/x-python"- name: "python"- nbconvert_exporter: "python"- pygments_lexer: "ipython2"- version: "2.7.15"------# Lorem ipsum--**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus-bibendum felis dictum sodales.--``` code-print("hello")-```--## Pyout--``` code-from IPython.display import HTML-HTML("""-<script>-console.log("hello");-</script>-<b>HTML</b>-""")-```--## Image--This image  will be-included as a cell attachment.-````--If you want to add cell attributes, group cells differently, or-add output to code cells, then you need to include divs to-indicate the structure. You can use either [fenced-divs][Extension: `fenced_divs`] or [native divs][Extension:-`native_divs`] for this. Here is an example:--````-:::::: {.cell .markdown}-# Lorem--**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus-bibendum felis dictum sodales.-::::::--:::::: {.cell .code execution_count=1}-``` {.python}-print("hello")-```--::: {.output .stream .stdout}-```-hello-```-:::-::::::--:::::: {.cell .code execution_count=2}-``` {.python}-from IPython.display import HTML-HTML("""-<script>-console.log("hello");-</script>-<b>HTML</b>-""")-```--::: {.output .execute_result execution_count=2}-```{=html}-<script>-console.log("hello");-</script>-<b>HTML</b>-hello-```-:::-::::::-````--If you include raw HTML or TeX in an output cell, use the-[raw attribute][Extension: `fenced_attribute`], as shown-in the last cell of the example above. Although pandoc can-process "bare" raw HTML and TeX, the result is often-interspersed raw elements and normal textual elements, and-in an output cell pandoc expects a single, connected raw-block. To avoid using raw HTML or TeX except when-marked explicitly using raw attributes, we recommend-specifying the extensions `-raw_html-raw_tex+raw_attribute` when-translating between Markdown and ipynb notebooks.--Note that options and extensions that affect reading and-writing of Markdown will also affect Markdown cells in ipynb-notebooks. For example, `--wrap=preserve` will preserve-soft line breaks in Markdown cells; `--atx-headers` will-cause ATX-style headings to be used; and `--preserve-tabs` will-prevent tabs from being turned to spaces.--# Syntax highlighting--Pandoc will automatically highlight syntax in [fenced code blocks] that-are marked with a language name. The Haskell library [skylighting] is-used for highlighting. Currently highlighting is supported only for-HTML, EPUB, Docx, Ms, and LaTeX/PDF output. To see a list of language names-that pandoc will recognize, type `pandoc --list-highlight-languages`.--The color scheme can be selected using the `--highlight-style` option.-The default color scheme is `pygments`, which imitates the default color-scheme used by the Python library pygments (though pygments is not actually-used to do the highlighting). To see a list of highlight styles,-type `pandoc --list-highlight-styles`.--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:-- pandoc --print-highlight-style pygments > my.theme--Then edit `my.theme` and use it like this:-- pandoc --highlight-style 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-`--syntax-definition` option to load a [KDE-style XML syntax definition-file](https://docs.kde.org/stable5/en/kate/katepart/highlight.html).-Before writing your own, have a look at KDE's [repository of syntax-definitions](https://github.com/KDE/syntax-highlighting/tree/master/data/syntax).--To disable highlighting, use the `--no-highlight` option.--[skylighting]: https://github.com/jgm/skylighting--# Custom Styles--Custom styles can be used in the docx and ICML formats.--## Output--By default, pandoc's docx and ICML output applies a predefined set of styles-for blocks such as paragraphs and block quotes, and uses largely default-formatting (italics, bold) for inlines. This will work for most-purposes, especially alongside a `reference.docx` file. However, if you-need to apply your own styles to blocks, or match a preexisting set of-styles, pandoc allows you to define custom styles for blocks and text-using `div`s and `span`s, respectively.--If you define a `div` or `span` with the attribute `custom-style`,-pandoc will apply your specified style to the contained elements (with-the exception of elements whose function depends on a style, like-headings, code blocks, block quotes, or links). So, for example, using-the `bracketed_spans` syntax,-- [Get out]{custom-style="Emphatically"}, he said.--would produce a docx file with "Get out" styled with character-style `Emphatically`. Similarly, using the `fenced_divs` syntax,-- Dickinson starts the poem simply:-- ::: {custom-style="Poetry"}- | A Bird came down the Walk---- | He did not know I saw---- :::--would style the two contained lines with the `Poetry` paragraph style.--For docx output, styles will be defined in the output file as inheriting-from normal text, if the styles are not yet in your reference.docx.-If they are already defined, pandoc will not alter the definition.--This feature allows for greatest customization in conjunction with-[pandoc filters]. If you want all paragraphs after block quotes to be-indented, you can write a filter to apply the styles necessary. If you-want all italics to be transformed to the `Emphasis` character style-(perhaps to change their color), you can write a filter which will-transform all italicized inlines to inlines within an `Emphasis`-custom-style `span`.--For docx output, you don't need to enable any extensions for-custom styles to work.--[pandoc filters]: https://pandoc.org/filters.html--## Input--The docx reader, by default, only reads those styles that it can-convert into pandoc elements, either by direct conversion or-interpreting the derivation of the input document's styles.--By enabling the [`styles` extension](#ext-styles) in the docx reader-(`-f docx+styles`), you can produce output that maintains the styles-of the input document, using the `custom-style` class. Paragraph-styles are interpreted as divs, while character styles are interpreted-as spans.--For example, using the `custom-style-reference.docx` file in the test-directory, we have the following different outputs:--Without the `+styles` extension:-- $ pandoc test/docx/custom-style-reference.docx -f docx -t markdown- This is some text.-- This is text with an *emphasized* text style. And this is text with a- **strengthened** text style.-- > Here is a styled paragraph that inherits from Block Text.--And with the extension:-- $ pandoc test/docx/custom-style-reference.docx -f docx+styles -t markdown-- ::: {custom-style="First Paragraph"}- This is some text.- :::-- ::: {custom-style="Body Text"}- This is text with an [emphasized]{custom-style="Emphatic"} text style.- And this is text with a [strengthened]{custom-style="Strengthened"}- text style.- :::-- ::: {custom-style="My Block Style"}- > Here is a styled paragraph that inherits from Block Text.- :::--With these custom styles, you can use your input document as a-reference-doc while creating docx output (see below), and maintain the-same styles in your input and output files.--# Custom readers and writers--Pandoc can be extended with custom readers and writers written-in [Lua]. (Pandoc includes a Lua interpreter, so Lua need not-be installed separately.)--To use a custom reader or writer, simply specify the path to the-Lua script in place of the input or output format. For example:-- pandoc -t data/sample.lua- pandoc -f my_custom_markup_language.lua -t latex -s--If the script is not found relative to the working directory,-it will be sought in the `readers` or `writers` subdirectory-of the user data directory (see `--data-dir`).--A custom reader is a Lua script that defines one function,-Reader, which takes a string as input and returns a Pandoc-AST. See the [Lua filters documentation] for documentation-of the functions that are available for creating pandoc-AST elements. For parsing, the [lpeg] parsing library-is available by default. To see a sample custom reader:-- pandoc --print-default-data-file creole.lua--If you want your custom reader to have access to reader options-(e.g. the tab stop setting), you give your Reader function a-second `options` parameter.--A custom writer is a Lua script that defines a function-that specifies how to render each element in a Pandoc AST.-To see a documented example which you can modify according-to your needs:-- pandoc --print-default-data-file sample.lua--Note that custom writers have no default template. If you want-to use `--standalone` with a custom writer, you will need to-specify a template manually using `--template` or add a new-default template with the name-`default.NAME_OF_CUSTOM_WRITER.lua` to the `templates`-subdirectory of your user data directory (see [Templates]).--[Lua]: https://www.lua.org-[lpeg]: http://www.inf.puc-rio.br/~roberto/lpeg/--# Reproducible builds--Some of the document formats pandoc targets (such as EPUB,-docx, and ODT) include build timestamps in the generated document.-That means that the files generated on successive builds will-differ, even if the source does not. To avoid this, set the-`SOURCE_DATE_EPOCH` environment variable, and the timestamp will-be taken from it instead of the current time.-`SOURCE_DATE_EPOCH` should contain an integer unix timestamp-(specifying the number of seconds since midnight UTC January 1, 1970).--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).--# Running pandoc as a web server--If you rename (or symlink) the pandoc executable to-`pandoc-server`, it will start up a web server with a JSON-API. This server exposes most of the conversion functionality-of pandoc. For full documentation, see the [pandoc-server]-man page.--If you rename (or symlink) the pandoc executable to-`pandoc-server.cgi`, it will function as a CGI program-exposing the same API as `pandoc-server`.--`pandoc-server` is designed to be maximally secure; it uses-Haskell's type system to provide strong guarantees that no I/O-will be performed on the server during pandoc conversions.--[pandoc-server]: https://github.com/jgm/pandoc/blob/master/doc/pandoc-server.md---# A note on security--1. Although pandoc itself will not create or modify any files other- than those you explicitly ask it create (with the exception- of temporary files used in producing PDFs), a filter or custom- writer could in principle do anything on your file system. Please- audit filters and custom writers very carefully before using them.--2. Several input formats (including HTML, Org, and RST) support `include`- directives that allow the contents of a file to be included in the- output. An untrusted attacker could use these to view the contents of- files on the file system. (Using the `--sandbox` option can- protect against this threat.)--3. Several output formats (including RTF, FB2, HTML with- `--self-contained`, EPUB, Docx, and ODT) will embed encoded- or raw images into the output file. An untrusted attacker- could exploit this to view the contents of non-image files on the- file system. (Using the `--sandbox` option can protect- against this threat, but will also prevent including images in- these formats.)--4. If your application uses pandoc as a Haskell library (rather than- shelling out to the executable), it is possible to use it in a mode- that fully isolates pandoc from your file system, by running the- pandoc operations in the `PandocPure` monad. See the document- [Using the pandoc API](https://pandoc.org/using-the-pandoc-api.html)- for more details. (This corresponds to the use of the `--sandbox`- option on the command line.)--5. Pandoc's parsers can exhibit pathological performance on some- corner cases. It is wise to put any pandoc operations under- a timeout, to avoid DOS attacks that exploit these issues.- If you are using the pandoc executable, you can add the- command line options `+RTS -M512M -RTS` (for example) to limit- the heap size to 512MB. Note that the `commonmark` parser- (including `commonmark_x` and `gfm`) is much less vulnerable- to pathological performance than the `markdown` parser, so- it is a better choice when processing untrusted input.--6. The HTML generated by pandoc is not guaranteed to be safe.- If `raw_html` is enabled for the Markdown input, users can- inject arbitrary HTML. Even if `raw_html` is disabled,- users can include dangerous content in URLs and attributes.- To be safe, you should run all HTML generated from untrusted- user input through an HTML sanitizer.--# Authors--Copyright 2006--2022 John MacFarlane (jgm@berkeley.edu). Released+date: 2026-06-03+---++# Synopsis++`pandoc` [*options*] [*input-file*]...++# Description++Pandoc is a [Haskell] library for converting from one markup format to+another, and a command-line tool that uses this library.++Pandoc can convert between numerous markup and word processing formats,+including, but not limited to, various flavors of [Markdown], [HTML],+[LaTeX] and [Word docx]. For the full lists of input and output formats,+see the `--from` and `--to` [options below][General options].+Pandoc can also produce [PDF] output: see [creating a PDF], below.++Pandoc's enhanced version of Markdown includes syntax for [tables],+[definition lists], [metadata blocks], [footnotes], [citations], [math],+and much more. See below under [Pandoc's Markdown].++Pandoc has a modular design: it consists of a set of readers, which parse+text in a given format and produce a native representation of the document+(an _abstract syntax tree_ or AST), and a set of writers, which convert+this native representation into a target format. Thus, adding an input+or output format requires only adding a reader or writer. Users can also+run custom [pandoc filters] to modify the intermediate AST.++Because pandoc's intermediate representation of a document is less+expressive than many of the formats it converts between, one should+not expect perfect conversions between every format and every other.+Pandoc attempts to preserve the structural elements of a document, but+not formatting details such as margin size. And some document elements,+such as complex tables, may not fit into pandoc's simple document+model. While conversions from pandoc's Markdown to all formats aspire+to be perfect, conversions from formats more expressive than pandoc's+Markdown can be expected to be lossy.++## Using pandoc++If no *input-files* are specified, input is read from *stdin*.+Output goes to *stdout* by default. For output to a file,+use the `-o`/`--output` option:++ pandoc -o output.html input.txt++By default, pandoc produces a document fragment. To produce a standalone+document (e.g. a valid HTML file including `<head>` and `<body>`),+use the `-s` or `--standalone` flag:++ pandoc -s -o output.html input.txt++For more information on how standalone documents are produced, see+[Templates] below.++If multiple input files are given, pandoc will concatenate them all (with+blank lines between them) before parsing. (Use `--file-scope` to parse files+individually.)++## Specifying formats++The format of the input and output can be specified explicitly using+command-line options. The input format can be specified using the+`-f/--from` option, the output format using the `-t/--to` option.+Thus, to convert `hello.txt` from Markdown to LaTeX, you could type:++ pandoc -f markdown -t latex hello.txt++To convert `hello.html` from HTML to Markdown:++ pandoc -f html -t markdown hello.html++Supported input and output formats are listed below under [Options]+(see `-f` for input formats and `-t` for output formats). You+can also use `pandoc --list-input-formats` and+`pandoc --list-output-formats` to print lists of supported+formats.++If the input or output format is not specified explicitly, pandoc+will attempt to guess it from the extensions of the filenames.+Thus, for example,++ pandoc -o hello.tex hello.txt++will convert `hello.txt` from Markdown to LaTeX. If no output file+is specified (so that output goes to *stdout*), or if the output file's+extension is unknown, the output format will default to HTML.+If no input file is specified (so that input comes from *stdin*), or+if the input files' extensions are unknown, the input format will+be assumed to be Markdown.++## Character encoding++Pandoc uses the UTF-8 character encoding for both input and output.+If your local character encoding is not UTF-8, you+should pipe input and output through [`iconv`]:++ iconv -t utf-8 input.txt | pandoc | iconv -f utf-8++Note that in some output formats (such as HTML, LaTeX, ConTeXt,+RTF, OPML, DocBook, and Texinfo), information about+the character encoding is included in the document header, which+will only be included if you use the `-s/--standalone` option.++[`iconv`]: https://www.gnu.org/software/libiconv/++## Creating a PDF++To produce a PDF, specify an output file with a `.pdf` extension:++ pandoc test.txt -o test.pdf++By default, pandoc will use LaTeX to create the PDF, which requires+that a LaTeX engine be installed (see `--pdf-engine` below).+Alternatively, pandoc can use ConTeXt, roff ms, or HTML as an+intermediate format. To do this, specify an output file with a+`.pdf` extension, as before, but add the `--pdf-engine` option+or `-t context`, `-t html`, or `-t ms` to the command line.+The tool used to generate the PDF from the intermediate format+may be specified using `--pdf-engine`.++You can control the PDF style using variables, depending on+the intermediate format used: see [variables for LaTeX],+[variables for ConTeXt], [variables for `wkhtmltopdf`],+[variables for ms]. When HTML is used as an intermediate+format, the output can be styled using `--css`.++To debug the PDF creation, it can be useful to look at the intermediate+representation: instead of `-o test.pdf`, use for example `-s -o test.tex`+to output the generated LaTeX. You can then test it with `pdflatex test.tex`.++When using LaTeX, the following packages need to be available+(they are included with all recent versions of [TeX Live]):+[`amsfonts`], [`amsmath`], [`lm`], [`unicode-math`],+[`iftex`], [`listings`] (if the+`--listings` option is used), [`fancyvrb`], [`longtable`],+[`booktabs`], [`multirow`] (if the document contains a table with+cells that cross multiple rows), [`graphicx`] (if the document+contains images), [`bookmark`], [`xcolor`],+[`soul`], [`geometry`] (with the `geometry` variable set),+[`setspace`] (with `linestretch`), and+[`babel`] (with `lang`). If `CJKmainfont` is set, [`xeCJK`]+is needed if `xelatex` is used, else [`luatexja`] is needed if+`lualatex` is used. [`framed`] is required if code is highlighted in a+scheme that use a colored background. The use of `xelatex` or+`lualatex` as the PDF engine requires [`fontspec`]. `lualatex`+uses [`selnolig`] and [`lua-ul`]. `xelatex` uses [`bidi`] (with+the `dir` variable set).+If the `mathspec` variable is set, `xelatex` will use [`mathspec`]+instead of [`unicode-math`]. The [`csquotes`] package will be used+for [typography] if the `csquotes` variable or metadata field is+set to a true value. The [`natbib`], [`biblatex`], [`bibtex`],+and [`biber`] packages can optionally be used for [citation+rendering]. 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),+[`parskip`] (for better inter-paragraph spaces), [`xurl`] (for+better line breaks in URLs), and [`footnotehyper`] or+[`footnote`] (to allow footnotes in tables).++[TeX Live]: https://www.tug.org/texlive/+[`amsfonts`]: https://ctan.org/pkg/amsfonts+[`amsmath`]: https://ctan.org/pkg/amsmath+[`babel`]: https://ctan.org/pkg/babel+[`biber`]: https://ctan.org/pkg/biber+[`biblatex`]: https://ctan.org/pkg/biblatex+[`bibtex`]: https://ctan.org/pkg/bibtex+[`bidi`]: https://ctan.org/pkg/bidi+[`bookmark`]: https://ctan.org/pkg/bookmark+[`booktabs`]: https://ctan.org/pkg/booktabs+[`csquotes`]: https://ctan.org/pkg/csquotes+[`fancyvrb`]: https://ctan.org/pkg/fancyvrb+[`fontspec`]: https://ctan.org/pkg/fontspec+[`footnote`]: https://ctan.org/pkg/footnote+[`footnotehyper`]: https://ctan.org/pkg/footnotehyper+[`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+[`lm`]: https://ctan.org/pkg/lm+[`lua-ul`]: https://ctan.org/pkg/lua-ul+[`luatexja`]: https://ctan.org/pkg/luatexja+[`longtable`]: https://ctan.org/pkg/longtable+[`mathspec`]: https://ctan.org/pkg/mathspec+[`microtype`]: https://ctan.org/pkg/microtype+[`multirow`]: https://ctan.org/pkg/multirow+[`natbib`]: https://ctan.org/pkg/natbib+[`parskip`]: https://ctan.org/pkg/parskip+[`polyglossia`]: https://ctan.org/pkg/polyglossia+[`prince`]: https://www.princexml.com/+[`setspace`]: https://ctan.org/pkg/setspace+[`soul`]: https://ctan.org/pkg/soul+[`unicode-math`]: https://ctan.org/pkg/unicode-math+[`upquote`]: https://ctan.org/pkg/upquote+[`weasyprint`]: https://weasyprint.org+[`wkhtmltopdf`]: https://wkhtmltopdf.org+[`xcolor`]: https://ctan.org/pkg/xcolor+[`xeCJK`]: https://ctan.org/pkg/xecjk+[`xurl`]: https://ctan.org/pkg/xurl+[`selnolig`]: https://ctan.org/pkg/selnolig++++## Reading from the Web++Instead of an input file, an absolute URI may be given. In this case+pandoc will fetch the content using HTTP:++ pandoc -f html -t markdown https://www.fsf.org++It is possible to supply a custom User-Agent string or other+header when requesting a document from a URL:++ pandoc -f html -t markdown --request-header User-Agent:"Mozilla/5.0" \+ https://www.fsf.org++# Options++## General options {.options}++`-f` *FORMAT*, `-r` *FORMAT*, `--from=`*FORMAT*, `--read=`*FORMAT*++: Specify input format. *FORMAT* can be:++ ::: {#input-formats}+ - `asciidoc` ([AsciiDoc] markup)+ - `bibtex` ([BibTeX] bibliography)+ - `biblatex` ([BibLaTeX] bibliography)+ - `bits` ([BITS] XML, alias for `jats`)+ - `commonmark` ([CommonMark] Markdown)+ - `commonmark_x` ([CommonMark] Markdown with extensions)+ - `creole` ([Creole 1.0])+ - `csljson` ([CSL JSON] bibliography)+ - `csv` ([CSV] table)+ - `tsv` ([TSV] table)+ - `djot` ([Djot markup])+ - `docbook` ([DocBook])+ - `docx` ([Word docx])+ - `dokuwiki` ([DokuWiki markup])+ - `endnotexml` ([EndNote XML bibliography])+ - `epub` ([EPUB])+ - `fb2` ([FictionBook2] e-book)+ - `gfm` ([GitHub-Flavored Markdown]),+ or the deprecated and less accurate `markdown_github`;+ use [`markdown_github`](#markdown-variants) only+ if you need extensions not supported in [`gfm`](#markdown-variants).+ - `haddock` ([Haddock markup])+ - `html` ([HTML])+ - `ipynb` ([Jupyter notebook])+ - `jats` ([JATS] XML)+ - `jira` ([Jira]/Confluence wiki markup)+ - `json` (JSON version of native AST)+ - `latex` ([LaTeX])+ - `markdown` ([Pandoc's Markdown])+ - `markdown_mmd` ([MultiMarkdown])+ - `markdown_phpextra` ([PHP Markdown Extra])+ - `markdown_strict` (original unextended [Markdown])+ - `mediawiki` ([MediaWiki markup])+ - `man` ([roff man])+ - `mdoc` ([mdoc] manual page markup)+ - `muse` ([Muse])+ - `native` (native Haskell)+ - `odt` ([OpenDocument text document][ODT])+ - `opml` ([OPML])+ - `org` ([Emacs Org mode])+ - `pod` (Perl's [Plain Old Documentation])+ - `pptx` ([PowerPoint])+ - `ris` ([RIS] bibliography)+ - `rtf` ([Rich Text Format])+ - `rst` ([reStructuredText])+ - `t2t` ([txt2tags])+ - `textile` ([Textile])+ - `tikiwiki` ([TikiWiki markup])+ - `twiki` ([TWiki markup])+ - `typst` ([typst])+ - `vimwiki` ([Vimwiki])+ - `xlsx` ([Excel spreadsheet][XLSX])+ - `xml` (XML version of native AST)+ - the path of a custom Lua reader, see [Custom readers and writers] below+ :::++ Extensions can be individually enabled or disabled by+ appending `+EXTENSION` or `-EXTENSION` to the format name.+ See [Extensions] below, for a list of extensions and+ their names. See `--list-input-formats` and `--list-extensions`,+ below.++`-t` *FORMAT*, `-w` *FORMAT*, `--to=`*FORMAT*, `--write=`*FORMAT*++: Specify output format. *FORMAT* can be:++ ::: {#output-formats}+ - `ansi` (text with [ANSI escape codes], for terminal viewing)+ - `asciidoc` (modern [AsciiDoc] as interpreted by [AsciiDoctor])+ - `asciidoc_legacy` ([AsciiDoc] as interpreted by [`asciidoc-py`]).+ - `asciidoctor` (deprecated synonym for `asciidoc`)+ - `bbcode` [BBCode]+ - `bbcode_fluxbb` [BBCode (FluxBB)]+ - `bbcode_phpbb` [BBCode (phpBB)]+ - `bbcode_steam` [BBCode (Steam)]+ - `bbcode_hubzilla` [BBCode (Hubzilla)]+ - `bbcode_xenforo` [BBCode (xenForo)]+ - `beamer` ([LaTeX beamer][`beamer`] slide show)+ - `bibtex` ([BibTeX] bibliography)+ - `biblatex` ([BibLaTeX] bibliography)+ - `chunkedhtml` (zip archive of multiple linked HTML files)+ - `commonmark` ([CommonMark] Markdown)+ - `commonmark_x` ([CommonMark] Markdown with extensions)+ - `context` ([ConTeXt])+ - `csljson` ([CSL JSON] bibliography)+ - `djot` ([Djot markup])+ - `docbook` or `docbook4` ([DocBook] 4)+ - `docbook5` (DocBook 5)+ - `docx` ([Word docx])+ - `dokuwiki` ([DokuWiki markup])+ - `epub` or `epub3` ([EPUB] v3 book)+ - `epub2` (EPUB v2)+ - `fb2` ([FictionBook2] e-book)+ - `gfm` ([GitHub-Flavored Markdown]),+ or the deprecated and less accurate `markdown_github`;+ use [`markdown_github`](#markdown-variants) only+ if you need extensions not supported in [`gfm`](#markdown-variants).+ - `haddock` ([Haddock markup])+ - `html` or `html5` ([HTML], i.e. [HTML5]/XHTML [polyglot markup])+ - `html4` ([XHTML] 1.0 Transitional)+ - `icml` ([InDesign ICML])+ - `ipynb` ([Jupyter notebook])+ - `jats_archiving` ([JATS] XML, Archiving and Interchange Tag Set)+ - `jats_articleauthoring` ([JATS] XML, Article Authoring Tag Set)+ - `jats_publishing` ([JATS] XML, Journal Publishing Tag Set)+ - `jats` (alias for `jats_archiving`)+ - `jira` ([Jira]/Confluence wiki markup)+ - `json` (JSON version of native AST)+ - `latex` ([LaTeX])+ - `man` ([roff man])+ - `markdown` ([Pandoc's Markdown])+ - `markdown_mmd` ([MultiMarkdown])+ - `markdown_phpextra` ([PHP Markdown Extra])+ - `markdown_strict` (original unextended [Markdown])+ - `markua` ([Markua])+ - `mediawiki` ([MediaWiki markup])+ - `ms` ([roff ms])+ - `muse` ([Muse])+ - `native` (native Haskell)+ - `odt` ([OpenDocument text document][ODT])+ - `opml` ([OPML])+ - `opendocument` ([OpenDocument XML])+ - `org` ([Emacs Org mode])+ - `pdf` ([PDF])+ - `plain` (plain text)+ - `pptx` ([PowerPoint] slide show)+ - `rst` ([reStructuredText])+ - `rtf` ([Rich Text Format])+ - `texinfo` ([GNU Texinfo])+ - `textile` ([Textile])+ - `slideous` ([Slideous] HTML and JavaScript slide show)+ - `slidy` ([Slidy] HTML and JavaScript slide show)+ - `dzslides` ([DZSlides] HTML5 + JavaScript slide show)+ - `revealjs` ([reveal.js] HTML5 + JavaScript slide show)+ - `s5` ([S5] HTML and JavaScript slide show)+ - `tei` ([TEI Simple])+ - `typst` ([typst])+ - `vimdoc` ([Vimdoc])+ - `xml` (XML version of native AST)+ - `xwiki` ([XWiki markup])+ - `zimwiki` ([ZimWiki markup])+ - the path of a custom Lua writer, see [Custom readers and writers] below+ :::++ Note that `odt`, `docx`, `epub`, and `pdf` output will not be directed+ to *stdout* unless forced with `-o -`.++ Extensions can be individually enabled or+ disabled by appending `+EXTENSION` or `-EXTENSION` to the format+ name. See [Extensions] below, for a list of extensions and their+ names. See `--list-output-formats` and `--list-extensions`, below.++`-o` *FILE*, `--output=`*FILE*++: Write output to *FILE* instead of *stdout*. If *FILE* is+ `-`, output will go to *stdout*, even if a non-textual format+ (`docx`, `odt`, `epub2`, `epub3`) is specified. If the+ output format is `chunkedhtml` and *FILE* has no extension,+ then instead of producing a `.zip` file pandoc will create+ a directory *FILE* and unpack the zip archive there+ (unless *FILE* already exists, in which case an error+ will be raised).++`--data-dir=`*DIRECTORY*++: Specify the user data directory to search for pandoc data files.+ If this option is not specified, the default user data directory+ will be used. On \*nix and macOS systems this will be the `pandoc`+ subdirectory of the XDG data directory (by default,+ `$HOME/.local/share`, overridable by setting the `XDG_DATA_HOME`+ environment variable). If that directory does not exist and+ `$HOME/.pandoc` exists, it will be used (for backwards compatibility).+ On Windows the default user data directory is `%APPDATA%\pandoc`.+ You can find the default user data directory on your system by+ looking at the output of `pandoc --version`.+ Data files placed in this directory (for example, `reference.odt`,+ `reference.docx`, `epub.css`, `templates`) will override+ pandoc's normal defaults. (Note that the user data directory+ is not created by pandoc, so you will need to create it yourself+ if you want to make use of it.)++`-d` *FILE*, `--defaults=`*FILE*++: Specify a set of default option settings. *FILE* is a YAML or JSON+ file whose fields correspond to command-line option+ settings. All options for document conversion, including input+ and output files, can be set using a defaults file. The file will+ be searched for first in the working directory, and then in+ the `defaults` subdirectory of the user data directory+ (see `--data-dir`). The `.yaml` extension will be added if+ *FILE* lacs an extension. See the section [Defaults files]+ for more information on the file format. Settings from the+ defaults file may be overridden or extended by subsequent+ options on the command line.++`--bash-completion`++: Generate a bash completion script. To enable bash completion+ with pandoc, add this to your `.bashrc`:++ eval "$(pandoc --bash-completion)"++`--sandbox[=true|false]`++: Run pandoc in a sandbox, limiting IO operations in readers+ and writers to reading the files specified on the command line.+ Note that this option does not limit IO operations by+ filters or in the production of PDF documents. But it does+ offer security against, for example, disclosure of files+ through the use of `include` directives. Anyone using+ pandoc on untrusted user input should use this option.++ Note: some readers and writers (e.g., `docx`) need access to data+ files. If these are stored on the file system, then pandoc+ will not be able to find them when run in `--sandbox` mode+ and will raise an error. For these applications, we+ recommend using a pandoc binary compiled with the `embed_data_files`+ option, which causes the data files to be baked into the binary+ instead of being stored on the file system.++`--verbose`++: Give verbose debugging output.++`--quiet`++: Suppress warning messages.++`--fail-if-warnings[=true|false]`++: Exit with error status if there are any warnings.++`--log=`*FILE*++: Write log messages in machine-readable JSON format to+ *FILE*. All messages above DEBUG level will be written,+ regardless of verbosity settings (`--verbose`, `--quiet`).++`--list-input-formats`++: List supported input formats, one per line.++`--list-output-formats`++: List supported output formats, one per line.++`--list-extensions`[`=`*FORMAT*]++: List supported extensions for *FORMAT*, one per line, preceded+ by a `+` or `-` indicating whether it is enabled by default+ in *FORMAT*. If *FORMAT* is not specified, defaults for+ pandoc's Markdown are given.++`--list-highlight-languages`++: List supported languages for syntax highlighting, one per+ line.++`--list-highlight-styles`++: List supported styles for syntax highlighting, one per line.+ See `--syntax-highlighting`.++`-v`, `--version`++: Print version.++`-h`, `--help`++: Show usage message.++[ANSI escape codes]: https://en.wikipedia.org/wiki/ANSI_escape_code+[Markdown]: https://daringfireball.net/projects/markdown/+[CommonMark]: https://commonmark.org+[PHP Markdown Extra]: https://michelf.ca/projects/php-markdown/extra/+[GitHub-Flavored Markdown]: https://help.github.com/articles/github-flavored-markdown/+[MultiMarkdown]: https://fletcherpenney.net/multimarkdown/+[reStructuredText]: https://docutils.sourceforge.io/docs/ref/rst/introduction.html+[S5]: https://meyerweb.com/eric/tools/s5/+[Slidy]: https://www.w3.org/Talks/Tools/Slidy2/+[Slideous]: https://goessner.net/articles/slideous/+[HTML]: https://www.w3.org/html/+[HTML5]: https://html.spec.whatwg.org/+[polyglot markup]: https://www.w3.org/TR/html-polyglot/+[XHTML]: https://www.w3.org/TR/xhtml1/+[LaTeX]: https://www.latex-project.org/+[`beamer`]: https://ctan.org/pkg/beamer+[Beamer User's Guide]: http://mirrors.ctan.org/macros/latex/contrib/beamer/doc/beameruserguide.pdf+[ConTeXt]: https://www.contextgarden.net/+[Rich Text Format]: https://en.wikipedia.org/wiki/Rich_Text_Format+[DocBook]: https://docbook.org+[Djot markup]: https://djot.net+[JATS]: https://jats.nlm.nih.gov+[BITS]: https://jats.nlm.nih.gov/extensions/bits/+[Jira]: https://jira.atlassian.com/secure/WikiRendererHelpAction.jspa?section=all+[txt2tags]: https://txt2tags.org+[EPUB]: http://idpf.org/epub+[OPML]: https://opml.org/spec2.opml+[OpenDocument XML]: https://www.oasis-open.org/2021/06/16/opendocument-v1-3-oasis-standard-published/+[ODT]: https://en.wikipedia.org/wiki/OpenDocument+[Plain Old Documentation]: https://perldoc.perl.org/perlpod+[Textile]: https://textile-lang.com+[MediaWiki markup]: https://www.mediawiki.org/wiki/Help:Formatting+[DokuWiki markup]: https://www.dokuwiki.org/dokuwiki+[ZimWiki markup]: https://zim-wiki.org/manual/Help/Wiki_Syntax.html+[XWiki markup]: https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/XWikiSyntax/+[XLSX]: https://en.wikipedia.org/wiki/Microsoft_Excel#File_formats+[Vimdoc]: https://vimhelp.org/helphelp.txt.html#help-writing+[TWiki markup]: https://twiki.org/cgi-bin/view/TWiki/TextFormattingRules+[TikiWiki markup]: https://doc.tiki.org/Wiki-Syntax-Text#The_Markup_Language_Wiki-Syntax+[Haddock markup]: https://www.haskell.org/haddock/doc/html/ch03s08.html+[Creole 1.0]: http://www.wikicreole.org/wiki/Creole1.0+[CSV]: https://tools.ietf.org/html/rfc4180+[TSV]: https://www.iana.org/assignments/media-types/text/tab-separated-values+[roff man]: https://man.cx/groff_man(7)+[roff ms]: https://man.cx/groff_ms(7)+[Haskell]: https://www.haskell.org+[GNU Texinfo]: https://www.gnu.org/software/texinfo/+[RIS]: https://en.wikipedia.org/wiki/RIS_(file_format)+[Emacs Org mode]: https://orgmode.org+[AsciiDoc]: https://asciidoc.org/+[AsciiDoctor]: https://asciidoctor.org/+[`asciidoc-py`]: https://github.com/asciidoc-py/asciidoc-py+[DZSlides]: https://paulrouget.com/dzslides/+[Word docx]: https://en.wikipedia.org/wiki/Office_Open_XML+[PDF]: https://www.adobe.com/pdf/+[reveal.js]: https://revealjs.com/+[FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1+[Jupyter notebook]: https://nbformat.readthedocs.io/en/latest/+[InDesign ICML]: https://web.archive.org/web/20211006210211/https://wwwimages.adobe.com/www.adobe.com/content/dam/acom/en/devnet/indesign/sdk/cs6/idml/idml-cookbook.pdf+[TEI Simple]: https://github.com/TEIC/TEI-Simple+[Muse]: https://amusewiki.org/library/manual+[PowerPoint]: https://en.wikipedia.org/wiki/Microsoft_PowerPoint+[Vimwiki]: https://vimwiki.github.io+[CSL JSON]: https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html+[BibTeX]: https://ctan.org/pkg/bibtex+[BibLaTeX]: https://ctan.org/pkg/biblatex+[Markua]: https://leanpub.com/markua/read+[EndNote XML bibliography]: https://support.clarivate.com/Endnote/s/article/EndNote-XML-Document-Type-Definition+[typst]: https://typst.app+[mdoc]: https://mandoc.bsd.lv/man/mdoc.7.html+[BBCode]: https://www.bbcode.org/reference.php+[BBCode (FluxBB)]: https://web.archive.org/web/20210623155046/https://fluxbb.org/forums/help.php#bbcode+[BBCode (Hubzilla)]: https://hubzilla.org/help/member/bbcode+[BBCode (Steam)]: https://steamcommunity.com/comment/ForumTopic/formattinghelp+[BBCode (phpBB)]: https://www.phpbb.com/community/help/bbcode+[BBCode (xenForo)]: https://www.xenfocus.com/community/help/bb-codes/++## Reader options {.options}++`--shift-heading-level-by=`*NUMBER*++: Shift heading levels by a positive or negative integer.+ For example, with `--shift-heading-level-by=-1`, level 2+ headings become level 1 headings, and level 3 headings+ become level 2 headings. Headings cannot have a level+ less than 1, so a heading that would be shifted below level 1+ becomes a regular paragraph. Exception: with a shift of -N,+ a level-N heading at the beginning of the document+ replaces the metadata title. `--shift-heading-level-by=-1`+ is a good choice when converting HTML or Markdown documents that+ use an initial level-1 heading for the document title and+ level-2+ headings for sections. `--shift-heading-level-by=1`+ may be a good choice for converting Markdown documents that+ use level-1 headings for sections to HTML, since pandoc uses+ a level-1 heading to render the document title.++`--base-header-level=`*NUMBER*++: *Deprecated. Use `--shift-heading-level-by`=X instead,+ where X = NUMBER - 1.* Specify the base level for headings+ (defaults to 1).++`--indented-code-classes=`*CLASSES*++: Specify classes to use for indented code blocks---for example,+ `perl,numberLines` or `haskell`. Multiple classes may be separated+ by spaces or commas.++`--default-image-extension=`*EXTENSION*++: Specify a default extension to use when image paths/URLs have no+ extension. This allows you to use the same source for formats that+ require different kinds of images. Currently this option only affects+ the Markdown and LaTeX readers.++`--file-scope[=true|false]`++: Parse each file individually before combining for multifile+ documents. This will allow footnotes in different files with the+ same identifiers to work as expected. If this option is set,+ footnotes and links will not work across files. Reading binary+ files (docx, odt, epub) implies `--file-scope`.++ If two or more files are processed using `--file-scope`,+ prefixes based on the filenames will be added to identifiers+ in order to disambiguate them, and internal links will+ be adjusted accordingly. For example, a header with+ identifier `foo` in `subdir/file1.txt` will have its+ identifier changed to `subdir__file1.txt__foo`.++`-F` *PROGRAM*, `--filter=`*PROGRAM*++: Specify an executable to be used as a filter transforming the+ pandoc AST after the input is parsed and before the output is+ written. The executable should read JSON from stdin and write+ JSON to stdout. The JSON must be formatted like pandoc's own+ JSON input and output. The name of the output format will be+ passed to the filter as the first argument. Hence,++ pandoc --filter ./caps.py -t latex++ is equivalent to++ pandoc -t json | ./caps.py latex | pandoc -f json -t latex++ The latter form may be useful for debugging filters.++ Filters may be written in any language. `Text.Pandoc.JSON`+ exports `toJSONFilter` to facilitate writing filters in Haskell.+ Those who would prefer to write filters in python can use the+ module [`pandocfilters`], installable from PyPI. There are also+ pandoc filter libraries in [PHP], [perl], and+ [JavaScript/node.js].++ In order of preference, pandoc will look for filters in++ 1. a specified full or relative path (executable or+ non-executable),++ 2. `$DATADIR/filters` (executable or non-executable)+ where `$DATADIR` is the user data directory (see+ `--data-dir`, above),++ 3. `$PATH` (executable only).++ Filters, Lua-filters, and citeproc processing are applied in+ the order specified on the command line.++`-L` *SCRIPT*, `--lua-filter=`*SCRIPT*++: Transform the document in a similar fashion as JSON filters (see+ `--filter`), but use pandoc's built-in Lua filtering system. The given+ Lua script is expected to return a list of Lua filters which will be+ applied in order. Each Lua filter must contain element-transforming+ functions indexed by the name of the AST element on which the filter+ function should be applied.++ The `pandoc` Lua module provides helper functions for element+ creation. It is always loaded into the script's Lua environment.++ See the [Lua filters documentation] for further details.++ In order of preference, pandoc will look for Lua filters in++ 1. a specified full or relative path,++ 2. `$DATADIR/filters` where `$DATADIR` is the user data+ directory (see `--data-dir`, above).++ Filters, Lua filters, and citeproc processing are applied in+ the order specified on the command line.++`-M` *KEY*[`=`*VAL*], `--metadata=`*KEY*[`:`*VAL*]++: Set the metadata field *KEY* to the value *VAL*. A value specified+ on the command line overrides a value specified in the document+ using [YAML metadata blocks][Extension: `yaml_metadata_block`].+ Values will be parsed as YAML boolean or string values. If no value is+ specified, the value will be treated as Boolean true. Like+ `--variable`, `--metadata` causes template variables to be set.+ But unlike `--variable`, `--metadata` affects the metadata of the+ underlying document (which is accessible from filters and may be+ printed in some output formats) and metadata values will be escaped+ when inserted into the template.++`--metadata-file=`*FILE*++: Read metadata from the supplied YAML (or JSON) file. This+ option can be used with every input format, but string scalars+ in the metadata file will always be parsed as Markdown. (If the+ input format is Markdown or a Markdown variant, then the+ same variant will be used to parse the metadata file;+ if it is a non-Markdown format, pandoc's default Markdown+ extensions will be used.) This option can be used+ repeatedly to include multiple metadata files; values in+ files specified later on the command line will be preferred+ over those specified in earlier files. Metadata values+ specified inside the document, or by using `-M`, overwrite+ values specified with this option. The file will be searched+ for first in the working directory, and then in the `metadata`+ subdirectory of the user data directory (see `--data-dir`).++`-p`, `--preserve-tabs[=true|false]`++: Preserve tabs instead of converting them to spaces. (By default, pandoc+ converts tabs to spaces before parsing its input.) Note that this will+ only affect tabs in literal code spans and code blocks. Tabs in regular+ text are always treated as spaces.++`--tab-stop=`*NUMBER*++: Specify the number of spaces per tab (default is 4).++`--track-changes=accept`|`reject`|`all`++: Specifies what to do with insertions, deletions, and comments+ produced by the MS Word "Track Changes" feature. `accept` (the+ default) processes all the insertions and deletions.+ `reject` ignores them. Both `accept` and `reject` ignore comments.+ `all` includes all insertions, deletions, and comments, wrapped+ in spans with `insertion`, `deletion`, `comment-start`, and+ `comment-end` classes, respectively. The author and time of+ change is included. `all` is useful for scripting: only+ accepting changes from a certain reviewer, say, or before a+ certain date. If a paragraph is inserted or deleted,+ `track-changes=all` produces a span with the class+ `paragraph-insertion`/`paragraph-deletion` before the+ affected paragraph break. This option only affects the docx+ reader.++`--extract-media=`*DIR*|*FILE*`.zip`++: Extract images and other media contained in or linked from+ the source document to the path *DIR*, creating it if+ necessary, and adjust the images references in the document+ so they point to the extracted files. Media are downloaded,+ read from the file system, or extracted from a binary+ container (e.g. docx), as needed. The original file paths+ are used if they are relative paths not containing `..`.+ Otherwise filenames are constructed from the SHA1 hash of+ the contents.++ If the path given ends in `.zip`, then instead of creating+ a directory, pandoc will create a zip archive containing the+ media files.++`--abbreviations=`*FILE*++: Specifies a custom abbreviations file, with abbreviations+ one to a line. If this option is not specified, pandoc will+ read the data file `abbreviations` from the user data+ directory or fall back on a system default. To see the+ system default, use+ `pandoc --print-default-data-file=abbreviations`. The only+ use pandoc makes of this list is in the Markdown reader.+ Strings found in this list will be followed by a nonbreaking+ space, and the period will not produce sentence-ending space+ in formats like LaTeX. The strings may not contain spaces.++`--typst-input=`*KEY*[`=`*VAL*]++: Set a parameter value that will be made available to the typst+ parser in `sys.inputs`, like `--input` in the `typst` CLI.+ Either `:` or `=` may be used to separate *KEY* from *VAL*.+ Values containing spaces must be quoted.++`--trace[=true|false]`++: Print diagnostic output tracing parser progress to stderr.+ This option is intended for use by developers in diagnosing+ performance issues.++[`pandocfilters`]: https://github.com/jgm/pandocfilters+[PHP]: https://github.com/vinai/pandocfilters-php+[perl]: https://metacpan.org/pod/Pandoc::Filter+[JavaScript/node.js]: https://github.com/mvhenderson/pandoc-filter-node+[Lua filters documentation]: https://pandoc.org/lua-filters.html++## General writer options {.options}++`-s`, `--standalone`++: Produce output with an appropriate header and footer (e.g. a+ standalone HTML, LaTeX, TEI, or RTF file, not a fragment). This option+ is set automatically for `pdf`, `epub`, `epub3`, `fb2`, `docx`, and `odt`+ output. For `native` output, this option causes metadata to+ be included; otherwise, metadata is suppressed.++`--template=`*FILE*|*URL*++: Use the specified file as a custom template for the generated document.+ Implies `--standalone`. See [Templates], below, for a+ description of template syntax. If the template is not found,+ pandoc will search for it in the `templates` subdirectory of+ the user data directory (see `--data-dir`). If no extension+ is specified and an extensionless template is not found,+ pandoc will look for a template with an extension+ corresponding to the writer, so that `--template=special`+ looks for `special.html` for HTML output. If this option is+ not used, a default template appropriate for the output+ format will be used (see `-D/--print-default-template`).++`-V` *KEY*[`=`*VAL*], `--variable=`*KEY*[`=`*VAL*]++: Set the template variable *KEY* to the string value *VAL* when rendering+ the document in standalone mode. Either `:` or `=` may be used+ to separate *KEY* from *VAL*. If no *VAL* is specified, the+ key will be given the value `true`. Structured values (lists, maps)+ cannot be assigned using this option, but they can be assigned in+ the `variables` section of a [defaults file][Defaults files] or+ using the `--variable-json` option. If the variable already has+ a *list* value, the value will be added to the list. If it already+ has another kind of value, it will be made into a list containing+ the previous and the new value. For example,+ `-V author=Joe -V author=Sue` makes `author` contain a list+ of strings: `Joe` and `Sue`.++`--variable-json=`*KEY*[`=`*JSON*]++: Set the template variable *KEY* to the value specified by a JSON+ string (this may be a boolean, a string, a list, or a mapping;+ a number will be treated as a string). For example,+ `--variable-json foo=false` will give `foo` the boolean false+ value, while `--variable-json foo='"false"'` will give it the+ string value `"false"`. Either `:` or `=` may be used to+ separate *KEY* from *VAL*. If the variable already has a+ value, this value will be replaced.++`-D` *FORMAT*, `--print-default-template=`*FORMAT*++: Print the system default template for an output *FORMAT*. (See `-t`+ for a list of possible *FORMAT*s.) Templates in the user data+ directory are ignored. This option may be used with+ `-o`/`--output` to redirect output to a file, but+ `-o`/`--output` must come before `--print-default-template`+ on the command line.++ Note that some of the default templates use partials, for+ example `styles.html`. To print the partials, use+ `--print-default-data-file`: for example,+ `--print-default-data-file=templates/styles.html`.++`--print-default-data-file=`*FILE*++: Print a system default data file. Files in the user data directory+ are ignored. This option may be used with `-o`/`--output` to+ redirect output to a file, but `-o`/`--output` must come before+ `--print-default-data-file` on the command line.++`--eol=crlf`|`lf`|`native`++: Manually specify line endings: `crlf` (Windows), `lf`+ (macOS/Linux/UNIX), or `native` (line endings appropriate+ to the OS on which pandoc is being run). The default is+ `native`.++`--dpi`=*NUMBER*++: Specify the default dpi (dots per inch) value for conversion+ from pixels to inch/centimeters and vice versa. (Technically,+ the correct term would be ppi: pixels per inch.) The default+ is 96dpi. When images contain information about dpi+ internally, the encoded value is used instead of the default+ specified by this option.++`--wrap=auto`|`none`|`preserve`++: Determine how text is wrapped in the output (the source+ code, not the rendered version). With `auto` (the default),+ pandoc will attempt to wrap lines to the column width specified by+ `--columns` (default 72). With `none`, pandoc will not wrap+ lines at all. With `preserve`, pandoc will attempt to+ preserve the wrapping from the source document (that is,+ where there are nonsemantic newlines in the source, there+ will be nonsemantic newlines in the output as well).+ In `ipynb` output, this option affects wrapping of the+ contents of Markdown cells.++`--columns=`*NUMBER*++: Specify length of lines in characters. This affects text wrapping+ in the generated source code (see `--wrap`). It also affects+ calculation of column widths for plain text tables (see [Tables] below).++`--toc[=true|false]`, `--table-of-contents[=true|false]`++: Include an automatically generated table of contents (or, in+ the case of `latex`, `context`, `docx`, `odt`,+ `opendocument`, `rst`, or `ms`, an instruction to create+ one) in the output document. This option has no effect+ unless `-s/--standalone` is used, and it has no effect+ on `man`, `docbook4`, `docbook5`, or `jats` output.++ Note that if you are producing a PDF via `ms` and using+ (the default) `groff` as a `--pdf-engine`, the table of+ contents will appear at the end of the document. If you would+ prefer it to be at the beginning of the document, before the+ title, you can use `--pdf-engine=pdfroff`.++`--toc-depth=`*NUMBER*++: Specify the number of section levels to include in the table+ of contents. The default is 3 (which means that level-1, 2, and 3+ headings will be listed in the contents).++`--lof[=true|false]`, `--list-of-figures[=true|false]`++: Include an automatically generated list of figures (or, in+ some formats, an instruction to create one) in the output+ document. This option has no effect unless `-s/--standalone`+ is used, and it only has an effect on `latex`, `context`, and+ `docx` output.++`--lot[=true|false]`, `--list-of-tables[=true|false]`++: Include an automatically generated list of tables (or, in+ some formats, an instruction to create one) in the output+ document. This option has no effect unless `-s/--standalone`+ is used, and it only has an effect on `latex`, `context`, and+ `docx` output.++`--strip-comments[=true|false]`++: Strip out HTML comments in the Markdown or Textile source,+ rather than passing them on to Markdown, Textile or HTML+ output as raw HTML. This does not apply to HTML comments+ inside raw HTML blocks when the `markdown_in_html_blocks`+ extension is not set.++`--syntax-highlighting=default|none|idiomatic|`*STYLE*`|`*FILE*++: 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.++ The default for HTML, EPUB, Docx, Ms, Man, and LaTeX output is+ to use the internal highlighter with the default style; for Typst+ it is to use Typst's own syntax highlighting system.++ 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+ `.theme` may be supplied. This will be parsed as a KDE+ syntax highlighting theme and (if valid) used as the+ highlighting style.++ 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 `--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.++`--syntax-definition=`*FILE*++: Instructs pandoc to load a KDE XML syntax definition file,+ which will be used for syntax highlighting of appropriately+ marked code blocks. This can be used to add support for+ new languages or to use altered syntax definitions for+ existing languages. This option may be repeated to add+ multiple syntax definitions.++`-H` *FILE*, `--include-in-header=`*FILE*|*URL*++: Include contents of *FILE*, verbatim, at the end of the header.+ This can be used, for example, to include special+ CSS or JavaScript in HTML documents. This option can be used+ repeatedly to include multiple files in the header. They will be+ included in the order specified. Implies `--standalone`.++`-B` *FILE*, `--include-before-body=`*FILE*|*URL*++: Include contents of *FILE*, verbatim, at the beginning of the+ document body (e.g. after the `<body>` tag in HTML, or the+ `\begin{document}` command in LaTeX). This can be used to include+ navigation bars or banners in HTML documents. This option can be+ used repeatedly to include multiple files. They will be included in+ the order specified. Implies `--standalone`. Note that if the+ output format is `odt`, this file must be in OpenDocument XML format+ suitable for insertion into the body of the document, and if+ the output is `docx`, this file must be in appropriate+ OpenXML format.++`-A` *FILE*, `--include-after-body=`*FILE*|*URL*++: Include contents of *FILE*, verbatim, at the end of the document+ body (before the `</body>` tag in HTML, or the+ `\end{document}` command in LaTeX). This option can be used+ repeatedly to include multiple files. They will be included in the+ order specified. Implies `--standalone`. Note that if the+ output format is `odt`, this file must be in OpenDocument XML format+ suitable for insertion into the body of the document, and if+ the output is `docx`, this file must be in appropriate+ OpenXML format.++`--resource-path=`*SEARCHPATH*++: List of paths to search for images and other resources.+ The paths should be separated by `:` on Linux, UNIX, and+ macOS systems, and by `;` on Windows. If `--resource-path`+ is not specified, the default resource path is the working+ directory. Note that, if `--resource-path` is specified,+ the working directory must be explicitly listed or it+ will not be searched. For example:+ `--resource-path=.:test` will search the working directory+ and the `test` subdirectory, in that order.+ This option can be used repeatedly. Search path components+ that come later on the command line will be searched before+ those that come earlier, so+ `--resource-path foo:bar --resource-path baz:bim` is+ equivalent to `--resource-path baz:bim:foo:bar`.+ Note that this option only has an effect when pandoc+ itself needs to find an image (e.g., in producing a+ PDF or docx, or when `--embed-resources` is used.)+ It will not cause image paths to be rewritten in other+ cases (e.g., when pandoc is generating LaTeX or HTML).++`--request-header=`*NAME*`:`*VAL*++: Set the request header *NAME* to the value *VAL* when making+ HTTP requests (for example, when a URL is given on the+ command line, or when resources used in a document must be+ downloaded). If you're behind a proxy, you also need to set+ the environment variable `http_proxy` to `http://...`.++`--no-check-certificate[=true|false]`++: Disable the certificate verification to allow access to+ unsecure HTTP resources (for example when the certificate+ is no longer valid or self signed).++## Options affecting specific writers {.options}++`--self-contained[=true|false]`++: *Deprecated synonym for `--embed-resources --standalone`.*++`--embed-resources[=true|false]`++: Produce a standalone HTML file with no external dependencies, using+ `data:` URIs to incorporate the contents of linked scripts, stylesheets,+ images, and videos. The resulting file should be "self-contained," in the+ sense that it needs no external files and no net access to be displayed+ properly by a browser. This option works only with HTML output formats,+ including `html4`, `html5`, `html+lhs`, `html5+lhs`, `s5`, `slidy`,+ `slideous`, `dzslides`, and `revealjs`. Scripts, images, and stylesheets at+ absolute URLs will be downloaded; those at relative URLs will be sought+ relative to the working directory (if the first source+ file is local) or relative to the base URL (if the first source+ file is remote). Elements with the attribute+ `data-external="1"` will be left alone; the documents they+ link to will not be incorporated in the document.+ Limitation: resources that are loaded dynamically through+ JavaScript cannot be incorporated; as a result, fonts may+ be missing when `--mathjax` is used, and some+ advanced features (e.g. zoom or speaker notes) may not work+ in an offline "self-contained" `reveal.js` slide show.++ For SVG images, `img` tags with `data:` URIs are used,+ unless the image has the class `inline-svg`, in which case+ an inline SVG element is inserted. This approach is+ recommended when there are many occurrences of the same+ SVG in a document, as `<use>` elements will be used to+ reduce duplication.++`--link-images[=true|false]`++: Include links to images instead of embedding the images in ODT.+ (This option currently only affects ODT output.)++`--html-q-tags[=true|false]`++: Use `<q>` tags for quotes in HTML. (This option only has an+ effect if the `smart` extension is enabled for the input+ format used.)++`--ascii[=true|false]`++: Use only ASCII characters in output. Currently supported for XML+ and HTML formats (which use entities instead of UTF-8 when this+ option is selected), CommonMark, gfm, and Markdown (which use+ entities), roff man and ms (which use hexadecimal escapes), and to a+ limited degree LaTeX (which uses standard commands for accented+ characters when possible).++`--reference-links[=true|false]`++: Use reference-style links, rather than inline links, in writing Markdown+ or reStructuredText. By default inline links are used. The+ placement of link references is affected by the+ `--reference-location` option.++`--reference-location=block`|`section`|`document`++: Specify whether footnotes (and references, if `reference-links` is+ set) are placed at the end of the current (top-level) block, the+ current section, or the document. The default is+ `document`. Currently this option only affects the+ `markdown`, `muse`, `html`, `epub`, `slidy`, `s5`, `slideous`,+ `dzslides`, and `revealjs` writers. In slide formats,+ specifying `--reference-location=section` will cause notes+ to be rendered at the bottom of a slide.++`--figure-caption-position=above`|`below`++: Specify whether figure captions go above or below figures+ (default is `below`). This option only affects HTML,+ LaTeX, Docx, ODT, and Typst output.++`--table-caption-position=above`|`below`++: Specify whether table captions go above or below tables+ (default is `above`). This option only affects HTML,+ LaTeX, Docx, ODT, and Typst output.++`--markdown-headings=setext`|`atx`++: Specify whether to use ATX-style (`#`-prefixed) or+ Setext-style (underlined) headings for level 1 and 2+ headings in Markdown output. (The default is `atx`.)+ ATX-style headings are always used for levels 3+.+ This option also affects Markdown cells in `ipynb` output.++`--list-tables[=true|false]`++: Render tables as list tables in RST output.++`--top-level-division=default`|`section`|`chapter`|`part`++: Treat top-level headings as the given division type in+ LaTeX, ConTeXt, DocBook, and TEI output. The hierarchy+ order is part, chapter, then section; all headings are+ shifted such that the top-level heading becomes the+ specified type. The default behavior is to determine the+ best division type via heuristics: unless other conditions+ apply, `section` is chosen. When the `documentclass`+ variable is set to `report`, `book`, or `memoir` (unless the+ `article` option is specified), `chapter` is implied as the+ setting for this option. If `beamer` is the output format,+ specifying either `chapter` or `part` will cause top-level+ headings to become `\part{..}`, while second-level headings+ remain as their default type.++ In Docx output, this option adds section breaks before first-level+ headings if `chapter` is selected, and before first- and second-level+ headings if `part` is selected. Footnote numbers will restart+ with each section break unless the reference doc modifies this.++`-N`, `--number-sections=[true|false]`++: Number section headings in LaTeX, ConTeXt, HTML, Docx, ms, or EPUB+ output. By default, sections are not numbered. Sections with class+ `unnumbered` will never be numbered, even if `--number-sections`+ is specified.++`--number-offset=`*NUMBER*[`,`*NUMBER*`,`*...*]++: Offsets for section heading numbers. The first number is added+ to the section number for level-1 headings, the second for+ level-2 headings, and so on. So, for example, if you+ want the first level-1 heading in your document to be+ numbered "6" instead of "1", specify `--number-offset=5`.+ If your document starts with a level-2 heading which you want+ to be numbered "1.5", specify `--number-offset=1,4`.+ `--number-offset` only directly affects the number of the+ first section heading in a document; subsequent numbers+ increment in the normal way. Implies `--number-sections`.+ Currently this feature only affects HTML and Docx output.++`--listings[=true|false]`++: *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].++`-i`, `--incremental[=true|false]`++: Make list items in slide shows display incrementally (one by one).+ The default is for lists to be displayed all at once.++`--slide-level=`*NUMBER*++: Specifies that headings with the specified level create+ slides (for `beamer`, `revealjs`, `pptx`, `s5`, `slidy`,+ `slideous`, `dzslides`). Headings above this level in the+ hierarchy are used to divide the slide show into sections;+ headings below this level create subheads within a slide.+ Valid values are 0-6. If a slide level of 0 is specified,+ slides will not be split automatically on headings, and+ horizontal rules must be used to indicate slide boundaries.+ If a slide level is not specified explicitly, the slide level+ will be set automatically based on the contents of the+ document; see [Structuring the slide show].++`--section-divs[=true|false]`++: Wrap sections in `<section>` tags (or `<div>` tags for `html4`),+ and attach identifiers to the enclosing `<section>` (or `<div>`)+ rather than the heading itself (see+ [Heading identifiers], below). This option only affects+ HTML output (and does not affect HTML slide formats).++`--email-obfuscation=none`|`javascript`|`references`++: Specify a method for obfuscating `mailto:` links in HTML documents.+ `none` leaves `mailto:` links as they are. `javascript` obfuscates+ them using JavaScript. `references` obfuscates them by printing their+ letters as decimal or hexadecimal character references. The default+ is `none`.++`--id-prefix=`*STRING*++: Specify a prefix to be added to all identifiers and internal links+ in HTML and DocBook output, and to footnote numbers in Markdown+ and Haddock output. This is useful for preventing duplicate+ identifiers when generating fragments to be included in other pages.++`-T` *STRING*, `--title-prefix=`*STRING*++: Specify *STRING* as a prefix at the beginning of the title+ that appears in the HTML header (but not in the title as it+ appears at the beginning of the HTML body). Implies `--standalone`.++`-c` *URL*, `--css=`*URL*++: Link to a CSS style sheet. This option can be used repeatedly to+ include multiple files. They will be included in the order specified.+ This option only affects HTML (including HTML slide shows)+ and EPUB output. It should be used together with+ `-s/--standalone`, because the link to the stylesheet goes+ in the document header.++ A stylesheet is required for generating EPUB. If none is+ provided using this option (or the `css` or `stylesheet`+ metadata fields), pandoc will look for a file `epub.css` in the+ user data directory (see `--data-dir`). If it is not+ found there, sensible defaults will be used.++[`--reference-doc=`*FILE*|*URL*]{#option--reference-doc}++: Use the specified file as a style reference in producing a+ docx or ODT file.++ Docx++ : For best results, the reference docx should be a modified+ version of a docx file produced using pandoc. The contents+ of the reference docx are ignored, but its stylesheets and+ document properties (including margins, page size, header,+ and footer) are used in the new docx. If no reference docx+ is specified on the command line, pandoc will look for a+ file `reference.docx` in the user data directory (see+ `--data-dir`). If this is not found either, sensible+ defaults will be used.++ To produce a custom `reference.docx`, first get a copy of+ the default `reference.docx`: `pandoc+ -o custom-reference.docx --print-default-data-file reference.docx`.+ Then open `custom-reference.docx` in Word or LibreOffice, modify the+ styles as you wish, and save the file. For best+ results, do not make changes to this file other than+ modifying the styles used by pandoc:++ Paragraph styles:++ - Normal+ - Body Text+ - First Paragraph+ - Compact+ - Title+ - Subtitle+ - Author+ - Date+ - Abstract+ - AbstractTitle+ - Bibliography+ - Heading 1+ - Heading 2+ - Heading 3+ - Heading 4+ - Heading 5+ - Heading 6+ - Heading 7+ - Heading 8+ - Heading 9+ - Block Text [for block quotes]+ - Footnote Block Text [for block quotes in footnotes]+ - Source Code+ - Footnote Text+ - Definition Term+ - Definition+ - Caption+ - Table Caption+ - Image Caption+ - Figure+ - Captioned Figure+ - TOC Heading++ Character styles:++ - Default Paragraph Font+ - Verbatim Char+ - Footnote Reference+ - Hyperlink+ - Section Number++ Table style:++ - Table++ ODT++ : For best results, the reference ODT should be a modified+ version of an ODT produced using pandoc. The contents of+ the reference ODT are ignored, but its stylesheets are used+ in the new ODT. If no reference ODT is specified on the+ command line, pandoc will look for a file `reference.odt` in+ the user data directory (see `--data-dir`). If this is not+ found either, sensible defaults will be used.++ To produce a custom `reference.odt`, first get a copy of+ the default `reference.odt`: `pandoc+ -o custom-reference.odt --print-default-data-file reference.odt`.+ Then open `custom-reference.odt` in LibreOffice, modify+ the styles as you wish, and save the file.++ PowerPoint++ : Templates included with Microsoft PowerPoint 2013 (either with+ `.pptx` or `.potx` extension) are known to work, as are most+ templates derived from these.++ The specific requirement is that the template should contain layouts+ with the following names (as seen within PowerPoint):++ - Title Slide+ - Title and Content+ - Section Header+ - Two Content+ - Comparison+ - Content with Caption+ - Blank++ For each name, the first layout found with that name will be used.+ If no layout is found with one of the names, pandoc will output a+ warning and use the layout with that name from the default reference+ doc instead. (How these layouts are used is described in [PowerPoint+ layout choice](#powerpoint-layout-choice).)++ All templates included with a recent version of MS PowerPoint+ will fit these criteria. (You can click on `Layout` under the+ `Home` menu to check.)++ You can also modify the default `reference.pptx`: first run+ `pandoc -o custom-reference.pptx --print-default-data-file+ reference.pptx`, and then modify `custom-reference.pptx`+ in MS PowerPoint (pandoc will use the layouts with the names+ listed above).++`--split-level=`*NUMBER*++: Specify the heading level at which to split an EPUB or+ chunked HTML document into separate files. The default is to split+ into chapters at level-1 headings. In the case of EPUB, this+ option only affects the internal composition of the EPUB, not the way+ chapters and sections are displayed to users. Some+ readers may be slow if the chapter files are too large, so for large+ documents with few level-1 headings, one might want to use a chapter+ level of 2 or 3. For chunked HTML, this option determines+ how much content goes in each "chunk."++`--chunk-template=`*PATHTEMPLATE*++: Specify a template for the filenames in a `chunkedhtml` document.+ In the template, `%n` will be replaced by the chunk number (padded+ with leading 0s to 3 digits), `%s` with the section number of the chunk,+ `%h` with the heading text (with formatting removed), `%i` with+ the section identifier. For example, `section-%s-%i.html` might+ be resolved to `section-1.1-introduction.html`. The characters+ `/` and `\` are not allowed in chunk templates and will be+ ignored. The default is `%s-%i.html`.++`--epub-chapter-level=`*NUMBER*++: *Deprecated synonym for `--split-level`.*++`--epub-cover-image=`*FILE*++: Use the specified image as the EPUB cover. It is recommended+ that the image be less than 1000px in width and height. Note that+ in a Markdown source document you can also specify `cover-image`+ in a YAML metadata block (see [EPUB Metadata], below).++`--epub-title-page=true`|`false`++: Determines whether a the title page is included in the EPUB+ (default is `true`).++`--epub-metadata=`*FILE*++: Look in the specified XML file for metadata for the EPUB.+ The file should contain a series of [Dublin Core elements].+ For example:++ <dc:rights>Creative Commons</dc:rights>+ <dc:language>es-AR</dc:language>++ By default, pandoc will include the following metadata elements:+ `<dc:title>` (from the document title), `<dc:creator>` (from the+ document authors), `<dc:date>` (from the document date, which should+ be in [ISO 8601 format]), `<dc:language>` (from the `lang`+ variable, or, if is not set, the locale), and `<dc:identifier+ id="BookId">` (a randomly generated UUID). Any of these may be+ overridden by elements in the metadata file.++ Note: if the source document is Markdown, a YAML metadata block+ in the document can be used instead. See below under+ [EPUB Metadata].++`--epub-embed-font=`*FILE*++: Embed the specified font in the EPUB. This option can be repeated+ to embed multiple fonts. Wildcards can also be used: for example,+ `DejaVuSans-*.ttf`. However, if you use wildcards on the command+ line, be sure to escape them or put the whole filename in single quotes,+ to prevent them from being interpreted by the shell. To use the+ embedded fonts, you will need to add declarations like the following+ to your CSS (see `--css`):++ @font-face {+ font-family: DejaVuSans;+ font-style: normal;+ font-weight: normal;+ src:url("../fonts/DejaVuSans-Regular.ttf");+ }+ @font-face {+ font-family: DejaVuSans;+ font-style: normal;+ font-weight: bold;+ src:url("../fonts/DejaVuSans-Bold.ttf");+ }+ @font-face {+ font-family: DejaVuSans;+ font-style: italic;+ font-weight: normal;+ src:url("../fonts/DejaVuSans-Oblique.ttf");+ }+ @font-face {+ font-family: DejaVuSans;+ font-style: italic;+ font-weight: bold;+ src:url("../fonts/DejaVuSans-BoldOblique.ttf");+ }+ body { font-family: "DejaVuSans"; }++`--epub-subdirectory=`*DIRNAME*++: Specify the subdirectory in the OCF container that is to hold+ the EPUB-specific contents. The default is `EPUB`. To put+ the EPUB contents in the top level, use an empty string.++`--ipynb-output=all|none|best`++: Determines how ipynb output cells are treated. `all` means+ that all of the data formats included in the original are+ preserved. `none` means that the contents of data cells+ are omitted. `best` causes pandoc to try to pick the+ richest data block in each output cell that is compatible+ with the output format. The default is `best`.++`--pdf-engine=`*PROGRAM*++: Use the specified engine when producing PDF output.+ Valid values are `pdflatex`, `lualatex`, `xelatex`, `latexmk`,+ `tectonic`, `wkhtmltopdf`, `weasyprint`, `pagedjs-cli`,+ `prince`, `context`, `groff`, `pdfroff`, and `typst`.+ If the engine is not in your PATH, the full path of the engine+ may be specified here. If this option is not specified,+ pandoc uses the following defaults depending on the output+ format specified using `-t/--to`:++ - `-t latex` or none: `pdflatex` (other options: `xelatex`, `lualatex`,+ `tectonic`, `latexmk`)+ - `-t context`: `context`+ - `-t html`: `weasyprint` (other options: `prince`, `wkhtmltopdf`,+ `pagedjs-cli`;+ see [print-css.rocks](https://print-css.rocks) for a good+ introduction to PDF generation from HTML/CSS)+ - `-t ms`: `groff`+ - `-t typst`: `typst`++ This option is normally intended to be used when a PDF+ file is specified as `-o/--output`. However, it may still+ have an effect when other output formats are requested.+ For example, `ms` output will include `.pdfhref` macros+ only if a `--pdf-engine` is selected, and the macros will+ be differently encoded depending on whether `groff` or+ `pdfroff` is specified.++`--pdf-engine-opt=`*STRING*++: Use the given string as a command-line argument to the `pdf-engine`.+ For example, to use a persistent directory `foo` for `latexmk`'s+ auxiliary files, use `--pdf-engine-opt=-outdir=foo`.+ Note that no check for duplicate options is done.++[Dublin Core elements]: https://www.dublincore.org/specifications/dublin-core/dces/+[ISO 8601 format]: https://www.w3.org/TR/NOTE-datetime+[Encoding issue with the listings package]:+ https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings#Encoding_issue++## Citation rendering {.options}++`-C`, `--citeproc`++: Process the citations in the file, replacing them with+ rendered citations and adding a bibliography.+ Citation processing will not take place unless bibliographic+ data is supplied, either through an external file specified+ using the `--bibliography` option or the `bibliography`+ field in metadata, or via a `references` section in metadata+ containing a list of citations in CSL YAML format with+ Markdown formatting. The style is controlled by a [CSL]+ stylesheet specified using the `--csl` option or the `csl`+ field in metadata. (If no stylesheet is specified,+ the `chicago-author-date` style will be used by default.)+ The citation processing transformation may be applied before+ or after filters or Lua filters (see `--filter`,+ `--lua-filter`): these transformations are applied in the+ order they appear on the command line. For more+ information, see the section on [Citations].++ Note: if this option is specified, the `citations` extension+ will be disabled automatically in the writer, to ensure that+ the citeproc-generated citations will be rendered instead of+ the format's own citation syntax.++`--bibliography=`*FILE*++: Set the `bibliography` field in the document's metadata to *FILE*,+ overriding any value set in the metadata. If you supply+ this argument multiple times, each *FILE* will be added to+ bibliography. If *FILE* is a URL, it will be fetched+ via HTTP. If *FILE* is not found relative to the+ working directory, it will be sought in the resource path+ (see `--resource-path`).++`--csl=`*FILE*++: Set the `csl` field in the document's metadata to *FILE*,+ overriding any value set in the metadata. (This is equivalent to+ `--metadata csl=FILE`.) If *FILE* is a URL, it will be+ fetched via HTTP. If *FILE* is not found relative to the+ working directory, it will be sought in the resource path+ (see `--resource-path`) and finally in the `csl`+ subdirectory of the pandoc user data directory.++`--citation-abbreviations=`*FILE*++: Set the `citation-abbreviations` field in the document's metadata to+ *FILE*, overriding any value set in the metadata. (This is equivalent to+ `--metadata citation-abbreviations=FILE`.)+ If *FILE* is a URL, it will be fetched via HTTP. If *FILE* is not+ found relative to the working directory, it will be sought+ in the resource path (see `--resource-path`) and finally in+ the `csl` subdirectory of the pandoc user data directory.++`--natbib`++: Use [`natbib`] for citations in LaTeX output. This option+ is not for use with the `--citeproc` option or with PDF+ output. It is intended for use in producing a LaTeX file+ that can be processed with [`bibtex`].++`--biblatex`++: Use [`biblatex`] for citations in LaTeX output. This option+ is not for use with the `--citeproc` option or with PDF+ output. It is intended for use in producing a LaTeX file+ that can be processed with [`bibtex`] or [`biber`].++## Math rendering in HTML {.options}++The default is to render TeX math as far as possible using+Unicode characters. Formulas are put inside a `span` with+`class="math"`, so that they may be styled differently from the+surrounding text if needed. However, this gives acceptable+results only for basic math, usually you will want to use+`--mathjax` or another of the following options.++`--mathjax`[`=`*URL*]++: Use [MathJax] to display embedded TeX math in HTML output.+ TeX math will be put between `\(...\)` (for inline math)+ or `\[...\]` (for display math) and wrapped in `<span>` tags+ with class `math`. Then the MathJax JavaScript will render it.+ The *URL* should point to the `MathJax.js` load script.+ If a *URL* is not provided, a link to the Cloudflare CDN will+ be inserted.++`--mathml`++: Convert TeX math to [MathML] (in `epub3`, `docbook4`,+ `docbook5`, `jats`, `html4` and `html5`). This is the+ default in `odt` output. MathML is supported natively by+ the main web browsers and select e-book readers.++`--webtex`[`=`*URL*]++: Convert TeX formulas to `<img>` tags that link to an external script+ that converts formulas to images. The formula will be URL-encoded+ and concatenated with the URL provided. For SVG images you can for+ example use `--webtex https://latex.codecogs.com/svg.latex?`.+ If no URL is specified, the CodeCogs URL generating PNGs+ will be used (`https://latex.codecogs.com/png.latex?`).+ Note: the `--webtex` option will affect Markdown output+ as well as HTML, which is useful if you're targeting a+ version of Markdown without native math support.++`--katex`[`=`*URL*]++: Use [KaTeX] to display embedded TeX math in HTML output.+ The *URL* is the base URL for the KaTeX library. That directory+ should contain a `katex.min.js` and a `katex.min.css` file.+ If a *URL* is not provided, a link to the KaTeX CDN will be inserted.++`--gladtex`++: Enclose TeX math in `<eq>` tags in HTML output. The resulting HTML+ can then be processed by [GladTeX] to produce SVG images of the typeset+ formulas and an HTML file with these images embedded.++ pandoc -s --gladtex input.md -o myfile.htex+ gladtex -d image_dir myfile.htex+ # produces myfile.html and images in image_dir++[MathML]: https://www.w3.org/Math/+[MathJax]: https://www.mathjax.org+[KaTeX]: https://github.com/Khan/KaTeX+[GladTeX]: https://humenda.github.io/GladTeX/++## Options for wrapper scripts {.options}++`--dump-args[=true|false]`++: Print information about command-line arguments to *stdout*, then exit.+ This option is intended primarily for use in wrapper scripts.+ The first line of output contains the name of the output file specified+ with the `-o` option, or `-` (for *stdout*) if no output file was+ specified. The remaining lines contain the command-line arguments,+ one per line, in the order they appear. These do not include regular+ pandoc options and their arguments, but do include any options appearing+ after a `--` separator at the end of the line.++`--ignore-args[=true|false]`++: Ignore command-line arguments (for use in wrapper scripts).+ Regular pandoc options are not ignored. Thus, for example,++ pandoc --ignore-args -o foo.html -s foo.txt -- -e latin1++ is equivalent to++ pandoc -o foo.html -s++# Exit codes++If pandoc completes successfully, it will return exit code 0.+Nonzero exit codes have the following meanings:++ Code Error+----- ------------------------------------+ 1 PandocIOError+ 3 PandocFailOnWarningError+ 4 PandocAppError+ 5 PandocTemplateError+ 6 PandocOptionError+ 21 PandocUnknownReaderError+ 22 PandocUnknownWriterError+ 23 PandocUnsupportedExtensionError+ 24 PandocCiteprocError+ 25 PandocBibliographyError+ 31 PandocEpubSubdirectoryError+ 43 PandocPDFError+ 44 PandocXMLError+ 47 PandocPDFProgramNotFoundError+ 61 PandocHttpError+ 62 PandocShouldNeverHappenError+ 63 PandocSomeError+ 64 PandocParseError+ 66 PandocMakePDFError+ 67 PandocSyntaxMapError+ 83 PandocFilterError+ 84 PandocLuaError+ 89 PandocNoScriptingEngine+ 91 PandocMacroLoop+ 92 PandocUTF8DecodingError+ 93 PandocIpynbDecodingError+ 94 PandocUnsupportedCharsetError+ 95 PandocInputNotTextError+ 97 PandocCouldNotFindDataFileError+ 98 PandocCouldNotFindMetadataFileError+ 99 PandocResourceNotFound+----- ------------------------------------++# Defaults files++The `--defaults` option may be used to specify a package+of options, in the form of a YAML or JSON file. Examples in+this section will be given in YAML, but the equivalent forms in+JSON will also work.++Fields that are omitted will just have their regular+default values. So a defaults file can be as simple as+one line:++``` yaml+verbosity: INFO+```++or in JSON:++``` json+{ "verbosity": "INFO" }+```++In fields that expect a file path (or list of file paths), the+following syntax may be used to interpolate environment variables:++``` yaml+csl: ${HOME}/mycsldir/special.csl+```++`${USERDATA}` may also be used; this will always resolve to the+user data directory that is current when the defaults file is+parsed, regardless of the setting of the environment+variable `USERDATA`.++`${.}` will resolve to the directory containing the defaults+file itself. This allows you to refer to resources contained+in that directory:++``` yaml+epub-cover-image: ${.}/cover.jpg+epub-metadata: ${.}/meta.xml+resource-path:+- . # the working directory from which pandoc is run+- ${.}/images # the images subdirectory of the directory+ # containing this defaults file+```++This environment variable interpolation syntax *only* works in+fields that expect file paths.++Defaults files can be placed in the `defaults` subdirectory of+the user data directory and used from any directory. For+example, one could create a file specifying defaults for writing+letters, save it as `letter.yaml` in the `defaults` subdirectory+of the user data directory, and then invoke these defaults+from any directory using `pandoc --defaults letter`+or `pandoc -dletter`.++When multiple defaults are used, their contents will be combined.++Note that, where command-line arguments may be repeated+(`--metadata-file`, `--css`, `--include-in-header`,+`--include-before-body`, `--include-after-body`, `--variable`,+`--metadata`, `--syntax-definition`), the values specified on+the command line will combine with values specified in the+defaults file, rather than replacing them.++The following tables show the mapping between the command line and+defaults file entries.+++----------------------------------+-----------------------------------++| command line | defaults file |++:=================================+:==================================++| ``` | ``` yaml |+| foo.md | input-file: foo.md |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| foo.md bar.md | input-files: |+| | - foo.md |+| | - bar.md |+| ``` | ``` |++----------------------------------+-----------------------------------+++The value of `input-files` may be left empty to indicate input from+stdin, and it can be an empty sequence `[]` for no input.++## General options+++----------------------------------+-----------------------------------++| command line | defaults file |++:=================================+:==================================++| ``` | ``` yaml |+| --from markdown+emoji | from: markdown+emoji |+| ``` | ``` |+| | ``` yaml |+| | reader: markdown+emoji |+| | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --to markdown+hard_line_breaks | to: markdown+hard_line_breaks |+| ``` | ``` |+| | ``` yaml |+| | writer: markdown+hard_line_breaks |+| | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --output foo.pdf | output-file: foo.pdf |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --output - | output-file: |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --data-dir dir | data-dir: dir |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --defaults file | defaults: |+| ``` | - file |+| | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --verbose | verbosity: INFO |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --quiet | verbosity: ERROR |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --fail-if-warnings | fail-if-warnings: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --sandbox | sandbox: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --log=FILE | log-file: FILE |+| ``` | ``` |++----------------------------------+-----------------------------------+++Options specified in a defaults file itself always have priority over+those in another file included with a `defaults:` entry.++`verbosity` can have the values `ERROR`, `WARNING`, or `INFO`.++## Reader options+++----------------------------------+-----------------------------------++| command line | defaults file |++:=================================+:==================================++| ``` | ``` yaml |+| --shift-heading-level-by -1 | shift-heading-level-by: -1 |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --indented-code-classes python | indented-code-classes: |+| | - python |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --default-image-extension ".jpg" | default-image-extension: '.jpg' |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --file-scope | file-scope: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --citeproc \ | filters: |+| --lua-filter count-words.lua \ | - citeproc |+| --filter special.lua | - count-words.lua |+| | - type: json |+| | path: special.lua |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --metadata key=value \ | metadata: |+| --metadata key2 | key: value |+| | key2: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --metadata-file meta.yaml | metadata-files: |+| | - meta.yaml |+| ``` | ``` |+| | ``` yaml |+| | metadata-file: meta.yaml |+| | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --preserve-tabs | preserve-tabs: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --tab-stop 8 | tab-stop: 8 |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --track-changes accept | track-changes: accept |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --extract-media dir | extract-media: dir |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --abbreviations abbrevs.txt | abbreviations: abbrevs.txt |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --typst-input foo=bar | typst-inputs: |+| | foo: bar |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --trace | trace: true |+| ``` | ``` |++----------------------------------+-----------------------------------+++Metadata values specified in a defaults file are parsed as literal+string text, not Markdown.++Filters will be assumed to be Lua filters if they have the `.lua`+extension, and JSON filters otherwise. But the filter type can also be+specified explicitly, as shown. Filters are run in the order specified.+To include the built-in citeproc filter, use either `citeproc` or+`{type: citeproc}`.++## General writer options+++----------------------------------+-----------------------------------++| command line | defaults file |++:=================================+:==================================++| ``` | ``` yaml |+| --standalone | standalone: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --template letter | template: letter |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --variable key=val \ | variables: |+| --variable key2 | key: val |+| | key2: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --eol nl | eol: nl |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --dpi 300 | dpi: 300 |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --wrap preserve | wrap: "preserve" |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --columns 72 | columns: 72 |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --table-of-contents | table-of-contents: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --toc | toc: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --toc-depth 3 | toc-depth: 3 |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --strip-comments | strip-comments: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --no-highlight | syntax-highlighting: 'none' |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --syntax-highlighting kate | syntax-highlighting: kate |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --syntax-definition mylang.xml | syntax-definitions: |+| | - mylang.xml |+| ``` | ``` |+| | ``` yaml |+| | syntax-definition: mylang.xml |+| | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --include-in-header inc.tex | include-in-header: |+| | - inc.tex |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --include-before-body inc.tex | include-before-body: |+| | - inc.tex |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --include-after-body inc.tex | include-after-body: |+| | - inc.tex |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --resource-path .:foo | resource-path: ['.','foo'] |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --request-header foo:bar | request-headers: |+| | - ["User-Agent", "Mozilla/5.0"] |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --no-check-certificate | no-check-certificate: true |+| ``` | ``` |++----------------------------------+-----------------------------------++++## Options affecting specific writers+++----------------------------------+-----------------------------------++| command line | defaults file |++:=================================+:==================================++| ``` | ``` yaml |+| --self-contained | self-contained: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --link-images | link-images: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --html-q-tags | html-q-tags: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --ascii | ascii: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --reference-links | reference-links: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --reference-location block | reference-location: block |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --figure-caption-position=above | figure-caption-position: above |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --table-caption-position=below | table-caption-position: below |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --markdown-headings atx | markdown-headings: atx |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --list-tables | list-tables: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --top-level-division chapter | top-level-division: chapter |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --number-sections | number-sections: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --number-offset=1,4 | number-offset: \[1,4\] |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --listings | listings: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --list-of-figures | list-of-figures: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --lof | lof: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --list-of-tables | list-of-tables: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --lot | lot: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --incremental | incremental: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --slide-level 2 | slide-level: 2 |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --section-divs | section-divs: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --email-obfuscation references | email-obfuscation: references |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --id-prefix ch1 | identifier-prefix: ch1 |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --title-prefix MySite | title-prefix: MySite |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --css styles/screen.css \ | css: |+| --css styles/special.css | - styles/screen.css |+| | - styles/special.css |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --reference-doc my.docx | reference-doc: my.docx |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --epub-cover-image cover.jpg | epub-cover-image: cover.jpg |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --epub-title-page=false | epub-title-page: false |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --epub-metadata meta.xml | epub-metadata: meta.xml |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --epub-embed-font special.otf \ | epub-fonts: |+| --epub-embed-font headline.otf | - special.otf |+| | - headline.otf |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --split-level 2 | split-level: 2 |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --chunk-template="%i.html" | chunk-template: "%i.html" |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --epub-subdirectory="" | epub-subdirectory: '' |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --ipynb-output best | ipynb-output: best |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --pdf-engine xelatex | pdf-engine: xelatex |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --pdf-engine-opt=--shell-escape | pdf-engine-opts: |+| | - '-shell-escape' |+| ``` | ``` |+| | ``` yaml |+| | pdf-engine-opt: '-shell-escape' |+| | ``` |++----------------------------------+-----------------------------------+++## Citation rendering+++----------------------------------+-----------------------------------++| command line | defaults file |++:=================================+:==================================++| ``` | ``` yaml |+| --citeproc | citeproc: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --bibliography logic.bib | bibliography: logic.bib |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --csl ieee.csl | csl: ieee.csl |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --citation-abbreviations ab.json | citation-abbreviations: ab.json |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --natbib | cite-method: natbib |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --biblatex | cite-method: biblatex |+| ``` | ``` |++----------------------------------+-----------------------------------+++`cite-method` can be `citeproc`, `natbib`, or `biblatex`. This only+affects LaTeX output. If you want to use citeproc to format citations,+you should also set 'citeproc: true'.++If you need control over when the citeproc processing is done relative+to other filters, you should instead use `citeproc` in the list+of `filters` (see [Reader options](#reader-options-1)).++## Math rendering in HTML+++----------------------------------+-----------------------------------++| command line | defaults file |++:=================================+:==================================++| ``` | ``` yaml |+| --mathjax | html-math-method: |+| | method: mathjax |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --mathml | html-math-method: |+| | method: mathml |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --webtex | html-math-method: |+| | method: webtex |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --katex | html-math-method: |+| | method: katex |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --gladtex | html-math-method: |+| | method: gladtex |+| ``` | ``` |++----------------------------------+-----------------------------------+++In addition to the values listed above, `method` can have the+value `plain`.++If the command line option accepts a URL argument, an `url:` field can+be added to `html-math-method:`.++## Options for wrapper scripts+++----------------------------------+-----------------------------------++| command line | defaults file |++:=================================+:==================================++| ``` | ``` yaml |+| --dump-args | dump-args: true |+| ``` | ``` |++----------------------------------+-----------------------------------++| ``` | ``` yaml |+| --ignore-args | ignore-args: true |+| ``` | ``` |++----------------------------------+-----------------------------------+++# Templates++When the `-s/--standalone` option is used, pandoc uses a template to+add header and footer material that is needed for a self-standing+document. To see the default template that is used, just type++ pandoc -D *FORMAT*++where *FORMAT* is the name of the output format. A custom template+can be specified using the `--template` option. You can also override+the system default templates for a given output format *FORMAT*+by putting a file `templates/default.*FORMAT*` in the user data+directory (see `--data-dir`, above). *Exceptions:*++- For `odt` output, customize the `default.opendocument` template.+- For `docx` output, customize the `default.openxml` template.+- For `pdf` output, customize the `default.latex` template+ (or the `default.context` template, if you use `-t context`,+ or the `default.ms` template, if you use `-t ms`, or the+ `default.html` template, if you use `-t html`).+- `pptx` has no template.++Note that `docx`, `odt`, and `pptx` output can also be customized+using `--reference-doc`. Use a reference doc to adjust the styles+in your document; use a template to handle variable interpolation and+customize the presentation of metadata, the position of the table+of contents, boilerplate text, etc.++Templates contain *variables*, which allow for the inclusion of+arbitrary information at any point in the file. They may be set at the+command line using the `-V/--variable` option. If a variable is not set,+pandoc will look for the key in the document's metadata, which can be set+using either [YAML metadata blocks][Extension: `yaml_metadata_block`]+or with the `-M/--metadata` option. In addition, some variables+are given default values by pandoc. See [Variables] below for+a list of variables used in pandoc's default templates.++If you use custom templates, you may need to revise them as pandoc+changes. We recommend tracking the changes in the default templates,+and modifying your custom templates accordingly. An easy way to do this+is to fork the [pandoc-templates] repository and merge in+changes after each pandoc release.++ [pandoc-templates]: https://github.com/jgm/pandoc-templates++## Template syntax++### Comments++Anything between the sequence `$--` and the end of the+line will be treated as a comment and omitted from the output.++### Delimiters++To mark variables and control structures in the template,+either `$`...`$` or `${`...`}` may be used as delimiters.+The styles may also be mixed in the same template, but the+opening and closing delimiter must match in each case. The+opening delimiter may be followed by one or more spaces+or tabs, which will be ignored. The closing delimiter may+be preceded by one or more spaces or tabs, which will be+ignored.++To include a literal `$` in the document, use `$$`.++### Interpolated variables++A slot for an interpolated variable is a variable name surrounded+by matched delimiters. Variable names must begin with a letter+and can contain letters, numbers, `_`, `-`, and `.`. The+keywords `it`, `if`, `else`, `endif`, `for`, `sep`, and `endfor` may+not be used as variable names. Examples:++```+$foo$+$foo.bar.baz$+$foo_bar.baz-bim$+$ foo $+${foo}+${foo.bar.baz}+${foo_bar.baz-bim}+${ foo }+```++Variable names with periods are used to get at structured+variable values. So, for example, `employee.salary` will return the+value of the `salary` field of the object that is the value of+the `employee` field.++- If the value of the variable is a simple value, it will be+ rendered verbatim. (Note that no escaping is done;+ the assumption is that the calling program will escape+ the strings appropriately for the output format.)+- If the value is a list, the values will be concatenated.+- If the value is a map, the string `true` will be rendered.+- Every other value will be rendered as the empty string.++### Conditionals++A conditional begins with `if(variable)` (enclosed in+matched delimiters) and ends with `endif` (enclosed in matched+delimiters). It may optionally contain an `else` (enclosed in+matched delimiters). The `if` section is used if+`variable` has a true value, otherwise the `else`+section is used (if present). The following values count+as true:++- any map+- any array containing at least one true value+- any nonempty string+- boolean True++Note that in YAML metadata (and metadata specified on the+command line using `-M/--metadata`), unquoted `true` and `false` will be+interpreted as Boolean values. But a variable specified on the+command line using `-V/--variable` will always be given a string+value. Hence a conditional `if(foo)` will be triggered if you+use `-V foo=false`, but not if you use `-M foo=false`.++Examples:++```+$if(foo)$bar$endif$++$if(foo)$+ $foo$+$endif$++$if(foo)$+part one+$else$+part two+$endif$++${if(foo)}bar${endif}++${if(foo)}+ ${foo}+${endif}++${if(foo)}+${ foo.bar }+${else}+no foo!+${endif}+```++The keyword `elseif` may be used to simplify complex nested+conditionals:++```+$if(foo)$+XXX+$elseif(bar)$+YYY+$else$+ZZZ+$endif$+```++### For loops++A for loop begins with `for(variable)` (enclosed in+matched delimiters) and ends with `endfor` (enclosed in matched+delimiters).++- If `variable` is an array, the material inside the loop will+ be evaluated repeatedly, with `variable` being set to each+ value of the array in turn, and concatenated.+- If `variable` is a map, the material inside will be set to+ the map.+- If the value of the associated variable is not an array or+ a map, a single iteration will be performed on its value.++Examples:++```+$for(foo)$$foo$$sep$, $endfor$++$for(foo)$+ - $foo.last$, $foo.first$+$endfor$++${ for(foo.bar) }+ - ${ foo.bar.last }, ${ foo.bar.first }+${ endfor }++$for(mymap)$+$it.name$: $it.office$+$endfor$+```++You may optionally specify a separator between consecutive+values using `sep` (enclosed in matched delimiters). The+material between `sep` and the `endfor` is the separator.++```+${ for(foo) }${ foo }${ sep }, ${ endfor }+```++Instead of using `variable` inside the loop, the special+anaphoric keyword `it` may be used.++```+${ for(foo.bar) }+ - ${ it.last }, ${ it.first }+${ endfor }+```++### Partials++Partials (subtemplates stored in different files) may be+included by using the name of the partial, followed+by `()`, for example:++```+${ styles() }+```++Partials will be sought in the directory containing+the main template. The file name will be assumed to+have the same extension as the main template if it+lacks an extension. When calling the partial, the+full name including file extension can also be used:++```+${ styles.html() }+```++(If a partial is not found in the directory of the+template and the template path is given as a relative+path, it will also be sought in the `templates`+subdirectory of the user data directory.)++Partials may optionally be applied to variables using+a colon:++```+${ date:fancy() }++${ articles:bibentry() }+```++If `articles` is an array, this will iterate over its+values, applying the partial `bibentry()` to each one. So the+second example above is equivalent to++```+${ for(articles) }+${ it:bibentry() }+${ endfor }+```++Note that the anaphoric keyword `it` must be used when+iterating over partials. In the above examples,+the `bibentry` partial should contain `it.title`+(and so on) instead of `articles.title`.++Final newlines are omitted from included partials.++Partials may include other partials.++A separator between values of an array may be specified+in square brackets, immediately after the variable name+or partial:++```+${months[, ]}++${articles:bibentry()[; ]}+```++The separator in this case is literal and (unlike with `sep`+in an explicit `for` loop) cannot contain interpolated+variables or other template directives.++### Nesting++To ensure that content is "nested," that is, subsequent lines+indented, use the `^` directive:++```+$item.number$ $^$$item.description$ ($item.price$)+```++In this example, if `item.description` has multiple lines,+they will all be indented to line up with the first line:++```+00123 A fine bottle of 18-year old+ Oban whiskey. ($148)+```++To nest multiple lines to the same level, align them+with the `^` directive in the template. For example:++```+$item.number$ $^$$item.description$ ($item.price$)+ (Available til $item.sellby$.)+```++will produce++```+00123 A fine bottle of 18-year old+ Oban whiskey. ($148)+ (Available til March 30, 2020.)+```++If a variable occurs by itself on a line, preceded by whitespace+and not followed by further text or directives on the same line,+and the variable's value contains multiple lines, it will be+nested automatically.++### Breakable spaces++Normally, spaces in the template itself (as opposed to values of+the interpolated variables) are not breakable, but they can be+made breakable in part of the template by using the `~` keyword+(ended with another `~`).++```+$~$This long line may break if the document is rendered+with a short line length.$~$+```++### Pipes++A pipe transforms the value of a variable or partial. Pipes are+specified using a slash (`/`) between the variable name (or partial)+and the pipe name. Example:++```+$for(name)$+$name/uppercase$+$endfor$++$for(metadata/pairs)$+- $it.key$: $it.value$+$endfor$++$employee:name()/uppercase$+```++Pipes may be chained:++```+$for(employees/pairs)$+$it.key/alpha/uppercase$. $it.name$+$endfor$+```++Some pipes take parameters:++```+|----------------------|------------|+$for(employee)$+$it.name.first/uppercase/left 20 "| "$$it.name.salary/right 10 " | " " |"$+$endfor$+|----------------------|------------|+```++Currently the following pipes are predefined:++- `pairs`: Converts a map or array to an array of maps,+ each with `key` and `value` fields. If the original+ value was an array, the `key` will be the array index,+ starting with 1.++- `uppercase`: Converts text to uppercase.++- `lowercase`: Converts text to lowercase.++- `length`: Returns the length of the value: number+ of characters for a textual value, number of elements+ for a map or array.++- `reverse`: Reverses a textual value or array,+ and has no effect on other values.++- `first`: Returns the first value of an array, if+ applied to a non-empty array; otherwise returns+ the original value.++- `last`: Returns the last value of an array, if+ applied to a non-empty array; otherwise returns+ the original value.++- `rest`: Returns all but the first value of an array, if+ applied to a non-empty array; otherwise returns+ the original value.++- `allbutlast`: Returns all but the last value of an array, if+ applied to a non-empty array; otherwise returns+ the original value.++- `chomp`: Removes trailing newlines (and breakable space).++- `nowrap`: Disables line wrapping on breakable spaces.++- `alpha`: Converts textual values that can be+ read as an integer into lowercase alphabetic+ characters `a..z` (mod 26). This can be used to get lettered+ enumeration from array indices. To get uppercase+ letters, chain with `uppercase`.++- `roman`: Converts textual values that can be+ read as an integer into lowercase roman numerals.+ This can be used to get lettered enumeration from array indices.+ To get uppercase roman, chain with `uppercase`.++- `left n "leftborder" "rightborder"`: Renders a textual value+ in a block of width `n`, aligned to the left, with an optional+ left and right border. Has no effect on other values. This+ can be used to align material in tables. Widths are positive+ integers indicating the number of characters. Borders+ are strings inside double quotes; literal `"` and `\` characters+ must be backslash-escaped.++- `right n "leftborder" "rightborder"`: Renders a textual value+ in a block of width `n`, aligned to the right, and has no+ effect on other values.++- `center n "leftborder" "rightborder"`: Renders a textual+ value in a block of width `n`, aligned to the center, and has+ no effect on other values.+++## Variables++### Metadata variables++`title`, `author`, `date`+: allow identification of basic aspects of the document. Included+ in PDF metadata through LaTeX and ConTeXt. These can be set+ through a [pandoc title block][Extension: `pandoc_title_block`],+ which allows for multiple authors, or through a+ [YAML metadata block][Extension: `yaml_metadata_block`]:++ ---+ author:+ - Aristotle+ - Peter Abelard+ ...++ Note that if you just want to set PDF or HTML metadata, without+ including a title block in the document itself, you can+ set the `title-meta`, `author-meta`, and `date-meta`+ variables. (By default these are set automatically, based+ on `title`, `author`, and `date`.) The page title in HTML+ is set by `pagetitle`, which is equal to `title` by default.++`subtitle`+: document subtitle, included in HTML, EPUB, LaTeX, ConTeXt, and docx+ documents++`abstract`+: document summary, included in HTML, LaTeX, ConTeXt, AsciiDoc, and docx+ documents++`abstract-title`+: 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.++`keywords`+: list of keywords to be included in HTML, PDF, ODT, pptx, docx+ and AsciiDoc metadata; repeat as for `author`, above++`subject`+: document subject, included in ODT, PDF, docx, EPUB, and pptx metadata++`description`+: document description, included in ODT, docx and pptx metadata. Some+ applications show this as `Comments` metadata.++`category`+: document category, included in docx and pptx metadata++Additionally,+any root-level string metadata, not included in ODT, docx+or pptx metadata is added as a *custom property*.+The following [YAML] metadata block for instance:++ ---+ title: 'This is the title'+ subtitle: "This is the subtitle"+ author:+ - Author One+ - Author Two+ description: |+ This is a long+ description.++ It consists of two paragraphs+ ...++will include `title`, `author` and `description` as standard document+properties and `subtitle` as a custom property when converting to docx,+ODT or pptx.++### Language variables++`lang`+: identifies the main language of the document using IETF language+ tags (following the [BCP 47] standard), such as `en` or `en-GB`.+ The [Language subtag lookup] tool can look up or verify these tags.+ This affects most formats, and controls hyphenation in PDF output+ when using LaTeX (through [`babel`] and [`polyglossia`]) or ConTeXt.++ Use native pandoc [Divs and Spans] with the `lang` attribute to+ switch the language:++ ---+ lang: en-GB+ ...++ Text in the main document language (British English).++ ::: {lang=fr-CA}+ > Cette citation est écrite en français canadien.+ :::++ More text in English. ['Zitat auf Deutsch.']{lang=de}++`dir`+: the base script direction, either `rtl` (right-to-left)+ or `ltr` (left-to-right).++ For bidirectional documents, native pandoc `span`s and+ `div`s with the `dir` attribute (value `rtl` or `ltr`) can+ be used to override the base direction in some output+ formats. This may not always be necessary if the final+ renderer (e.g. the browser, when generating HTML) supports+ the [Unicode Bidirectional Algorithm].++ When using LaTeX for bidirectional documents, only the+ `xelatex` engine is fully supported (use+ `--pdf-engine=xelatex`).++[BCP 47]: https://tools.ietf.org/html/bcp47+[Unicode Bidirectional Algorithm]: https://www.w3.org/International/articles/inline-bidi-markup/uba-basics+[Language subtag lookup]: https://r12a.github.io/app-subtags/++### Variables for HTML++`document-css`+: Enables inclusion of most of the [CSS] in the `styles.html`+ [partial](#partials) (have a look with+ `pandoc --print-default-data-file=templates/styles.html`).+ Unless you use `--css`, this variable+ is set to `true` by default. You can disable it with+ e.g. `pandoc -M document-css=false`.++`mainfont`+: sets the CSS `font-family` property on the `html` element.++`fontsize`+: sets the base CSS `font-size`, which you'd usually set+ to e.g. `20px`, but it also accepts `pt`+ (12pt = 16px in most browsers).++`fontcolor`+: sets the CSS `color` property on the `html` element.++`linkcolor`+: sets the CSS `color` property on all links.++`monofont`+: sets the CSS `font-family` property on `code` elements.++`monobackgroundcolor`+: sets the CSS `background-color` property on `code` elements+ and adds extra padding.++`linestretch`+: sets the CSS `line-height` property on the `html` element,+ which is preferred to be unitless.++`maxwidth`+: sets the CSS `max-width` property (default is 36em).++`backgroundcolor`+: sets the CSS `background-color` property on the `html` element.++`margin-left`, `margin-right`, `margin-top`, `margin-bottom`+: sets the corresponding CSS `padding` properties on the `body` element.++To override or extend some [CSS] for just one document, include for example:++ ---+ header-includes: |+ <style>+ blockquote {+ font-style: italic;+ }+ tr.even {+ background-color: #f0f0f0;+ }+ td, th {+ padding: 0.5em 2em 0.5em 0.5em;+ }+ tbody {+ border-bottom: none;+ }+ </style>+ ---++[CSS]: https://developer.mozilla.org/en-US/docs/Learn/CSS++### Variables for HTML math++`classoption`+: when using `--katex`, you can render display math equations+ flush left using [YAML metadata](#layout) or with `-M+ classoption=fleqn`.++### Variables for HTML slides++These affect HTML output when [producing slide shows with+pandoc](#slide-shows).++`institute`+: author affiliations: can be a list when there are multiple authors++`revealjs-url`+: base URL for reveal.js documents (defaults to+ `https://unpkg.com/reveal.js@^5`)++`s5-url`+: base URL for S5 documents (defaults to `s5/default`)++`slidy-url`+: base URL for Slidy documents (defaults to+ `https://www.w3.org/Talks/Tools/Slidy2`)++`slideous-url`+: base URL for Slideous documents (defaults to `slideous`)++`title-slide-attributes`+: additional attributes for the title slide of reveal.js slide shows.+ See [background in reveal.js, beamer, and pptx] for an example.++`highlightjs-theme`+: highlight.js theme for code highlighting when using+ `--syntax-highlighting=idiomatic` with reveal.js (defaults to+ `monokai`). See the [highlight.js demo page] for available themes.++[highlight.js demo page]: https://highlightjs.org/demo++All [reveal.js configuration options] are available as variables.+To turn off boolean flags that default to true in reveal.js, use `0`.++[reveal.js configuration options]: https://revealjs.com/config/++### Variables for Beamer slides++These variables change the appearance of PDF slides using [`beamer`].++`aspectratio`+: slide aspect ratio (`43` for 4:3 [default], `169` for 16:9,+ `1610` for 16:10, `149` for 14:9, `141` for 1.41:1, `54` for 5:4,+ `32` for 3:2)++`beameroption`+: add extra beamer option with `\setbeameroption{}`++`institute`+: author affiliations: can be a list when there are multiple authors++`logo`+: logo image for slides++`logooptions`+: options for logo image (e.g., `width`, `height`)++`navigation`+: controls navigation symbols (default is `empty` for no navigation+ symbols; other valid values are `frame`, `vertical`, and `horizontal`)++`section-titles`+: enables "title pages" for new sections (default is true)++`theme`, `colortheme`, `fonttheme`, `innertheme`, `outertheme`+: beamer themes++`themeoptions`, `colorthemeoptions`, `fontthemeoptions`, `innerthemeoptions`, `outerthemeoptions`+: options for LaTeX beamer themes (lists)++`titlegraphic`+: image for title slide: can be a list++`titlegraphicoptions`+: options for title slide image (e.g., `width`, `height`)++`shorttitle`, `shortsubtitle`, `shortauthor`, `shortinstitute`, `shortdate`+: some beamer themes use short versions of the title, subtitle, author,+ institute, date++### Variables for PowerPoint++These variables control the visual aspects of a slide show that+are not easily controlled via templates.++`monofont`+: font to use for code.++### Variables for LaTeX++Pandoc uses these variables when [creating a PDF] with a LaTeX engine.++#### Layout++`block-headings`+: make `\paragraph` and `\subparagraph` (fourth- and+ fifth-level headings, or fifth- and sixth-level with book+ classes) free-standing rather than run-in; requires further+ formatting to distinguish from `\subsubsection` (third- or+ fourth-level headings). Instead of using this option,+ [KOMA-Script] can adjust headings more extensively:++ ---+ documentclass: scrartcl+ header-includes: |+ \RedeclareSectionCommand[+ beforeskip=-10pt plus -2pt minus -1pt,+ afterskip=1sp plus -1sp minus 1sp,+ font=\normalfont\itshape]{paragraph}+ \RedeclareSectionCommand[+ beforeskip=-10pt plus -2pt minus -1pt,+ afterskip=1sp plus -1sp minus 1sp,+ font=\normalfont\scshape,+ indent=0pt]{subparagraph}+ ...++`classoption`+: option for document class, e.g. `oneside`; repeat for multiple options:++ ---+ classoption:+ - twocolumn+ - landscape+ ...++`documentclass`+: document class: usually one of the standard classes,+ [`article`], [`book`], and [`report`]; the [KOMA-Script]+ equivalents, `scrartcl`, `scrbook`, and `scrreprt`, which+ default to smaller margins; or [`memoir`]++`geometry`+: option for [`geometry`] package, e.g. `margin=1in`;+ repeat for multiple options:++ ---+ geometry:+ - top=30mm+ - left=20mm+ - heightrounded+ ...++`shorthands`+: Enable language-specific shorthands when loading `babel`.+ (By default, pandoc includes `shorthands=off` when loading+ `babel`, disabling language-specific shorthands.)++`hyperrefoptions`+: option for [`hyperref`] package, e.g. `linktoc=all`;+ repeat for multiple options:++ ---+ hyperrefoptions:+ - linktoc=all+ - pdfwindowui+ - pdfpagemode=FullScreen+ ...++`indent`+: if true, pandoc will use document class settings for+ indentation (the default LaTeX template otherwise removes+ indentation and adds space between paragraphs)++`linestretch`+: adjusts line spacing using the [`setspace`]+ package, e.g. `1.25`, `1.5`++`margin-left`, `margin-right`, `margin-top`, `margin-bottom`+: sets margins if `geometry` is not used (otherwise `geometry`+ overrides these)++`pagestyle`+: control `\pagestyle{}`: the default article class+ supports `plain` (default), `empty` (no running heads or page numbers),+ and `headings` (section titles in running heads)++`papersize`+: paper size, e.g. `letter`, `a4`++`secnumdepth`+: numbering depth for sections (with `--number-sections` option+ or `numbersections` variable)++`beamerarticle`+: produce an article from Beamer slides. Note: if you set+ this variable, you must specify the beamer writer but use the+ default *LaTeX* template: for example,+ `pandoc -Vbeamerarticle -t beamer --template default.latex`.++`handout`+: produce a handout version of Beamer slides (with overlays condensed+ into single slides)++`csquotes`+: load `csquotes` package and use `\enquote` or `\enquote*` for quoted text.++`csquotesoptions`+: options to use for `csquotes` package (repeat for multiple options).++`babeloptions`+: options to pass to the babel package (may be repeated for+ multiple options). This defaults to `provide=*` if the main+ language isn't a European language written with Latin or+ Cyrillic script or Vietnamese. Most users will not need to+ adjust the default setting.++#### Fonts++`fontenc`+: allows font encoding to be specified through `fontenc` package (with+ `pdflatex`); default is `T1` (see [LaTeX font encodings guide])++`fontfamily`+: font package for use with `pdflatex`:+ [TeX Live] includes many options, documented in the [LaTeX Font Catalogue].+ The default is [Latin Modern][`lm`].++`fontfamilyoptions`+: options for package used as `fontfamily`; repeat for multiple options.+ For example, to use the Libertine font with proportional lowercase+ (old-style) figures through the [`libertinus`] package:++ ---+ fontfamily: libertinus+ fontfamilyoptions:+ - osf+ - p+ ...++`fontsize`+: font size for body text. The standard classes allow 10pt, 11pt, and+ 12pt. To use another size, set `documentclass` to one of+ the [KOMA-Script] classes, such as `scrartcl` or `scrbook`.++`mainfont`, `sansfont`, `monofont`, `mathfont`, `CJKmainfont`, `CJKsansfont`, `CJKmonofont`+: font families for use with `xelatex` or+ `lualatex`: take the name of any system font, using the+ [`fontspec`] package. `CJKmainfont` uses the [`xecjk`] package if `xelatex` is used,+ or the [`luatexja`] package if `lualatex` is used.++`mainfontoptions`, `sansfontoptions`, `monofontoptions`, `mathfontoptions`, `CJKoptions`, `luatexjapresetoptions`+: options to use with `mainfont`, `sansfont`, `monofont`, `mathfont`,+ `CJKmainfont` in `xelatex` and `lualatex`. Allow for any+ choices available through [`fontspec`]; repeat for multiple+ options. For example, to use the [TeX Gyre] version of+ Palatino with lowercase figures:++ ---+ mainfont: TeX Gyre Pagella+ mainfontoptions:+ - Numbers=Lowercase+ - Numbers=Proportional+ ...++`mainfontfallback`, `sansfontfallback`, `monofontfallback`+: fonts to try if a glyph isn't found in `mainfont`, `sansfont`, or `monofont`+ respectively. These are lists. The font name must be followed by a colon+ and optionally a set of options, for example:++ ---+ mainfontfallback:+ - "FreeSans:"+ - "NotoColorEmoji:mode=harf"+ ...++ Font fallbacks currently only work with `lualatex`.++`babelfonts`+: a map of Babel language names (e.g. `chinese`) to the font+ to be used with the language:++ ---+ babelfonts:+ chinese-hant: "Noto Serif CJK TC"+ russian: "Noto Serif"+ ...++`microtypeoptions`+: options to pass to the microtype package++#### Links++`colorlinks`+: add color to link text; automatically enabled if any of+ `linkcolor`, `filecolor`, `citecolor`, `urlcolor`, or `toccolor` are set++`boxlinks`+: add visible box around links (has no effect if `colorlinks` is set)++`linkcolor`, `filecolor`, `citecolor`, `urlcolor`, `toccolor`+: color for internal links, external links, citation links, linked+ URLs, and links in table of contents, respectively: uses options+ allowed by [`xcolor`], including the `dvipsnames`, `svgnames`, and+ `x11names` lists++`links-as-notes`+: causes links to be printed as footnotes++`urlstyle`+: style for URLs (e.g., `tt`, `rm`, `sf`, and, the default, `same`)++#### Front matter++`lof`, `lot`+: include list of figures, list of tables (can also be set using+ `--lof/--list-of-figures`, `--lot/--list-of-tables`)++`thanks`+: contents of acknowledgments footnote after document title++`toc`+: include table of contents (can also be set using+ `--toc/--table-of-contents`)++`toc-depth`+: level of section to include in table of contents++#### BibLaTeX Bibliographies++These variables function when using BibLaTeX for [citation rendering].++`biblatexoptions`+: list of options for biblatex++`biblio-style`+: bibliography style, when used with `--natbib` and `--biblatex`++`biblio-title`+: bibliography title, when used with `--natbib` and `--biblatex`++`bibliography`+: bibliography to use for resolving references++`natbiboptions`+: list of options for natbib++#### Other++`pdf-trailer-id`+: the PDF trailer ID; must be two PDF byte strings if set,+ conventionally with 16 bytes each. E.g.,+ `<00112233445566778899aabbccddeeff>+ <00112233445566778899aabbccddeeff>`.++ See the section on [reproducible builds].++`pdfstandard`+: PDF standard(s) for the document, e.g. `ua-2`, `a-4f`.+ Supports PDF/A, PDF/X, and PDF/UA variants.+ Requires LuaLaTeX and LaTeX 2023+. Repeat for multiple standards:++ ---+ pdfstandard:+ - ua-2+ - a-4f+ ...++[KOMA-Script]: https://ctan.org/pkg/koma-script+[LaTeX Font Catalogue]: https://tug.org/FontCatalogue/+[LaTeX font encodings guide]: https://ctan.org/pkg/encguide+[TeX Gyre]: http://www.gust.org.pl/projects/e-foundry/tex-gyre+[`article`]: https://ctan.org/pkg/article+[`book`]: https://ctan.org/pkg/book+[`libertinus`]: https://ctan.org/pkg/libertinus+[`memoir`]: https://ctan.org/pkg/memoir+[`report`]: https://ctan.org/pkg/report++### Variables for ConTeXt++Pandoc uses these variables when [creating a PDF] with ConTeXt.++`fontsize`+: font size for body text (e.g. `10pt`, `12pt`)++`headertext`, `footertext`+: text to be placed in running header or footer (see [ConTeXt Headers and+ Footers]); repeat up to four times for different placement++`indenting`+: controls indentation of paragraphs, e.g. `yes,small,next` (see+ [ConTeXt Indentation]); repeat for multiple options++`interlinespace`+: adjusts line spacing, e.g. `4ex` (using [`setupinterlinespace`]);+ repeat for multiple options++`layout`+: options for page margins and text arrangement (see [ConTeXt Layout]);+ repeat for multiple options++`linkcolor`, `contrastcolor`+: color for links outside and inside a page, e.g. `red`, `blue` (see+ [ConTeXt Color])++`linkstyle`+: typeface style for links, e.g. `normal`, `bold`, `slanted`, `boldslanted`,+ `type`, `cap`, `small`++`lof`, `lot`+: include list of figures, list of tables++`mainfont`, `sansfont`, `monofont`, `mathfont`+: font families: take the name of any system font (see+ [ConTeXt Font Switching])++`mainfontfallback`, `sansfontfallback`, `monofontfallback`+: list of fonts to try, in order, if a glyph is not found in the+ main font. Use `\definefallbackfamily`-compatible font name syntax.+ Emoji fonts are unsupported.++`margin-left`, `margin-right`, `margin-top`, `margin-bottom`+: sets margins, if `layout` is not used (otherwise `layout`+ overrides these)++`pagenumbering`+: page number style and location (using [`setuppagenumbering`]);+ repeat for multiple options++`papersize`+: paper size, e.g. `letter`, `A4`, `landscape` (see [ConTeXt Paper Setup]);+ repeat for multiple options++`pdfa`+: adds to the preamble the setup necessary to generate PDF/A+ of the type specified, e.g. `1a:2005`, `2a`. If no type is+ specified (i.e. the value is set to True, by e.g.+ `--metadata=pdfa` or `pdfa: true` in a YAML metadata block),+ `1b:2005` will be used as default, for reasons of backwards+ compatibility. Using `--variable=pdfa` without specified value+ is not supported. To successfully generate PDF/A the required+ ICC color profiles have to be available and the content and all+ included files (such as images) have to be standard-conforming.+ The ICC profiles and output intent may be specified using the+ variables `pdfaiccprofile` and `pdfaintent`. See also [ConTeXt+ PDFA] for more details.++`pdfaiccprofile`+: when used in conjunction with `pdfa`, specifies the ICC profile to use+ in the PDF, e.g. `default.cmyk`. If left unspecified, `sRGB.icc` is+ used as default. May be repeated to include multiple profiles. Note that+ the profiles have to be available on the system. They can be obtained+ from [ConTeXt ICC Profiles].++`pdfaintent`+: when used in conjunction with `pdfa`, specifies the output intent for+ the colors, e.g. `ISO coated v2 300\letterpercent\space (ECI)`+ If left unspecified, `sRGB IEC61966-2.1` is used as default.++`toc`+: include table of contents (can also be set using+ `--toc/--table-of-contents`)++`urlstyle`+: typeface style for links without link text, e.g. `normal`, `bold`, `slanted`, `boldslanted`,+ `type`, `cap`, `small`++`whitespace`+: spacing between paragraphs, e.g. `none`, `small` (using+ [`setupwhitespace`])++`includesource`+: include all source documents as file attachments in the PDF file++[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/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++### Variables for `wkhtmltopdf`++Pandoc uses these variables when [creating a PDF] with [`wkhtmltopdf`].+The `--css` option also affects the output.++`footer-html`, `header-html`+: add information to the header and footer++`margin-left`, `margin-right`, `margin-top`, `margin-bottom`+: set the page margins++`papersize`+: sets the PDF paper size++### Variables for man pages++`adjusting`+: adjusts text to left (`l`), right (`r`), center (`c`),+ or both (`b`) margins++`footer`+: footer in man pages++`header`+: header in man pages++`section`+: section number in man pages++### Variables for Texinfo++`version`+: version of software (used in title and title page)++`filename`+: name of info file to be generated (defaults to a name based on the+ texi filename)++### Variables for Typst++`template`+: Typst template to use (relative path only).++`margin`+: A dictionary with the fields defined in the Typst documentation:+ `x`, `y`, `top`, `bottom`, `left`, `right`.++`papersize`+: Paper size: `a4`, `us-letter`, etc.++`mainfont`+: Name of system font to use for the main font.++`fontsize`+: Font size (e.g., `12pt`).++`section-numbering`+: Schema to use for numbering sections, e.g. `1.A.1`.++`page-numbering`+: Schema to use for numbering pages, e.g. `1` or `i`, or+ an empty string to omit page numbering.++`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`+: `A` (Avant Garde), `B` (Bookman), `C` (Helvetica), `HN`+ (Helvetica Narrow), `P` (Palatino), or `T` (Times New Roman).+ This setting does not affect source code, which is always+ displayed using monospace Courier. These built-in fonts are+ limited in their coverage of characters. Additional fonts may+ be installed using the script [`install-font.sh`] provided+ by Peter Schaffter and documented in detail on [his web+ site][ms-font-steps].++`indent`+: paragraph indent (e.g. `2m`)++`lineheight`+: line height (e.g. `12p`)++`pointsize`+: point size (e.g. `10p`)++[`install-font.sh`]: https://www.schaffter.ca/mom/bin/install-font.sh+[ms-font-steps]: https://www.schaffter.ca/mom/momdoc/appendices.html#steps++### Variables set automatically++Pandoc sets these variables automatically in response to [options] or+document contents; users can also modify them. These vary depending+on the output format, and include the following:++`body`+: body of document++`date-meta`+: the `date` variable converted to ISO 8601 YYYY-MM-DD,+ included in all HTML based formats (dzslides, epub,+ html, html4, html5, revealjs, s5, slideous, slidy).+ The recognized formats for `date` are: `mm/dd/yyyy`,+ `mm/dd/yy`, `yyyy-mm-dd` (ISO 8601), `dd MM yyyy`+ (e.g. either `02 Apr 2018` or `02 April 2018`),+ `MM dd, yyyy` (e.g. `Apr. 02, 2018` or `April 02, 2018),+ `yyyy[mm[dd]]` (e.g. `20180402, `201804` or `2018`).++`header-includes`+: contents specified by `-H/--include-in-header` (may have multiple+ values)++`include-before`+: contents specified by `-B/--include-before-body` (may have+ multiple values)++`include-after`+: contents specified by `-A/--include-after-body` (may have+ multiple values)++`meta-json`+: JSON representation of all of the document's metadata. Field+ values are transformed to the selected output format.++`numbersections`+: non-null value if `-N/--number-sections` was specified++`sourcefile`, `outputfile`+: source and destination filenames, as given on the command line.+ `sourcefile` can also be a list if input comes from multiple files,+ or empty if input is from stdin. You can use the following snippet in+ your template to distinguish them:++ $if(sourcefile)$+ $for(sourcefile)$+ $sourcefile$+ $endfor$+ $else$+ (stdin)+ $endif$++ Similarly, `outputfile` can be `-` if output goes to the terminal.++ If you need absolute paths, use e.g. `$curdir$/$sourcefile$`.++`pdf-engine`+: name of PDF engine if provided using `--pdf-engine`, or the+ default engine for the format if PDF output is requested.++`curdir`+: working directory from which pandoc is run.++`pandoc-version`+: pandoc version.++`toc`+: non-null value if `--toc/--table-of-contents` was specified++`toc-title`+: title of table of contents (works only with EPUB,+ HTML, revealjs, opendocument, odt, docx, pptx, beamer, LaTeX).+ Note that in docx and pptx a custom `toc-title` will be+ picked up from metadata, but cannot be set as a variable.++[pandoc-templates]: https://github.com/jgm/pandoc-templates++# Extensions++The behavior of some of the readers and writers can be adjusted by+enabling or disabling various extensions.++An extension can be enabled by adding `+EXTENSION`+to the format name and disabled by adding `-EXTENSION`. For example,+`--from markdown_strict+footnotes` is strict Markdown with footnotes+enabled, while `--from markdown-footnotes-pipe_tables` is pandoc's+Markdown without footnotes or pipe tables.++The Markdown reader and writer make by far the most use of extensions.+Extensions only used by them are therefore covered in the+section [Pandoc's Markdown] below (see [Markdown variants] for+`commonmark` and `gfm`). In the following, extensions that also work+for other formats are covered.++Note that Markdown extensions added to the `ipynb` format+affect Markdown cells in Jupyter notebooks (as do command-line+options like `--markdown-headings`).++## Typography++### Extension: `smart` ###++Interpret straight quotes as curly quotes, `---` as em-dashes,+`--` as en-dashes, and `...` as ellipses. Nonbreaking spaces are+inserted after certain abbreviations, such as "Mr."++This extension can be enabled/disabled for the following formats:++input formats+: `markdown`, `commonmark`, `latex`, `mediawiki`, `org`, `rst`, `twiki`,+ `html`++output formats+: `markdown`, `latex`, `context`, `org`, `rst`++enabled by default in+: `markdown`, `latex`, `context` (both input and output)++Note: If you are *writing* Markdown, then the `smart` extension+has the reverse effect: what would have been curly quotes comes+out straight.++In LaTeX, `smart` means to use the standard TeX ligatures+for quotation marks (` `` ` and ` '' ` for double quotes,+`` ` `` and `` ' `` for single quotes) and dashes (`--` for+en-dash and `---` for em-dash). If `smart` is disabled,+then in reading LaTeX pandoc will parse these characters+literally. In writing LaTeX, enabling `smart` tells pandoc+to use the ligatures when possible; if `smart` is disabled+pandoc will use unicode quotation mark and dash characters.++## Headings and sections++### Extension: `auto_identifiers` ###++A heading without an explicitly specified identifier will be+automatically assigned a unique identifier based on the heading text.++This extension can be enabled/disabled for the following formats:++input formats+: `markdown`, `latex`, `rst`, `mediawiki`, `textile`, `man`++output formats+: `markdown`, `muse`++enabled by default in+: `markdown`, `muse`, `man`++The default algorithm used to derive the identifier from the+heading text is:++ - Remove all formatting, links, etc.+ - Remove all footnotes.+ - Remove all non-alphanumeric characters,+ except underscores, hyphens, and periods.+ - Replace all spaces and newlines with hyphens.+ - Convert all alphabetic characters to lowercase.+ - Remove everything up to the first letter (identifiers may+ not begin with a number or punctuation mark).+ - If nothing is left after this, use the identifier `section`.++Thus, for example,++ Heading Identifier+ ------------------------------- ----------------------------+ `Heading identifiers in HTML` `heading-identifiers-in-html`+ `Maître d'hôtel` `maître-dhôtel`+ `*Dogs*?--in *my* house?` `dogs--in-my-house`+ `[HTML], [S5], or [RTF]?` `html-s5-or-rtf`+ `3. Applications` `applications`+ `33` `section`++These rules should, in most cases, allow one to determine the identifier+from the heading text. The exception is when several headings have the+same text; in this case, the first will get an identifier as described+above; the second will get the same identifier with `-1` appended; the+third with `-2`; and so on.++(However, a different algorithm is used if+`gfm_auto_identifiers` is enabled; see below.)++These identifiers are used to provide link targets in the table of+contents generated by the `--toc|--table-of-contents` option. They+also make it easy to provide links from one section of a document to+another. A link to this section, for example, might look like this:++ See the section on+ [heading identifiers](#heading-identifiers-in-html-latex-and-context).++Note, however, that this method of providing links to sections works+only in HTML, LaTeX, and ConTeXt formats.++If the `--section-divs` option is specified, then each section will+be wrapped in a `section` (or a `div`, if `html4` was specified),+and the identifier will be attached to the enclosing `<section>`+(or `<div>`) tag rather than the heading itself. This allows entire+sections to be manipulated using JavaScript or treated differently in+CSS.++### Extension: `ascii_identifiers` ###++Causes the identifiers produced by `auto_identifiers` to be pure ASCII.+Accents are stripped off of accented Latin letters, and non-Latin+letters are omitted.++### Extension: `gfm_auto_identifiers` ###++Changes the algorithm used by `auto_identifiers` to conform to+GitHub's method. Spaces are converted to dashes (`-`),+uppercase characters to lowercase characters, and punctuation+characters other than `-` and `_` are removed.+Emojis are replaced by their names.++## Math Input++The extensions [`tex_math_dollars`](#extension-tex_math_dollars),+[`tex_math_gfm`](#extension-tex_math_gfm),+[`tex_math_single_backslash`](#extension-tex_math_single_backslash), and+[`tex_math_double_backslash`](#extension-tex_math_double_backslash)+are described in the section about Pandoc's Markdown.++However, they can also be used with HTML input. This is handy for+reading web pages formatted using MathJax, for example.++## Raw HTML/TeX++The following extensions are described in more detail in+their respective sections of [Pandoc's Markdown]:++- [`raw_html`](#extension-raw_html) allows HTML elements which+ are not representable in pandoc's AST to be parsed as raw HTML.+ By default, this is disabled for HTML input.++- [`raw_tex`](#extension-raw_tex) allows raw LaTeX, TeX, and ConTeXt+ to be included in a document. This extension can be enabled/disabled+ for the following formats (in addition to `markdown`):++ input formats+ : `latex`, `textile`, `html` (environments, `\ref`, and+ `\eqref` only), `ipynb`++ output formats+ : `textile`, `commonmark`++ Note: as applied to `ipynb`, `raw_html` and `raw_tex` affect not+ only raw TeX in Markdown cells, but data with mime type+ `text/html` in output cells. Since the `ipynb` reader attempts+ to preserve the richest possible outputs when several options+ are given, you will get best results if you disable `raw_html`+ and `raw_tex` when converting to formats like `docx` which don't+ allow raw `html` or `tex`.++- [`native_divs`](#extension-native_divs) causes HTML `div`+ elements to be parsed as native pandoc Div blocks.+ If you want them to be parsed as raw HTML, use+ `-f html-native_divs+raw_html`.++- [`native_spans`](#extension-native_spans) causes HTML `span`+ elements to be parsed as native pandoc Span inlines.+ If you want them to be parsed as raw HTML, use+ `-f html-native_spans+raw_html`. If you want to drop all+ `div`s and `span`s when converting HTML to Markdown, you+ can use `pandoc -f html-native_divs-native_spans -t markdown`.++## Literate Haskell support++### Extension: `literate_haskell` ###++Treat the document as literate Haskell source.++This extension can be enabled/disabled for the following formats:++input formats+: `markdown`, `rst`, `latex`++output formats+: `markdown`, `rst`, `latex`, `html`++If you append `+lhs` (or `+literate_haskell`) to one of the formats+above, pandoc will treat the document as literate Haskell source.+This means that++ - In Markdown input, "bird track" sections will be parsed as Haskell+ code rather than block quotations. Text between `\begin{code}`+ and `\end{code}` will also be treated as Haskell code. For+ ATX-style headings the character '=' will be used instead of '#'.++ - In Markdown output, code blocks with classes `haskell` and `literate`+ will be rendered using bird tracks, and block quotations will be+ indented one space, so they will not be treated as Haskell code.+ In addition, headings will be rendered setext-style (with underlines)+ rather than ATX-style (with '#' characters). (This is because ghc+ treats '#' characters in column 1 as introducing line numbers.)++ - In restructured text input, "bird track" sections will be parsed+ as Haskell code.++ - In restructured text output, code blocks with class `haskell` will+ be rendered using bird tracks.++ - In LaTeX input, text in `code` environments will be parsed as+ Haskell code.++ - In LaTeX output, code blocks with class `haskell` will be rendered+ inside `code` environments.++ - In HTML output, code blocks with class `haskell` will be rendered+ with class `literatehaskell` and bird tracks.++Examples:++ pandoc -f markdown+lhs -t html++reads literate Haskell source formatted with Markdown conventions and writes+ordinary HTML (without bird tracks).++ pandoc -f markdown+lhs -t html+lhs++writes HTML with the Haskell code in bird tracks, so it can be copied+and pasted as literate Haskell source.++Note that GHC expects the bird tracks in the first column, so indented+literate code blocks (e.g. inside an itemized environment) will not be+picked up by the Haskell compiler.++## Other extensions++### Extension: `empty_paragraphs` ###++Allows empty paragraphs. By default empty paragraphs are+omitted.++This extension can be enabled/disabled for the following formats:++input formats+: `docx`, `html`++output formats+: `docx`, `odt`, `opendocument`, `html`, `latex`++### Extension: `native_numbering` ###++Enables native numbering of figures and tables. Enumeration+starts at 1.++This extension can be enabled/disabled for the following formats:++output formats+: `odt`, `opendocument`, `docx`++### Extension: `xrefs_name` ###++Links to headings, figures and tables inside the document are+substituted with cross-references that will use the name or caption+of the referenced item. The original link text is replaced once+the generated document is refreshed. This extension can be combined+with `xrefs_number` in which case numbers will appear before the+name.++Text in cross-references is only made consistent with the referenced+item once the document has been refreshed.++This extension can be enabled/disabled for the following formats:++output formats+: `odt`, `opendocument`++### Extension: `xrefs_number` ###++Links to headings, figures and tables inside the document are+substituted with cross-references that will use the number+of the referenced item. The original link text is discarded.+This extension can be combined with `xrefs_name` in which case+the name or caption numbers will appear after the number.++For the `xrefs_number` to be useful heading numbers must be enabled+in the generated document, also table and figure captions must be enabled+using for example the `native_numbering` extension.++Numbers in cross-references are only visible in the final document once+it has been refreshed.++This extension can be enabled/disabled for the following formats:++output formats+: `odt`, `opendocument`++### Extension: `styles` ### {#ext-styles}++When converting from docx, add `custom-styles` attributes+for all docx styles, regardless of whether pandoc understands+the meanings of these styles. Because attributes cannot be+added directly to paragraphs or text in the pandoc AST,+paragraph styles will cause Divs to be created and character+styles will cause Spans to be created to hold the attributes.+(Table styles will be added to the Table elements directly.)+This extension can be used with [docx custom styles](#custom-styles).++input formats+: `docx`++### Extension: `amuse` ###++In the `muse` input format, this enables Text::Amuse+extensions to Emacs Muse markup.++### Extension: `raw_markdown` ###++In the `ipynb` input format, this causes Markdown cells+to be included as raw Markdown blocks (allowing lossless+round-tripping) rather than being parsed. Use this only+when you are targeting `ipynb` or a Markdown-based+output format.++### Extension: `citations` (typst) {#typst-citations}++When the `citations` extension is enabled in `typst`+(as it is by default), `typst` citations will+be parsed as native pandoc citations, and native+pandoc citations will be rendered as `typst` citations.++### Extension: `citations` (org) {#org-citations}++When the `citations` extension is enabled in `org`,+org-cite and org-ref style citations will be parsed as+native pandoc citations, and org-cite citations will+be used to render native pandoc citations.++ [org-cite]: https://orgmode.org/manual/Citations.html+ [org-ref]: https://github.com/jkitchin/org-ref++### Extension: `citations` (docx) {#docx-citations}++When `citations` is enabled in `docx`, citations inserted+by Zotero or Mendeley or EndNote plugins will be parsed as native+pandoc citations. (Otherwise, the formatted citations generated+by the bibliographic software will be parsed as regular text.)++### Extension: `fancy_lists` (org) {#org-fancy-lists}++Some aspects of [Pandoc's Markdown fancy lists](#extension-fancy_lists) are also+accepted in `org` input, mimicking the option `org-list-allow-alphabetical` in+Emacs. As in Org Mode, enabling this extension allows lowercase and uppercase+alphabetical markers for ordered lists to be parsed in addition to arabic ones.+Note that for Org, this does not include roman numerals or the `#` placeholder+that are enabled by the extension in Pandoc's Markdown.++### Extension: `element_citations` ###++In the `jats` output formats, this causes reference items to+be replaced with `<element-citation>` elements. These+elements are not influenced by CSL styles, but all information+on the item is included in tags.++### Extension: `ntb` ###++In the `context` output format this enables the use of [Natural Tables+(TABLE)](https://wiki.contextgarden.net/TABLE) instead of the default+[Extreme Tables (xtables)](https://wiki.contextgarden.net/xtables).+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+suitable for the production of tagged PDFs. This includes+additional markers for paragraphs and alternative markup for+emphasized text. The `emphasis-command` template variable is set+if the extension is enabled.++# Pandoc's Markdown++Pandoc understands an extended and slightly revised version of+John Gruber's [Markdown] syntax. This document explains the syntax,+noting differences from original Markdown. Except where noted, these+differences can be suppressed by using the `markdown_strict` format instead+of `markdown`. Extensions can be enabled or disabled to specify the+behavior more granularly. They are described in the following. See also+[Extensions] above, for extensions that work also on other formats.++## Philosophy++Markdown is designed to be easy to write, and, even more importantly,+easy to read:++> A Markdown-formatted document should be publishable as-is, as plain+> text, without looking like it's been marked up with tags or formatting+> instructions.\+> -- [John Gruber](https://daringfireball.net/projects/markdown/syntax#philosophy)++This principle has guided pandoc's decisions in finding syntax for+tables, footnotes, and other extensions.++There is, however, one respect in which pandoc's aims are different+from the original aims of Markdown. Whereas Markdown was originally+designed with HTML generation in mind, pandoc is designed for multiple+output formats. Thus, while pandoc allows the embedding of raw HTML,+it discourages it, and provides other, non-HTMLish ways of representing+important document elements like definition lists, tables, mathematics, and+footnotes.++## Paragraphs++A paragraph is one or more lines of text followed by one or more blank lines.+Newlines are treated as spaces, so you can reflow your paragraphs as you like.+If you need a hard line break, put two or more spaces at the end of a line.++### Extension: `escaped_line_breaks` ###++A backslash followed by a newline is also a hard line break.+Note: in multiline and grid table cells, this is the only way+to create a hard line break, since trailing spaces in the cells+are ignored.++## Headings++There are two kinds of headings: Setext and ATX.++### Setext-style headings ###++A setext-style heading is a line of text "underlined" with a row of `=` signs+(for a level-one heading) or `-` signs (for a level-two heading):++ A level-one heading+ ===================++ A level-two heading+ -------------------++The heading text can contain inline formatting, such as emphasis (see+[Inline formatting], below).+++### ATX-style headings ###++An ATX-style heading consists of one to six `#` signs and a line of+text, optionally followed by any number of `#` signs. The number of+`#` signs at the beginning of the line is the heading level:++ ## A level-two heading++ ### A level-three heading ###++As with setext-style headings, the heading text can contain formatting:++ # A level-one heading with a [link](/url) and *emphasis*++### Extension: `blank_before_header` ###++Original Markdown syntax does not require a blank line before a heading.+Pandoc does require this (except, of course, at the beginning of the+document). The reason for the requirement is that it is all too easy for a+`#` to end up at the beginning of a line by accident (perhaps through line+wrapping). Consider, for example:++ I like several of their flavors of ice cream:+ #22, for example, and #5.++### Extension: `space_in_atx_header` ###++Many Markdown implementations do not require a space between the+opening `#`s of an ATX heading and the heading text, so that+`#5 bolt` and `#hashtag` count as headings. With this extension,+pandoc does require the space.++### Heading identifiers ###++See also the [`auto_identifiers`+extension](#extension-auto_identifiers) above.++### Extension: `header_attributes` ###++Headings can be assigned attributes using this syntax at the end+of the line containing the heading text:++ {#identifier .class .class key=value key=value}++Thus, for example, the following headings will all be assigned the identifier+`foo`:++ # My heading {#foo}++ ## My heading ## {#foo}++ My other heading {#foo}+ ---------------++(This syntax is compatible with [PHP Markdown Extra].)++Note that although this syntax allows assignment of classes and key/value+attributes, writers generally don't use all of this information. Identifiers,+classes, and key/value attributes are used in HTML and HTML-based formats such+as EPUB and slidy. Identifiers are used for labels and link anchors in the+LaTeX, ConTeXt, Textile, Jira markup, and AsciiDoc writers.++Headings with the class `unnumbered` will not be numbered, even if+`--number-sections` is specified. A single hyphen (`-`) in an attribute+context is equivalent to `.unnumbered`, and preferable in non-English+documents. So,++ # My heading {-}++is just the same as++ # My heading {.unnumbered}++If the `unlisted` class is present in addition to `unnumbered`,+the heading will not be included in a table of contents.+(Currently this feature is only implemented for certain+formats: those based on LaTeX and HTML, PowerPoint, and RTF.)++### Extension: `implicit_header_references` ###++Pandoc behaves as if reference links have been defined for each heading.+So, to link to a heading++ # Heading identifiers in HTML++you can simply write++ [Heading identifiers in HTML]++or++ [Heading identifiers in HTML][]++or++ [the section on heading identifiers][heading identifiers in+ HTML]++instead of giving the identifier explicitly:++ [Heading identifiers in HTML](#heading-identifiers-in-html)++If there are multiple headings with identical text, the corresponding+reference will link to the first one only, and you will need to use explicit+links to link to the others, as described above.++Like regular reference links, these references are case-insensitive.++Explicit link reference definitions always take priority over+implicit heading references. So, in the following example, the+link will point to `bar`, not to `#foo`:++ # Foo++ [foo]: bar++ See [foo]++## Block quotations++Markdown uses email conventions for quoting blocks of text.+A block quotation is one or more paragraphs or other block elements+(such as lists or headings), with each line preceded by a `>` character+and an optional space. (The `>` need not start at the left margin, but+it should not be indented more than three spaces.)++ > This is a block quote. This+ > paragraph has two lines.+ >+ > 1. This is a list inside a block quote.+ > 2. Second item.++A "lazy" form, which requires the `>` character only on the first+line of each block, is also allowed:++ > This is a block quote. This+ paragraph has two lines.++ > 1. This is a list inside a block quote.+ 2. Second item.++Among the block elements that can be contained in a block quote are+other block quotes. That is, block quotes can be nested:++ > This is a block quote.+ >+ > > A block quote within a block quote.++If the `>` character is followed by an optional space, that space+will be considered part of the block quote marker and not part of+the indentation of the contents. Thus, to put an indented code+block in a block quote, you need five spaces after the `>`:++ > code++### Extension: `blank_before_blockquote` ###++Original Markdown syntax does not require a blank line before a+block quote. Pandoc does require this (except, of course, at+the beginning of the document). The reason for the requirement+is that it is all too easy for a `>` to end up at the beginning+of a line by accident (perhaps through line wrapping). So,+unless the `markdown_strict` format is used, the following does+not produce a nested block quote in pandoc:++ > This is a block quote.+ >> Not nested, since `blank_before_blockquote` is enabled by default+++## Verbatim (code) blocks++### Indented code blocks ###++A block of text indented four spaces (or one tab) is treated as verbatim+text: that is, special characters do not trigger special formatting,+and all spaces and line breaks are preserved. For example,++ if (a > 3) {+ moveShip(5 * gravity, DOWN);+ }++The initial (four space or one tab) indentation is not considered part+of the verbatim text, and is removed in the output.++Note: blank lines in the verbatim text need not begin with four spaces.+++### Fenced code blocks ###++### Extension: `fenced_code_blocks` ###++In addition to standard indented code blocks, pandoc supports+*fenced* code blocks. These begin with a row of three or more+tildes (`~`) and end with a row of tildes that must be at least as long as+the starting row. Everything between these lines is treated as code. No+indentation is necessary:++ ~~~~~~~+ if (a > 3) {+ moveShip(5 * gravity, DOWN);+ }+ ~~~~~~~++Like regular code blocks, fenced code blocks must be separated+from surrounding text by blank lines.++If the code itself contains a row of tildes or backticks, just use a longer+row of tildes or backticks at the start and end:++ ~~~~~~~~~~~~~~~~+ ~~~~~~~~~~+ code including tildes+ ~~~~~~~~~~+ ~~~~~~~~~~~~~~~~++### Extension: `backtick_code_blocks` ###++Same as `fenced_code_blocks`, but uses backticks (`` ` ``) instead of tildes+(`~`).++### Extension: `fenced_code_attributes` ###++Optionally, you may attach attributes to fenced or backtick code block using+this syntax:++ ~~~~ {#mycode .haskell .numberLines startFrom="100"}+ qsort [] = []+ qsort (x:xs) = qsort (filter (< x) xs) ++ [x] +++ qsort (filter (>= x) xs)+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++Here `mycode` is an identifier, `haskell` and `numberLines` are+classes, and `startFrom` is an attribute with value `100`. Some+output formats can use this information to do syntax+highlighting. Currently, the only output formats that use this+information are HTML, LaTeX, Docx, Ms, and PowerPoint. If+highlighting is supported for your output format and language,+then the code block above will appear highlighted, with numbered+lines. (To see which languages are supported, type `pandoc+--list-highlight-languages`.) Otherwise, the code block above+will appear as follows:++ <pre id="mycode" class="haskell numberLines" startFrom="100">+ <code>+ ...+ </code>+ </pre>++The `numberLines` (or `number-lines`) class will cause the lines+of the code block to be numbered, starting with `1` or the value+of the `startFrom` attribute. The `lineAnchors` (or+`line-anchors`) class will cause the lines to be clickable+anchors in HTML output.++A shortcut form can also be used for specifying the language of+the code block:++ ```haskell+ qsort [] = []+ ```++This is equivalent to:++ ``` {.haskell}+ qsort [] = []+ ```++This shortcut form may be combined with attributes:++ ```haskell {.numberLines}+ qsort [] = []+ ```++Which is equivalent to:++ ``` {.haskell .numberLines}+ qsort [] = []+ ```++If the `fenced_code_attributes` extension is disabled, but+input contains class attribute(s) for the code block, the first+class attribute will be printed after the opening fence as a bare+word.++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++### Extension: `line_blocks` ###++A line block is a sequence of lines beginning with a vertical bar (`|`)+followed by a space. The division into lines will be preserved in+the output, as will any leading spaces; otherwise, the lines will+be formatted as Markdown. This is useful for verse and addresses:++ | The limerick packs laughs anatomical+ | In space that is quite economical.+ | But the good ones I've seen+ | So seldom are clean+ | And the clean ones so seldom are comical++ | 200 Main St.+ | Berkeley, CA 94718++The lines can be hard-wrapped if needed, but the continuation+line must begin with a space.++ | The Right Honorable Most Venerable and Righteous Samuel L.+ Constable, Jr.+ | 200 Main St.+ | Berkeley, CA 94718++Inline formatting (such as emphasis) is allowed in the content+(though it can't cross line boundaries). Block-level formatting+(such as block quotes or lists) is not recognized.++This syntax is borrowed from [reStructuredText].++## Lists++### Bullet lists ###++A bullet list is a list of bulleted list items. A bulleted list+item begins with a bullet (`*`, `+`, or `-`). Here is a simple+example:++ * one+ * two+ * three++This will produce a "compact" list. If you want a "loose" list, in which+each item is formatted as a paragraph, put spaces between the items:++ * one++ * two++ * three++The bullets need not be flush with the left margin; they may be+indented one, two, or three spaces. The bullet must be followed+by whitespace.++List items look best if subsequent lines are flush with the first+line (after the bullet):++ * here is my first+ list item.+ * and my second.++But Markdown also allows a "lazy" format:++ * here is my first+ list item.+ * and my second.++### Block content in list items ###++A list item may contain multiple paragraphs and other block-level+content. However, subsequent paragraphs must be preceded by a blank line+and indented to line up with the first non-space content after+the list marker.++ * First paragraph.++ Continued.++ * Second paragraph. With a code block, which must be indented+ eight spaces:++ { code }++Exception: if the list marker is followed by an indented code+block, which must begin 5 spaces after the list marker, then+subsequent paragraphs must begin two columns after the last+character of the list marker:++ * code++ continuation paragraph++List items may include other lists. In this case the preceding blank+line is optional. The nested list must be indented to line up with+the first non-space character after the list marker of the+containing list item.++ * fruits+ + apples+ - macintosh+ - red delicious+ + pears+ + peaches+ * vegetables+ + broccoli+ + chard++As noted above, Markdown allows you to write list items "lazily," instead of+indenting continuation lines. However, if there are multiple paragraphs or+other blocks in a list item, the first line of each must be indented.++ + A lazy, lazy, list+ item.++ + Another one; this looks+ bad but is legal.++ Second paragraph of second+ list item.++### Ordered lists ###++Ordered lists work just like bulleted lists, except that the items+begin with enumerators rather than bullets.++In original Markdown, enumerators are decimal numbers followed+by a period and a space. The numbers themselves are ignored, so+there is no difference between this list:++ 1. one+ 2. two+ 3. three++and this one:++ 5. one+ 7. two+ 1. three++### Extension: `fancy_lists` ###++Unlike original Markdown, pandoc allows ordered list items to be marked+with uppercase and lowercase letters and roman numerals, in addition to+Arabic numerals. List markers may be enclosed in parentheses or followed by a+single right-parenthesis or period. They must be separated from the+text that follows by at least one space, and, if the list marker is a+capital letter with a period, by at least two spaces.[^2]++[^2]: The point of this rule is to ensure that normal paragraphs+ starting with people's initials, like++ B. Russell won a Nobel Prize (but not for "On Denoting").++ do not get treated as list items.++ This rule will not prevent++ (C) 2007 Joe Smith++ from being interpreted as a list item. In this case, a backslash+ escape can be used:++ (C\) 2007 Joe Smith++The `fancy_lists` extension also allows '`#`' to be used as an+ordered list marker in place of a numeral:++ #. one+ #. two++Note: the '`#`' ordered list marker doesn't work with `commonmark`.++### Extension: `startnum` ###++Pandoc also pays attention to the type of list marker used, and to the+starting number, and both of these are preserved where possible in the+output format. Thus, the following yields a list with numbers followed+by a single parenthesis, starting with 9, and a sublist with lowercase+roman numerals:++ 9) Ninth+ 10) Tenth+ 11) Eleventh+ i. subone+ ii. subtwo+ iii. subthree++Pandoc will start a new list each time a different type of list+marker is used. So, the following will create three lists:++ (2) Two+ (5) Three+ 1. Four+ * Five++If default list markers are desired, use `#.`:++ #. one+ #. two+ #. three++### Extension: `task_lists` ###++Pandoc supports task lists, using the syntax of GitHub-Flavored Markdown.++ - [ ] an unchecked task list item+ - [x] checked item++### Definition lists ###++### Extension: `definition_lists` ###++Pandoc supports definition lists, using the syntax of+[PHP Markdown Extra] with some extensions.[^3]++ Term 1++ : Definition 1++ Term 2 with *inline markup*++ : Definition 2++ { some code, part of Definition 2 }++ Third paragraph of definition 2.++Each term must fit on one line, which may optionally be followed by+a blank line, and must be followed by one or more definitions.+A definition begins with a colon or tilde, which may be indented one+or two spaces.++A term may have multiple definitions, and each definition may+consist of one or more indented block elements (paragraph, code block,+list, etc.). The blocks in the definition shoud be indented to the column+of the first non-space content after the `:` or `~` marker, or+(if the `four_space_rule` extension is enabled) four spaces or+one tab stop. As with other Markdown lists, you can "lazily" omit+indentation in paragraph continuation lines:++ Term 1++ : Definition+ with lazy continuation.++ Second paragraph of the definition.++If you leave space before the definition (as in the example above),+the text of the definition will be treated as a paragraph. In some+output formats, this will mean greater spacing between term/definition+pairs. For a more compact definition list, omit the space before the+definition:++ Term 1+ ~ Definition 1++ Term 2+ ~ Definition 2a+ ~ Definition 2b++Note that space between items in a definition list is required.++[^3]: I have been influenced by the suggestions of [David+ Wheeler](https://justatheory.com/2009/02/modest-markdown-proposal/).++### Numbered example lists ###++### Extension: `example_lists` ###++The special list marker `@` can be used for sequentially numbered+examples. The first list item with a `@` marker will be numbered '1',+the next '2', and so on, throughout the document. The numbered examples+need not occur in a single list; each new list using `@` will take up+where the last stopped. So, for example:++ (@) My first example will be numbered (1).+ (@) My second example will be numbered (2).++ Explanation of examples.++ (@) My third example will be numbered (3).++Numbered examples can be labeled and referred to elsewhere in the+document:++ (@good) This is a good example.++ As (@good) illustrates, ...++The label can be any string of alphanumeric characters, underscores,+or hyphens.++Continuation paragraphs in example lists must always+be indented four spaces, regardless of the length of the+list marker. That is, example lists always behave as if the+`four_space_rule` extension is set. This is because example+labels tend to be long, and indenting content to the+first non-space character after the label would be awkward.++You can repeat an earlier numbered example by re-using its label:++ (@foo) Sample sentence.++ Intervening text...++ This theory can explain the case we saw earlier (repeated):++ (@foo) Sample sentence.++This only works reliably, though, if the repeated item is in a list+by itself, because each numbered example list will be numbered+continuously from its starting number.++### Ending a list ###++What if you want to put an indented code block after a list?++ - item one+ - item two++ { my code block }++Trouble! Here pandoc (like other Markdown implementations) will treat+`{ my code block }` as the second paragraph of item two, and not as+a code block.++To "cut off" the list after item two, you can insert some non-indented+content, like an HTML comment, which won't produce visible output in+any format:++ - item one+ - item two++ <!-- end of list -->++ { my code block }++You can use the same trick if you want two consecutive lists instead+of one big list:++ 1. one+ 2. two+ 3. three++ <!-- -->++ 1. uno+ 2. dos+ 3. tres++## Horizontal rules++A line containing a row of three or more `*`, `-`, or `_` characters+(optionally separated by spaces) produces a horizontal rule:++ * * * *++ ---------------++We strongly recommend that horizontal rules be separated from+surrounding text by blank lines. If a horizontal rule is not+followed by a blank line, pandoc may try to interpret the+lines that follow as a YAML metadata block or a table.++## Tables++Four kinds of tables may be used. The first three kinds presuppose the use of+a fixed-width font, such as Courier. The fourth kind can be used with+proportionally spaced fonts, as it does not require lining up columns.++### Extension: `table_captions` ###++A caption may optionally be provided with all 4 kinds of tables (as+illustrated in the examples below). A caption is a paragraph beginning+with the string `Table:` (or `table:` or just `:`), which will be stripped+off. It may appear either before or after the table.++### Extension: `simple_tables` ###++Simple tables look like this:++ Right Left Center Default+ ------- ------ ---------- -------+ 12 12 12 12+ 123 123 123 123+ 1 1 1 1++ Table: Demonstration of simple table syntax.++The header and table rows must each fit on one line. Column+alignments are determined by the position of the header text relative+to the dashed line below it:[^4]++ - If the dashed line is flush with the header text on the right side+ but extends beyond it on the left, the column is right-aligned.+ - If the dashed line is flush with the header text on the left side+ but extends beyond it on the right, the column is left-aligned.+ - If the dashed line extends beyond the header text on both sides,+ the column is centered.+ - If the dashed line is flush with the header text on both sides,+ the default alignment is used (in most cases, this will be left).++[^4]: This scheme is due to Michel Fortin, who proposed it on the+ [Markdown discussion list](http://six.pairlist.net/pipermail/markdown-discuss/2005-March/001097.html).++The table must end with a blank line, or a line of dashes followed by+a blank line.++The column header row may be omitted, provided a dashed line is used+to end the table. For example:++ ------- ------ ---------- -------+ 12 12 12 12+ 123 123 123 123+ 1 1 1 1+ ------- ------ ---------- -------++When the header row is omitted, column alignments are determined on the basis+of the first line of the table body. So, in the tables above, the columns+would be right, left, center, and right aligned, respectively.++### Extension: `multiline_tables` ###++Multiline tables allow header and table rows to span multiple lines+of text (but cells that span multiple columns or rows of the table are+not supported). Here is an example:++ -------------------------------------------------------------+ Centered Default Right Left+ Header Aligned Aligned Aligned+ ----------- ------- --------------- -------------------------+ First row 12.0 Example of a row that+ spans multiple lines.++ Second row 5.0 Here's another one. Note+ the blank line between+ rows.+ -------------------------------------------------------------++ Table: Here's the caption. It, too, may span+ multiple lines.++These work like simple tables, but with the following differences:++ - They must begin with a row of dashes, before the header text+ (unless the header row is omitted).+ - They must end with a row of dashes, then a blank line.+ - The rows must be separated by blank lines.++In multiline tables, the table parser pays attention to the widths of+the columns, and the writers try to reproduce these relative widths in+the output. So, if you find that one of the columns is too narrow in the+output, try widening it in the Markdown source.++The header may be omitted in multiline tables as well as simple tables:++ ----------- ------- --------------- -------------------------+ First row 12.0 Example of a row that+ spans multiple lines.++ Second row 5.0 Here's another one. Note+ the blank line between+ rows.+ ----------- ------- --------------- -------------------------++ : Here's a multiline table without a header.++It is possible for a multiline table to have just one row, but the row+should be followed by a blank line (and then the row of dashes that ends+the table), or the table may be interpreted as a simple table.++### Extension: `grid_tables` ###++Grid tables look like this:++ : Sample grid table.++ +---------------+---------------+--------------------++ | Fruit | Price | Advantages |+ +===============+===============+====================++ | Bananas | $1.34 | - built-in wrapper |+ | | | - bright color |+ +---------------+---------------+--------------------++ | Oranges | $2.10 | - cures scurvy |+ | | | - tasty |+ +---------------+---------------+--------------------+++The row of `=`s separates the header from the table body,+and can be omitted for a headerless table. The cells of grid+tables may contain arbitrary block elements (multiple+paragraphs, code blocks, lists, etc.).++Cells can span multiple columns or rows:++ +---------------------+----------++ | Property | Earth |+ +=============+=======+==========++ | | min | -89.2 °C |+ | Temperature +-------+----------++ | 1961-1990 | mean | 14 °C |+ | +-------+----------++ | | max | 56.7 °C |+ +-------------+-------+----------+++A table header may contain more than one row:++ +---------------------+-----------------------++ | Location | Temperature 1961-1990 |+ | | in degree Celsius |+ | +-------+-------+-------++ | | min | mean | max |+ +=====================+=======+=======+=======++ | Antarctica | -89.2 | N/A | 19.8 |+ +---------------------+-------+-------+-------++ | Earth | -89.2 | 14 | 56.7 |+ +---------------------+-------+-------+-------+++Alignments can be specified as with pipe tables, by putting+colons at the boundaries of the separator line after the+header:++ +---------------+---------------+--------------------++ | Right | Left | Centered |+ +==============:+:==============+:==================:++ | Bananas | $1.34 | built-in wrapper |+ +---------------+---------------+--------------------+++For headerless tables, the colons go on the top line instead:++ +--------------:+:--------------+:------------------:++ | Right | Left | Centered |+ +---------------+---------------+--------------------+++A table foot can be defined by enclosing it with separator lines+that use `=` instead of `-`:++ +---------------+---------------++ | Fruit | Price |+ +===============+===============++ | Bananas | $1.34 |+ +---------------+---------------++ | Oranges | $2.10 |+ +===============+===============++ | Sum | $3.44 |+ +===============+===============+++The foot must always be placed at the very bottom of the table.++Grid tables can be created easily using Emacs' table-mode+(`M-x table-insert`).++### Extension: `pipe_tables` ###++Pipe tables look like this:++ | Right | Left | Default | Center |+ |------:|:-----|---------|:------:|+ | 12 | 12 | 12 | 12 |+ | 123 | 123 | 123 | 123 |+ | 1 | 1 | 1 | 1 |++ : Demonstration of pipe table syntax.++The syntax is identical to [PHP Markdown Extra tables]. The beginning and+ending pipe characters are optional, but pipes are required between all+columns. The colons indicate column alignment as shown. The header+cannot be omitted. To simulate a headerless table, include a header+with blank cells.++Since the pipes indicate column boundaries, columns need not be vertically+aligned, as they are in the above example. So, this is a perfectly+legal (though ugly) pipe table:++ fruit| price+ -----|-----:+ apple|2.05+ pear|1.37+ orange|3.09++The cells of pipe tables cannot contain block elements like paragraphs+and lists, and cannot span multiple lines. If any line of the+Markdown source is longer than the column width (see `--columns`),+then the table will take up the full text width and the cell+contents will wrap, with the relative cell widths determined by+the number of dashes in the line separating the table header+from the table body. (For example `---|-` would make the first column 3/4+and the second column 1/4 of the full text width.)+On the other hand, if no lines are wider than column width, then+cell contents will not be wrapped, and the cells will be sized+to their contents.++Note: pandoc also recognizes pipe tables of the following+form, as can be produced by Emacs' orgtbl-mode:++ | One | Two |+ |-----+-------|+ | my | table |+ | is | nice |++The difference is that `+` is used instead of `|`. Other orgtbl features+are not supported. In particular, to get non-default column alignment,+you'll need to add colons as above.++[PHP Markdown Extra tables]: https://michelf.ca/projects/php-markdown/extra/#table++### Extension: `table_attributes` ###++Attributes may be attached to tables by including them at the end+of the caption. (For the syntax, see+[`header_attributes`][Extension: `header_attributes`].)++ : Here's the caption. {#ident .class key="value"}++## Metadata blocks++### Extension: `pandoc_title_block` ###++If the file begins with a title block++ % title+ % author(s) (separated by semicolons)+ % date++it will be parsed as bibliographic information, not regular text. (It+will be used, for example, in the title of standalone LaTeX or HTML+output.) The block may contain just a title, a date and an author,+or all three elements. If you want to include an author but no+title, or a title and a date but no author, you need a blank line:++```+%+% Author+```++```+% My title+%+% June 15, 2006+```++The title may occupy multiple lines, but continuation lines must+begin with leading space, thus:++```+% My title+ on multiple lines+```++If a document has multiple authors, the authors may be put on+separate lines with leading space, or separated by semicolons, or+both. So, all of the following are equivalent:++```+% Author One+ Author Two+```++```+% Author One; Author Two+```++```+% Author One;+ Author Two+```++The date must fit on one line.++All three metadata fields may contain standard inline formatting+(italics, links, footnotes, etc.).++Title blocks will always be parsed, but they will affect the output only+when the `--standalone` (`-s`) option is chosen. In HTML output, titles+will appear twice: once in the document head---this is the title that+will appear at the top of the window in a browser---and once at the+beginning of the document body. The title in the document head can have+an optional prefix attached (`--title-prefix` or `-T` option). The title+in the body appears as an H1 element with class "title", so it can be+suppressed or reformatted with CSS. If a title prefix is specified with+`-T` and no title block appears in the document, the title prefix will+be used by itself as the HTML title.++The man page writer extracts a title, man page section number, and+other header and footer information from the title line. The title+is assumed to be the first word on the title line, which may optionally+end with a (single-digit) section number in parentheses. (There should+be no space between the title and the parentheses.) Anything after+this is assumed to be additional footer and header text. A single pipe+character (`|`) should be used to separate the footer text from the header+text. Thus,++ % PANDOC(1)++will yield a man page with the title `PANDOC` and section 1.++ % PANDOC(1) Pandoc User Manuals++will also have "Pandoc User Manuals" in the footer.++ % PANDOC(1) Pandoc User Manuals | Version 4.0++will also have "Version 4.0" in the header.++### Extension: `yaml_metadata_block` ###++A [YAML] metadata block is a valid YAML object, delimited by a line of three+hyphens (`---`) at the top and a line of three hyphens (`---`) or three dots+(`...`) at the bottom. The initial line `---` must not be followed by a blank+line. A YAML metadata block may occur anywhere in the document, but if+it is not at the beginning, it must be preceded by a blank line.+(Note that JSON may be used as well, because JSON is a subset of YAML.)++Note that, because of the way pandoc concatenates input files+when several are provided, you may also keep the metadata in a+separate YAML file and pass it to pandoc as an argument, along+with your Markdown files:++ pandoc chap1.md chap2.md chap3.md metadata.yaml -s -o book.html++Just be sure that the YAML file begins with `---` and ends with `---` or+`...`. Alternatively, you can use the `--metadata-file` option. Using+that approach however, you cannot reference content (like footnotes)+from the main Markdown input document.++Metadata will be taken from the fields of the YAML object and added to any+existing document metadata. Metadata can contain lists and objects (nested+arbitrarily), but all string scalars will be interpreted as Markdown. Fields+with names ending in an underscore will be ignored by pandoc. (They may be+given a role by external processors.) Field names must not be+interpretable as YAML numbers or boolean values (so, for+example, `yes`, `True`, and `15` cannot be used as field names).++A document may contain multiple metadata blocks. If two+metadata blocks attempt to set the same field, the value from+the second block will be taken.++Each metadata block is handled internally as an independent YAML document.+This means, for example, that any YAML anchors defined in a block cannot be+referenced in another block.++When pandoc is used with `-t markdown` to create a Markdown document,+a YAML metadata block will be produced only if the `-s/--standalone`+option is used. All of the metadata will appear in a single block+at the beginning of the document.++Note that [YAML] escaping rules must be followed. Thus, for example,+if a title contains a colon, it must be quoted, and if it contains a+backslash escape, then it must be ensured that it is not treated as a+[YAML escape sequence]. The pipe character (`|`) can be used to begin+an indented block that will be interpreted literally, without need for+escaping. This form is necessary when the field contains blank lines+or block-level formatting:++ ---+ title: 'This is the title: it contains a colon'+ author:+ - Author One+ - Author Two+ keywords: [nothing, nothingness]+ abstract: |+ This is the abstract.++ It consists of two paragraphs.+ ...++The literal block after the `|` must be indented relative to the+line containing the `|`. If it is not, the YAML will be invalid+and pandoc will not interpret it as metadata. For an overview+of the complex rules governing YAML, see the [Wikipedia entry on+YAML syntax].++Template variables will be set automatically from the metadata. Thus, for+example, in writing HTML, the variable `abstract` will be set to the HTML+equivalent of the Markdown in the `abstract` field:++ <p>This is the abstract.</p>+ <p>It consists of two paragraphs.</p>++Variables can contain arbitrary YAML structures, but the template must match+this structure. The `author` variable in the default templates expects a+simple list or string, but can be changed to support more complicated+structures. The following combination, for example, would add an affiliation+to the author if one is given:++ ---+ title: The document title+ author:+ - name: Author One+ affiliation: University of Somewhere+ - name: Author Two+ affiliation: University of Nowhere+ ...++To use the structured authors in the example above, you would need a custom+template:++ $for(author)$+ $if(author.name)$+ $author.name$$if(author.affiliation)$ ($author.affiliation$)$endif$+ $else$+ $author$+ $endif$+ $endfor$++Raw content to include in the document's header may be specified+using `header-includes`; however, it is important to mark up+this content as raw code for a particular output format, using+the [`raw_attribute` extension](#extension-raw_attribute), or it+will be interpreted as Markdown. For example:++ header-includes:+ - |+ ```{=latex}+ \let\oldsection\section+ \renewcommand{\section}[1]{\clearpage\oldsection{#1}}+ ```++Note: the `yaml_metadata_block` extension works not just with+`markdown` but with `commonmark` (and it is enabled by default in+`gfm` and `commonmark_x`). However, in `commonmark`, `gfm`,+and `commonmark_x`, the following restrictions apply:++- The YAML metadata block must occur at the beginning of the+ document (and there can be only one). If multiple files are+ given as arguments to pandoc, only the first can be a YAML+ metadata block.++- The leaf nodes of the YAML structure are parsed in isolation from+ each other and from the rest of the document. So, for+ example, you can't use a reference link in these contexts+ if the link definition is somewhere else in the document.++[YAML escape sequence]: https://yaml.org/spec/1.2/spec.html#id2776092+[Wikipedia entry on YAML syntax]: https://en.wikipedia.org/wiki/YAML#Syntax++## Backslash escapes++### Extension: `all_symbols_escapable` ###++Except inside a code block or inline code, any punctuation or space+character preceded by a backslash will be treated literally, even if it+would normally indicate formatting. Thus, for example, if one writes++ *\*hello\**++one will get++ <em>*hello*</em>++instead of++ <strong>hello</strong>++This rule is easier to remember than original Markdown's rule,+which allows only the following characters to be backslash-escaped:++ \`*_{}[]()>#+-.!++(However, if the `markdown_strict` format is used, the original Markdown rule+will be used.)++A backslash-escaped space is parsed as a nonbreaking space. In TeX output,+it will appear as `~`. In HTML and XML output, it will appear as a+literal unicode nonbreaking space character (note that it will thus+actually look "invisible" in the generated HTML source; you can still+use the `--ascii` command-line option to make it appear as an explicit+entity).++A backslash-escaped newline (i.e. a backslash occurring at the end of+a line) is parsed as a hard line break. It will appear in TeX output as+`\\` and in HTML as `<br />`. This is a nice alternative to+Markdown's "invisible" way of indicating hard line breaks using+two trailing spaces on a line.++Backslash escapes do not work in verbatim contexts.++## Inline formatting++### Emphasis ###++To *emphasize* some text, surround it with `*`s or `_`, like this:++ This text is _emphasized with underscores_, and this+ is *emphasized with asterisks*.++Double `*` or `_` produces **strong emphasis**:++ This is **strong emphasis** and __with underscores__.++A `*` or `_` character surrounded by spaces, or backslash-escaped,+will not trigger emphasis:++ This is * not emphasized *, and \*neither is this\*.++### Extension: `intraword_underscores` ###++Because `_` is sometimes used inside words and identifiers,+pandoc does not interpret a `_` surrounded by alphanumeric+characters as an emphasis marker. If you want to emphasize+just part of a word, use `*`:++ feas*ible*, not feas*able*.++### Strikeout ###++### Extension: `strikeout` ###++To strike out a section of text with a horizontal line, begin and end it+with `~~`. Thus, for example,++ This ~~is deleted text.~~+++### Superscripts and subscripts ###++### Extension: `superscript`, `subscript` ###++Superscripts may be written by surrounding the superscripted text by `^`+characters; subscripts may be written by surrounding the subscripted+text by `~` characters. Thus, for example,++ H~2~O is a liquid. 2^10^ is 1024.++The text between `^...^` or `~...~` may not contain spaces or+newlines. If the superscripted or subscripted text contains+spaces, these spaces must be escaped with backslashes. (This is+to prevent accidental superscripting and subscripting through+the ordinary use of `~` and `^`, and also bad interactions with+footnotes.) Thus, if you want the letter P with 'a cat' in+subscripts, use `P~a\ cat~`, not `P~a cat~`.++### Verbatim ###++To make a short span of text verbatim, put it inside backticks:++ What is the difference between `>>=` and `>>`?++If the verbatim text includes a backtick, use double backticks:++ Here is a literal backtick `` ` ``.++(The spaces after the opening backticks and before the closing+backticks will be ignored.)++The general rule is that a verbatim span starts with a string+of consecutive backticks (optionally followed by a space)+and ends with a string of the same number of backticks (optionally+preceded by a space).++Note that backslash-escapes (and other Markdown constructs) do not+work in verbatim contexts:++ This is a backslash followed by an asterisk: `\*`.++### Extension: `inline_code_attributes` ###++Attributes can be attached to verbatim text, just as with+[fenced code blocks]:++ `<$>`{.haskell}++### Underline ###++To underline text, use the `underline` class:++ [Underline]{.underline}++Or, without the `bracketed_spans` extension (but with `native_spans`):++ <span class="underline">Underline</span>++This will work in all output formats that support underline.++### Small caps ###++To write small caps, use the `smallcaps` class:++ [Small caps]{.smallcaps}++Or, without the `bracketed_spans` extension:++ <span class="smallcaps">Small caps</span>++For compatibility with other Markdown flavors, CSS is also supported:++ <span style="font-variant:small-caps;">Small caps</span>++This will work in all output formats that support small caps.++### Highlighting ###++To highlight text, use the `mark` class:++ [Mark]{.mark}++Or, without the `bracketed_spans` extension (but with `native_spans`):++ <span class="mark">Mark</span>++This will work in all output formats that support highlighting.+++## Math++### Extension: `tex_math_dollars` ###++Anything between two `$` characters will be treated as TeX math. The+opening `$` must have a non-space character immediately to its right,+while the closing `$` must have a non-space character immediately to its+left, and must not be followed immediately by a digit. Thus,+`$20,000 and $30,000` won't parse as math. If for some reason+you need to enclose text in literal `$` characters, backslash-escape+them and they won't be treated as math delimiters.++For display math, use `$$` delimiters. (In this case, the delimiters+may be separated from the formula by whitespace. However, there can be+no blank lines between the opening and closing `$$` delimiters.)++TeX math will be printed in all output formats. How it is rendered+depends on the output format:++LaTeX+ ~ It will appear verbatim surrounded by `\(...\)` (for inline+ math) or `\[...\]` (for display math).++Markdown, Emacs Org mode, ConTeXt, ZimWiki+ ~ It will appear verbatim surrounded by `$...$` (for inline+ math) or `$$...$$` (for display math).++XWiki+ ~ It will appear verbatim surrounded by `{{formula}}..{{/formula}}`.++reStructuredText+ ~ It will be rendered using an [interpreted text role `:math:`].++AsciiDoc+ ~ For AsciiDoc output math will appear verbatim surrounded by+ `latexmath:[...]`. For `asciidoc_legacy` the bracketed+ material will also include inline or display math delimiters.++Texinfo+ ~ It will be rendered inside a `@math` command.++roff man, Jira markup+ ~ It will be rendered verbatim without `$`'s.++MediaWiki, DokuWiki+ ~ It will be rendered inside `<math>` tags.++Textile+ ~ It will be rendered inside `<span class="math">` tags.++RTF, OpenDocument+ ~ It will be rendered, if possible, using Unicode characters,+ and will otherwise appear verbatim.++ODT+ ~ It will be rendered, if possible, using MathML.++DocBook+ ~ If the `--mathml` flag is used, it will be rendered using MathML+ in an `inlineequation` or `informalequation` tag. Otherwise it+ will be rendered, if possible, using Unicode characters.++Docx and PowerPoint+ ~ It will be rendered using OMML math markup.++FictionBook2+ ~ If the `--webtex` option is used, formulas are rendered as images+ using CodeCogs or other compatible web service, downloaded+ and embedded in the e-book. Otherwise, they will appear verbatim.++HTML, Slidy, DZSlides, S5, EPUB+ ~ The way math is rendered in HTML will depend on the+ command-line options selected. Therefore see [Math rendering in HTML]+ above.++[interpreted text role `:math:`]: https://docutils.sourceforge.io/docs/ref/rst/roles.html#math++## Raw HTML++### Extension: `raw_html` ###++Markdown allows you to insert raw HTML (or DocBook) anywhere in a document+(except verbatim contexts, where `<`, `>`, and `&` are interpreted+literally). (Technically this is not an extension, since standard+Markdown allows it, but it has been made an extension so that it can+be disabled if desired.)++The raw HTML is passed through unchanged in HTML, S5, Slidy, Slideous,+DZSlides, EPUB, Markdown, CommonMark, Emacs Org mode, and Textile+output, and suppressed in other formats.++For a more explicit way of including raw HTML in a Markdown+document, see the [`raw_attribute` extension][Extension: `raw_attribute`].++In the CommonMark format, if `raw_html` is enabled, superscripts,+subscripts, strikeouts and small capitals will be represented as HTML.+Otherwise, plain-text fallbacks will be used. Note that even if+`raw_html` is disabled, tables will be rendered with HTML syntax if+they cannot use pipe syntax.++### Extension: `markdown_in_html_blocks` ###++Original Markdown allows you to include HTML "blocks": blocks+of HTML between balanced tags that are separated from the surrounding text+with blank lines, and start and end at the left margin. Within+these blocks, everything is interpreted as HTML, not Markdown;+so (for example), `*` does not signify emphasis.++Pandoc behaves this way when the `markdown_strict` format is used; but+by default, pandoc interprets material between HTML block tags as Markdown.+Thus, for example, pandoc will turn++ <table>+ <tr>+ <td>*one*</td>+ <td>[a link](https://google.com)</td>+ </tr>+ </table>++into++ <table>+ <tr>+ <td><em>one</em></td>+ <td><a href="https://google.com">a link</a></td>+ </tr>+ </table>++whereas `Markdown.pl` will preserve it as is.++There is one exception to this rule: text between `<script>`,+`<style>`, `<pre>`, and `<textarea>` tags is not interpreted as Markdown.++This departure from original Markdown should make it easier to mix+Markdown with HTML block elements. For example, one can surround+a block of Markdown text with `<div>` tags without preventing it+from being interpreted as Markdown.++### Extension: `native_divs` ###++Use native pandoc `Div` blocks for content inside `<div>` tags.+For the most part this should give the same output as+`markdown_in_html_blocks`, but it makes it easier to write pandoc+filters to manipulate groups of blocks.++### Extension: `native_spans` ###++Use native pandoc `Span` blocks for content inside `<span>` tags.+For the most part this should give the same output as `raw_html`,+but it makes it easier to write pandoc filters to manipulate groups+of inlines.++### Extension: `raw_tex` ###++In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be+included in a document. Inline TeX commands will be preserved and passed+unchanged to the LaTeX and ConTeXt writers. Thus, for example, you can use+LaTeX to include BibTeX citations:++ This result was proved in \cite{jones.1967}.++Note that in LaTeX environments, like++ \begin{tabular}{|l|l|}\hline+ Age & Frequency \\ \hline+ 18--25 & 15 \\+ 26--35 & 33 \\+ 36--45 & 22 \\ \hline+ \end{tabular}++the material between the begin and end tags will be interpreted as raw+LaTeX, not as Markdown.++For a more explicit and flexible way of including raw TeX in a+Markdown document, see the [`raw_attribute`+extension][Extension: `raw_attribute`].++Inline LaTeX is ignored in output formats other than Markdown, LaTeX,+Emacs Org mode, and ConTeXt.++### Generic raw attribute ###++### Extension: `raw_attribute` ###++Inline spans and fenced code blocks with a special+kind of attribute will be parsed as raw content with the+designated format. For example, the following produces a raw+roff `ms` block:++ ```{=ms}+ .MYMACRO+ blah blah+ ```+And the following produces a raw `html` inline element:++ This is `<a>html</a>`{=html}++This can be useful to insert raw xml into `docx` documents, e.g.+a pagebreak:++ ```{=openxml}+ <w:p>+ <w:r>+ <w:br w:type="page"/>+ </w:r>+ </w:p>+ ```++The format name should match the target format name (see+`-t/--to`, above, for a list, or use `pandoc+--list-output-formats`). Use `openxml` for `docx` output,+`opendocument` for `odt` output, `html5` for `epub3` output,+`html4` for `epub2` output, and `latex`, `beamer`,+`ms`, or `html5` for `pdf` output (depending on what you+use for `--pdf-engine`).++This extension presupposes that the relevant kind of+inline code or fenced code block is enabled. Thus, for+example, to use a raw attribute with a backtick code block,+`backtick_code_blocks` must be enabled.++The raw attribute cannot be combined with regular attributes.++## LaTeX macros++### Extension: `latex_macros` ###++When this extension is enabled, pandoc will parse LaTeX+macro definitions and apply the resulting macros to all LaTeX+math and raw LaTeX. So, for example, the following will work in+all output formats, not just LaTeX:++ \newcommand{\tuple}[1]{\langle #1 \rangle}++ $\tuple{a, b, c}$++Note that LaTeX macros will not be applied if they occur+inside a raw span or block marked with the+[`raw_attribute` extension](#extension-raw_attribute).++When `latex_macros` is disabled, the raw LaTeX and math will+not have macros applied. This is usually a better approach when+you are targeting LaTeX or PDF.++Macro definitions in LaTeX will be passed through as raw LaTeX+only if `latex_macros` is not enabled. Macro definitions in+Markdown source (or other formats allowing `raw_tex`) will+be passed through regardless of whether `latex_macros` is+enabled.++## Links++Markdown allows links to be specified in several ways.++### Automatic links ###++If you enclose a URL or email address in pointy brackets, it+will become a link:++ <https://google.com>+ <sam@green.eggs.ham>++### Inline links ###++An inline link consists of the link text in square brackets,+followed by the URL in parentheses. (Optionally, the URL can+be followed by a link title, in quotes.)++ This is an [inline link](/url), and here's [one with+ a title](https://fsf.org "click here for a good time!").++There can be no space between the bracketed part and the parenthesized part.+The link text can contain formatting (such as emphasis), but the title cannot.++Email addresses in inline links are not autodetected, so they have to be+prefixed with `mailto`:++ [Write me!](mailto:sam@green.eggs.ham)++### Reference links ###++An *explicit* reference link has two parts, the link itself and the link+definition, which may occur elsewhere in the document (either+before or after the link).++The link consists of link text in square brackets, followed by a label in+square brackets. (There cannot be space between the two unless the+`spaced_reference_links` extension is enabled.) If the label is empty+(`[]`), then it will be implicitly be taken to be the same as the link text;+thus `[foo][]` is equivalent to `[foo][foo]`. (If the+`shortcut_reference_links` extension is enabled, the empty `[]`+may be omitted.)++The link definition consists of the bracketed label, followed by+a colon and a space, followed by the URL, and optionally (after a+space) a link title either in quotes or in parentheses. The label+must not be parseable as a citation (assuming the `citations`+extension is enabled): citations take precedence over link+labels.++Here are some examples of reference links and link definitions;++ See [the website *I* built][my website].++ See [my website][] and [the bar page][1] and+ the [home page of the FSF][fsf].++ [my website]: http://foo.bar.baz+ [1]: /foo/bar.html "My title, optional"+ [fsf]: https://fsf.org (The Free Software Foundation)+ [special page]: /bar#special 'A title in single quotes'++The URL in a link definition may optionally be surrounded by+angle brackets:++ [my label 5]: <http://foo.bar.baz>++The title may go on the next line:++ [my label 3]: https://fsf.org+ "The Free Software Foundation"++Note that link labels are not case sensitive. So, this will work:++ Here is [my link][FOO]++ [Foo]: /bar/baz++The link definition may come either before or after a+reference link that uses the label.++Note: In some Markdown implementations, reference link+definitions cannot occur in nested constructions such as list+items or block quotes. Pandoc lifts this arbitrary-seeming+restriction. So the following is fine in pandoc, though not in+all implementations:++ > My block [quote].+ >+ > [quote]: /foo++### Extension: `shortcut_reference_links` ###++In a *shortcut* reference link, the second pair of brackets may+be omitted entirely:++ See [my website].++ [my website]: http://foo.bar.baz++### Internal links ###++To link to another section of the same document, use the automatically+generated identifier (see [Heading identifiers]). For example:++ See the [Introduction](#introduction).++or++ See the [Introduction].++ [Introduction]: #introduction++Internal links are currently supported for HTML formats (including+HTML slide shows and EPUB), LaTeX, and ConTeXt.++## Images++A link immediately preceded by a `!` will be treated as an image.+The link text will be used as the image's alt text:++ ++ ![movie reel]++ [movie reel]: movie.gif++### Extension: `implicit_figures` ###++An image with nonempty alt text, occurring by itself in a+paragraph, will be rendered as a figure with a caption. The+image's description will be used as the caption.++ ++How this is rendered depends on the output format. Some output+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.++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:++ \++Note that in reveal.js slide shows, an image in a paragraph+by itself that has the `r-stretch` class will fill the screen,+and the caption and figure tags will be omitted.++To specify an alt text for the image that is different+from the caption, you can use an explicit attribute (assuming the+`link_attributes` extension is set):++ {alt="description of image"}++For LaTeX output, you can specify a [figure's+positioning](https://www.overleaf.com/learn/latex/Positioning_images_and_tables#The_figure_environment)+by adding the `latex-placement` attribute.++ {latex-placement="ht"}++### Extension: `link_attributes` ###++Attributes can be set on links and images:++ An inline {#id .class width=30 height=20px}+ and a reference ![image][ref] with attributes.++ [ref]: foo.jpg "optional title" {#id .class key=val key2="val 2"}++(This syntax is compatible with [PHP Markdown Extra] when only `#id`+and `.class` are used.)++For HTML and EPUB, all known HTML5 attributes except `width` and+`height` (but including `srcset` and `sizes`) are passed through+as is. Unknown attributes are passed through as custom+attributes, with `data-` prepended. The other writers ignore+attributes that are not specifically supported by their output format.++The `width` and `height` attributes on images are treated specially. When+used without a unit, the unit is assumed to be pixels. However, any of+the following unit identifiers can be used: `px`, `cm`, `mm`, `in`, `inch`+and `%`. There must not be any spaces between the number and the unit.+For example:++```+{ width=50% }+```++- Dimensions may be converted to a form that is compatible with+ the output format (for example, dimensions given in pixels will+ be converted to inches when converting HTML to LaTeX). Conversion+ between pixels and physical measurements is affected by the+ `--dpi` option (by default, 96 dpi is assumed, unless the image+ itself contains dpi information).+- The `%` unit is generally relative to some available space.+ For example the above example will render to the following.+ - HTML: `<img href="file.jpg" style="width: 50%;" />`+ - LaTeX: `\includegraphics[width=0.5\textwidth,height=\textheight]{file.jpg}`+ (If you're using a custom template, you need to configure `graphicx`+ as in the default template.)+ - ConTeXt: `\externalfigure[file.jpg][width=0.5\textwidth]`+- Some output formats have a notion of a class+ ([ConTeXt](https://wiki.contextgarden.net/Using_Graphics#Multiple_Image_Settings))+ or a unique identifier (LaTeX `\caption`), or both (HTML).+- When no `width` or `height` attributes are specified, the fallback+ is to look at the image resolution and the dpi metadata embedded in+ the image file.++## Divs and Spans++Using the `native_divs` and `native_spans` extensions+(see [above][Extension: `native_divs`]), HTML syntax can+be used as part of Markdown to create native `Div` and `Span`+elements in the pandoc AST (as opposed to raw HTML).+However, there is also nicer syntax available:++### Extension: `fenced_divs` ###++Allow special fenced syntax for native `Div` blocks. A Div+starts with a fence containing at least three consecutive+colons plus some attributes. The attributes may optionally+be followed by another string of consecutive colons.++Note: the `commonmark` parser doesn't permit colons after+the attributes.++The attribute syntax is exactly as in fenced code blocks (see+[Extension: `fenced_code_attributes`]). As with fenced+code blocks, one can use either attributes in curly braces+or a single unbraced word, which will be treated as a class+name. The Div ends with another line containing a string of at+least three consecutive colons. The fenced Div should be+separated by blank lines from preceding and following blocks.++Example:++ ::::: {#special .sidebar}+ Here is a paragraph.++ And another.+ :::::++Fenced divs can be nested. Opening fences are distinguished+because they *must* have attributes:++ ::: Warning ::::::+ This is a warning.++ ::: Danger+ This is a warning within a warning.+ :::+ ::::::::::::::::::++Fences without attributes are always closing fences. Unlike+with fenced code blocks, the number of colons in the closing+fence need not match the number in the opening fence. However,+it can be helpful for visual clarity to use fences of different+lengths to distinguish nested divs from their parents.+++### Extension: `bracketed_spans` ###++A bracketed sequence of inlines, as one would use to begin+a link, will be treated as a `Span` with attributes if it is+followed immediately by attributes:++ [This is *some text*]{.class key="val"}++## Footnotes++### Extension: `footnotes` ###++Pandoc's Markdown allows footnotes, using the following syntax:++ Here is a footnote reference,[^1] and another.[^longnote]++ [^1]: Here is the footnote.++ [^longnote]: Here's one with multiple blocks.++ Subsequent paragraphs are indented to show that they+ belong to the previous footnote.++ { some.code }++ The whole paragraph can be indented, or just the first+ line. In this way, multi-paragraph footnotes work like+ multi-paragraph list items.++ This paragraph won't be part of the note, because it+ isn't indented.++The identifiers in footnote references may not contain spaces, tabs,+newlines, or the characters `^`, `[`, or `]`. These identifiers+are used only to correlate the footnote reference with the note+itself; in the output, footnotes will be numbered sequentially.++The footnotes themselves need not be placed at the end of the+document. They may appear anywhere except inside other block elements+(lists, block quotes, tables, etc.). Each footnote should be+separated from surrounding content (including other footnotes)+by blank lines.++### Extension: `inline_notes` ###++Inline footnotes are also allowed (though, unlike regular notes,+they cannot contain multiple paragraphs). The syntax is as follows:++ Here is an inline note.^[Inline notes are easier to write, since+ you don't have to pick an identifier and move down to type the+ note.]++Inline and regular footnotes may be mixed freely.++## Citation syntax++### Extension: `citations` ###++To cite a bibliographic item with an identifier foo, use the+syntax `@foo`. Normal citations should be included in square+brackets, with semicolons separating distinct items:++ Blah blah [@doe99; @smith2000; @smith2004].++How this is rendered depends on the citation style. In an+author-date style, it might render as++ Blah blah (Doe 1999, Smith 2000, 2004).++In a footnote style, it might render as++ Blah blah.[^1]++ [^1]: John Doe, "Frogs," *Journal of Amphibians* 44 (1999);+ Susan Smith, "Flies," *Journal of Insects* (2000);+ Susan Smith, "Bees," *Journal of Insects* (2004).++See the [CSL user documentation] for more information about CSL+styles and how they affect rendering.++Unless a citation key starts with a letter, digit, or `_`,+and contains only alphanumerics and single internal punctuation+characters (`:.#$%&-+?<>~/`), it must be surrounded+by curly braces, which are not considered part of the key.+In `@Foo_bar.baz.`, the key is `Foo_bar.baz` because the final+period is not *internal* punctuation, so it is not included in+the key. In `@{Foo_bar.baz.}`, the key is `Foo_bar.baz.`, including+the final period.+In `@Foo_bar--baz`, the key is `Foo_bar` because the repeated internal+punctuation characters terminate the key.+The curly braces are recommended if you use URLs as+keys: `[@{https://example.com/bib?name=foobar&date=2000}, p. 33]`.++Citation items may optionally include a prefix, a locator, and+a suffix. In++ Blah blah [see @doe99, pp. 33-35 and *passim*; @smith04, chap. 1].++the first item (`doe99`) has prefix `see `, locator `pp. 33-35`,+and suffix `and *passim*`. The second item (`smith04`) has+locator `chap. 1` and no prefix or suffix.++Pandoc uses some heuristics to separate the locator from the+rest of the subject. It is sensitive to the locator terms+defined in the [CSL locale files]. Either abbreviated or+unabbreviated forms are accepted. In the `en-US` locale, locator+terms can be written in either singular or plural forms, as+`book`, `bk.`/`bks.`; `chapter`, `chap.`/`chaps.`; `column`,+`col.`/`cols.`; `figure`, `fig.`/`figs.`; `folio`,+`fol.`/`fols.`; `number`, `no.`/`nos.`; `line`, `l.`/`ll.`;+`note`, `n.`/`nn.`; `opus`, `op.`/`opp.`; `page`, `p.`/`pp.`;+`paragraph`, `para.`/`paras.`; `part`, `pt.`/`pts.`; `section`,+`sec.`/`secs.`; `sub verbo`, `s.v.`/`s.vv.`; `verse`,+`v.`/`vv.`; `volume`, `vol.`/`vols.`; `¶`/`¶¶`; `§`/`§§`. If no+locator term is used, "page" is assumed.++In complex cases, you can force something to be treated as+a locator by enclosing it in curly braces or prevent parsing+the suffix as locator by prepending curly braces:++ [@smith{ii, A, D-Z}, with a suffix]+ [@smith, {pp. iv, vi-xi, (xv)-(xvii)} with suffix here]+ [@smith{}, 99 years later]++A minus sign (`-`) before the `@` will suppress mention of+the author in the citation. This can be useful when the+author is already mentioned in the text:++ Smith says blah [-@smith04].++You can also write an author-in-text citation, by omitting the+square brackets:++ @smith04 says blah.++ @smith04 [p. 33] says blah.++This will cause the author's name to be rendered, followed by+the bibliographical details. Use this form when you want to+make the citation the subject of a sentence.++When you are using a note style, it is usually better to let+citeproc create the footnotes from citations rather than writing+an explicit note. If you do write an explicit note that+contains a citation, note that normal citations will be put in+parentheses, while author-in-text citations will not. For+this reason, it is sometimes preferable to use the+author-in-text style inside notes when using a note style.++Many CSL styles will format citations differently when the+same source has been cited earlier. In documents with chapters,+it is usually desirable to reset this position information+at the beginning of every chapter. To do this, add the class+`reset-citation-positions` to the heading for each chapter:++ # The Beginning {.reset-citation-positions}++Note that this class only has an effect when placed on+top-level headings; it is ignored in nested blocks.++[CSL user documentation]: https://citationstyles.org/authors/+[CSL]: https://docs.citationstyles.org/en/stable/specification.html+[CSL markup specs]: https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html#html-like-formatting-tags+[Chicago Manual of Style]: https://chicagomanualofstyle.org+[Citation Style Language]: https://citationstyles.org+[Zotero Style Repository]: https://www.zotero.org/styles+[finding and editing styles]: https://citationstyles.org/authors/+[CSL locale files]: https://github.com/citation-style-language/locales++## Non-default extensions++The following Markdown syntax extensions are not enabled by default+in pandoc, but may be enabled by adding `+EXTENSION` to the format+name, where `EXTENSION` is the name of the extension. Thus, for+example, `markdown+hard_line_breaks` is Markdown with hard line breaks.++### Extension: `rebase_relative_paths` ###++Rewrite relative paths for Markdown links and images, depending+on the path of the file containing the link or image link. For+each link or image, pandoc will compute the directory of the+containing file, relative to the working directory, and prepend+the resulting path to the link or image path.++The use of this extension is best understood by example.+Suppose you have a subdirectory for each chapter of a book,+`chap1`, `chap2`, `chap3`. Each contains a file `text.md` and a+number of images used in the chapter. You would like to have+`` in `chap1/text.md` refer to+`chap1/spider.jpg` and `` in `chap2/text.md`+refer to `chap2/spider.jpg`. To do this, use++ pandoc chap*/*.md -f markdown+rebase_relative_paths++Without this extension, you would have to use+`` in `chap1/text.md` and+`` in `chap2/text.md`. Links with+relative paths will be rewritten in the same way as images.++Absolute paths and URLs are not changed. Neither are empty+paths or paths consisting entirely of a fragment, e.g., `#foo`.++Note that relative paths in reference links and images will+be rewritten relative to the file containing the link+reference definition, not the file containing the reference link+or image itself, if these differ.++### Extension: `mark` ###++To highlight out a section of text, begin and end it with+with `==`. Thus, for example,++ This ==is deleted text.==++### Extension: `attributes` ###++Allows attributes to be attached to any inline or block-level+element when parsing `commonmark`.+The syntax for the attributes is the same as that+used in [`header_attributes`][Extension: `header_attributes`].++- Attributes that occur immediately after an inline+ element affect that element. If they follow a space, then they+ belong to the space. (Hence, this option subsumes+ `inline_code_attributes` and `link_attributes`.)+- Attributes that occur immediately before a block+ element, on a line by themselves, affect that+ element.+- Consecutive attribute specifiers may be used,+ either for blocks or for inlines. Their attributes+ will be combined.+- Attributes that occur at the end of the text of+ a Setext or ATX heading (separated by whitespace+ from the text) affect the heading element. (Hence, this+ option subsumes `header_attributes`.)+- Attributes that occur after the opening fence+ in a fenced code block affect the code block element. (Hence,+ this option subsumes `fenced_code_attributes`.)+- Attributes that occur at the end of a reference+ link definition affect links that refer to that+ definition.++Note that pandoc's AST does not currently allow attributes+to be attached to arbitrary elements. Hence a Span or Div+container will be added if needed.++### Extension: `old_dashes` ###++Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes:+`-` before a numeral is an en-dash, and `--` is an em-dash.+This option only has an effect if `smart` is enabled. It is+selected automatically for `textile` input.++### Extension: `angle_brackets_escapable` ###++Allow `<` and `>` to be backslash-escaped, as they can be in+GitHub flavored Markdown but not original Markdown. This is+implied by pandoc's default `all_symbols_escapable`.++### Extension: `lists_without_preceding_blankline` ###++Allow a list to occur right after a paragraph, with no intervening+blank space.++### Extension: `four_space_rule` ###++Selects the pandoc <= 2.0 behavior for parsing lists, so that+four spaces indent are needed for list item continuation+paragraphs.++### Extension: `spaced_reference_links` ###++Allow whitespace between the two components of a reference link,+for example,++ [foo] [bar].++### Extension: `hard_line_breaks` ###++Causes all newlines within a paragraph to be interpreted as hard line+breaks instead of spaces.++### Extension: `ignore_line_breaks` ###++Causes newlines within a paragraph to be ignored, rather than being+treated as spaces or as hard line breaks. This option is intended for+use with East Asian languages where spaces are not used between words,+but text is divided into lines for readability.++### Extension: `east_asian_line_breaks` ###++Causes newlines within a paragraph to be ignored, rather than+being treated as spaces or as hard line breaks, when they occur+between two East Asian wide characters. This is a better choice+than `ignore_line_breaks` for texts that include a mix of East+Asian wide characters and other characters.++### Extension: `emoji` ###++Parses textual emojis like `:smile:` as Unicode emoticons.++### Extension: `tex_math_gfm` ###++Supports two GitHub-specific formats for math.+Inline math: ``$`e=mc^2`$``.++Display math:++````+``` math+e=mc^2+```+````++### Extension: `tex_math_single_backslash` ###++Causes anything between `\(` and `\)` to be interpreted as inline+TeX math, and anything between `\[` and `\]` to be interpreted+as display TeX math. Note: a drawback of this extension is that+it precludes escaping `(` and `[`.++### Extension: `tex_math_double_backslash` ###++Causes anything between `\\(` and `\\)` to be interpreted as inline+TeX math, and anything between `\\[` and `\\]` to be interpreted+as display TeX math.++### Extension: `markdown_attribute` ###++By default, pandoc interprets material inside block-level tags as Markdown.+This extension changes the behavior so that Markdown is only parsed+inside block-level tags if the tags have the attribute `markdown=1`.++### Extension: `mmd_title_block` ###++Enables a [MultiMarkdown] style title block at the top of+the document, for example:++ Title: My title+ Author: John Doe+ Date: September 1, 2008+ Comment: This is a sample mmd title block, with+ a field spanning multiple lines.++See the MultiMarkdown documentation for details. If `pandoc_title_block` or+`yaml_metadata_block` is enabled, it will take precedence over+`mmd_title_block`.++### Extension: `abbreviations` ###++Parses PHP Markdown Extra abbreviation keys, like++ *[HTML]: Hypertext Markup Language++Note that the pandoc document model does not support+abbreviations, so if this extension is enabled, abbreviation keys are+simply skipped (as opposed to being parsed as paragraphs).++### Extension: `alerts` ###++Supports [GitHub-style Markdown alerts], like++ > [!TIP]+ > Helpful advice for doing things better or more easily.++ [GitHub-style Markdown alerts]: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts++### Extension: `autolink_bare_uris` ###++Makes all absolute URIs into links, even when not surrounded by+pointy braces `<...>`.++### Extension: `mmd_link_attributes` ###++Parses MultiMarkdown-style key-value attributes on link+and image references. This extension should not be confused with the+[`link_attributes`](#extension-link_attributes) extension.++ This is a reference ![image][ref] with MultiMarkdown attributes.++ [ref]: https://path.to/image "Image title" width=20px height=30px+ id=myId class="myClass1 myClass2"++### Extension: `mmd_header_identifiers` ###++Parses MultiMarkdown-style heading identifiers (in square brackets,+after the heading but before any trailing `#`s in an ATX heading).++### Extension: `gutenberg` ###++Use [Project Gutenberg] conventions for `plain` output:+all-caps for strong emphasis, surround by underscores+for regular emphasis, add extra blank space around headings.++ [Project Gutenberg]: https://www.gutenberg.org++### Extension: `sourcepos` ###++Include source position attributes when parsing `commonmark`.+For elements that accept attributes, a `data-pos` attribute+is added; other elements are placed in a surrounding+Div or Span element with a `data-pos` attribute.++### Extension: `short_subsuperscripts` ###++Parse MultiMarkdown-style subscripts and superscripts, which start with+a '~' or '^' character, respectively, and include the alphanumeric sequence+that follows. For example:++ x^2 = 4++or++ Oxygen is O~2.++### Extension: `wikilinks_title_after_pipe` ###++Pandoc supports multiple Markdown wikilink syntaxes, regardless of+whether the title is before or after the pipe.++Using `--from=markdown+wikilinks_title_after_pipe` results in+```[[Wiki]]+[[URL|title]]+```++while using `--from=markdown+wikilinks_title_before_pipe` results+in+```[[Wiki]]+[[title|URL]]+```++## Markdown variants++In addition to pandoc's extended Markdown, the following Markdown+variants are supported:++- `markdown_phpextra` (PHP Markdown Extra)+- `markdown_github` (deprecated GitHub-Flavored Markdown)+- `markdown_mmd` (MultiMarkdown)+- `markdown_strict` (Markdown.pl)+- `commonmark` (CommonMark)+- `gfm` (Github-Flavored Markdown)+- `commonmark_x` (CommonMark with many pandoc extensions)++To see which extensions are supported for a given format,+and which are enabled by default, you can use the command++ pandoc --list-extensions=FORMAT++where `FORMAT` is replaced with the name of the format.++Note that the list of extensions for `commonmark`,+`gfm`, and `commonmark_x` are defined relative to default+commonmark. So, for example, `backtick_code_blocks`+does not appear as an extension, since it is enabled by+default and cannot be disabled.++# Citations++When the `--citeproc` option is used, pandoc can automatically generate+citations and a bibliography in a number of styles. Basic usage is++ pandoc --citeproc myinput.txt++To use this feature, you will need to have++- a document containing citations (see [Citation syntax]);+- a source of bibliographic data: either an external bibliography+ file or a list of `references` in the document's YAML metadata;+- optionally, a [CSL] citation style.++## Specifying bibliographic data++You can specify an external bibliography using the+`bibliography` metadata field in a YAML metadata section or the+`--bibliography` command line argument. If you want to use+multiple bibliography files, you can supply multiple+`--bibliography` arguments or set `bibliography` metadata field+to YAML array. A bibliography may have any of these formats:++ Format File extension+ ------------ --------------+ BibLaTeX .bib+ BibTeX .bibtex+ CSL JSON .json+ CSL YAML .yaml+ RIS .ris++Note that `.bib` can be used with both BibTeX and BibLaTeX files;+use the extension `.bibtex` to force interpretation as BibTeX.++In BibTeX and BibLaTeX databases, pandoc parses LaTeX markup+inside fields such as `title`; in CSL YAML databases, pandoc+Markdown; and in CSL JSON databases, an [HTML-like markup][CSL+markup specs]:++`<i>...</i>`+: italics++`<b>...</b>`+: bold++`<span style="font-variant:small-caps;">...</span>` or `<sc>...</sc>`+: small capitals++`<sub>...</sub>`+: subscript++`<sup>...</sup>`+: superscript++`<span class="nocase">...</span>`+: prevent a phrase from being capitalized as title case++As an alternative to specifying a bibliography file using+`--bibliography` or the YAML metadata field `bibliography`, you+can include the citation data directly in the `references` field+of the document's YAML metadata. The field should contain an+array of YAML-encoded references, for example:++ ---+ references:+ - type: article-journal+ id: WatsonCrick1953+ author:+ - family: Watson+ given: J. D.+ - family: Crick+ given: F. H. C.+ issued:+ date-parts:+ - - 1953+ - 4+ - 25+ title: 'Molecular structure of nucleic acids: a structure for+ deoxyribose nucleic acid'+ title-short: Molecular structure of nucleic acids+ container-title: Nature+ volume: 171+ issue: 4356+ page: 737-738+ DOI: 10.1038/171737a0+ URL: https://www.nature.com/articles/171737a0+ language: en-GB+ ...++If both an external bibliography and inline (YAML metadata)+references are provided, both will be used. In case of+conflicting `id`s, the inline references will take precedence.++Note that pandoc can be used to produce such a YAML metadata+section from a BibTeX, BibLaTeX, or CSL JSON bibliography:++ pandoc chem.bib -s -f biblatex -t markdown+ pandoc chem.json -s -f csljson -t markdown++Indeed, pandoc can convert between any of these+citation formats:++ pandoc chem.bib -s -f biblatex -t csljson+ pandoc chem.yaml -s -f markdown -t biblatex++Running pandoc on a bibliography file with the `--citeproc`+option will create a formatted bibliography in the format+of your choice:++ pandoc chem.bib -s --citeproc -o chem.html+ pandoc chem.bib -s --citeproc -o chem.pdf++### Capitalization in titles++If you are using a bibtex or biblatex bibliography, then observe+the following rules:++ - English titles should be in title case. Non-English titles should+ be in sentence case, and the `langid` field in biblatex should be+ set to the relevant language. (The following values are treated+ as English: `american`, `british`, `canadian`, `english`,+ `australian`, `newzealand`, `USenglish`, or `UKenglish`.)++ - As is standard with bibtex/biblatex, proper names should be+ protected with curly braces so that they won't be lowercased+ in styles that call for sentence case. For example:++ title = {My Dinner with {Andre}}++ - In addition, words that should remain lowercase (or camelCase)+ should be protected:++ title = {Spin Wave Dispersion on the {nm} Scale}++ Though this is not necessary in bibtex/biblatex, it is necessary+ with citeproc, which stores titles internally in sentence case,+ and converts to title case in styles that require it. Here we+ protect "nm" so that it doesn't get converted to "Nm" at this stage.++If you are using a CSL bibliography (either JSON or YAML), then observe+the following rules:++ - All titles should be in sentence case.++ - Use the `language` field for non-English titles to prevent their+ conversion to title case in styles that call for this. (Conversion+ happens only if `language` begins with `en` or is left empty.)++ - Protect words that should not be converted to title case using+ this syntax:++ Spin wave dispersion on the <span class="nocase">nm</span> scale++### Conference Papers, Published vs. Unpublished++For a formally published conference paper, use the biblatex entry type+`inproceedings` (which will be mapped to CSL `paper-conference`).++For an unpublished manuscript, use the biblatex entry type+`unpublished` without an `eventtitle` field (this entry type+will be mapped to CSL `manuscript`).++For a talk, an unpublished conference paper, or a poster+presentation, use the biblatex entry type `unpublished` with an+`eventtitle` field (this entry type will be mapped to CSL+`speech`). Use the biblatex `type` field to indicate the type,+e.g. "Paper", or "Poster". `venue` and `eventdate` may be useful+too, though `eventdate` will not be rendered by most CSL styles.+Note that `venue` is for the event's venue, unlike `location`+which describes the publisher's location; do not use the latter+for an unpublished conference paper.+++## Specifying a citation style++Citations and references can be formatted using any style supported by the+[Citation Style Language], listed in the [Zotero Style Repository].+These files are specified using the `--csl` option or the `csl`+(or `citation-style`) metadata field. By default, pandoc will+use the [Chicago Manual of Style] author-date format. (You can+override this default by copying a CSL style of your choice+to `default.csl` in your user data directory.)+The CSL project provides further information on [finding and+editing styles].++The `--citation-abbreviations` option (or the+`citation-abbreviations` metadata field) may be used to specify+a JSON file containing abbreviations of journals that should be+used in formatted bibliographies when `form="short"` is+specified. The format of the file can be illustrated with an+example:+++ { "default": {+ "container-title": {+ "Lloyd's Law Reports": "Lloyd's Rep",+ "Estates Gazette": "EG",+ "Scots Law Times": "SLT"+ }+ }+ }+++## Citations in note styles++Pandoc's citation processing is designed to allow you to+move between author-date, numerical, and note styles without+modifying the Markdown source. When you're using a note+style, avoid inserting footnotes manually. Instead, insert+citations just as you would in an author-date style---for+example,++ Blah blah [@foo, p. 33].++The footnote will be created automatically. Pandoc will take+care of removing the space and moving the note before or+after the period, depending on the setting of+`notes-after-punctuation`, as described below in [Other relevant+metadata fields].++In some cases you may need to put a citation inside a regular+footnote. Normal citations in footnotes (such as `[@foo, p.+33]`) will be rendered in parentheses. In-text citations (such+as `@foo [p. 33]`) will be rendered without parentheses. (A+comma will be added if appropriate.) Thus:++ [^1]: Some studies [@foo; @bar, p. 33] show that+ frubulicious zoosnaps are quantical. For a survey+ of the literature, see @baz [chap. 1].+++## 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:[^note-on-refs]++ ::: {#refs}+ :::++Otherwise, it will be placed at the end of the document.+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)+or at the end of your document:++ last paragraph...++ # References++The bibliography will be inserted after this heading. Note that+the `unnumbered` class will be added to this heading, so that the+section will not be numbered.++If you want to put the bibliography into a variable in your+template, one way to do that is to put the div with id `refs`+into a metadata field, e.g.++ ---+ refs: |+ ::: {#refs}+ :::+ ...++You can then put the variable `$refs$` into your template where+you want the bibliography to be placed.++## Including uncited items in the bibliography++If you want to include items in the bibliography without actually+citing them in the body text, you can define a dummy `nocite` metadata+field and put the citations there:++ ---+ nocite: |+ @item1, @item2+ ...++ @item3++In this example, the document will contain a citation for `item3`+only, but the bibliography will contain entries for `item1`, `item2`, and+`item3`.++It is possible to create a bibliography with all the citations,+whether or not they appear in the document, by using a wildcard:++ ---+ nocite: |+ @*+ ...++For LaTeX output, you can also use [`natbib`] or [`biblatex`] to+render the bibliography. In order to do so, specify bibliography+files as outlined above, and add `--natbib` or `--biblatex`+argument to pandoc invocation. Bear in mind that bibliography+files have to be in either BibTeX (for `--natbib`)+or BibLaTeX (for `--biblatex`) format.++## Other relevant metadata fields++A few other metadata fields affect bibliography formatting:++`link-citations`+: If true, citations will be hyperlinked to the+ corresponding bibliography entries (for author-date and+ numerical styles only). Defaults to false.++`link-bibliography`+: If true, DOIs, PMCIDs, PMID, and URLs in bibliographies will+ be rendered as hyperlinks. (If an entry contains a DOI, PMCID,+ PMID, or URL, but none of these fields are rendered by the style,+ then the title, or in the absence of a title the whole entry, will+ be hyperlinked.) Defaults to true.++`lang`+: The `lang` field will affect how the style is localized,+ for example in the translation of labels, the use+ of quotation marks, and the way items are sorted.+ (For backwards compatibility, `locale` may be used instead+ of `lang`, but this use is deprecated.)++ A BCP 47 language tag is expected: for example, `en`,+ `de`, `en-US`, `fr-CA`, `ug-Cyrl`. The unicode extension+ syntax (after `-u-`) may be used to specify options for+ collation (sorting) more precisely. Here are some examples:++ - `zh-u-co-pinyin`: Chinese with the Pinyin collation.+ - `es-u-co-trad`: Spanish with the traditional collation+ (with `Ch` sorting after `C`).+ - `fr-u-kb`: French with "backwards" accent sorting+ (with `coté` sorting after `côte`).+ - `en-US-u-kf-upper`: English with uppercase letters sorting+ before lower (default is lower before upper).++`notes-after-punctuation`+: If true (the default for note styles), pandoc will put+ footnote references or superscripted numerical citations+ after following punctuation. For example, if the source+ contains `blah blah [@jones99].`, the result will look like+ `blah blah.[^1]`, with the note moved after the period and+ the space collapsed. If false, the space will still be+ collapsed, but the footnote will not be moved after the+ punctuation. The option may also be used in numerical styles+ that use superscripts for citation numbers (but for these+ styles the default is not to move the citation).+++# Slide shows++You can use pandoc to produce an HTML + JavaScript slide presentation+that can be viewed via a web browser. There are five ways to do this,+using [S5], [DZSlides], [Slidy], [Slideous], or [reveal.js].+You can also produce a PDF slide show using LaTeX [`beamer`], or+slide shows in Microsoft [PowerPoint] format.++Here's the Markdown source for a simple slide show, `habits.txt`:++ % Habits+ % John Doe+ % March 22, 2005++ # In the morning++ ## Getting up++ - Turn off alarm+ - Get out of bed++ ## Breakfast++ - Eat eggs+ - Drink coffee++ # In the evening++ ## Dinner++ - Eat spaghetti+ - Drink wine++ ------------------++ ++ ## Going to sleep++ - Get in bed+ - Count sheep++To produce an HTML/JavaScript slide show, simply type++ pandoc -t FORMAT -s habits.txt -o habits.html++where `FORMAT` is either `s5`, `slidy`, `slideous`, `dzslides`, or `revealjs`.++For Slidy, Slideous, reveal.js, and S5, the file produced by+pandoc with the `-s/--standalone` option embeds a link to+JavaScript and CSS files, which are assumed to be available at+the relative path `s5/default` (for S5), `slideous` (for+Slideous), `reveal.js` (for reveal.js), or at the Slidy website+at `w3.org` (for Slidy). (These paths can be changed by setting+the `slidy-url`, `slideous-url`, `revealjs-url`, or `s5-url`+variables; see [Variables for HTML slides], above.) For+DZSlides, the (relatively short) JavaScript and CSS are included+in the file by default.++With all HTML slide formats, the `--self-contained` option can+be used to produce a single file that contains all of the data+necessary to display the slide show, including linked scripts,+stylesheets, images, and videos.++To produce a PDF slide show using beamer, type++ pandoc -t beamer habits.txt -o habits.pdf++Note that a reveal.js slide show can also be converted to a PDF+by printing it to a file from the browser.++To produce a PowerPoint slide show, type++ pandoc habits.txt -o habits.pptx++## Structuring the slide show++By default, the *slide level* is the highest heading level in+the hierarchy that is followed immediately by content, and not another+heading, somewhere in the document. In the example above, level-1 headings+are always followed by level-2 headings, which are followed by content,+so the slide level is 2. This default can be overridden using the+`--slide-level` option.++The document is carved up into slides according to the following+rules:++ * A horizontal rule always starts a new slide.++ * A heading at the slide level always starts a new slide.++ * Headings *below* the slide level in the hierarchy create+ headings *within* a slide. (In beamer, a "block" will be+ created. If the heading has the class `example`, an+ `exampleblock` environment will be used; if it has the class+ `alert`, an `alertblock` will be used; otherwise a regular+ `block` will be used.)++ * Headings *above* the slide level in the hierarchy create+ "title slides," which just contain the section title+ and help to break the slide show into sections.+ Non-slide content under these headings will be included+ on the title slide (for HTML slide shows) or in a+ subsequent slide with the same title (for beamer).++ * A title page is constructed automatically from the document's title+ block, if present. (In the case of beamer, this can be disabled+ by commenting out some lines in the default template.)++These rules are designed to support many different styles of slide show. If+you don't care about structuring your slides into sections and subsections,+you can either just use level-1 headings for all slides (in that case, level 1+will be the slide level) or you can set `--slide-level=0`.++Note: in reveal.js slide shows, if slide level is 2, a two-dimensional+layout will be produced, with level-1 headings building horizontally+and level-2 headings building vertically. It is not recommended that+you use deeper nesting of section levels with reveal.js unless you set+`--slide-level=0` (which lets reveal.js produce a one-dimensional layout+and only interprets horizontal rules as slide boundaries).++### PowerPoint layout choice++When creating slides, the pptx writer chooses from a number of pre-defined+layouts, based on the content of the slide:++Title Slide+: This layout is used for the initial slide, which is generated and+ filled from the metadata fields `date`, `author`, and `title`, if+ they are present.++Section Header+: This layout is used for what pandoc calls “title slides”, i.e.+ slides which start with a header which is above the slide level in+ the hierarchy.++Two Content+: This layout is used for two-column slides, i.e. slides containing a+ div with class `columns` which contains at least two divs with class+ `column`.++Comparison+: This layout is used instead of “Two Content” for any two-column+ slides in which at least one column contains text followed by+ non-text (e.g. an image or a table).++Content with Caption+: This layout is used for any non-two-column slides which contain text+ followed by non-text (e.g. an image or a table).++Blank+: This layout is used for any slides which only contain blank content,+ e.g. a slide containing only speaker notes, or a slide containing+ only a non-breaking space.++Title and Content+: This layout is used for all slides which do not match the criteria+ for another layout.++These layouts are chosen from the default pptx reference doc included with+pandoc, unless an alternative reference doc is specified using+`--reference-doc`.++## Incremental lists++By default, these writers produce lists that display "all at once."+If you want your lists to display incrementally (one item at a time),+use the `-i` option. If you want a particular list to depart from the+default, put it in a `div` block with class `incremental` or+`nonincremental`. So, for example, using the `fenced div` syntax, the+following would be incremental regardless of the document default:++ ::: incremental++ - Eat spaghetti+ - Drink wine++ :::++or++ ::: nonincremental++ - Eat spaghetti+ - Drink wine++ :::++While using `incremental` and `nonincremental` divs is the+recommended method of setting incremental lists on a per-case basis,+an older method is also supported: putting lists inside a blockquote+will depart from the document default (that is, it will display+incrementally without the `-i` option and all at once with the `-i`+option):++ > - Eat spaghetti+ > - Drink wine++Both methods allow incremental and nonincremental lists to be mixed+in a single document.++If you want to include a block-quoted list, you can work around+this behavior by putting the list inside a fenced div, so that+it is not the direct child of the block quote:++ > ::: wrapper+ > - a+ > - list in a quote+ > :::++## Inserting pauses++You can add "pauses" within a slide by including a paragraph containing+three dots, separated by spaces:++ # Slide with a pause++ content before the pause++ . . .++ content after the pause++Note: this feature is not yet implemented for PowerPoint output.++## Styling the slides++You can change the style of HTML slides by putting customized CSS files+in `$DATADIR/s5/default` (for S5), `$DATADIR/slidy` (for Slidy),+or `$DATADIR/slideous` (for Slideous),+where `$DATADIR` is the user data directory (see `--data-dir`, above).+The originals may be found in pandoc's system data directory (generally+`$CABALDIR/pandoc-VERSION/s5/default`). Pandoc will look there for any+files it does not find in the user data directory.++For dzslides, the CSS is included in the HTML file itself, and may+be modified there.++All [reveal.js configuration options] can be set through variables.+For example, themes can be used by setting the `theme` variable:++ -V theme=moon++Or you can specify a custom stylesheet using the `--css` option.++To style beamer slides, you can specify a `theme`, `colortheme`,+`fonttheme`, `innertheme`, and `outertheme`, using the `-V` option:++ pandoc -t beamer habits.txt -V theme:Warsaw -o habits.pdf++Note that heading attributes will turn into slide attributes+(on a `<div>` or `<section>`) in HTML slide formats, allowing you+to style individual slides. In beamer, a number of heading+classes and attributes are recognized as frame options and+will be passed through as options to the frame: see+[Frame attributes in beamer], below.++## Speaker notes++Speaker notes are supported in reveal.js, PowerPoint (pptx),+and beamer output. You can add notes to your Markdown document thus:++ ::: notes++ This is my note.++ - It can contain Markdown+ - like this list++ :::++To show the notes window in reveal.js, press `s` while viewing the+presentation. Speaker notes in PowerPoint will be available, as usual,+in handouts and presenter view.++Notes are not yet supported for other slide formats, but the notes+will not appear on the slides themselves.++### Speaker notes on the title slide (PowerPoint)++For PowerPoint output, the title slide is generated from the document's+YAML metadata block. To add speaker notes to this slide, use a `notes`+field in the metadata:++ ---+ title: My Presentation+ author: Jane Doe+ notes: |+ Welcome everyone to this presentation.++ Remember to introduce yourself and mention the key topics.+ ---++The `notes` field can contain multiple paragraphs and Markdown formatting.++## Columns++To put material in side by side columns, you can use a native+div container with class `columns`, containing two or more div+containers with class `column` and a `width` attribute:++ :::::::::::::: {.columns}+ ::: {.column width="40%"}+ contents...+ :::+ ::: {.column width="60%"}+ contents...+ :::+ ::::::::::::::++Note: Specifying column widths does not currently work for PowerPoint.++### Additional columns attributes in beamer++The div containers with classes `columns` and `column` can optionally have+an `align` attribute.+The class `columns` can optionally have a `totalwidth` attribute or an+`onlytextwidth` class.++ :::::::::::::: {.columns align=center totalwidth=8em}+ ::: {.column width="40%"}+ contents...+ :::+ ::: {.column width="60%" align=bottom}+ contents...+ :::+ ::::::::::::::++The `align` attributes on `columns` and `column` can be used with the+values `top`, `top-baseline`, `center` and `bottom` to vertically align+the columns. It defaults to `top` in `columns`.++The `totalwidth` attribute limits the width of the columns to the given value.++ :::::::::::::: {.columns align=top .onlytextwidth}+ ::: {.column width="40%" align=center}+ contents...+ :::+ ::: {.column width="60%"}+ contents...+ :::+ ::::::::::::::++The class `onlytextwidth` sets the `totalwidth` to `\textwidth`.++See Section 12.7 of the [Beamer User's Guide] for more details.++## Frame attributes in beamer++Sometimes it is necessary to add the LaTeX `[fragile]` option to+a frame in beamer (for example, when using the `minted` environment).+This can be forced by adding the `fragile` class to the heading+introducing the slide:++ # Fragile slide {.fragile}++All of the other frame attributes described in Section 8.1 of+the [Beamer User's Guide] may also be used: `allowdisplaybreaks`,+`allowframebreaks`, `b`, `c`, `s`, `t`, `environment`, `label`, `plain`,+`shrink`, `standout`, `noframenumbering`, `squeeze`.+`allowframebreaks` is recommended especially for bibliographies, as+it allows multiple slides to be created if the content overfills the+frame:++ # References {.allowframebreaks}++In addition, the `frameoptions` attribute may be used to+pass arbitrary frame options to a beamer slide:++ # Heading {frameoptions="squeeze,shrink,customoption=foobar"}++## Background in reveal.js, beamer, and pptx++Background images can be added to self-contained reveal.js slide shows,+beamer slide shows, and pptx slide shows.++### On all slides (beamer, reveal.js, pptx)++With beamer and reveal.js, the configuration option `background-image` can be+used either in the YAML metadata block or as a command-line variable to get the same image on every slide.++Note that for reveal.js, the `background-image` will be used as+a `parallaxBackgroundImage` (see below).++For pptx, you can use a `--reference-doc` in which+background images have been set on the [relevant+layouts](#powerpoint-layout-choice).++#### `parallaxBackgroundImage` (reveal.js)++For reveal.js, there is also the reveal.js-native option+`parallaxBackgroundImage`, which produces a parallax scrolling background.+You must also set `parallaxBackgroundSize`, and can optionally set+`parallaxBackgroundHorizontal`+and `parallaxBackgroundVertical` to configure the scrolling behaviour.+See the [reveal.js+documentation](https://revealjs.com/backgrounds/#parallax-background)+for more details about the meaning of these options.++In reveal.js's overview mode, the parallaxBackgroundImage will show up+only on the first slide.++### On individual slides (reveal.js, pptx)++To set an image for a particular reveal.js or pptx slide, add+`{background-image="/path/to/image"}` to the first slide-level heading on the+slide (which may even be empty).++As the [HTML writers pass unknown attributes+through](#extension-link_attributes), other reveal.js background settings also+work on individual slides, including `background-size`, `background-repeat`,+`background-color`, `transition`, and `transition-speed`. (The `data-` prefix+will automatically be added.)++Note: `data-background-image` is also supported in pptx for consistency with+reveal.js – if `background-image` isn’t found, `data-background-image` will be+checked.++### On the title slide (reveal.js, pptx)++To add a background image to the automatically generated title slide for+reveal.js, use the `title-slide-attributes` variable in the YAML metadata block.+It must contain a map of attribute names and values. (Note that the `data-`+prefix is required here, as it isn’t added automatically.)++For pptx, pass a `--reference-doc` with the background+image set on the “Title Slide” layout.++### Example (reveal.js)++```+---+title: My Slide Show+parallaxBackgroundImage: /path/to/my/background_image.png+title-slide-attributes:+ data-background-image: /path/to/title_image.png+ data-background-size: contain+---++## Slide One++Slide 1 has background_image.png as its background.++## {background-image="/path/to/special_image.jpg"}++Slide 2 has a special image for its background, even though the heading has no content.+```++# EPUBs++## EPUB Metadata++There are two ways to specify metadata for an EPUB. The first is to use+the `--epub-metadata` option, which takes as its argument an XML file+with [Dublin Core elements].++The second way is to use YAML, either in a+[YAML metadata block][Extension: `yaml_metadata_block`] in a Markdown+document, or in a separate YAML file specified with `--metadata-file`.+Here is an example of a YAML metadata block with EPUB metadata:++ ---+ title:+ - type: main+ text: My Book+ - type: subtitle+ text: An investigation of metadata+ creator:+ - role: author+ text: John Smith+ - role: editor+ text: Sarah Jones+ identifier:+ - scheme: DOI+ text: doi:10.234234.234/33+ publisher: My Press+ rights: © 2007 John Smith, CC BY-NC+ ibooks:+ version: 1.3.4+ ...++The following fields are recognized:++`identifier`+ ~ Either a string value or an object with fields `text` and+ `scheme`. Valid values for `scheme` are `ISBN-10`,+ `GTIN-13`, `UPC`, `ISMN-10`, `DOI`, `LCCN`, `GTIN-14`,+ `ISBN-13`, `Legal deposit number`, `URN`, `OCLC number`,+ `Co-publisher’s ISBN-13`, `ISMN-13`, `ISBN-A`, `JP e-code`,+ `OLCC number`, `JP Magazine ID`, `UPC-12+5`, `BNF Control number`,+ `ISSN-13`, `ARK`, `Digital file internal version number`.++`title`+ ~ Either a string value, or an object with fields `file-as` and+ `type`, or a list of such objects. Valid values for `type` are+ `main`, `subtitle`, `short`, `collection`, `edition`, `extended`.++`creator`+ ~ Either a string value, or an object with fields `role`, `file-as`,+ and `text`, or a list of such objects. Valid values for `role` are+ [MARC relators], but+ pandoc will attempt to translate the human-readable versions+ (like "author" and "editor") to the appropriate marc relators.++`contributor`+ ~ Same format as `creator`.++`date`+ ~ A string value in `YYYY-MM-DD` format. (Only the year is necessary.)+ Pandoc will attempt to convert other common date formats.++`lang` (or legacy: `language`)+ ~ A string value in [BCP 47] format. Pandoc will default to the local+ language if nothing is specified.++`subject`+ ~ Either a string value, or an object with fields `text`, `authority`,+ and `term`, or a list of such objects. Valid values for `authority`+ are either a [reserved authority value] (currently `AAT`, `BIC`,+ `BISAC`, `CLC`, `DDC`, `CLIL`, `EuroVoc`, `MEDTOP`, `LCSH`, `NDC`,+ `Thema`, `UDC`, and `WGS`) or an absolute IRI identifying a custom+ scheme. Valid values for `term` are defined by the scheme.++`description`+ ~ A string value.++`type`+ ~ A string value.++`format`+ ~ A string value.++`relation`+ ~ A string value.++`coverage`+ ~ A string value.++`rights`+ ~ A string value.++`belongs-to-collection`+ ~ A string value. Identifies the name of a collection to which+ the EPUB Publication belongs.++`group-position`+ ~ The `group-position` field indicates the numeric position in which+ the EPUB Publication belongs relative to other works belonging to+ the same `belongs-to-collection` field.++`cover-image`+ ~ A string value (path to cover image).++`css` (or legacy: `stylesheet`)+ ~ A string value (path to CSS stylesheet).++`page-progression-direction`+ ~ Either `ltr` or `rtl`. Specifies the `page-progression-direction`+ attribute for the [`spine` element].++`accessModes`+ ~ An array of strings ([schema][accessibility schema]).+ Defaults to `["textual"]`.++`accessModeSufficient`+ ~ An array of strings ([schema][accessibility schema]).+ Defaults to `["textual"]`.++`accessibilityHazards`+ ~ An array of strings ([schema][accessibility schema]).+ Defaults to `["none"]`.++`accessibilityFeatures`+ ~ An array of strings ([schema][accessibility schema]).+ Defaults to++ - "alternativeText"+ - "readingOrder"+ - "structuralNavigation"+ - "tableOfContents"++`accessibilitySummary`+ ~ A string value.++`ibooks`+ ~ iBooks-specific metadata, with the following fields:++ - `version`: (string)+ - `specified-fonts`: `true`|`false` (default `false`)+ - `ipad-orientation-lock`: `portrait-only`|`landscape-only`+ - `iphone-orientation-lock`: `portrait-only`|`landscape-only`+ - `binding`: `true`|`false` (default `true`)+ - `scroll-axis`: `vertical`|`horizontal`|`default`++[accessibility schema]: https://kb.daisy.org/publishing/docs/metadata/schema.org/index.html+[MARC relators]: https://loc.gov/marc/relators/relaterm.html+[reserved authority value]: https://idpf.github.io/epub-registries/authorities/+[`spine` element]: http://idpf.org/epub/301/spec/epub-publications.html#sec-spine-elem++## The `epub:type` attribute++For `epub3` output, you can mark up the heading that corresponds to an EPUB+chapter using the [`epub:type` attribute][epub-type]. For example, to set+the attribute to the value `prologue`, use this Markdown:++ # My chapter {epub:type=prologue}++Which will result in:++ <body epub:type="frontmatter">+ <section epub:type="prologue">+ <h1>My chapter</h1>++Pandoc will output `<body epub:type="bodymatter">`, unless+you use one of the following values, in which case either+`frontmatter` or `backmatter` will be output.++`epub:type` of first section `epub:type` of body+---------------------------- ------------------+prologue frontmatter+abstract frontmatter+acknowledgments frontmatter+copyright-page frontmatter+dedication frontmatter+credits frontmatter+keywords frontmatter+imprint frontmatter+contributors frontmatter+other-credits frontmatter+errata frontmatter+revision-history frontmatter+titlepage frontmatter+halftitlepage frontmatter+seriespage frontmatter+foreword frontmatter+preface frontmatter+frontispiece frontmatter+appendix backmatter+colophon backmatter+bibliography backmatter+index backmatter++[epub-type]: http://www.idpf.org/epub/31/spec/epub-contentdocs.html#sec-epub-type-attribute++## Linked media++By default, pandoc will download media referenced from any `<img>`, `<audio>`,+`<video>` or `<source>` element present in the generated EPUB,+and include it in the EPUB container, yielding a completely+self-contained EPUB. If you want to link to external media resources+instead, use raw HTML in your source and add `data-external="1"` to the tag+with the `src` attribute. For example:++ <audio controls="1">+ <source src="https://example.com/music/toccata.mp3"+ data-external="1" type="audio/mpeg">+ </source>+ </audio>++If the input format already is HTML then `data-external="1"` will work+as expected for `<img>` elements. Similarly, for Markdown, external+images can be declared with `{external=1}`. Note that this+only works for images; the other media elements have no native+representation in pandoc's AST and require the use of raw HTML.++## EPUB styling++By default, pandoc will include some basic styling+contained in its `epub.css` data file. (To see this,+use `pandoc --print-default-data-file epub.css`.)+To use a different CSS file, just use the `--css` command+line option. A few inline styles are defined in addition; these+are essential for correct formatting of pandoc's HTML output.++The `document-css` variable may be set if the more opinionated+styling of pandoc's default HTML templates is desired (and+in that case the variables defined in [Variables for HTML] may+be used to fine-tune the style).++# Chunked HTML++`pandoc -t chunkedhtml` will produce a zip archive of linked+HTML files, one for each section of the original document.+Internal links will automatically be adjusted to point to+the right place, images linked to under the working directory+will be incorporated, and navigation links will be added.+In addition, a JSON file `sitemap.json` will be included+describing the hierarchical structure of the files.++If an output file without an extension is specified, then+it will be interpreted as a directory and the zip archive+will be automatically unpacked into it (unless it already+exists, in which case an error will be raised). Otherwise+a `.zip` file will be produced.++The navigation links can be customized by adjusting the+template. By default, a table of contents is included only+on the top page. To include it on every page, set the+`toc` variable manually.++# Jupyter notebooks++When creating a [Jupyter notebook], pandoc will try to infer the+notebook structure. Code blocks with the class `code` will be+taken as code cells, and intervening content will be taken as+Markdown cells. Attachments will automatically be created for+images in Markdown cells. Metadata will be taken from the+`jupyter` metadata field. For example:++````+---+title: My notebook+jupyter:+ nbformat: 4+ nbformat_minor: 5+ kernelspec:+ display_name: Python 2+ language: python+ name: python2+ language_info:+ codemirror_mode:+ name: ipython+ version: 2+ file_extension: ".py"+ mimetype: "text/x-python"+ name: "python"+ nbconvert_exporter: "python"+ pygments_lexer: "ipython2"+ version: "2.7.15"+---++# Lorem ipsum++**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus+bibendum felis dictum sodales.++``` code+print("hello")+```++## Pyout++``` code+from IPython.display import HTML+HTML("""+<script>+console.log("hello");+</script>+<b>HTML</b>+""")+```++## Image++This image  will be+included as a cell attachment.+````++If you want to add cell attributes, group cells differently, or+add output to code cells, then you need to include divs to+indicate the structure. You can use either [fenced+divs][Extension: `fenced_divs`] or [native divs][Extension:+`native_divs`] for this. Here is an example:++````+:::::: {.cell .markdown}+# Lorem++**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus+bibendum felis dictum sodales.+::::::++:::::: {.cell .code execution_count=1}+``` {.python}+print("hello")+```++::: {.output .stream .stdout}+```+hello+```+:::+::::::++:::::: {.cell .code execution_count=2}+``` {.python}+from IPython.display import HTML+HTML("""+<script>+console.log("hello");+</script>+<b>HTML</b>+""")+```++::: {.output .execute_result execution_count=2}+```{=html}+<script>+console.log("hello");+</script>+<b>HTML</b>+hello+```+:::+::::::+````++If you include raw HTML or TeX in an output cell, use the+[raw attribute](#extension-raw_attribute), as shown+in the last cell of the example above. Although pandoc can+process "bare" raw HTML and TeX, the result is often+interspersed raw elements and normal textual elements, and+in an output cell pandoc expects a single, connected raw+block. To avoid using raw HTML or TeX except when+marked explicitly using raw attributes, we recommend+specifying the extensions `-raw_html-raw_tex+raw_attribute` when+translating between Markdown and ipynb notebooks.++Note that options and extensions that affect reading and+writing of Markdown will also affect Markdown cells in ipynb+notebooks. For example, `--wrap=preserve` will preserve+soft line breaks in Markdown cells; `--markdown-headings=setext` will+cause Setext-style headings to be used; and `--preserve-tabs` will+prevent tabs from being turned to spaces.++# Vimdoc++Vimdoc writer generates Vim help files and makes use of the following metadata+variables:++``` yaml+abstract: "A short description"+author: Author+title: Title++# Vimdoc-specific+filename: "definition-lists.txt"+vimdoc-prefix: pandoc+```++Complete header requires `abstract`, `author`, `title` and `filename` to+be set. Compiling file with such metadata produces the following file+(assumes `--standalone`, see [Templates]):++``` vimdoc+*definition-lists.txt* A short description++ Title by Author+++ Type |gO| to see the table of contents.++[...]++ vim:tw=72:sw=4:ts=4:ft=help:norl:et:+```++If `vimdoc-prefix` is set, all non-command tags are prefixed with its+value, it is used to prevent tag collision: all headers have a tag+(either inferred or explicit) and multiple help pages can have the same+header names, therefore collision is to be expected. Let our input be+the following markdown file:++``` markdown+## Header++`:[range]Fnl {expr}`{#:Fnl}+: Evaluates {expr} or range++`vim.b`{#vim.b}+: Buffer-scoped (`:h b:`) variables for the current buffer. Invalid or unset+ key returns `nil`. Can be indexed with an integer to access variables for a+ specific buffer.++[Span]{#span}+: generic inline container for phrasing content, which does not inherently+ represent anything.+```++Convert it to vimdoc:++``` vimdoc+------------------------------------------------------------------------+Header *header*++:[range]Fnl {expr} *:Fnl*+ Evaluates {expr} or range+`vim.b` *vim.b*+ Buffer-scoped (|b:|) variables for the current buffer. Invalid or+ unset key returns `nil`. Can be indexed with an integer to access+ variables for a specific buffer.+Span *span*+ generic inline container for phrasing content, which does not+ inherently represent anything.+```++Convert it to vimdoc with metadata variable set (e.g. with+`-M vimdoc-prefix=pandoc`)++``` vimdoc+------------------------------------------------------------------------+Header *pandoc-header*++:[range]Fnl {expr} *:Fnl*+ Evaluates {expr} or range+`vim.b` *pandoc-vim.b*+ Buffer-scoped (|b:|) variables for the current buffer. Invalid or+ unset key returns `nil`. Can be indexed with an integer to access+ variables for a specific buffer.+Span *pandoc-span*+ generic inline container for phrasing content, which does not+ inherently represent anything.+```++`vim.b` and `Span` got their prefixes but not `:Fnl` because ex-commands+(those starting with `:`) don't get a prefix, since they are considered+unique across help pages.++In both cases `:help b:` became reference `|b:|` (also works with+`:h b:`). Links pointing to either <https://vimhelp.org/> or+<https://neovim.io/doc/user> become references too.++Vim traditionally wraps at 78, but Pandoc defaults to 72. Use+`--columns 78` to match Vim.++# Syntax highlighting++Pandoc will automatically highlight syntax in [fenced code blocks] that+are marked with a language name. The Haskell library [skylighting] is+used for highlighting. Currently highlighting is supported only for+HTML, EPUB, Docx, Ms, Man, Typst, and LaTeX/PDF output. To see a list+of language names that pandoc will recognize, type `pandoc+--list-highlight-languages`.++The color scheme can be selected using the `--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+`--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 --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+`--syntax-definition` option to load a [KDE-style XML syntax definition+file](https://docs.kde.org/stable5/en/kate/katepart/highlight.html).+Before writing your own, have a look at KDE's [repository of syntax+definitions](https://github.com/KDE/syntax-highlighting/tree/master/data/syntax).++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 `--syntax-highlighting=none`.++To use a format's idiomatic syntax highlighting instead of+pandoc's built-in highlighting, use `--syntax-highlighting=idiomatic`.+Currently, `idiomatic` only affects the following formats:++- In reveal.js, it causes reveal.js's highlighting plugin to be+ used for source code highlighting. The style may be customized+ by setting the `highlightjs-theme` variable.++- In Typst, it causes Typst's built-in highlighting to be used.+ (This is also the default for Typst.)++- In LaTeX, it causes the [`listings`][] package to be used. Note that+ `listings` does not support multi-byte encoding for source code. To handle+ UTF-8 you would need to use a custom template. This issue is fully+ documented here: [Encoding issue with the listings package][].++- In other formats, `idiomatic` will have the same result as `default`.++[skylighting]: https://github.com/jgm/skylighting++# Custom Styles++Custom styles can be used in the docx, odt and ICML formats.++## Output++By default, pandoc's odt, docx and ICML output applies a predefined set of+styles for blocks such as paragraphs and block quotes, and uses largely+default formatting (italics, bold) for inlines. This will work for most+purposes, especially alongside a [reference doc](#option--reference-doc) file.+However, if you need to apply your own styles to blocks, or match a preexisting+set of styles, pandoc allows you to define custom styles for blocks and text+using `div`s and `span`s, respectively.++If you define a Div, Span, or Table with the attribute+`custom-style`, pandoc will apply your specified style to the+contained elements (with the exception of elements whose function+depends on a style, like headings, code blocks, block quotes, or+links). So, for example, using the `bracketed_spans` syntax,++ [Get out]{custom-style="Emphatically"}, he said.++would produce a file with "Get out" styled with character+style `Emphatically`. Similarly, using the `fenced_divs` syntax,++ Dickinson starts the poem simply:++ ::: {custom-style="Poetry"}+ | A Bird came down the Walk---+ | He did not know I saw---+ :::++would style the two contained lines with the `Poetry` paragraph style.++Styles will be defined in the output file as inheriting+from normal text (docx) or Default Paragraph Style (odt), if the+styles are not yet in your [reference doc](#option--reference-doc).+If they are already defined, pandoc will not alter the definition.++This feature allows for greatest customization in conjunction with+[pandoc filters]. If you want all paragraphs after block quotes to be+indented, you can write a filter to apply the styles necessary. If you+want all italics to be transformed to the `Emphasis` character style+(perhaps to change their color), you can write a filter which will+transform all italicized inlines to inlines within an `Emphasis`+custom-style `span`.++For docx or odt output, you don't need to enable any extensions for+custom styles to work.++For icml output, you can also set an `object-style` in images:++ {object-style="fixedSizeImage"}++In InDesign you'll see that object style given to the image,+and you'll be able to customize it, or load its definition from+a template of yours.++[pandoc filters]: https://pandoc.org/filters.html++## Input++The docx reader, by default, only reads those styles that it can+convert into pandoc elements, either by direct conversion or+interpreting the derivation of the input document's styles.++By enabling the [`styles` extension](#ext-styles) in the docx reader+(`-f docx+styles`), you can produce output that maintains the styles+of the input document, using the `custom-style` class. A `custom-style`+attribute will be added for each style. Divs will be created to+hold the paragraph styles, and Spans to hold the character styles.+Table styles will be applied directly to the Table.++For example, using the `custom-style-reference.docx` file in the test+directory, we have the following different outputs:++Without the `+styles` extension:++ $ pandoc test/docx/custom-style-reference.docx -f docx -t markdown+ This is some text.++ This is text with an *emphasized* text style. And this is text with a+ **strengthened** text style.++ > Here is a styled paragraph that inherits from Block Text.++And with the extension:++ $ pandoc test/docx/custom-style-reference.docx -f docx+styles -t markdown++ ::: {custom-style="First Paragraph"}+ This is some text.+ :::++ ::: {custom-style="Body Text"}+ This is text with an [emphasized]{custom-style="Emphatic"} text style.+ And this is text with a [strengthened]{custom-style="Strengthened"}+ text style.+ :::++ ::: {custom-style="My Block Style"}+ > Here is a styled paragraph that inherits from Block Text.+ :::++With these custom styles, you can use your input document as a+reference-doc while creating docx output (see below), and maintain the+same styles in your input and output files.++# Custom readers and writers++Pandoc can be extended with custom readers and writers written+in [Lua]. (Pandoc includes a Lua interpreter, so Lua need not+be installed separately.)++To use a custom reader or writer, simply specify the path to the+Lua script in place of the input or output format. For example:++ pandoc -t data/sample.lua+ pandoc -f my_custom_markup_language.lua -t latex -s++If the script is not found relative to the working directory,+it will be sought in the `custom` subdirectory of the user data+directory (see `--data-dir`).++A custom reader is a Lua script that defines one function,+Reader, which takes a string as input and returns a Pandoc+AST. See the [Lua filters documentation] for documentation+of the functions that are available for creating pandoc+AST elements. For parsing, the [lpeg] parsing library+is available by default. To see a sample custom reader:++ pandoc --print-default-data-file creole.lua++If you want your custom reader to have access to reader options+(e.g. the tab stop setting), you give your Reader function a+second `options` parameter.++A custom writer is a Lua script that defines a function+that specifies how to render each element in a Pandoc AST.+See the [djot-writer.lua] for a full-featured example.++Note that custom writers have no default template. If you want+to use `--standalone` with a custom writer, you will need to+specify a template manually using `--template` or add a new+default template with the name+`default.NAME_OF_CUSTOM_WRITER.lua` to the `templates`+subdirectory of your user data directory (see [Templates]).++[Lua]: https://www.lua.org+[lpeg]: http://www.inf.puc-rio.br/~roberto/lpeg/+[djot-writer.lua]: https://github.com/jgm/djot.lua/blob/main/djot-writer.lua++# Reproducible builds++Some of the document formats pandoc targets (such as EPUB,+docx, and ODT) include build timestamps in the generated document.+That means that the files generated on successive builds will+differ, even if the source does not. To avoid this, set the+`SOURCE_DATE_EPOCH` environment variable, and the timestamp will+be taken from it instead of the current time.+`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).++# Accessible PDFs and PDF archiving standards++PDF is a flexible format, and using PDF in certain contexts+requires additional conventions. For example, PDFs are not+accessible by default; they define how characters are placed on a+page but do not contain semantic information on the content.+However, it is possible to generate accessible PDFs, which use+tagging to add semantic information to the document.++Pandoc defaults to LaTeX to generate PDF. LaTeX's `\DocumentMetadata`+interface supports PDF standards and tagging when using LuaLaTeX;+set the `pdfstandard` variable to enable this (see below). For older+LaTeX installations, alternative engines must be used.++The PDF standards PDF/A and PDF/UA define further restrictions+intended to optimize PDFs for archiving and accessibility. Tagging+is commonly used in combination with these standards to ensure+best results.++Note, however, that standard compliance depends on many things,+including the colorspace of embedded images. Pandoc cannot check+this, and external programs must be used to ensure that generated+PDFs are in compliance.++## LaTeX++Set the `pdfstandard` variable to produce tagged PDFs conforming+to PDF/A, PDF/X, or PDF/UA standards. For example:++ pandoc -V pdfstandard=ua-2 --pdf-engine=lualatex doc.md -o doc.pdf++Multiple standards can be combined:++ ---+ pdfstandard:+ - ua-2+ - a-4f+ ---++The required PDF version is inferred automatically. This feature+requires LuaLaTeX in TeX Live 2025 with LaTeX kernel 2025-06-01+or newer.++## ConTeXt++ConTeXt always produces tagged PDFs, but the quality depends on+the input. The default ConTeXt markup generated by pandoc is+optimized for readability and reuse, not tagging. Enable the+[`tagging`](#extension--tagging) format extension to force markup+that is optimized for tagging. For example:++ pandoc -t context+tagging doc.md -o doc.pdf++A recent `context` version should be used, as older versions+contained a bug that lead to invalid PDF metadata.++## WeasyPrint++The HTML-based engine WeasyPrint includes experimental support for+PDF/A and PDF/UA since version 57. Tagged PDFs can created with++ pandoc --pdf-engine=weasyprint \+ --pdf-engine-opt=--pdf-variant=pdf/ua-1 ...++The feature is experimental and standard compliance should not be+assumed.++## Prince XML++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 \+ --pdf-engine-opt=--tagged-pdf ...++See the prince documentation for more info.++## Typst++Typst 0.12 can produce PDF/A-2b:++ pandoc --pdf-engine=typst --pdf-engine-opt=--pdf-standard=a-2b ...++## Word Processors++Word processors like LibreOffice and MS Word can also be used to+generate standardized and tagged PDF output. Pandoc does not+support direct conversions via these tools. However, pandoc can+convert a document to a `docx` or `odt` file, which can then be+opened and converted to PDF with the respective word processor.+See the documentation for [Word][word-accessible-pdfs] and+[LibreOffice][lo-pdf-export].++[word-accessible-pdfs]: https://support.microsoft.com/en-us/office/create-accessible-pdfs-064625e0-56ea-4e16-ad71-3aa33bb4b7ed+[lo-pdf-export]: https://help.libreoffice.org/latest/en-US/text/shared/01/ref_pdf_export_general.html+++# Running pandoc as a web server++If you rename (or symlink) the pandoc executable to+`pandoc-server`, or if you call pandoc with `server` as the first+argument, it will start up a web server with a JSON API. This+server exposes most of the conversion functionality of pandoc. For+full documentation, see the [pandoc-server] man page.++If you rename (or symlink) the pandoc executable to+`pandoc-server.cgi`, it will function as a CGI program+exposing the same API as `pandoc-server`.++`pandoc-server` is designed to be maximally secure; it uses+Haskell's type system to provide strong guarantees that no I/O+will be performed on the server during pandoc conversions.++[pandoc-server]: https://github.com/jgm/pandoc/blob/master/doc/pandoc-server.md++# Running pandoc as a Lua interpreter++Calling the pandoc executable under the name `pandoc-lua` or with+`lua` as the first argument will make it function as a standalone+Lua interpreter. The behavior is mostly identical to that of the+[standalone `lua` executable][lua standalone], version 5.4.+All `pandoc.*` packages, as well as the packages `re` and `lpeg`,+are available via global variables. Furthermore, the globals+`PANDOC_VERSION`, `PANDOC_STATE`, and `PANDOC_API_VERSION` are+set at startup. For full documentation, see the [pandoc-lua] man page.++[lua standalone]: https://www.lua.org/manual/5.4/manual.html#7+[pandoc-lua]: https://github.com/jgm/pandoc/blob/master/doc/pandoc-lua.md++# A note on security++1. Although pandoc itself will not create or modify any files other+ than those you explicitly ask it create (with the exception+ of temporary files used in producing PDFs), a filter or custom+ writer could in principle do anything on your file system. Please+ audit filters and custom writers very carefully before using them.++2. Several input formats (including LaTeX, Org, RST, and Typst)+ support `include` directives that allow the contents of a file to be+ included in the output. An untrusted attacker could use these+ to view the contents of files on the file system. (Using the+ `--sandbox` option can protect against this threat.)++3. Several output formats (including RTF, FB2, HTML with+ `--self-contained`, EPUB, Docx, and ODT) will embed encoded+ or raw images into the output file. An untrusted attacker+ could exploit this to view the contents of non-image files on the+ file system. (Using the `--sandbox` option can protect+ against this threat, but will also prevent including images in+ these formats.)++4. In reading HTML files, pandoc will attempt to include the+ contents of `iframe` elements by fetching content from the+ local file or URL specified by `src`. If untrusted HTML is+ processed on a server, this has the potential to reveal anything+ readable by the process running the server. Using the `-f html+raw_html`+ will mitigate this threat by causing the whole `iframe`+ to be parsed as a raw HTML block. Using `--sandbox` will also+ protect against the threat.++5. If your application uses pandoc as a Haskell library (rather than+ shelling out to the executable), it is possible to use it in a mode+ that fully isolates pandoc from your file system, by running the+ pandoc operations in the `PandocPure` monad. See the document+ [Using the pandoc API](https://pandoc.org/using-the-pandoc-api.html)+ for more details. (This corresponds to the use of the `--sandbox`+ option on the command line.)++6. Pandoc's parsers can exhibit pathological performance on some+ corner cases. It is wise to put any pandoc operations under+ a timeout, to avoid DOS attacks that exploit these issues.+ If you are using the pandoc executable, you can add the+ command line options `+RTS -M512M -RTS` (for example) to limit+ the heap size to 512MB. Note that the `commonmark` parser+ (including `commonmark_x` and `gfm`) is much less vulnerable+ to pathological performance than the `markdown` parser, so+ it is a better choice when processing untrusted input.++7. The HTML generated by pandoc is not guaranteed to be safe.+ If `raw_html` is enabled for the Markdown input, users can+ inject arbitrary HTML. Even if `raw_html` is disabled,+ users can include dangerous content in URLs and attributes.+ To be safe, you should run all HTML generated from untrusted+ user input through an HTML sanitizer.++# Authors++Copyright 2006--2024 John MacFarlane (jgm@berkeley.edu). Released under the [GPL], version 2 or greater. This software carries no warranty of any kind. (See COPYRIGHT for full copyright and warranty notices.) For a full list of contributors, see the file
@@ -11,7 +11,7 @@ release](https://img.shields.io/hackage/v/pandoc.svg?label=hackage)](https://hackage.haskell.org/package/pandoc) [](https://formulae.brew.sh/formula/pandoc) [](https://www.stackage.org/lts/package/pandoc-types)+package](https://stackage.org/package/pandoc/badge/lts)](https://www.stackage.org/lts/package/pandoc) [](https://github.com/jgm/pandoc/actions) [](https://www.gnu.org/licenses/gpl.html)@@ -22,12 +22,17 @@ Pandoc is a [Haskell](https://haskell.org) library for converting from one markup format to another, and a command-line tool that uses this-library. It can convert *from*+library. +It can convert *from*+ <div id="input-formats"> +- `asciidoc` ([AsciiDoc](https://asciidoc.org/) markup) - `bibtex` ([BibTeX](https://ctan.org/pkg/bibtex) bibliography) - `biblatex` ([BibLaTeX](https://ctan.org/pkg/biblatex) bibliography)+- `bits` ([BITS](https://jats.nlm.nih.gov/extensions/bits/) XML, alias+ for `jats`) - `commonmark` ([CommonMark](https://commonmark.org) Markdown) - `commonmark_x` ([CommonMark](https://commonmark.org) Markdown with extensions)@@ -39,6 +44,7 @@ - `tsv` ([TSV](https://www.iana.org/assignments/media-types/text/tab-separated-values) table)+- `djot` ([Djot markup](https://djot.net)) - `docbook` ([DocBook](https://docbook.org)) - `docx` ([Word docx](https://en.wikipedia.org/wiki/Office_Open_XML)) - `dokuwiki` ([DokuWiki markup](https://www.dokuwiki.org/dokuwiki))@@ -76,11 +82,18 @@ - `mediawiki` ([MediaWiki markup](https://www.mediawiki.org/wiki/Help:Formatting)) - `man` ([roff man](https://man.cx/groff_man(7)))+- `mdoc` ([mdoc](https://mandoc.bsd.lv/man/mdoc.7.html) manual page+ markup) - `muse` ([Muse](https://amusewiki.org/library/manual)) - `native` (native Haskell)-- `odt` ([ODT](https://en.wikipedia.org/wiki/OpenDocument))-- `opml` ([OPML](http://dev.opml.org/spec2.html))+- `odt` ([OpenDocument text+ document](https://en.wikipedia.org/wiki/OpenDocument))+- `opml` ([OPML](https://opml.org/spec2.opml)) - `org` ([Emacs Org mode](https://orgmode.org))+- `pod` (Perl’s [Plain Old+ Documentation](https://perldoc.perl.org/perlpod))+- `pptx`+ ([PowerPoint](https://en.wikipedia.org/wiki/Microsoft_PowerPoint)) - `ris` ([RIS](https://en.wikipedia.org/wiki/RIS_(file_format)) bibliography) - `rtf` ([Rich Text@@ -88,12 +101,16 @@ - `rst` ([reStructuredText](https://docutils.sourceforge.io/docs/ref/rst/introduction.html)) - `t2t` ([txt2tags](https://txt2tags.org))-- `textile` ([Textile](https://www.promptworks.com/textile))+- `textile` ([Textile](https://textile-lang.com)) - `tikiwiki` ([TikiWiki markup](https://doc.tiki.org/Wiki-Syntax-Text#The_Markup_Language_Wiki-Syntax)) - `twiki` ([TWiki markup](https://twiki.org/cgi-bin/view/TWiki/TextFormattingRules))+- `typst` ([typst](https://typst.app)) - `vimwiki` ([Vimwiki](https://vimwiki.github.io))+- `xlsx` ([Excel+ spreadsheet](https://en.wikipedia.org/wiki/Microsoft_Excel#File_formats))+- `xml` (XML version of native AST) - the path of a custom Lua reader, see [Custom readers and writers](https://pandoc.org/MANUAL.html#custom-readers-and-writers) below@@ -104,11 +121,29 @@ <div id="output-formats"> -- `asciidoc` ([AsciiDoc](https://www.methods.co.nz/asciidoc/)) or- `asciidoctor` ([AsciiDoctor](https://asciidoctor.org/))+- `ansi` (text with [ANSI escape+ codes](https://en.wikipedia.org/wiki/ANSI_escape_code), for terminal+ viewing)+- `asciidoc` (modern [AsciiDoc](https://asciidoc.org/) as interpreted by+ [AsciiDoctor](https://asciidoctor.org/))+- `asciidoc_legacy` ([AsciiDoc](https://asciidoc.org/) as interpreted by+ [`asciidoc-py`](https://github.com/asciidoc-py/asciidoc-py)).+- `asciidoctor` (deprecated synonym for `asciidoc`)+- `bbcode` [BBCode](https://www.bbcode.org/reference.php)+- `bbcode_fluxbb` [BBCode+ (FluxBB)](https://web.archive.org/web/20210623155046/https://fluxbb.org/forums/help.php#bbcode)+- `bbcode_phpbb` [BBCode+ (phpBB)](https://www.phpbb.com/community/help/bbcode)+- `bbcode_steam` [BBCode+ (Steam)](https://steamcommunity.com/comment/ForumTopic/formattinghelp)+- `bbcode_hubzilla` [BBCode+ (Hubzilla)](https://hubzilla.org/help/member/bbcode)+- `bbcode_xenforo` [BBCode+ (xenForo)](https://www.xenfocus.com/community/help/bb-codes/) - `beamer` ([LaTeX beamer](https://ctan.org/pkg/beamer) slide show) - `bibtex` ([BibTeX](https://ctan.org/pkg/bibtex) bibliography) - `biblatex` ([BibLaTeX](https://ctan.org/pkg/biblatex) bibliography)+- `chunkedhtml` (zip archive of multiple linked HTML files) - `commonmark` ([CommonMark](https://commonmark.org) Markdown) - `commonmark_x` ([CommonMark](https://commonmark.org) Markdown with extensions)@@ -116,6 +151,7 @@ - `csljson` ([CSL JSON](https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html) bibliography)+- `djot` ([Djot markup](https://djot.net)) - `docbook` or `docbook4` ([DocBook](https://docbook.org) 4) - `docbook5` (DocBook 5) - `docx` ([Word docx](https://en.wikipedia.org/wiki/Office_Open_XML))@@ -138,7 +174,7 @@ markup](https://www.w3.org/TR/html-polyglot/)) - `html4` ([XHTML](https://www.w3.org/TR/xhtml1/) 1.0 Transitional) - `icml` ([InDesign- ICML](https://wwwimages.adobe.com/www.adobe.com/content/dam/acom/en/devnet/indesign/sdk/cs6/idml/idml-cookbook.pdf))+ ICML](https://web.archive.org/web/20211006210211/https://wwwimages.adobe.com/www.adobe.com/content/dam/acom/en/devnet/indesign/sdk/cs6/idml/idml-cookbook.pdf)) - `ipynb` ([Jupyter notebook](https://nbformat.readthedocs.io/en/latest/)) - `jats_archiving` ([JATS](https://jats.nlm.nih.gov) XML, Archiving and@@ -168,10 +204,11 @@ - `ms` ([roff ms](https://man.cx/groff_ms(7))) - `muse` ([Muse](https://amusewiki.org/library/manual)) - `native` (native Haskell)-- `odt` ([OpenOffice text+- `odt` ([OpenDocument text document](https://en.wikipedia.org/wiki/OpenDocument))-- `opml` ([OPML](http://dev.opml.org/spec2.html))-- `opendocument` ([OpenDocument](http://opendocument.xml.org))+- `opml` ([OPML](https://opml.org/spec2.opml))+- `opendocument` ([OpenDocument+ XML](https://www.oasis-open.org/2021/06/16/opendocument-v1-3-oasis-standard-published/)) - `org` ([Emacs Org mode](https://orgmode.org)) - `pdf` ([PDF](https://www.adobe.com/pdf/)) - `plain` (plain text)@@ -183,7 +220,7 @@ - `rtf` ([Rich Text Format](https://en.wikipedia.org/wiki/Rich_Text_Format)) - `texinfo` ([GNU Texinfo](https://www.gnu.org/software/texinfo/))-- `textile` ([Textile](https://www.promptworks.com/textile))+- `textile` ([Textile](https://textile-lang.com)) - `slideous` ([Slideous](https://goessner.net/articles/slideous/) HTML and JavaScript slide show) - `slidy` ([Slidy](https://www.w3.org/Talks/Tools/Slidy2/) HTML and@@ -195,6 +232,10 @@ - `s5` ([S5](https://meyerweb.com/eric/tools/s5/) HTML and JavaScript slide show) - `tei` ([TEI Simple](https://github.com/TEIC/TEI-Simple))+- `typst` ([typst](https://typst.app))+- `vimdoc`+ ([Vimdoc](https://vimhelp.org/helphelp.txt.html#help-writing))+- `xml` (XML version of native AST) - `xwiki` ([XWiki markup](https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/XWikiSyntax/)) - `zimwiki` ([ZimWiki@@ -241,8 +282,9 @@ Guide](https://pandoc.org/MANUAL.html). It is also available [here](MANUAL.txt) as pandoc-flavored Markdown. The website also contains some [examples of the use of-pandoc](https://pandoc.org/demos.html) and a limited [online-demo](https://pandoc.org/try).+pandoc](https://pandoc.org/demos.html), a limited [online+demo](https://pandoc.org/try), and a [WebAssembly-based online+demo](https://pandoc.org/app). ## Contributing @@ -252,7 +294,7 @@ ## License -© 2006-2022 John MacFarlane (jgm@berkeley.edu). Released under the+© 2006-2024 John MacFarlane (jgm@berkeley.edu). Released under the [GPL](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html "GNU General Public License"), version 2 or greater. This software carries no warranty of any kind. (See COPYRIGHT for full copyright and warranty notices.)
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
@@ -1,33 +0,0 @@-{- |- Module : Main- Copyright : Copyright (C) 2006-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley@edu>- Stability : alpha- Portability : portable--Parses command-line options and calls the appropriate readers and-writers.--}-module Main where-import qualified Control.Exception as E-import Text.Pandoc.App (convertWithOpts, defaultOpts, options, parseOptions)-import Text.Pandoc.Error (handleError)-import Text.Pandoc.Server (ServerOpts(..), parseServerOpts, app)-import Safe (readDef)-import System.Environment (getProgName, lookupEnv)-import qualified Network.Wai.Handler.CGI as CGI-import qualified Network.Wai.Handler.Warp as Warp-import Network.Wai.Middleware.Timeout (timeout)--main :: IO ()-main = E.handle (handleError . Left) $ do- prg <- getProgName- cgiTimeout <- maybe 2 (readDef 2) <$> lookupEnv "PANDOC_SERVER_TIMEOUT"- case prg of- "pandoc-server.cgi" -> CGI.run (timeout cgiTimeout app)- "pandoc-server" -> do- sopts <- parseServerOpts- Warp.run (serverPort sopts) (timeout (serverTimeout sopts) app)- _ -> parseOptions options defaultOpts >>= convertWithOpts
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2012-2022 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2012-2024 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -28,6 +28,7 @@ import qualified Data.ByteString.Lazy as BL import Data.Maybe (mapMaybe) import Data.List (sortOn)+import Text.Pandoc.Format (FlavoredFormat(..)) readerBench :: Pandoc -> T.Text@@ -36,16 +37,17 @@ | name `elem` ["bibtex", "biblatex", "csljson"] = Nothing readerBench doc name = either (const Nothing) Just $ runPure $ do- (rdr, rexts) <- getReader name- (wtr, wexts) <- getWriter name+ (rdr, rexts) <- getReader $ FlavoredFormat name mempty+ (wtr, wexts) <- getWriter $ FlavoredFormat name mempty+ tmpl <- Just <$> compileDefaultTemplate name case (rdr, wtr) of (TextReader r, TextWriter w) -> do inp <- w def{ writerWrapText = WrapAuto- , writerExtensions = wexts } doc+ , writerExtensions = wexts+ , writerTemplate = tmpl } doc return $ bench (T.unpack name) $ nf (either (error . show) id . runPure . r def) inp (ByteStringReader r, ByteStringWriter w) -> do- tmpl <- Just <$> compileDefaultTemplate name inp <- w def{ writerWrapText = WrapAuto , writerExtensions = wexts , writerTemplate = tmpl } doc@@ -70,7 +72,7 @@ | name `elem` ["bibtex", "biblatex", "csljson"] = Nothing writerBench imgs doc name = either (const Nothing) Just $ runPure $ do- (wtr, wexts) <- getWriter name+ (wtr, wexts) <- getWriter $ FlavoredFormat name mempty case wtr of TextWriter writerFun -> return $ bench (T.unpack name)
@@ -1,4 +0,0 @@-packages: pandoc.cabal-tests: True-flags: +embed_data_files-constraints: aeson >= 2.0.1.0
@@ -1,7926 +1,14647 @@ # Revision history for pandoc -## pandoc 2.19.2 (2022-08-22)-- * Fix regression with data uris in 2.19.1 (#8239).- In 2.19.1 we used the base64URL encoding rather than base64.-- * pandoc-server: handle `citeproc` parameter as documented (#8235).-- * Org reader: treat *emacs-jupyter* src blocks as code cells (#8236,- Albert Krewinkel). This improves support for notebook-like org files- that are intended to be used with emacs-jupyter package.-- * HTML writer and templates: revert to using `width` property for column- widths (Albert Krewinkel). The default `flex` and `overflow-x` properties- of a column are set to `auto`. In combination, these changes allow to- get good results when using columns with or without explicit widths.-- * Org writer (Albert Krewinkel):-- + Add support for jupyter nodebook cells (#6367).- + Prefix code language of ipynb code blocks with `jupyter-`.- This is the convention used by the *emacs-jupyter* package.- + Keep code block attributes as header args. This allows to keep more- information in the resulting `src` blocks, making it easier to- roundtrip from or through Org. Org babel ignores unknown header- arguments.- + Add code block identifier as `#+name` to src blocks.-- * Fix some typos in the codebase (luz paz).-- * Require hslua-module-path 1.0.3 (#8228, Albert Krewinkel).--## pandoc 2.19.1 (2022-08-18)-- * Add server capabilities.-- + New exported module Text.Pandoc.Server [API change].- + The pandoc executable now starts up a web server when renamed or- symlinked as `pandoc-server`, and functions as a CGI program when- renamed or symlinked as `pandoc-server.cgi`. See the man page for- `pandoc-server` for full documentation.-- * Text.Pandoc.App.Opts: Redo `FromJSON` for `Opt` so that optional- values can be omitted (in which case the values from- `defaultOptions` are used).-- * Org reader: treat "abstract" block as metadata (Albert Krewinkel, #8204).- A block of type "abstract" is assumed to define the document's abstract.- It is transferred from the main text to the metadata.-- * Org template: add abstract from metadata as block of type "abstract"- (#8204).-- * HTML writer: use `flex` property for column widths- (Albert Krewinkel, #8232).-- * LaTeX writer:-- + Add label to tables that have an identifier (Albert Krewinkel, #8219).- Tables with an identifier are marked with a `\label`. A caption is- always included in this case, even if the caption is empty.- + Use `\textquotesingle` for straight quotes in text.- + Fix widths of multicolumn cells (#8218).-- * LaTeX template: fix behavior of `colorlinks` variable (Albert- Krewinkel, #8226). Fixes a regression in 2.19 that required the- `boxlinks` variable to be set in addition to the usual link coloring- variables. Otherwise links were never colored in LaTeX PDF output.-- * Text.Pandoc.Highlighting: Export `lookupHighlightingStyle`- [API change]. Previously this lived in an unexported module- Text.Pandoc.App.CommandLineOptions, under the name- `lookupHighlightStyle`.-- * Text.Pandoc.App:-- + Remove unneeded MonadIO constraints in readSources.- + Factor out `convertWithOpts'` from `convertWithOpts`.- This runs in any PandocMonad, MonadIO, MonadMask instance.- So far it is not exported, but it might find a use later.-- * Support `--strip-comments` in commonmark/gfm (#8222).- This change makes the commonmark reader sensitive to- `readerStripComments`.-- * Lua: add function `pandoc.utils.citeproc` (Albert Krewinkel).- The function runs the *citeproc* processor on a Pandoc document.- Exposing this functionality to Lua allows to make citation processing- part of a filter or writer, simplifies the creation of multiple- bibliographies, and enables the use of varying citation styles in- different parts of a document.-- * Refactor `linux/make_artifacts.sh`.-- * Update INSTALL.md installation from source instructions.-- * Use base64 package instead of base64-bytestring. It is supposed to be- faster and more standards-compliant.-- * trypandoc improvements:-- + Add dropdown with canned examples.- + Add citeproc support.- + Support csv, bibliographic and binary formats.- + Add load from file.- + Add permalink. Don't always reload page.- + Use vanilla JS and CSS + the new `pandoc-server.cgi`.-- * Allow haddock-library-1.11.0.-- * Convert `tool/extract-changes.hs` to a Lua filter.---## pandoc 2.19 (2022-08-03)-- * Add `--embed-resources` flag (Elliot Bobrow, #7331). This can be- used to embed resources without implying `--standalone`.- Deprecate `--self-contained` in favor of `--embed-resources --standalone`.-- * Allow environment variable interpolation in `highlight-style`- and `pdf-engine` fields in defaults files- (#8061; Jaehwang Jung, #8073).-- * Allow placing custom readers and writers in user data directory- (Albert Krewinkel, #8112) (`readers` and `writers` subdirectories).-- * Add `tsv` (tab separated values) as an input format (#7974).- [API change]: Text.Pandoc.Readers.CSV now exports `readTSV`.- Internal change: In Text.Pandoc.CSV, `CSVOptions` has changed- so that `csvQuote` takes a Maybe value.-- * Add `tex_math_dollars` to `gfm` default extensions (reflecting- gfm's new support for math).-- * RST, Org, Markdown readers: support rowspans and colspans in grid tables- (#8202, Albert Krewinkel). Note: the writers does not yet support these- more complex grid table features, so these complex grid tables will- not round-trip.-- * HTML, LaTeX, and MediaWiki readers: use `formatCode`- (#8162, #8129, Elliot Bobrow). This moves formatting from inside inline- code elements to the outside, since pandoc's Code element only takes string- content.-- * Markdown reader:-- + Don't parse inline notes with blank lines inside (#8028).- + Allow attributes in special spans (e.g. `smallcaps`, `underline`)- (Albert krewinkel, #4102). These spans are parsed as- SmallCaps or Underline elements, but any attributes are included- in a wrapping Span.-- * HTML reader:-- + Allow sublists that are not marked as items (Albert- Krewinkel, #8150). This is technically invalid HTML, but it can- be found in the wild and browsers handle it.-- * Org reader (Albert Krewinkel):-- + Recognize absolute paths on Windows (Albert Krewinkel, #8201).- + Recognize {webp,jxl} files as images (YI).- + Allow attrs for Org tables (Albert Krewinkel, #8049). Tables with- attributes are no longer wrapped in Div elements; attributes are added- directly to the table element.- + Support line selection in INCLUDE directives (Brian Leung, #8060).- + Fix Post / Pre mixup when setting emphasis chars (Amir Dekel, #8134).-- * LaTeX reader:-- + Support `\includesvg` (#8027).- + Unescape characters in `\lstinline` inside `\passthrough` (#8179).- + Improve `mathEnvWith` (#8122). When converting e.g. an align- environment to an aligned environment inside a Math element, we need- to include a newline before the `\end{aligned}`, since the previous- line might end in a comment.- + Fix treatment of extensions for `\input` in LaTeX reader (#8092).- Previously we required a `.tex` extension, but TeX- allows any extension for `\input` (as opposed to `\include`).-- * RTF reader:-- + support `\nosupersub` (#8170).-- * TikiWiki reader:-- + Support underlined text-- * DocBook reader:-- + Improved reading `<xref>` elements (Frerich Raabe, #8065).-- * JATS reader:-- + Strip `ref-` prefix from ref id in xref (#8007).- + Support edition in references (#8087).-- * RIS reader:-- + Make parser more forgiving (#8034). Allow blank lines after entries.- Allow entries with no space after the `-`, provided they- just have a newline, e.g. `DB -\n`.- + Get right order of names (#8055).-- * MediaWiki reader:-- + Allow HTML comment after row start (#8110).-- * DokuWiki reader:-- + The `tex_math_dollars` extension is now supported for `dokuwiki`- (but off by default) (#8178).- + Content inside `<latex>...</latex>` is parsed as raw LaTeX inline,- and inside `<LATEX>..</LATEX>` as raw LaTeX block (#8178).- + The behavior of `<php>...</php>` is changed, so that instead of- producing a code block, it produces raw HTML with `<?php ... ?>`.-- * LaTeX writer:-- + Improve grouping with autocites (#8088).- + Extend list of book documentclasses (Wentau Han, #8053).- + Fix width of multicolumn cells (Albert Krewinkel, #8090).- Cells spanning multiple columns must be given an explicit width,- calculated from the table properties.- + Beamer: allow containsverbatim as alternative to fragile (#8080).-- * HTML writer:-- + Add 'footnotes' identifier to footnotes section (#8043).- + Fix bug with `--number-offset`. This formerly caused section divs- to be produced, even when `--section-divs` was not specified (#8097).- + Use CSS flexboxes for columns (Albert Krewinkel). This allows- an arbitrary number of columns, while the previous approach assumed- exactly two columns.- + Allow "spanlike" classes to be combined (see #8194). Previously- classes like "underline" and "marked" had to be the first class- in a span in order for the span to be interpreted as a "ul" or- "mark" element. This commit allows these special classes to be- "stacked," e.g. `[test]{.mark .underline}`; in addition, the- special classes are no longer required to come first in the list- of classes.- + Avoid doubled style attribute when height and width are added to- style because of an image, but the image already has a style attribute- (#8047).- + Do not include the deprecated doc-endnote role (#8030).- doc-endnote was deprecated in DPUB-ARIA 1.1.- + Remove extra soft break for tasklist (black-desk, #8142).- Browser will display the extra newline character between checkbox and- text as a space, which make tasklist items cannot be aligned.-- * EPUB writer:-- + Allow choice of math method for v3 (#8164). Previously we always- used MathML for math in EPUB3, because the spec includes MathML.- But this is not widely supported by readers, so it seems better- to allow users to choose their math method as they can with- EPUB2 or HTML. **NOTE:** Existing workflows that produce EPUBv3- documents including math will be affected by this change. You- must add `--mathml` to your command line if you want to continue- producing MathML.-- * RST writer:-- + Fix missing spaces with nested inlines (#8182).- + Always escape literal backslash (#8178).-- * Ms writer:-- + Add comment in preamble stating generator.- + Fix roff ms syntax highlighting definitions (#8175, thanks to- Branden Robinson).-- * ConTeXt writer:-- + Support complex table structures (Albert Krewinkel, #8116).- The following table feature are now supported in ConTeXt:-- - colspans,- - rowspans,- - multiple bodies,- - row headers, and- - multi-row table head and foot.-- The wrapping `placetable` environment is also given a `reference` option- with the table identifier, enabling referencing of the table from within- the document.- + Unify link handling (Albert Krewinkel, #8096).- Autolinks, i.e. links with content that's the same as the linked URL,- are now marked with the `\url` command. All other links, both internal- and external, are created with the `\goto` command, leading to shorter,- slightly more idiomatic code. As before, autolinks can still be styled- via `\setupurl`, other links via `\setupinteraction`.- + Use "sectionlevel" environment for headings (Albert Krewinkel, #5539).- The document hierarchy is now conveyed using the- `\startsectionlevel`/`\stopsectionlevel` by default. This makes it easy- to include pandoc-generated snippets in documents at arbitrary levels.- The more semantic environments "chapter", "section", "subsection", etc.- are used if the `--top-level-division` command line parameter is set to- a non-default value.-- * Docx writer:-- + Add `w:lang` to `rPr` for Span and Div with lang attribute, so- that Word can know that "Apfel" is not a spelling error (#8026).- + Prevent crashing when handling invalid tables (Albert Krewinkel, #8102).- Tables with different numbers of cells per row would sometimes crash- pandoc. This fix prevents this by cutting off overlong rows.-- * ICML writer:-- + Support custom-style attribute on Table (#8079).-- * AsciiDoc writer:-- + Fix commas in link text (#8070). Commas in link text trigger- interpretation of attributes. To block this, we replace them with- numeric entities.- + Fix underline. We were rendering it as `+++text+++`; this is now- changed to `[.underline]#text#`. See comment at- <https://github.com/jgm/pandoc/issues/8070#issuecomment-1126883824>.-- * FB2 writer:-- + Fix handling of non-section Divs (#8123).-- * Markdown writer:-- + Disable soft wrapping when `hard_line_breaks` enabled (#8035).- We were already doing this for `markdown`; this commit does- the same thing for `markua` and `commonmark` and `gfm`.- + Avoid excessive indentation on bullet lists for `commonmark`,- `markua`, `gfm`. They are now nested by 2 spaces instead of 4 (#8011).-- * Text.Pandoc.Class:-- + Add new function `findFileWithDataFallback` [API Change]- (Albert Krewinkel).- + `fillMediaBag`: Keep attributes of original image on Span (Albert- Krewinkel, #8099). Images that cannot be fetched are replaced with a- Span that contains the image's description. The span now also retains- all original image attributes and inherits all attributes of the image.- Furthermore, the classes `image` and `placeholder` are added, and path- and title are store in attributes `original-image-src` and- `original-image-title`, respectively.-- * Text.Pandoc.Shared:-- + `makeSections`: don't make a section for a div with class "fragments"- (#8098).- + Ensure that Nulls are ignored by `makeSection` and in segmenting- slides (#8155).- + Add `formatCode` function to Text.Pandoc.Shared [API change]- (Elliot Bobrow, #8129).- + `taskListItemToAscii`: handle asciidoctor's characters (#8011).- Asciidoctor uses different unicode characters for task- lists; we should recognize them too and be able to convert- them to ascii task lists in formats like gfm.- + Deprecate `deLink` and mark for later removal.-- * Text.Pandoc.Writers.Shared:-- + `toTableOfContents`: Don't replace links with empty spans in TOC (#8020).-- * Text.Pandoc.Readers.Metadata:-- + Ensure that metadata values w/o trailing newlines are- parsed as inlines, as the manual states.- Previously, they were parsed as inlines if they would- otherwise have been a single Plain or Para, but otherwise- left unchanged. This led to some quirky results (e.g. #8143).- We now use the general function `blocksToInlines` from T.P.Shared.-- * Text.Pandoc.Parsing:-- + Simplify `gridTableWith'`, `gridTableWith` [API Change] (Albert- Krewinkel). The functions `gridTableWith` and `gridTableWith'` no- longer takes a boolean argument that toggles whether a table head- should be parsed: both, tables with heads and without heads, are- always accepted now.-- * Lua subsystem (Albert Krewinkel):-- + Extend `pandoc.system` module (Albert Krewinkel, #8184).- The module now has the additional functions `list_directory`,- `make_directory`, and `remove_directory`. This makes it easier to write- cross-platform scripts that need to inspect or modify the file system.- + Require pandoc-lua-marshal 0.1.7. Adds a `clone` methods to- Pandoc objects and allows to pass Blocks in instead of full- Caption elements.- + Add fields `pandoc.readers` and `pandoc.writers` (#8177).- The set of supported input and output formats is made available to Lua- users.- + Ensure that tables marshaled via JSON arrays behave like Lists.- This allows to invoke methods like `map` and `includes` on lists like- `PANDOC_WRITER_OPTIONS.extensions`.- + Require hslua-2.2.1, unless lua53 flag is set, and do not reset- foreign encoding before running Lua. This fixes a problem where- the encoding used for Lua filenames would sometimes mismatch the- encoding used by the OS.- + Simplify module loading code. Modules are now loaded directly;- the special pandoc Lua package searcher is no longer necessary and- has been removed.- + Add function pandoc.mediabag.fill (#8104). The function allows to- fill the mediabag with all images in a given document. Images that- cannot be fetched are replaced with a Span containing the- image description.-- * Populate mediabag after filters have run (Albert Krewinkel, #8099).- The mediabag is filled with document resources after the filters have- run. This allows, for example, filter authors to modify image paths- before pandoc tries to fetch the images.- Lua filters that rely on a filled mediabag can use the new- `pandoc.mediabag.fill` function to perform that action in the filter.-- * Ms template: redefine rather than removing .CH macro (#8175).-- * JATS template (Albert Krewinkel, except as noted):-- + Include particles, prefix, suffix in names.- + Mark authors with cor-id as corresponding authors.- Corresponding authors are marked by setting the attribute- `corresp="yes"` in their respective `<contrib>` element.- + Unconditionally include permissions element (#8040).- Fixes a bug that caused license information to be omitted when no- copyright information was provided.- + Follow JATS4R recommendation and PudMed Central for license URI- (Castedo Ellerman, #8041).-- * LaTeX template:-- + Rename `\textormath` to `\TextOrMath` (Hos Es, #8036).- + Fix links-as-notes (Albert Krewinkel, #8077).-- * HTML template styles:-- + Remove `span.underline` rule. This is superfluous now that we- render Underline as `<u>`.- + Improve CSS for task lists (#8151).-- * LaTeX template: Add `boxlinks` variable for LaTeX/PDF output (#8198).- If `boxlinks` is set but `colorlinks` is not, then boxes will- be printed around links (`hidelinks` will not be set in `hypersetup`).-- * `--self-contained`: Handle `url()` in `<style>` elements (#8193).-- * Text.Pandoc.PDF: use SHA1 hash of filename when converting SVG.- The previous code threw away the directory component of- the filename in constructing a new one. This led to- surprising results if you had e.g. `foo/pic.svg` and `bar/pic.svg`;- in the final PDF they'd be the same image, because the latter- would overwrite the former in the temp directory.-- * Remove Muse reader round-trip tests. These are nondeterministic and have- repeatedly failed on strange edge cases.-- * Update fonts MIME following IANA recommendation (Gabriel Lewertowski,- #8127).-- * Future compat change for `liftA2` export from Prelude (Georgi Lyubenov,- #8132).-- * Update `default.csl` from the latest chicago-author-date.csl.-- * Update manfilter.hs for greater portability (#8045).- The tables in our man pages were not rendering correctly- with mandoc, now used by default with macOS. mandoc doesn't- allow man formatting inside table cells. For maximum portability,- we now render the tables in plain format and include them as code- blocks in the man page.-- * CI: update macos container version (#8197, Sukka).-- * Add `nightly` flag. This causes a `-nightly-COMPILEDATE`- suffix to be added the the output of `--version` (#8016).- This is used in the nightly CI builds.-- * Update dependencies (aeson, skylighting, pandoc-lua-marshall,- citeproc, texmath).-- * Documentation improvements (thanks to Jiří Wolker,- Castedo Ellerman, Albert Krewinkel, Bastien Dumont, Cezar Drożak, Benjamin- Wuethrich, Ivan Panchenko, Sukil Etxenike, Masataka Ogawa).--## pandoc 2.18 (2022-04-04)-- * New input formats: `endnotexml` (EndNote XML bibliography),- `ris` (RIS bibliography).-- * A RIS bibliography file may now be used with `--citeproc`.-- * Citeproc: Allow a formatted bibliography to be placed in metadata fields- via a Div with class `refs` (#7969, #526). Thus, one can include a- metadata field, say `refs`, whose content is an- empty div with id `refs`, and the formatted bibliography will be put into- this metadata field. It may then be interpolated into a template using the- variable `refs`.-- * Ensure that you don't get PDF output to terminal. `-t pdf` now behaves- like `-t docx` and gives an error unless the output is redirected.-- * `--version` now prints hslua version (#7929) and- Lua version (#7997, Albert Krewinkel).-- * Change `--metadata-file` parsing so that, when the input format is not- markdown or a markdown variant, pandoc's markdown is used (#6832, #7926).- When the input format is a markdown variant, the same format is used.- Reason for the change: it doesn't make sense to run the markdown parser- with a set of extensions designed for a non-markdown format, and- this dramatically limits what people can do in metadata files.-- * Trim whitespace from math in `--webtex` (#7892).- This fixes problems with --webtex and markdown output,- when display math starts or ends with a newline.-- * `--self-contained`: issue warning rather than failing with an error- if a resource can't be found (#7904).-- * New exported module Text.Pandoc.Readers.EndNote, exporting- `readEndNoteXML` and `readEndNoteXMLCitation` [API change].-- * New exported module, Text.Pandoc.Readers.RIS, exporting `readRIS` (#7894)- [API change].-- * LaTeX reader:-- + Handle subequations as inline math environment (#7883).- + Rudimentary support for `vbox` (#7939).- + Support `\today` (#7905).- + Handle `\label` and `\ref` for footnotes (#7930).- + Allow inline groups starting with `\bgroup` (#7953).- + Use custom TokStream that keeps track of whether macros are expanded.- This allows us to improve performance a bit by avoiding unnecessary- runs of the macro expansion code (e.g. from 24 ms to 20 ms on- our standard benchmark).- + Further optimizations for inline parsing.- + Better handling of `\usepackage`. If the package is local but- causes parse errors, parse everything up to the error and skip the- rest. Issue a `CouldNotParseIncludeFile` warning indicating that- parsing failed at that point.- + Text.Pandoc.Readers.LaTeX.Parsing: Monoid and Semigroup instances for- TokStream.-- * HTML reader:-- + Give warnings and emit empty note when parsing- `<a epub:type="noteref">` and the identifier- doesn't correspond to anything in the note table (#7884).- Previously we just silently skipped these cases.- + Fix parsing of epub footnotes (#7884).-- * DocBook reader:-- + Handle complete set of entities as specified at- <https://www.w3.org/2003/entities/2007doc/byalpha.html> (#7938).- + Handle abstract in info section (#7747).- + Improve info parsing.- + Simplify metadata parsing code (#7747).- Handle abstract as block-level content.- Report skipped info elements with `--verbose`.- + Handle address and coyright in metadata (#7747).-- * DokuWiki reader:-- + Add DokuWiki table alignment (#5202, damon-sava-stanley).-- * RST reader:-- + Fix treatment of headerless simple tables (#7902).- + Wrap math in Span to preserve attributes (#7998, Albert Krewinkel).- Math elements with a name, classes, or other fields are wrapped in a- `Span` with these attributes.-- * JATS reader:-- + Improve handling of fn-group elements (#6348, Albert Krewinkel).- Footnotes in `<fn-group>` elements are collected and re-inserted into- the document as proper footnotes in the place where they are referenced.- + Handle `pub-date` (#8000).- + Support PMID, DOI, issue in citations (#7995).- + Improve refs parsing. Handle `issn` and `isbn`; use simpler form- for issued date.- + Strip 'ref-' from ref id in constructing CSL id. This allows better- round-tripping, because the JATS writer adds the `ref-` prefix to- the citation id to get the ref element's id.-- * Org reader:-- + Allow ":" in property drawer keys (Lucas V. R).- Any non-space character is allowed as property drawer key, including ":"- itself (so it is not really a delimiter). The real delimiter is a space- character, so in a drawer like- ```- :PROPERTIES:- ::k:ey:: value- :END:- ```- ":k:ey:" is a key with value "value".-- + Allow comments above property drawer.- + More flexible LaTeX environments (Lucas V. R).- + Handle `#+bibliography:` as metadata so that it can work with- `--citeproc`.- + Parse `#+print_bibliography:` as Div with id `refs`.- + Allow multiple `#+bibliography:`.-- * Markdown reader:-- + Allow one-column pipe tables with pipe on right (#7919).- + Remove restriction on identifiers, so they no longer need to- begin with a letter (#7920).-- * Docx reader:-- + Enable `citations` extension for docx reader (#7840).- When enabled, Zotero, Mendeley, and EndNote citations embedded in- a docx are parsed as native pandoc citations.- (When disabled, the generated citation- text and bibliography are passed through as regular text.)- The bibliography generated by the plugin is suppressed.- Instead, bibliographic data embedded in citation items is added- to the `references` metadata field so that it can be used- with `--citeproc`.-- * Docbook writer:-- + Interpret links without contents as cross-references (#7360, Jan Tojnar).- Links without text contents are converted to `<xref>` elements. DocBook- processors will generate appropriate cross-reference text when presented- with an xref element.-- * Docx writer:-- + Single numbering ID for examples (#7895, mjfs).- This change ensures that example list items all belong to a single- number sequence, so that if items are added or deleted in a word- processor, the other items will renumber automatically.- + Add bookmark with table id to table (#7989, Nikolai- Korobeinikov, #7285). This allows tables with ids to be linked to.-- * Ipynb writer:-- + Handle metadata better (#7928). Previously we used the markdown- writer to render metadata. This had some undesirable consequences- (e.g. en dash expanded to `--` when `smart` enabled), so now we use- the plain writer.-- * LaTeX writer:-- + Avoid extra space before `\CSLRightInline` (#7932).- + Add `scrreport` to `chaptersClasses` (#6168, ivardb).- + Support `page`,`trim`,`clip` attributes on images (#7181).- + Add `()` after booktabs rules (#8001). These commands take optional- arguments with () and [], which can lead to problems if the content- of the table cell begins with these characters.-- * RST writer:-- + Support all standard metadata ("bibliographic") fields.-- * HTML writer: performance improvements.-- * Org writer:-- + Stop indenting property drawers, quote blocks- (#3245, Albert Krewinkel). This follows the current default org-mode- behavior.-- * Markdown writer:-- + Move table-related code into submodule (Albert Krewinkel).- + Don't produce redundant header identifier when the- `gfm_auto_identifiers` extension is set (#7941).- + Update escaping rules for `\`. We now escape `\` only if `raw_tex`- is enabled or it is followed by a non-alphanumeric.-- * JATS writer:-- + Encode author "others" as `<etal/>` (Albert Krewinkel).- Citeproc adopted the BibTeX convention to use the author name "others"- when there are additional authors that are not named. JATS uses the- `<etal>` element for this.- + Avoid doubled ref-list element (#7990). Previously when generating JATS- with the `element_citations` extension enabled, the references were- put in a doubly-nested ref-list element (`<ref-list><ref-list>...`).- + Keep edition info in element citations (#7993, Albert Krewinkel).- + Fix handling of CSL variable 'page' (not 'pages' as we had before).- It should go to 'lpage' and 'rpage', not 'page-range'.-- * EPUB writer: refactor for clarity (#7991, Jonathan Dönszelmann,- Ola Wolska, Ivar de Bruin, Jaap de Jong).-- * Custom writer (Albert Krewinkel):-- + Support new-style Writer function (Albert Krewinkel).- See the documentation for custom writers for details.- + Produce stacktrace if Writer function fails-- * Text.Pandoc.Logging: add `CouldNotParseIncludeFile` constructor- for `LogMessage` [API change].-- * Text.Pandoc.Shared:-- + Put id attributes on TOC entries (#7907, damon-sava-stanley).- Naming scheme of id is "toc-" + id of linked to header/section.- Effects HTML, Markdown, Powerpoint, and RTF.- + Define `ordNub` as alias for `nubOrd` from containers package (#7963,- Albert Krewinkel).- + Export `ensureValidXmlIdentifiers`. This function changes identifiers- that don't start with letters, and internal links to these identifiers,- making them compatible with XML standards. The change- is simple: we add `id_` to the front. There is potential- for duplication if there are already `id_...` identifiers- defined, but this seems rare enough not to worry too much- about.-- * Ensure that valid XML identifiers are used in Docbook, EPUB, FB2,- HTML4, S5, Slidy, Slideous, ICML, ODT, TEI writers.- Thus, if you convert `[anchor]{#1} and [link to](#1)`,- `id_1` will be used instead of `1` for the identifier.-- * Lua (Albert Krewinkel).-- + Add module `pandoc.layout` to format and layout text.- + Move custom writer code into Lua hierarchy.- + Use pandoc-lua-marshal 0.1.5.- + Allow any type of callable object as argument to List- functions `filter`, `map`, and `find_if`. These previously- required the argument to be of type `function`, which was too- restrictive.- + Inline: the type of Image captions is now `Inlines` instead of `List`.- + Allow passing `Sources` to `pandoc.read` (#8002).-- * Text.Pandoc.PDF:-- + Restore `wkhtmltopdf` as default pdf engine for HTML (Albert Krewinkel).- + Allow custom writer as format if engine is explicitly specified (#7898,- Albert Krewinkel). Note that it may be necessary to explicitly- specify a template on the command line.-- * Text.Pandoc.MediaBag: improve detection of absolute paths (#7881).-- * Text.Pandoc.Extensions:-- + Remove `raw_tex` extension from list of commonmark extensions, and- from the `commonmark_x` defaults. commonmark doesn't parse raw TeX,- and it doesn't make sense to write it if we don't parse it.- + Remove `native_divs` from allowed gfm extensions (#7965). This allows- `<div>` to be suppressed using `-raw_html`. Previously `native_divs`- was enabled but could not be suppressed, because it was not in the- list of available extensions for commonmark-based formats.-- * Text.Pandoc.Parsing:-- + Partition module into (internal) submodules (#7962, Albert Krewinkel).- + Unify grid table parsing (#7971, Albert Krewinkel).- Grid table parsing in Markdown and RST are updated use the same- functions. Functions are generalized to meet requirements for both- formats. This change also lays the ground for further generalizations- in table parsers, including support for advanced table features.- [API change] in Text.Pandoc.Parsing:-- - Parse results of functions `tableWith'` and `gridTableWith'` are now a- `mf TableComponents` instead of a quadruple of alignments, column- widths, header rows and body rows.- - Additional exports from Text.Pandoc.Parsing:- `tableWith'`, `TableComponents`, `TableNormalization`,- `toTableComponents`, `toTableComponents'`.-- * Text.Pandoc.XML.Light: add versions of the parsers that allow- specifying a custom entity map. Exports new functions:- `parseXMLElementWithEntities`, `parseXMLContentsWithEntities` [API change].-- * Text.Pandoc.Writers.GridTable: improve module documentation (Albert- Krewinkel).-- * Text.Pandoc.Parsing.GridTable: simplify column handling code (Albert- Krewinkel).-- * Text.Pandoc.MIME: Add mime type for mkv extension (#7181).-- * Text.Pandoc.Asciify: Fix regression with `ascii_identifiers` and Turkish- undotted i (#8003).-- * Relax upper bound for hslua, allow hslua-2.2. (#7929)- Lua 5.4 is used by default after this is merged. Packagers may still- include Lua 5.3 instead by building pandoc with `--constraint='hslua <2.2'`.- Differences between 5.3 and 5.4 should not generally affect pandoc Lua- filters. See list of incompatible changes here:- <https://www.lua.org/manual/5.4/manual.html#8.1>-- * JATS template: allow multiple licenses (Albert Krewinkel).-- * LaTeX template:-- + Skip `\babelprovide` if `babel-lang` is empty (#7945) to avoid an error.- + Move hyperref near end of preamble (#5811). It now comes after- header-includes and right before title, author, date, abstract.- Note: Users who presuppose hyperref in their header-includes- will now have to add `\usepackage{hyperref}` to their header-includes- to make it available there. (The redundant `\usepackage` will- do no harm in this case.)- + Remove special redefinition of `\sout`. This used to be necessary to- avoid problems with hyperref, when headings contain strikeout text,- but it does not seem to be necessary any more (tested).-- * Tests: improve location reporting of failing tests (Albert Krewinkel).-- * Add tests for idempotency of `makeSections` (#7950).-- * Add armhf support in linux build script (#7944, Tony).-- * Use latest pandoc-types, so that toJSONFilter will work with- Meta and MetaValue.-- * Use latest doclayout, texmath, commonmark, citeproc.-- * INSTALL.md: add reference to install via winget (#7951, Guriy Samarin).-- * MANUAL.txt:-- - Document way to get list in block quote in slide shows (#7916).- - Minor changes to security section.- - Note that `smart` works for html input.- - Fix typos (#7934, Dimitris Apostolou).- - Fix documentation for citations and org mode.- - Remove claim that `--self-contained` does not work with `--mathjax`- (#682).-- * doc/org.md: remove obsolete citations section.- This mostly described citation formats we no longer support.-- * doc/lua-filters.md: Fix typo (#7981, Mario Lang).-- * Makefile: Use cabal for default build-- * Add `lua53` cabal flag. It is false by default. If set to true, compile- with hslua 2.1 and Lua 5.3, otherwise hslua 2.2 and Lua 5.4.---## pandoc 2.17.1.1 (2022-01-31)-- * Fix regression in 2.17.1 which caused problems finding- default files in the default user data directory. (Reverts- the item "logic bug in `fullDefaultsPath`", which was- misguided.)-- * Sample custom writer: use single quotes for strings (#7487,- Albert Krewinkel).--## pandoc 2.17.1 (2022-01-30)-- * Support `pagedjs-cli` as pdf engine (#7838, Albert Krewinkel).- PagedJS is a polyfill and supports the Paged Media standards by the W3C.- <https://www.pagedjs.org/>-- * CommonMark reader: fix source position after YAML metadata (#7863).-- * LaTeX reader:-- + Remove retokenizing in `rawLaTeXParser`.- + Ensure that `\raggedright` doesn't gobble an argument (#7757).- + Improve `descItem`. For some reason we were skipping- arbitrary blocks before `\item`. This is now changed to "skip- whitespace and comments."- + Improve handling of `\newif`. Adding a pair of braces around the- second argument of `\def` prevents LaTeX from an emergency stop- on input like the following (#6096).- ```- \newif\ifepub- \epubtrue- \ifepub- hi- \fi- ```-- * Docx reader: Parse both Zotero citation and bibliography as- `FieldInfo` (#7840).-- * LaTeX writer:-- + Allow arbitrary frameoptions to be passed to a beamer- frame, using the frameoptions attribute (#7869).- + Add s and squeeze to recognized beamer frameoptions (#7869).-- * Markdown writer: handle explicit column widths with pipe tables (#7847).- If a table has explicit column width information *and* the content- extends beyond the `--columns` width, we need to adjust the- widths of the pipe separators to encode this width information.-- * Docx writer: Separate tables even with RawBlocks between (#7224,- Michael Hoffmann). Adjacent docx tables need to be separated by an- empty paragraph. If there's a RawBlock between tables which renders- to nothing, be sure to still insert the empty paragraph so that- they will not collapse together.-- * Man writer: use custom font V for inline code (#7506).- The V font is defined conditionally, so that it renders- like CB in output formats that support that, and like B- in those that don't (e.g. the terminal).- Aliases also defined for VI, VB, VBI.-- * Asciidoc writer: Support checklists in asciidoctor writer (#7832,- Nikolai Korobeinikov, ricnorr). The checklist syntax (similar to- `task_list` in markdown) seems to be an asciidoctor-only addition.-- * HTML writer:-- + Avoid duplicate "style" attributes on table cells (#7871).- + Don't break lines inside code elements. With the new (default)- line wrapping of HTML, in conjunction with the default CSS which- includes `code { whitespace: pre-wrap; }`, spurious line- breaks could be introduced into inline code (#7858).-- * Custom writer: preserve order of element attributes (#7489, Albert- Krewinkel). Attribute key-value pairs are marshaled as AttributeList,- i.e., as a userdata type that behaves both like a list and a map. This- allows to preserve the order of key-value pairs.-- * Switch to hslua-2.1 (Albert Krewinkel). This allows for some code- simplification and improves stability.-- * Don't read files outside of user data directory (Even Brenden).- If a file path does not exist relative to the working directory, and- it does exist relative to the user data directory, but outside of- of the user data directory, do not read it. This applies to- `readDataFile` and `readMetadataFile` in PandocMonad and, by- extension, any module that uses these by passing them relative paths.-- * Text.Pandoc.Class.`makeCanonical`: Correctly handle consecutive ".."s- at the beginning of a path (Even Brenden). Prior to this commit,- `../../file` would evaluate to `file`, when it should be unchanged.-- * Search for metadata files in `$DATADIR/metadata` (#7851, Even Brenden).- If files specified with `--metadata-file` are not found in the working- directory, look in `$DATADIR/metadata` (#5876).-- * Text.Pandoc.Class: export `readMetadataFile` [API change] (#5876).-- * Text.Pandoc.Error: export new `PandocCouldNotFindMetadataFileError`- constructor for `PandocError` [API change] (#5876).-- * Avoid putting a frame around speaker notes in beamer (#7857).- If speaker notes (a Div with class 'notes') occur right- after a section heading, but above slide level, the- resulting `\note{..}` caommand should not be wrapped in- a frame, as that will cause a spurious blank slide.-- * CSS in HTML template: adjust #TOC and h1 on mobile (#7835, Mauro Bieg).-- * Text.Pandoc.Readers.LaTeX.Parsing: don't export `totoks`.- Make the first param of `tokenize` a SourcePos instead of- SourceName, and use it instead of `totoks`.-- * Text.Pandoc.Shared: Modify `stringify` so it ignores `[Citation]`- inside `Cite` (#7855). Otherwise we'll sometimes get two copies of- things, one from the `citationPrefix` or `citationSuffix` and another- from the embedded fallback text. When there is no fallback text,- we'll get no content. However, it really isn't an alternative to just- rely on the result of running `query` on the embedded `Citation`s;- this will result in a jumble of text rather than anything structured.-- * Omit `--enable-doc` in the cabal haddock invocation in- `tools/build-and-upload-api-docs.sh`.-- * Text.Pandoc.App.Opt: fix logic bug in `fullDefaultsPath`.- Previously we would (also) search the default user data directory- for a defaults file, even if a different user data directory- was specified using `--data-dir`. This was a mistake; if- `--data-dir` is used, the default user data directory should- not be searched.-- * Text.Pandoc.Shared: `defaultUserDataDir` behavior change (#7842).- If the XDG data directory is not defined (e.g. because- it's not supported in the OS or HOME isn't defined), we- return the empty string instead of raising an exception.-- * Update command tests to distinguish stderr and test exit status.-- * MANUAL: add that speaker notes can be used with beamer (#7856).-- * Update `build-and-upload-api-docs.sh`.-- * Document `--trace` option.- Document `no-check-certificate` in defaults files.- Document 'sandbox' option for defaults files. (#7873).-- * Fix pattern syntax in sample readability custom reader.-- * doc/custom-readers.lua: add example for "readable HTML."-- * Fix message in man page about where code can be found.-- * `manfilter.lua`: remove extra indent in table cells with code blocks.-- * Fix lua-filters documentation for table column widths (#7864).-- * epub.doc: Update links to KindleGen (#7846, Benson Muite, Mauro Bieg).- KindleGen has been deprecated and we need to link to archived versions.-- * Use tables in defaults files documentation, so each- default option is paired with the corresponding command-line- option (Carsten Allefeld).-- * Use skylighting 0.12.2.-- * Add pandoc-lua-marshal to Nix shell (#7849, Even Brenden).---## pandoc 2.17.0.1 (2022-01-14)-- * Require pandoc-lua-marshal 0.1.3.1 (#7831, Albert Krewinkel).- Fixes a problem with `List.includes` and `List.find` that caused a- Lua stackoverflow and subsequent program crash.-- * HTML template: load header-includes before math (#7833, Kolen Cheung).- MathJax expect the config comes before loading the MathJax script.- This change of order allows one to config MathJax via- header-includes, which loads before the MathJax script. Cf. #2750.-- * When reading defaults file, stop at a line `...`. This line signals- the end of a YAML document. This restores the behavior we got with- HsYaml. yaml complains about content past this line. See- https://github.com/jgm/pandoc/issues/4627#issuecomment-1012438765-- * Text.Pandoc.Citeproc: allow `notes-after-punctuation` to work with- numerical styles that use superscripts (e.g.- american-medical-association.csl), as well as with note styles. The- default setting of `notes-after-punctuation` is true for note styles- and false otherwise. This restores a behavior of pandoc-citeproc- that wasn't properly carried over to Citeproc (#7826, cf.- jgm/pandoc-citeproc#384).-- * Use commonmark-pandoc 0.2.1.2 (#7769).-- * Add FAQ on images in ipynb containers (#7749, Kolen Cheung).--## pandoc 2.17 (2022-01-12)-- * Support `markua` as an output format (#1871, Tim Wisotzki and- Saumel Lemmenmeier). Markua is a markdown variant used by Leanpub.-- * Add text wrapping for HTML output (#7764). Previously the HTML writer- was exceptional in not being sensitive to the `--wrap` option. With- this change `--wrap` now works for HTML. The default (as with other- formats) is automatic wrapping. Note that the contents of `script`,- `textarea`, and `pre` tags are always laid out with the `flush`- combinator, so that unwanted spaces won't be introduced if these occur- in an indented context in a template.-- * Don't read sources until in/out format are verified (#7797).-- * Issue error with `--list-extensions` for invalid formats (#7797).-- * Make `--citeproc` recognize `.yml` as well as `.yaml` extensions- as YAML bibliography files (#7707, Jörn Krenzer).-- * Use latest version of KaTeX with `--katex`.-- * Fix parsing of footnotes in `--metadata-file` (#7813). Previously- non-inline footnotes were not being parsed.-- * ODT reader:-- + Parse list-header as a list item (Tuong Nguyen Manh).-- * Commonmark reader:-- + Put sourcepos attribute on header, not enclosing div- with `-f commonmark+sourcepos` (#7769).-- * Markdown reader:-- + Don't allow `^` at beginning of link or image label (#7723).- This is reserved for footnotes. Fixes regression from 0a93acf.- + Fix parsing of "bare locators" after author-in-text citations.- Previously `@item [p. 12; @item2]` was incorrectly parsed as- three citations rather than two. This is now fixed by ensuring- that `prefix` doesn't gobble any semicolons.- + Revert changes to `inlinesInBalancedBrackets` (commit fa83246),- which caused regressions.- + Improve detection of pipe table line widths (#7713). Fixed- calculation of maximum column widths in pipe tables. It is- now based on the length of the markdown line, rather than a- "stringified" version of the parsed line. This should be- more predictable for users. In addition, we take into account- double-wide characters such as emojis.-- * Custom (Lua) readers:-- + First argument is now a list of sources instead of the- concatenated text (Albert Krewinkel). The list- structure can easily be converted to a string by applying- `tostring`, but it is also possible to access the elements- (each with a `text` and `name`). A small example is added- to the custom reader documentation, showcasing its use in a- reader that creates a syntax-highlighted code block for- each source code file passed as input. Existing readers- will still work through a fallback mechanism, issuing a- deprecation notice.-- * Org reader:-- + Parse official org-cite citations (#7329). We also support the older- org-ref style as a fallback. We no longer support the- "markdown style" or "Berkeley style" citations.- + Support alphabetical (fancy) lists (Lucas Viana). When the- `fancy_lists` extension is enabled, alphabetical list markers are- allowed, mimicking the behaviour of Org Mode when- `org-list-allow-alphabetical` is enabled.- + Support counter cookies in lists (Lucas Viana). Such cookies are- used to override the item counter in ordered lists. In org it is- possible to set the counter at any list item, but since Pandoc AST- does not support this, we restrict the usage to setting an offset for- the entire ordered list, by using the cookie in the first list item.- + Allow trailing spaces after key/value pairs in directives (Albert- Krewinkel). Ensures that spaces at the end of attribute directives like- `#+ATTR_HTML: :width 100%` (note the trailing spaces) are accepted.-- * LaTeX reader:-- + Omit visible content for `\label{...}`. Previously we- included the text of the label in square brackets, but this is- undesirable in many cases. See discussion in- <https://github.com/jgm/pandoc/issues/813#issuecomment-978232426>.- + Improve references (#813). Resolve references to theorem environments.- Remove the Span caused by "label" in figure, table, and theorem- environments; this had an id that duplicated the environments' id.- + Fix semantics of `\ref`. We were including the ams- environment type in addition to the number. This is proper- behavior for `\cref` but not for `\ref`. To support `\cref`- we need to store the environment label separately.- + Add babel mappings for Guajati (gu) and Oriya (or) (#7815).- + Fix typo `panjabi` -> `punjabi` in babel mappings (#7814).-- * HTML reader:-- + Parse attributes on links and images (#6970).-- * Docx reader:-- + Handle multiple pic elements inside a drawing (#7786).- + Change `elemToParPart` to return `[ParPart]` instead of `ParPart`.- Also remove `NullParPart `constructor, as it is no longer- needed. This will allow us to handle elements that contain- multiple ParParts, e.g. `w:drawing` elements with multiple `pic:pic`.-- * DocBook reader:-- + Collapse internal spaces in literal and other similar tags (#7821),- as the standard docbook toolchain does.- + Be sensitive to spacing="compact" in lists (#7799). When- `spacing="compact"` is set, Para elements are turned into Plain,- so we get a "tight" list.-- * Markdown writer:-- + Add new exported function `writeMarkua` from Text.Pandoc.Writers.Markdown- [API change] (#1871, Tim Wisotzki and Saumel Lemmenmeier).- + Fix indentation issue in footnotes (#7801).- + Avoid extra space before citation suffix if it already starts- with a space.- + Ensure semicolon between the locator and the next citation when an- author-in-text citation has a locator and following citations.- + Improve escaping for `#` (#7726).-- * Custom (Lua) writers:-- + Allow variables to be set via second return value of `Doc`- (#6731, Albert Krewinkel). New templates variables can be added by- giving variable-value pairs as a second return value of the- global function `Doc`. Example:- ```- function Doc (body, meta, vars)- vars.date = vars.date or os.date '%B %e, %Y'- return body, vars- end- ```- + Provide global `PANDOC_WRITER_OPTIONS` (#6731, Albert Krewinkel).- + Assign default Pandoc object to global `PANDOC_DOCUMENT` (Albert- Krewinkel). The default Pandoc object is now non-strict, i.e., only- the parts of the document that are accessed will be marshaled to Lua.- A special type is no longer necessary. This change also makes it- possible to use the global variable with library functions such as- `pandoc.utils.references`, or to inspect the document contents with- `walk()`.-- * LaTeX writer:-- + Fix typo `panjabi` -> `punjabi` in babel mappings (#7814).-- * MediaWiki writer:-- + Remove redundant display text for wiki links (Jesse Hathaway).-- * Docx writer:-- + Handle bullets correctly in lists by not reusing numIds- (#7689, Michael Hoffmann). This fixes a bug in which a Div in- a list item would receive bullets on its contained paragraphs.-- * Org writer:-- + Fix list items starting with a code block or other non-paragraph- content (#7810).- + Avoid blank lines after tight sublists (#7810).- + Fix extra blank line inserted after empty list item (#7810).- + Don't add blank line before lists (#7810).- + Support starting number cookies (Lucas Viana). This is necessary- for lists that start at a number other than 1.- + Support the new org-cite syntax (#7329).-- * Haddock writer:-- + Avoid blank lines after tight sublists (#7810).-- * Ipynb writer:-- + Ensure deterministic order of keys.- + Handle cell output with raw block of markdown (#7563, Kolen Cheung).- Write RawBlock of markdown in code-cell output. This is designed- to fit the behavior of #7561, which makes the ipynb reader parse- code-cell output with mime "text/markdown" to a RawBlock of markdown.- This commit makes the ipynb writer writes this RawBlock of markdown- back inside a code-cell output with the same mime, preserving this- information in round-trip.- + In choosing between multiple output options, always favor- those marked with the output format over images (Kolen Cheung).- Previously, both `fmt == f` case and Image have a rank of 1.-- * Ipynb reader & writer: properly handle cell "id" (#7728).- This is passed through if it exists (in Nb4); otherwise- the writer will add a random one so that all cells have an "id".-- * Ms writer:-- + Properly encode strings for PDF contents (#7731).-- * JATS writer:-- + Keep quotes in element-citations (Albert Krewinkel).- Fixed a bug that lead to quote characters being lost in- element-citations.-- * RTF writer:-- + Properly handle images in data URIs (#7771).-- * Commonmark writer:-- + Allow ')' delimiters on ordered lists.-- * RST writer:-- + Avoid extra blank line after empty list item (#7810).-- * HTML writer:-- + Make line breaks more consistent. With `--wrap=none`, we now- output line breaks between block-level elements. Previously they- were omitted entirely, so the whole document was on one line, unless- there were literal line breaks in pre sections. This makes- the HTML writer's behavior more consistent with that of- other writers. Also, regardless of wrap settings,- put newline after `<dd>` and after block-level elements in- the footnotes section. And add a line break between an `img` tag- and the associated `figcaption`.- + reveal.js: Make sure images with `r-stretch` are not in p tags.- They must be direct children of the section. There was previously- code to make this work with the older class name `stretch`, but- the name has changed in reveal.js.- + reveal.js: don't add `r-fit-text` class to section. It must go on- the header only.-- * AsciiDoc writer:-- + Improve detection of intraword emphasis (#7803).-- * OpenDocument writer:-- + Fix vertical alignment bug with display math (#7777). Previously some- displayed formulas would be floated above a preceding text line.- This is fixed by setting `vertical-rel` to `text` rather than- `paragraph-content`.-- * JATS template (Albert Krewinkel):-- + Fix position of contrib affiliations in authoring set. Any- `<aff>` element must come before any `<email>` element.- + Fix affiliation tagging in `articleauthoring` output.- Affiliations were `xlink`ed even in the articleauthoring tag set, but- `<aff>` are not allowed as children of `contrib-group` elements in that- tag set. Each affiliation must be listed directly in the contrib- element.- + Add support for article subtitles.-- * EPUB template:-- + Include abstract in default template.- + Ensure that the essential styles needed by pandoc (`styles.html`- partial) are included in the templates. This is important for correct- formatting of CSL bibliographies. Note that much of the styling in- `styles.html` will be ignored for EPUB, because of the conditional on- `document-css`. Setting the `document-css` variable will cause it- not to be ignored.-- * HTML template: Add abstract (#7588, Jannik Buhr, John MacFarlane).- By default, a localized title (the word "Abstract") will be- used, unless the variable `abstract-title` is set.-- * ConTeXt template: Make title appear in PDF title bar. This is- recommended for accessibility reasons. Note: doesn't work with macOS- Preview.app.-- * `reference.pptx`: change to use 16:9 aspect ratio, Powerpoint's default.-- * Text.Pandoc.Writers:-- + Do not export `writeCustom` [API change]. This ensures that all- writers exported in T.P.Writers are parameterized and work with any- `PandocMonad` type. This is consistent with T.P.Readers, as- `readCustom` is not exported from that module either.-- * Text.Pandoc.Writers.Shared:-- + `endsWithPlain` now returns True if the list ends with a list- that ends with a Plain, and so on recursively (#7810).-- * Text.Pandoc.Class.IO:-- + `writeMedia`: unescape percent-encoding in creating file path.- This addresses a problem with spaces in image filenames- when creating PDFs (#7819); it also affects `--extract-media`.-- * New internal module Text.Pandoc.Writers.Blaze, exporting `layoutMarkup`.- This converts a blaze Html structure into a doclayout Doc Text.-- * Text.Pandoc.Extensions:-- + `parseFormatSpec`: cleaner error message for invalid extensions.-- * Text.Pandoc.MediaBag:-- + Fix bug in `extractMedia`, which caused the test for `..`- in paths to fail, with the result that images with `..`- in the path name could be extracted outside of the- directory specified by `extractMedia`. It also led a check for- `media` in resource paths to fail in the docx reader.-- * Text.Pandoc.Citeproc:-- + Avoid adding comma before an author-in-text citation in a note- if it begins with a title (no author) (#7761).- + Text.Pandoc.Citeproc.Locator now exports `toLocatorMap`,- `LocatorInfo`, and `LocatorMap`. The type of `parseLocator`- has changed, so it now takes a `LocatorMap` rather than a `Locale`- as parameter, and returns a `LocatorInfo` instead of a tuple.- + Fix citation locator detection for German. `toLocatorMap` now- stores keys case-folded. We want to do a case-insensitive- comparison when parsing locators, so that e.g. both- `Chap.` and `chap.` work. Previously we case-folded terms- when doing the lookup, but they weren't case-folded in the- map itself, which led to locator-detection breaking for- German (where the terms have uppercase letters).-- * Lua (Albert Krewinkel):-- + Allow single elements as singleton MetaBlocks/MetaInlines. Single- elements should always be treated as singleton lists in the Lua- subsystem.- + Add `pandoc.template` module. The module provides a `compile`- function to use strings as templates.- + Add `pandoc.WriterOptions` constructor.- + Add function `pandoc.write`.- + Provide global `PANDOC_WRITER_OPTIONS` (#5221).- + The function Text.Pandoc.Filter.applyFilters now takes a filter- environment of type `Environment`, instead of a ReaderOptions value- [API change].- + The `Environment` type is exported from Text.Pandoc.Filter- and allows to combine ReaderOptions and WriterOptions in a single- value [API change].- + Global, exported from Text.Pandoc.Lua, has a new type constructor- `PANDOC_WRITER_OPTIONS` [API change].- + Add constructors `pandoc.Blocks` and `pandoc.Inlines`.- The functions convert their argument into a list of Block and Inline- values, respectively. When applied to a string, they split the- string into `Str` elements separated by `Space` or `SoftBreak`- (#7712).- + Support topdown traversals The traversal order of filters can now- be selected by setting the key `traverse` of the filter to either- `'topdown'` or `'typewise'`; the default remains `'typewise'`.- Topdown traversals can be cut short by returning `false` as a- second value from the filter function. No child-element of the- returned element is processed in that case.- + Marshal ReaderOptions field `extensions`, `track_changes` via JSON.- Extensions are now available as a list of strings; the track-changes- settings are given as the kebab-case representation used in JSON.- + Allow binary (byte string) readers to be used with `pandoc.read`.- + Use global state when parsing documents in `pandoc.read`.- The function `pandoc.read` is updated to use the same state that was- used while parsing the main input files. This ensures that log- messages are preserved and that images embedded in the input are- added to the mediabag.- + Cleanup stack in `peekReadOptionsTable`. A ReaderOptions element was- left on top of the stack when the `peekReadOptionsTable` function- was invoked.- + `walk` methods are added to `Pandoc`, `Block`, `Inline`,- `Blocks`, `Inlines` values; the methods are similar to- `pandoc.utils.walk_block` and `pandoc.utils.walk_inline`, but- apply to filter to the element's contents.- + Functions of name `Doc` are no longer accepted as alternatives for- `Pandoc` filter functions. This functionality was undocumented.- + Improve handling of empty caption, body by `from_simple_table`- #7776). Create truly empty table caption and body when these are- empty in the simple table.- + Change representation of `TableHead`, `TableFoot`, and `Row` values- (#7718). The objects now also follow the principle that element- attributes are accessible through the `.attr` field. Rows in `TableHead`- and `TableFoot` are available via the `.rows` field. Row objects have a- `.cells` field, containing the list of table cells.- + [Simplify](Simplify) code of `pandoc.utils.stringify`. Minor behavior change:- plain strings nested in tables are now included in the result string.- + Simplify and deprecate function `pandoc.utils.equals`. The function- is no longer required for element comparisons; it is now an alias- for the `==` operator.- + Add function `pandoc.utils.references` (#7752).- + Add new library function `pandoc.utils.type`. The function behaves- like the default `type` function from Lua's standard library,- but is aware of pandoc userdata types. A typical use-case would be- to determine the type of a metadata value.- + Fix return types of `blocks_to_inlines`, `make_sections`.- Ensures the returned lists have the correct type (`Inlines` and- `Blocks`, respectively).- + Use more natural representation for Reference values- Omit `false` boolean values, push integers as numbers.-- * Lua: use package pandoc-lua-marshal (#7719, Albert Krewinkel).- The marshaling functions for pandoc's AST are extracted into a separate- package. The package comes with a number of changes:-- + Pandoc's List module was rewritten in C, and error messages were- improved.- + Lists of `Block` and `Inline` elements are marshaled using the new- list types `Blocks` and `Inlines`, respectively. These types- currently behave identical to the generic List type, but give better- error messages. This also opens up the possibility of adding- element-specific methods to these lists in the future.- + Elements of type `MetaValue` are no longer pushed as values which- have `.t` and `.tag` properties. This was already true for- `MetaString` and `MetaBool` values, which are still marshaled as Lua- strings and booleans, respectively. Affected values:- - `MetaBlocks` values are marshaled as a `Blocks` list;- - `MetaInlines` values are marshaled as a `Inlines` list;- - `MetaList` values are marshaled as a generic pandoc `List`s.- - `MetaMap` values are marshaled as plain tables and no longer- given any metatable.- + `Cell` values are now marshaled as userdata objects; a constructor- function for table cells is provided as `pandoc.Cell`.- + The test suite for marshaled objects and their constructors has- been extended and improved.- + A bug in `Citation` objects, where setting a citation's suffix- modified it's prefix, has been fixed.- + Inlines, Blocks, and List objects now have an `__eq` metamethod,- testing equality by comparing two lists element-wise.-- * Powerpoint tests: shorten lines by grouping tests (Albert- Krewinkel). This makes the test output more pleasant to read- in narrow terminal windows.-- * make check: check for unreleased dependencies.-- * Add `tools/build-and-upload-api-docs.sh`.-- * Update cabal description.-- * `MANUAL.txt`: Add section on EPUB styling.-- * `MANUAL.txt`: clarify "standard Markdown" as "original Markdown"- (#7802, Martin Fischer).-- * `doc/custom-writers.md`: use filter to include source of example.-- * Add an example to `doc/custom-readers.md`.-- * Fix typo in `custom-readers.md` (#7722, Mauro Bieg).-- * `doc/jats.md`: add link to JATS documentation (Martin Fischer).-- * `doc/lua-filters.md`: many improvements (Albert Krewinkel,- John MacFarlane).-- * Use commonmark-extensions 0.2.3. This allows a bare-word class attribute- on fenced divs.-- * Use ipynb 0.2.-- * Use citeproc 0.6.0.1.-- * Use texmath 0.12.4.-- * Use doctemplates 0.10.0.1.--## pandoc 2.16.2 (2021-11-21)-- * Add interface for custom readers written in Lua (#7669).- Users can now do `-f myreader.lua` and pandoc will treat the- script `myreader.lua` as a custom reader, which parses an input- string to a pandoc AST, using the pandoc module defined for- Lua filters. A sample custom reader can be found in `data/creole.lua`.- Also see documentation in `doc/custom-readers.md`.-- * New module Text.Pandoc.Readers.Custom, exporting `readCustom` [API change].-- * Allow `plain` to be used in raw attribute syntax.-- * Accept empty `--metadata-file` (#7675).- This was a regression from 2.15 behavior.-- * Markdown reader: Improve `inlinesInBalancedBrackets`.- This is just a small improvement in terms of performance, but it's simpler- and more direct code. Also, we avoid parsing interparagraph spaces in- balanced brackets, as the original did.-- * BibTeX reader: Properly handle commented lines in BibTeX/BibLaTeX (#7668).-- * RST reader: handle class attribute for for custom roles (#7699,- willj-dev). Previously the class attribute was ignored, and the name- of the role used as the class.-- * DocBook reader:-- + Add `<titleabbr>` support (Rowan Rodrik van der Molen).- + Support for `<indexterm>` (#7607, Rowan Rodrik van der Molen).-- * LaTeX reader:-- + Add rudimentary support for `\autoref` (#7693).- + Add 'uri' class when parsing `\url`, for consistency- with treatment of autolinks in other formats (#7672).-- * JATS reader: Capture `alt-text` in figures (#7703, Aner Lucero).-- * MediaWiki writer: use HTML spans for anchors when header has id (#7697).- We need to generate a span when the header's ID doesn't match- the one MediaWiki would generate automatically. Note that MediaWiki's- generation scheme is different from pandoc's (it uses uppercase letters,- and `_` instead of `-`, for example). This means that in going from- markdown to mediawiki, we'll now get spans before almost every heading,- unless explicit identifiers are used that correspond to the ones MediaWiki- auto-generates. This is uglier output but it's necessary for internal- links to work properly.-- * Markdown writer: don't create autolinks when this loses information- (#7692). Previously we sometimes lost attributes when rendering links- as autolinks.-- * Text.Pandoc.Readers.Metadata: allow multiple YAML documents when parsing- YAML for `yamlBsToRefs`. Some people use `---` as the end delimiter in- YAML bibliography files, which causes the `yaml` library to emit an- error unless we explicitly allow multiple YAML documents (and just- consider the first).-- * JATS writer:-- + Ensure figures are wrapped with `<p>` in list items- (Albert Krewinkel). This prevents the generation of invalid output.- + Add URL to element citation entries (Albert Krewinkel).- The URL of a reference, if present, is added in tag `<uri>` to- element-citation entries.-- * HTML writer: Don't create invalid `data-` attribute for empty- attribute key (#7546).-- * LaTeX writer:-- + Babel mappings: use `ancientgreek` for `grc`.- + With `-t latex-smart`, don't generate `\ldots` from ellipsis (#7674).- Instead just use unicode ellipsis.-- * JATS template: fix `equal-contrib` attribute (Albert Krewinkel).- The standard requires the value to be either `yes` or `no`, but is was- set to `true` for authors who contributed equally.-- * reveal.js template: Add `disableLayout` variable (Christophe Dervieux).-- * Text.Pandoc.Error: sort errors in `handleError` by exit code- (Albert Krewinkel).-- * Text.Pandoc.Writers.Shared: Improve toLegacyTable (#7683,- Christian Despres).-- * Lua subsystem:-- + Include lpeg module (#7649, Albert Krewinkel). Compiles the `lpeg`- library (Parsing Expression Grammars For Lua) into- the program. Package maintainers may choose to rely on package- dependencies to make lpeg available, in which case they can compile- the with the constraint `lpeg +rely-on-shared-lpeg-library`.- `lpeg` and `re` are always made available in global variables,- without the need for a `require`.-- + Set `lpeg` and `re` as globals; allow shared lib access via `require`.- The `lpeg` and `re` modules are loaded into globals of the respective- name, but they are not necessarily registered as loaded packages. This- ensures that-- - the built-in library versions are preferred when setting the globals,- - a shared library is used if pandoc has been compiled without `lpeg`,- and- - the `require` mechanism can be used to load the shared library if- available, falling back to the internal version if possible and- necessary.-- + Fix argument order in constructor `pandoc.Cite` (Albert Krewinkel).- This restores the old behavior; argument order had been switched- accidentally in pandoc 2.15.-- + Add Pushable instance for `ReaderOptions` (Albert Krewinkel).-- + Allow to pass custom reader options to `pandoc.read` as an- optional third argument (#7656, Albert Krewinkel).- The object can either be a table or a ReaderOptions value- like `PANDOC_READER_OPTIONS`. Creating new ReaderOptions objects is- possible through the new constructor `pandoc.ReaderOptions`.-- + Display Pandoc values using their native Haskell representation- (Albert Krewinkel).-- + Require latest hslua (2.0.1) (#7661, #7657, Albert Krewinkel).- This fixes issues with-- - misleading error messages when a required function parameter is- omitted;- - absent properties still being listed in the output of `pairs`; and- - alias accessing leading to errors instead of returning `nil`, e.g.- with `(pandoc.Str '').identifier`.-- + Add missing space in "package not found" message (#7658, Albert- Krewinkel).-- * Update build files (#7696, Fabián Heredia Montiel).- Drop old windows 32-bit constraints.- Update cabal `tested-with` field to correspond to `ci.yml` matrix-- * Remove unneeded package dependencies from benchmark target.-- * Require ghc >= 8.6, base >= 4.12.- This allows us to get rid of the old custom prelude and- some crufty cpp. But the primary reason for this is that- conduit has bumped its base lower bound to 4.12, making it- impossible for us to support lower base versions.-- * Require Cabal 2.4. Use wildcards to ensure that all pptx tests are- included (#7677).-- * Update `bash_completion.tpl` (S.P.H.).-- * Add `data/creole.lua` as sample custom reader.-- * Add `doc/custom-readers.md` and `doc/custom-writers.md`.-- * `doc/lua-filters.md`: add section on global modules, including lpeg- (Albert Krewinkel).-- * `MANUAL.txt`: update table of exit codes and corresponding errors- (Albert Krewinkel).-- * Use latest texmath.--## pandoc 2.16.1 (2021-11-02)--- * Docx reader: don't let first line indents trigger block quotes (#7655).- This fixes a regression introduced in pandoc 2.15.-- * Docx writer: use `getTimestamp` for modification times in- reference.docx (#7654). This ensures that when `SOURCE_DATE_EPOCH` is- set, the modification times of files taken from the reference.docx will- be set deterministically, allowing for reproducible builds.-- * Lua subsystem (Albert Krewinkel):-- + Load module `pandoc.path` on startup (#7524). Previously the module- always had to be loaded via `require 'pandoc.path'`.- + Fix typo in SoftBreak constructor.- + Re-add `content` property to Strikeout elements.- Fixes a regression introduced in 2.15.- + Be more forgiving when retrieving the Image `caption` property.- Fixes a regression introduced in 2.15.- + Display Attr values using their native Haskell representation.- + Allow omitting the 2nd parameter in pandoc.Code constructor.- Fixes a regression introduced in 2.15 which required users to always- specify an Attr value when constructing a Code element.- + Allow to compare, show Citation values. Comparisons of Citation- values are performed in Haskell; values are equal if they represent- the same Haskell value. Converting a Citation value to a string- now yields its native Haskell string representation.- + Restore List behavior of MetaList (#7650). Fixes a regression- introduced in 2.16 which had MetaList elements lose- the `pandoc.List` properties.- + Restore `content` property on Header elements.- + Ensure Block elements have all expected properties.- + Ensure Inline elements have all expected properties.-- * Allow tasty-bench 0.3.x.--## pandoc 2.16 (2021-10-31)-- * Switch back from HsYAML to yaml for parsing YAML metadata (#6084).- HsYAML is around 20 times slower in parsing large YAML bibliographies.- In addition, HsYAML is not being actively maintained. This sets us back- in our attempts to free ourselves from C dependencies (#4535). But I- don't see a good alternative until a faster pure Haskell parser is available.- Notes:-- + We've removed the FromYAML instances for all types that had them, since- this is a HsYAML-specific typeclass [API change]. (The yaml package just- uses From/ToJSON instead of having a dedicated From/ToYAML class.)- + Unlike HsYAML (in the configuration we were using), yaml parses 'Y', 'N',- 'Yes', 'No', 'On', 'Off' as boolean values. Users may need to quote these- when they are meant to be interpreted as strings. Similarly, 'null' is- parsed as a YAML null value (and will be treated as an empty string by- pandoc rather than the string 'null'). Quoting it will force it to be- interpreted as a string.- + Some tests had to be adjusted accordingly.- + Pandoc now behaves in a more useful way when the YAML metadata contains- escaping errors: instead of just failng silently and falling back to- some other interpretation of the section, it raises a YAML parsing error.-- * Markdown writer: Ensure that special values are quoted in YAML metadata.- These include "Y", "yes", "on", and "off", which are now (with yaml library)- considered boolean values, as well as "null".-- * Change JSON encodings of some types.-- + For LineEnding use lowercase constructors, e.g. `crlf`, `native`.- + For HTMLSlideVariant use lowercase constructors.- + For ReaderOptions use e.g. `default-image-extension`- instead of `readerDefaultImageExtension` for field names.- + For Extension, use e.g. `tex_math_dollars` instead of- `Ext_tex_math_dollars` as constructor.- + For Extensions, use an array of Extensions, instead of- an object wrapping the tag `Extensions` and an integer.- (The integer representation is not supposed to be part of the- public API.)- + For Opt, use field names like `tab-stop` instead of `optTabStop`.-- * Docx writer:-- + Add IDs to native_numbering test (Tristan Stenner).- + Move ": " out of the caption bookmark (Tristan Stenner).- This is needed so that native references to the figure are included as- "As seen in Figure X, it is..." instead of "As seen in [Figure: X, it is..."-- * Lua (Albert Krewinkel, except as noted):-- + Use hslua module abstraction where possible.- + Fix placement of tests for Block elements in pandoc module tests- + Increase strictness when getting attribute keys- + Re-add `t` and `tag` property to Attr values.- Removal of these properties from Attr values was a regression.- + Fix `pandoc.utils.stringify` regression. The `pandoc.utils.stringify`- function returned empty strings when called with a string argument.- + Fix a copy/paste bug in Lua marshalling code (John MacFarlane, #7639).- This caused links to be changed to figures when Lua filters changed- link properties.- + Re-add `content` property to Link elements (#7647).- This was a regression introduced in version 2.15.- + Generate constants in module pandoc programmatically.- + Marshal SimpleTable, ListAttributes, Citation, and Block values as- userdata objects. Properties of Block values are marshalled lazily,- which generally improves performance considerably. Script users may also- notice the following differences:-- - Block element properties can no longer be accessed by numerical- indexing of the `.c` field. The `.c` property now serves as an alias- for `.content`, so some filter that used this undocumented method- for property access may continue to work, while others will need to- be updated and use proper property names.- - The marshalled Block elements now have a `show` method, and a- `__tostring` metamethod. Both return the Haskell string- representation of the element.- - Block values now have the Lua type `userdata` instead of `table`.-- * Add a short guide to pandoc's sources (Albert Krewinkel).-- * Fix epub files in epub reader tests, so that they are valid- according to epubcheck (#7586).-- * Allow time 1.13.-- * Require latest skylighting (0.12.1).-- * Fix build on GHC 9.2 (Joseph C. Sible).-- * Fix trypandoc so it builds with aeson > 2.---## pandoc 2.15 (2021-10-23)-- * Add `--sandbox` option (#5045).-- + Add sandbox feature. When this option is used, readers and writers- only have access to input files (and other files specified directly on- command line). This restriction is enforced in the type system.- + Filters, PDF production, custom writers are unaffected. This- feature only insulates the actual readers and writers, not- the pipeline around them in Text.Pandoc.App.- + Note that when `--sandboxed` is specified, readers won't have- access to the resource path, nor will anything have access to- the user data directory.-- * `--self-contained`: Fix bug that caused everything to be made a data- URI (#7635, #7367). We only need to use data URIs in certain cases, but- due to a bug they were being used always.-- * Pandoc will now fall back to latin1 encoding for inputs that can't be- read as UTF-8. This is what it did previously for content fetched- from the web and not marked as to content type. It makes sense to do- the same for local files. In this case a `NotUTF8Encoded` warning- will be issued, indicating that pandoc is interpreting the input as latin1.-- * Markdown reader:-- + Don't parse links or bracketed spans as citations (#7632).- Previously pandoc would parse `[link to (@a)](url)` as a- citation; similarly `[(@a)]{#ident}`. This is undesirable. One should- be able to use example references in citations, and even if `@a` is- not defined as an example reference, `[@a](url)` should be a link- containing an author-in-text citation rather than a normal citation- followed by literal `(url)`.- + Fix interaction of `--strip-comments` and list parsing (#7521).- Use of `--strip-comments` was causing tight lists to be rendered as- loose (as if the comment were a blank line).- + Fix parsing bug for math in bracketed spans and links (#7623).- This affects math with unbalanced brackets (e.g. `$(0,1]$`)- inside links, images, bracketed spans.- + Fix code blocks using `--preserve-tabs` (#7573). Previously they- did not behave as the equivalent input with spaces would.-- * DocBook reader:-- + Honor linenumbering attribute (Samuel Tardieu).- The attribute DocBook `linenumbering="numbered"` on code blocks- maps to the `numberLines` class internally.-- * LaTeX reader:-- + Implement siunitx v3 commands (#7614).- We support `\unit`, `\qty`, `\qtyrange`, and `\qtylist`- as synonynms of `\si`, `\SI`, `\SIrange`, and `\SIlist`.- + Properly handle `\^` followed by group closing (#7615).- + Recognize that `\vadjust` sometimes takes "pre" (#7531).- + Ignore (and gobble parameters of) CSLReferences environment (#7531).- Otherwise we get the parameters as numbers in the output.- + Restrict `\endinput` to current file (Simun Schuster).-- * RST reader: handle escaped colons in reference definitions (#7568).-- * HTML reader:-- + Handle empty tbody element in table (#7589).-- * Ipynb reader (Kolen Cheung):-- + Get cell output mime from `raw_mimetype` in addition to `format`.- (`format` is what the spec calls for, but `raw_mimetype` is- often used in practice; see jupyter/nbformat#229).- + Add more formats that can be handled as "raw" cells.- + Fix mime type for `rst`.- + Support `text/markdown`, which is now a supported mime type for raw- output (#7561).-- * RTF reader:-- + Support `\binN` for binary image data.- + If doc begins with {\rtf1 ... } only parse its contents.- Some documents seem to have non-RTF (e.g. XML) material after the- `{\rtf1 ... }` group.- + Ignore `\pgdsc` group. Otherwise we get style names treated as test.- + Better handling of `\*` and bookmarks. We now ensure that groups- starting with `\*` never cause text to be added to the document.- In addition, bookmarks now create a span between the start- and end of the bookmark, rather than an empty span.-- * Docx reader:-- + Avoid blockquote when parent style has more indent (Milan Bracke).- When a paragraph has an indentation different from the parent (named)- style, it used to be considered a blockquote. But this only makes sense- when the paragraph has more indentation. So this commit adds a check- for the indentation of the parent style.- + Fix handling of empty fields (Milan Bracke). Some fields only- have an `instrText` and no content, Pandoc didn't understand these,- causing other fields to be misunderstood because it seemed like- a field was still open when it wasn't.- + Implement PAGEREF fields (Milan Bracke). These fields, often used- in tables of contents, can be a hyperlink.- + Fix handling of nested fields (Milan Bracke). Fields delimited by- `fldChar` elements can contain other fields. Before, the nested- fields would be ignored, except for the end, which would be- considered the end of the parent field.- + Add placeholder for word diagram instead of just omitting it (Ezwal).-- * Org reader:-- + Don't parse a list as first item in a list item (#7557).- + Allow an initial `:PROPERTIES:` drawer to add to metadata (#7520).-- * Docx writer:-- + Make id used in `native_numbering` predictable (#7551).- If the image has the id IMAGEID, then we use the id ref_IMAGEID- for the figure number. This allows one to create a filter that- adds a figure number with figure name, e.g.- `<w:fldSimple w:instr=" REF ref_superfig "><w:r><w:t>Figure X</w:t>- </w:r></w:fldSimple>`.- If an image lack an id, an id of the form `ref_fig1` is used.- + Ensure we have unique ids for `wp:docPr` and `pic:cNvPr` elements- (#7527, #7503).- + Handle SVG images (#4058). This change has several parts:- - In Text.Pandoc.App, if the writer is docx, we fill the media- bag and attempt to convert any SVG images to PNG, adding these- to the media bag. The PNG backups have the same filenames as- the SVG images, but with an added .png extension. If the conversion- cannot be done (e.g. because rsvg-convert is not present),- a warning is omitted.- - In Text.Pandoc.Writers.Docx, we now use Word 2016's syntax for- including SVG images. If a PNG fallback is present in the media bag,- we include a link to that too.-- * Powerpoint writer (Emily Bourke):-- + Add support for more layouts (#5097). Up til now, four layouts- were supported: "Title Slide" (used for the automatically generated- metadata slide), "Section Header" (used for headings above slide- level), "Two Column" (used when there's a columns div), "Title and- Content" (used for all other slides). We now support three- additional layouts: "Comparison", "Content with Caption", and- "Blank". The manual describes the logic that determines which- layout is used for a slide. Layouts may be customized in the- reference doc.- + Support specifying slide background images using a `background-image`- attribute on the slide's heading. Only the "stretch" mode is supported,- and the background image is centred around the slide in the image's- larger axis, matching the observed default behaviour of PowerPoint.- + Add support for incremental lists (through same methods as in- other slide writers) (#5689).- + Copy embedded fonts from reference doc.- + Include all themes in output archive.- + Fix list level numbering (#4828, #4663). In PowerPoint,- the content of a top-level list is at the same level as the content- of a top-level paragraph: the only difference is that a list style- has been applied. Previously, the writer incremented the paragrap- h level on each list, turning what should be top-level lists into- second-level lists.- + Line up list continuation paragraphs. This commit- changes the `marL` and `indent` values used for plain paragraphs- and numbered lists, and changes the spacing defined in the- reference doc master for bulleted lists. For paragraphs, there is- now a left-indent taken from the `otherStyle` in the master.- For numbered lists, the number is positioned where the text would be- if this were a plain paragraph, and the text is indented to the next- level. This means that continuation paragraphs line up nicely with- numbered lists. Existing reference docs may need to be modified so- that `otherStyle` and `bodyStyle` indent levels match, for this- feature to work with them.- + Consolidate text runs when possible (jgm). This slims down the output- files by avoiding unnecessary text run elements.- + Support footers in the reference doc.- There is one behaviour which may not be immediately obvious: if the- reference doc specifies a fixed date (i.e. not automatically updating),- and there’s a date specified in the metadata for the document, the- footer date is replaced by the metadata date.- + Fix presentation rel numbering. Before now, the numbering of `rId`s- was inconsistent when making the presentation XML and when making- the presentation relationships XML.- + Don’t add relationships unnecessarily. Before now, for any layouts- added to the output from the default reference doc, the relationships- were unconditionally added to the output. However, if there was already- a layout in slideMaster1 at the same index then that results in- duplicate relationships.- + If slide level is 0, don't insert a slide break between a heading- and a following table, "columns" div, or paragraph starting- with an image.- + Fix capitalisation of `notesMasterId`.- + Restructure tests.-- * Asciidoc writer:-- + Translate numberLines attribute to `linesnum` switch (Samuel Tardieu).- + Improve escaping for `--` in URLs (#7529).-- * LaTeX writer:-- + Make babel use more idiomatic (#7604, hseg). Use babel's- bidi implementation. Import babel languages individually instead- of as package options. Move `header-includes` to after- `babel` setup so it can be modified.- + Use babel, not polyglossia, with xelatex. Previously polyglossia- worked better with xelatex, but that is no longer the case, so- we simplify the code so that babel is used with all latex- engines. This involves a change to the default LaTeX template.-- * Markdown writer:-- + Avoid bad wraps at the Doc Text level. Previously we tried to- do this at the Inline list level, but it makes more sense to- intervene on breaking spaces at the Doc Text level.- + Use `underline` class rather than `ul` for underline.- This only affects output with `bracketed_spans` enabled.- The markdown reader parses spans with either `.ul` or `.underline` as- Underline elements, but we're moving towards preferring the latter.-- * RST writer:-- + Properly handle anchors to ids with spaces or leading underscore- (#7593). In this cases we need the quoted form, e.g.- ```- .. _`foo bar`:-- .. _`_foo`:- ```- Side note: rST will "normalize" these identifiers anyway,- ignoring the underscore.-- * HTML writer:-- + Render `\ref` and `\eqref` as inline math, not display (see #7589).- + Pass through `\ref` and `\eqref` if MathJax is used (#7587).- + Pass through inline math environments with KaTeX.- + Support `--reference-location` for HTML output (#7461,- Francesco Mazzoli).- + Set "hash" to True by default (for reveal.js) (#7574). See #6968- where the motivation for setting "hash" to True is explained.-- * Native writer: Use pretty-show to format native output (#7580).- Previously we used our own homespun formatting. But this produces- over-long lines that aren't ideal for diffs in tests.- Performance is slower by about a factor of 10, but this isn't- really a problem because native isn't suitable as a serialization- format. (For serialization you should use json, because the reader- is so much faster than native.)-- * Org writer:-- + Don't indent contents of code blocks. We previously indented them- by two spaces, following a common convention. Since the convention- is fading, and the indentation is inconvenient for copy/paste, we are- discontinuing this practice.- + Update list of supported source languages in org writer (#5440).-- * Ipynb writer (Kolen Cheung):-- + Improve round trip identity for raw cell output.- See jupyter/nbformat#229. The Jupyter ecosystem, including nbconvert,- lab and notebook, deviated from their own spec in nbformat, where- they used the key `raw_mimetype` instead of `format`. Moreover,- the mime-type of rst used in Jupyter deviated from that suggested by- https://docutils.sourceforge.io/FAQ.html and is defined as- `text/restructuredtext` when chosen from "Raw NBConvert Format" in- Jupyter. The new behavior should matche the real world usage better,- hence improving the round-trip "identity" in raw-cell.- + Add more formats that can be handled as "raw" cells.-- * EPUB writer:-- + Add EPUB3 subject metadata (authority/term) (nuew).- This adds the ability to specify EPUB 3 `authority` and `term` specific- refinements to the `subject` tag. Specifying a plain `subject` tag in- metadata will function as before.- + Treat epub:type "frontispiece" as front matter (#7600).-- * reveal.js template: Fix line numbers in source code (#7634).- We need `overflow: visible` for these to work, and reveal's- default css disables this. So we re-enable it in the default template.-- * Text.Pandoc.Writers.Shared:-- + Export `splitSentences` as a Doc Text transform [API change].- Use this in man/ms. We used to attempt automatic sentence- splitting in man and ms output, since sentence-ending- periods need to be followed by two spaces or a newline in- these formats. But it's difficult to do this reliably at- the level of `[Inline]`.-- * Text.Pandoc.Translations: small revisions for compatibility- with aeson 2.-- * Don't prepend `file://` to `--syntax-definition` on Windows (#6374).- This was a fix for a problem in skylighting, but this- problem doesn't exist now that we've moved from HXT to xml-conduit.-- * Text.Pandoc.Extensions:-- + Add `Ext_footnotes` to default `gfm` etxensions. Now `gfm`- supports footnotes.- + Alphabetize Extension constructors (also affects `--list-extensions`).-- * Text.Pandoc.Citeproc.Util: Better implementation of `splitStrWhen`.- Previously the citeproc code had two less efficient- implementations.-- * Update documentation for definition_list extension (#7594).- In 2015, we relaxed indentation requirements for the first- line of a definition (see commit d3544dc and issue #2087), but- the documnentation wasn't updated to reflect the change.-- * Text.Pandoc.Citeproc.BibTeX: Fix expansion of special strings in series- e.g. `newseries` or `library` (#7591). Expansion should not happen- when these strings are protected in braces, or when they're- capitalized.-- * Text.Pandoc.Logging: add `NotUTF8Encoded` constructor to `LogMessage`- [API change].-- * Text.Pandoc.App.FormatHeuristics: remove `.tei.xml` extension for TEI- (#7630). This never worked, because `takeExtension`- only returns `.xml`. So it won't be missed if we remove it.-- * Text.Pandoc.Image:-- + Generalize `svgToPng` to MonadIO.- + `svgToPng`, change first parameter from WriterOptions to Int.-- * Text.Pandoc.Class:-- + Add `readStdinStrict` method to PandocMonad [API change].- + Generalize type of `extractMedia` [API change].- It was uselessly restricted to PandocIO, instead of any- instance of PandocMonad and MonadIO.-- * Text.Pandoc.Class.PandocIO: derive MonadCatch, MonadThrow, MonadMask.- This allows us to use `withTempDir` [API change].-- * Add module Text.Pandoc.Class.Sandbox, defining- `sandbox`. Exported via Text.Pandoc.Class. [API change]-- * Text.Pandoc.Filter: Generalize type of `applyFilters`- from PandocIO to any instance of MonadIO and PandocMonad [API change].-- * Text.Pandoc.PDF: generalize type of `makePDF`:- instead of PandocIO, it can be used in any instance of- PandocMonad, MonadIO, and MonadMask [API change].-- * Lua subsystem and custom writers: generalize types from PandocIO- to any instance of PandocMonad and MonadIO [API change].- The type of `runLua` is now-- (PandocMonad m, MonadIO m) =>- LuaE PandocError a -> m (Either PandocError a)-- The change from `Lua` to `LuaE PandocError` is due to the switch to- hslua-2.0; see next item.-- * Lua modules (Albert Krewinkel):-- + Switch to hslua-2.0. The new HsLua version takes a somewhat different- approach to marshalling and unmarshalling, relying less on typeclasses- and more on specialized types. This allows for better performance and- improved error messages. Furthermore, new abstractions allow to- document the code and exposed functions.- + Marshal Version values, Inline elements, Attr elements,- and Pandoc elements as userdata.- + Remove deprecated inline constructors `DoubleQuoted`,- `SingleQuoted`, `DisplayMath`, and `InlineMath`.- + Attr values are no longer normalized when assigned to an Inline- element property.- + It's no longer possible to access parts of Inline elements via- numerical indexes. E.g., `pandoc.Span('test')[2]` used to give- `pandoc.Str 'test'`, but yields `nil` now. This was undocumented- behavior not intended to be used in user scripts. Use named properties- instead.- + Accessing `.c` to get a JSON-like tuple of all components no longer- works. This was undocumented behavior.- + Only known properties can be set on an element value. Trying to set a- different property will now raise an error.- + Adds a new `pandoc.AttributeList()` constructor, which creates the- associative attribute list that is used as the third component of- `Attr` values. Values of this type can often be passed to constructors- instead of `Attr` values.- + Convert IOErrors to PandocErrors in `pandoc.pipe` function (#7523).-- * Text.Pandoc.PDF: Previously we had to run `runIOorExplode` inside- `withTempDir`. Now that PandocIO is an instance of MonadMask, this is- no longer necessary.-- * Text.Pandoc.App:-- + Reorganize to make it easier to limit IO in main loop.- Previously we used liftIO fairly liberally. The code has- been restructured to avoid this.- + Move output-file writing out of PandocMonad action.-- * Text.Pandoc.App.OutputSettings: Generalize some types- so we can run this with any instance of PandocMonad and MonadIO,- not just PandocIO.-- * Use `simpleFigure` builder in readers and `SimpleFigure`- pattern synonym in writers (Aner Lucero).-- * Allow time 1.12.-- * Use skylighting-0.12, skylighting-core-0.12.- This fixes highlighting issues with typescript, scala, and other- syntaxes that include keyword lists from different syntaxes.-- * Use citeproc 0.6, commonmark 0.2.2.1, commonmark-extensions 0.2.2,- texmath 0.12.3.2, ipynb 0.1.0.2. (These changes also allow- building with aeson >= 2.)-- * Require doclayout >= 0.3.1.1. This fixes recognition of "real widths"- of emoji characters, which is important for tabular layout.-- * Cut out over 100K of fat in epub test golden files.-- * Make `test/epub/wasteland.epub` valid.-- * Add missing `%` on some command tests.- This prevented `--accept` from working properly.-- * Command tests: raise error if command doesn't begin with `%`.-- * OOXML tests: use pretty-printed form to display diffs.- Otherwise everything is on one line and the diff is uninformative.-- * Fix compareXML helper in Tests.Writers.OOXML.- Given how it is used, we were getting "mine" and "good"- flipped in the test results.-- * MANUAL.txt:-- + Clarify `attributes` extension support (William Lupton).- + Document formats affected by `--reference-location`.- + Document error code 25- + Add some more info regarding `--slide-level=0` (Salim B).- + Add more to security section of manual.- + Mention support of `title-toc` (#7171, Christophe Dervieux).-- * doc/lua-filters.md:-- + Add missing type for Image title (Quinn).- + Improve order of Image fields (Quinn).- + Rephrase pandoc.path docs (#7548, Quinn).- + Do not leak working directory in TikZ filter (Jeroen de Haas).--## pandoc 2.14.2 (2021-08-21)-- * Allow `--slide-level=0` (#7476). When the slide level is set- to 0, headings won't be used at all in splitting the document- into slides. Horizontal rules must be used to separate slides.-- * Add RTF reader (#3982). `rtf` is now supported as an input- format as well as an output format. New module- Text.Pandoc.Readers.RTF (exporting `readRTF`). [API change]-- * HTML reader: treat comments as blank when parsing (#7482).-- * Markdown reader:-- + Fix raw LaTeX injection issue (#7497). Using a code block- containing `\end{verbatim}`, one could inject raw TeX into a- LaTeX document even when `raw_tex` is disabled. Thanks to- Augustin Laville for noticing the bug.- + Multimarkdown sub- and superscripts (#5512, OCzarnecki).- Added an extension `short_subsuperscripts` which modifies- the behavior of `subscript` and `superscript`, allowing- subscripts or superscripts containing only alphanumerics- to end with a space character (eg. `x^2 = 4` or `H~2 is- combustible`). This improves support for multimarkdown.-- * RST reader: Fix `:literal:` includes (#7513). These should create- code blocks, not insert raw RST.-- * LaTeX reader:-- + Proper implicit grouping around environment macros.- + Support `\global` before `\def`, `\let`, etc. (#7494).- + Fix scope for LaTeX macros (#7494). They should by default- scope over the group in which they are defined (except `\gdef`- and `\xdef`, which are global). In addition, environments must- be treated as groups.- + Improve handling of plain TeX macro primitives (#7474).- Fixed semantics for `\let`.- + Implement `\edef`, `\gdef`, and `\xdef`.-- * Docx reader: Improve docx reader's robustness in extracting- images (#7511). The docx reader made some assumptions about- how docx containers were laid out that were not always true, with- the result that some images in documents did not get- extracted.-- * LaTeX writer: Increase table column width precision (#7466,- Peter Fabinski). In some cases, the rounding performed by the- LaTeX table writer would introduce visible overrun outside- the text area. This adds two more decimal places to the width- values.-- * Powerpoint writer:-- + Include image title in description (#7352, Emily Bourke). The- image title (i.e. ``) was previously- ignored when writing to pptx. This commit includes it in- PowerPoint's description of the image, along with the link.- + Select layouts from reference doc by name (Emily Bourke). Until- now, users had to make sure that their reference doc contains- layouts in a specific order: the first four layouts in the file- had to have a specific structure. Now the layout selection uses- the layout names rather than order: users must make sure their- reference doc contains four layouts with specific names, and if- a layout with the right name isn’t found pandoc will emit- a warning and use the corresponding layout from the default- reference doc as a fallback.-- * Docx writer: be sensitive to the `native_numbering` extension- (#7499). Figure and table numbers are now only included if- `native_numbering` is enabled. (By default it is disabled.)- This is a behavior change with respect to 2.14.1, but the- default behavior is now that of previous versions. The- change was necessary to avoid incompatibilities between- pandoc's native numbering and third-party cross reference- filters like pandoc-crossref.-- * RTF writer:-- + Omit `\bin` in `\pict`. According to the spec, this is not- needed or wanted when the data is in hexadecimal format, as- here.- + Emit `\outlinelevel`` for section headings.-- * RTF template: specify font family for fixed-width font f1.- According to the spec, this is mandatory.-- * LaTeX writer: Use ulem for underline (#7351). ulem is- conditionally included already when the `strikeout` variable- is set, so we set this when there is underlined text, and use- `\uline` instead of `\underline`. This fixes wrapping for- underlined text.-- * Text.Pandoc.Citeproc:-- + Revise citeproc code to fit new citeproc 0.5 API (thanks to- Benjamin Bray). Linkification of URLs in the bibliography- is now done in the citeproc library, depending on the- setting of an option. We set that option depending on the- value of the metadata field `link-bibliography` (defaulting- to true, for consistency with earlier behavior). If a DOI,- PMID, PMCID, or URL field is present but not explicitly- rendered, the title (or if no title, the whole entry) is- hyperlinked. These changes implement the recommendations- from the draft CSL v1.0.2 spec (Appendix VI):- <https://github.com/citation-style-language/documentation/blob/master/specification.rst#appendix-vi-links>- + Avoid odd handling of quotes. Recent citeproc changes- allow us to ignore Quoted elements; citeproc now uses its own- method for represented quoted things, and only localizes and- flipflops quotes it adds itself. Convert Quoted in bib- entries to special Spans before passing them off to- citeproc. This ensures that we get proper localization and- flipflopping if, e.g., quotes are used in titles- (jgm/citeproc#87).- + Removed quote localization from citeproc processing.- This is now done in citeproc itself.-- * Text.Pandoc.Logging: Add PowerpointTemplateWarning log message- type [API change] (Emily Bourke).-- * Text.Pandoc.Extension: Add `Ext_short_subsuperscripts`- constructor to `Extension` [API change] (OCzarnecki).-- * Various sample.lua editorial fixes (#7493, #7487, William- Lupton).-- * Bump base-compat version so we get compatibility with base 4.12.-- * Use Prelude from base-compat for ghc 8.4 too.-- * Add haskell-language-server to shell.nix (#7496, Emily Bourke).-- * Tests.Helpers: export testGolden and use it in RTF reader.- This gives a diff output on failure.-- * Remove obsolete and incorrect sentence in `--slide-level` docs.-- * Add internal module Text.Pandoc.Network.HTTP, exporting- `urlEncode`.-- * Text.Pandoc.Parsing: `parseFromString`: preserve at least- the source directory (#7464). Previously we just set the- source name to "chunk" when parsing from strings, to avoid- misleading source positions. This had the side effect that- `rebase_relative_paths` would break inside sections that- were parsed as strings. So, now we use- "ORIGINAL_SOURCE_PATH_chunk" instead of just "chunk".-- * Text.Pandoc.MIME: use image/x-xcf instead of application/x-xcf- (#7454).-- * Don’t compare `cdLine` in OOXML golden tests (Emily Bourke).- The `cdLine` field gives the line of the file some CData was- found on, which reflects irrelevant formatting differences.-- * Provide more detailed XML diff in tests (Emily Bourke).-- * OOXML tests: silence warnings. These can make the test output- confusing, making people think tests are failing when they're- passing.-- * INSTALL.md: Add GitLab CI/CD example (#7448, Veratyr).-- * MANUAL.txt-- - Clarifications (William Lupton).- - Add a note on security risks of include directives.-- * Document use of the 'underline' class (#7492, #7484, William- Lupton).-- * Add a FAQ about the "Cannot allocate memory" error on M1 macs.-- * Use texmath 0.12.3.1.-- * Use released citeproc 0.5.-- * Remove dependency on HTTP package (#7456, mt_caret).--## pandoc 2.14.1 (2021-07-18)-- * Text.Pandoc.ImageSize: Add Tiff constructor for ImageType (#7405)- [Minor API change]. This allows pandoc to get size information from- tiff images.-- * Markdown reader: don't try to read contents in self-closing HTML tag.- Previously we had problems parsing raw HTML with self-closing- tags like `<col/>`. The problem was that pandoc would look- for a closing tag to close the markdown contents, but the- closing tag had, in effect, already been parsed by `htmlTag`.-- * LaTeX reader:-- + Avoid trailing hyphen in translating languages (#7447).- Previously `\foreignlanguage{english}` turned into `<span lang="en-">`.- The same issue affected Arabic.- + Support `\cline` in LaTeX tables (#7442).- + Improved parsing of raw LaTeX from Text streams (`rawLaTeXParser`,- used to read LaTeX in Markdown files, #7434). We now use source- positions from the token stream to tell us how much of the text stream- to consume. Getting this to work required a few other changes to- make token source positions accurate.-- * DocBook reader:-- + Handle images with imageobjectco elements (#7440).- + Add support for citerefentry (#7437, Jan Tojnar).-- * RST reader: fix regression with code includes (#7436).- With the recent changes to include infrastructure,- included code blocks were getting an extra newline.-- * HTML reader:-- + Recognize data-external when reading HTML img tags (#7429,- Michael Hoffmann). Preserve all attributes in img tags. If attributes- have a `data-` prefix, it will be stripped. In particular, this- preserves a `data-external` attribute as an `external` attribute in- the pandoc AST.- + Add col, colgroup to 'closes' definitions-- * HTML writer:-- + Remove duplicated alt text in HTML output (Aner Lucero).- + Remove `aria-hidden` when explicit alt text is provided (Aner Lucero).- + Set boolean values for reveal.js variables.-- * Docx writer:-- + Add table numbering for captioned tables.- The numbers are added using fields, so that Word can- create a list of tables that will update automatically.- + Support figure numbers. These are set up in such a way that they- will work with Word's automatic table of figures (#7392).-- * Markdown writer: put space between Plain and following fenced Div- (#4465).-- * EPUB writer: Don't incorporate externally linked images in EPUB documents- (#7430, Michael Hoffmann). Just as it is possible to avoid incorporating- an image in EPUB by passing `data-external="1"` to a raw HTML snippet,- this makes the same possible for native Images, by looking for an- associated `external` attribute.-- * Text.Pandoc.PDF:-- + Fix `svgIn` path error (#7431). We were duplicating- the temp directory; this didn't cause problems on macOS or linux- because there we use absolute paths for the temp directory.- But on Windows it caused errors converting SVG files.- + `convertImage`: normalize paths (#7431). This will avoid paths- on Windows with mixed path separators.-- * Text.Pandoc.Class: Always use / when adding directory to image destination- with `extractMedia`, even on Windows.-- * Text.Pandoc.Citeproc:-- + Allow `$` characters in bibtex keys (#7409).- + Set proper initial source name in parsing BibTeX (for better error- messages.)- + Revamp note citation handling (#7394). Use latest- citeproc, which uses a Span with a class rather than a Note for notes.- This helps us distinguish between user notes and citation notes. Don't- put citations at the beginning of a note in parentheses. Fix small bug- in handling of citations in notes, which led to commas at the end of- sentences in some cases.- + Cleanup and efficiency improvement in `deNote`.- + Improve punctuation moving with `--citeproc`. Previously, using- `--citeproc` could cause punctuation to move in quotes even when- there aer no citations. This has been changed; punctuation moving- is now limited to citations. In addition, we only move footnotes- around punctuation if the style is a note style, even if- `notes-after-punctuation` is `true`.-- * Use citeproc 0.10. This helps improve note citations (see above)- and eliminates double hyperlinks in author-in-text citations.- Author-only citations are no longer hyperlinked. See jgm/citeproc#77.- It also fixes moving of punctuation inside quotes to conform to- the CSL spec: only comma and period are moved, not question- mark or exclamation point.-- * Text.Pandoc.Error: fix line calculations in reporting parsec errors.- Also remove a spurious initial newline in the error report.-- * Use doctemplates 0.4.1, which gives us better support for boolean- variable values. Previously `$if(foo)$` would evaluate to true- for variables with boolean `false` values, because it cared only- about the string rendering (#7402).-- * Require commonmark-pandoc >= 0.2.2.1.- This fixes task lists with multiple paragraphs.-- * Use skylighting 0.11.-- * CSS in HTML template: reset overflow-wrap on code blocks- (Mauro Bieg, #7423).-- * LaTeX template: Revert change in PR #7295: "move title, author, date up- to top of preamble." The change caused problem for people who used- LaTeX commands defined defined later in the preamble in the title- or author fields (#7422).-- * Add `doc/faqs.md`. This is imported from the website; in the future the- website version will be drawn from here.- Added a FAQ on the use of `\AtEndPreamble` for cases when the contents of- `header-includes` need to refer to definitions that come later in the- preamble. See #7422.-- * Upgrade Debian 10 AMI for build-arm.sh.-- * CircleCI: change to using xcode 11.1.0 (macOS 10.14.4).- We previously built on 10.13, but 10.13 no longer gets- security updates and CirclCI is deprecating.--## pandoc 2.14.0.3 (2021-06-22)-- * Text.Pandoc.MediaBag `insertMediaBag`: ensure we get a sane mediaPath- for URLs (#7391). In earlier 2.14.x versions, we'd get- incorrect paths for resources downloaded from URLs when the- media are extracted (including in PDF production).- * Text.Pandoc.Parsing: improve `emailAddress` (#7398).- Previously the parser would accept characters in domains- that are illegal in domains, and this sometimes caused it- to gobble bits of the following text.- * txt2tags reader: modify the email address parser so- it still includes form parameters, even after the change to- `emailAddress` in Text.Pandoc.Parsing.- * Text.Pandoc.Readers.Metadata: Fix regression with comment-only YAML- metadata blocks (#7400).- * reveal.js writer and template: better handling of options. Previously- it was impossible to specify false values for options that default to- true (e.g. `center`); setting the option to false just caused the portion- of the template setting the option to be omitted. Now we prepopulate- all the variables with their default values, including them all- unconditionally and allowing them to be overridden.- * Markdown writer: Fix regression in code blocks with attributes (#7397).- Code blocks with a single class but nonempty attributes- were having attributes drop as a result of #7242.- * LaTeX writer:- + Add strut at end of minipage if it contains line breaks.- Without them, the last line is not as tall as it should be in- some cases.- + Always use a minipage for cells with line breaks, when- width information is available (#7393). Otherwise the way we treat them- can lead to content that overflows a cell.- + Use `\strut` instead of `~` before `\\` in empty line.- * Use lts-18.0 stack resolver.- * Require skylighting 0.10.5.2 (adding support for Swift).- * Require commonmark 0.2.1.- * Rephrase section on unsafe HTML in manual.- * Create SECURITY.md--## pandoc 2.14.0.2 (2021-06-13)-- * Fix MediaBag regressions (#7345). iIn the 2.14 release `--extract-media`- stopped working as before; there could be mismatches between the- paths in the rendered document and the extracted media.- This patch makes several changes that restore the earlier behavior- (while keeping the same API). The `mediaPath` in 2.14 was always- constructed from the SHA1 hash of the media contents. Now, we- preserve the original path unless it's an absolute path or contains- `..` segments (in that case we use a path based on the SHA1 hash of- the contents).-- In Text.Pandoc.MediaBag, `mediaDirectory` and `mediaItems` now use the- `mediaPath`, rather than the mediabag key, for the first component of the- tuple. This makes more sense, I think, and fits with the documentation of- these functions; eventually, though, we should rework the API so that- `mediaItems` returns both the keys and the MediaItems.-- In Text.Pandoc.Class.IO, rewriting of source paths in `extractMedia` has- been fixed.-- In Text.Pandoc.Class.PandocMonad, `fillMediaBag` has been modified so that- it doesn't modify image paths (that was part of the problem in #7345).-- We now do path normalization (e.g. `\` separators on Windows) in- writing the media.-- * Text.Pandoc.PDF:-- + Text.Pandoc.PDF: Fix regression in 2.14 for generation of PDFs with- SVGs (#7344).- + Only print relevant part of environment on `--verbose`. Since- `--verbose` output might be put in an issue, we want to avoid- spilling out secrets in environment variables.-- * Markdown reader: fix pipe table regression in 2.11.4 (#7343).- Previously pipe tables with empty headers (that is, a header- line with all empty cells) would be rendered as headerless- tables. This broke in 2.11.4. The fix here is to produce an- AST with an empty table head when a pipe table has all empty- header cells.-- * LaTeX reader: don't allow optional `*` on symbol control sequences- (#7340). Generally we allow optional starred variants of LaTeX commands- (since many allow them, and if we don't accept these explicitly,- ignoring the star usually gives acceptable results). But we- don't want to do this for `\(*\)` and similar cases.-- * Docx reader: handle absolute URIs in Relationship Target (#7374).-- * Docx writer: fix handling of empty table headers (Albert Krewinkel,- #7369). A table header which does not contain any cells is now treated as- an empty header.-- * LaTeX writer: Fix regression in table header position (#7347).- In recent versions the table headers were no longer bottom-aligned- (if more than one line). This patch fixes that by using minipages- for table headers in non-simple tables.-- * CommonMark writer:-- + Do not use simple class for fenced-divs (Jan Tojnar, amends #7242.)- + Do not throw away attributes when `Ext_attributes` is enabled.- `Ext_attributes` covers at least the following:- `Ext_fenced_code_attributes`, `Ext_header_attributes`,- `Ext_inline_code_attributes`, `Ext_link_attributes`.-- * Markdown writer:-- + Allow `pipe_tables` to be disabled for commonmark formats- (`commonmark_x`, `gfm`) (#7375).- + Re-use functions from Text.Pandoc.Markdown.Inline (Jan Tojnar).-- * DocBook writer: Remove non-existent admonitions (Jan Tojnar).- `attention`, `error` and `hint` are reStructuredText specific.-- * HTML writer: Don't omit width attribute on div (#7342).-- * Text.Pandoc.MIME, `extensionFromMimeType`: add a few special cases.- When we do a reverse lookup in the MIME table, we just get the- last match, so when the same mime type is associated with several- different extensions, we sometimes got weird results, e.g. `.vs`- for `text/plain`. These special cases help us get the most standard- extensions for mime types like `text/plain`.-- * Lua utils: fix handling of table headers in `from_simple_table` (Albert- Krewinkel, #7369). Passing an empty list of header cells now results- in an empty table header.-- * Text.Pandoc.Citeproc:-- + Avoid duplicate classes and attributes on references div.- + Fix regression in citeproc processing (#7376). If inline- references are used (in the metadata `references` field), we- should still only include in the bibliography items that are- actually cited (unless `nocite` is used).-- * Require citeproc 0.4.0.1. This fixes a bug which led to doubled- "et al." in some (rare) circumstances.-- * MANUAL.txt:-- + Mention GladTeX for EPUB export (Sebastian Humenda).- This updates the manual and the web site about the GladTeX usage.- + More details and a useful link for YAML syntax.-- * CONTRIBUTING.md: update modules overview (Albert Krewinkel).-- * using-the-pandoc-api.md: switch from String to Text (Albert Krewinkel).---## pandoc 2.14.0.1 (2021-06-01)-- * Commonmark reader: Fix regression in 2.14 with YAML metdata block parsing,- which could cause the document body to be omitted after metadata (#7339).-- * HTML reader: fix column width regression in 2.14 (#7334).- Column widths specified with a style attribute were off by a factor of 100.-- * Markdown reader: in `rebasePaths`, check for both Windows and Posix- absolute paths. Previously Windows pandoc was treating- `/foo/bar.jpg` as non-absolute.-- * Text.Pandoc.Logging: In rendering `LoadedResource`, use relative paths.-- * Docx writer: fix regression on captions (#7328). The "Table Caption"- style was no longer getting applied. (It was overwritten by "Compact.")-- * Use commonmark-extensions 0.2.1.2--## pandoc 2.14 (2021-05-28)-- * Change reader types, allowing better tracking of source positions- [API change]. Previously, when multiple file arguments were provided,- pandoc simply concatenated them and passed the contents to the readers,- which took a Text argument. As a result, the readers had no way of knowing- which file was the source of any particular bit of text. This meant that- we couldn't report accurate source positions on errors or include accurate- source positions as attributes in the AST. More seriously, it meant that- we couldn't resolve resource paths relative to the files containing them- (see e.g. #5501, #6632, #6384, #3752).-- * Add `rebase_relative_paths` extension (#3752). When enabled, this- extension rewrites relative image and link paths by prepending- the (relative) directory of the containing file. This- behavior is useful when your input sources are split- into multiple files, across several directories, with files- referring to images stored in the same directory. The- extension can be enabled for all markdown and commonmark-based formats.-- * Add Text.Pandoc.Sources (exported module), with a `Sources` type and a- `ToSources` class. A `Sources` wraps a list of `(SourcePos, Text)` pairs- [API change]. A parsec `Stream` instance is provided for `Sources`. The- module also exports versions of parsec's `satisfy` and other Char parsers- that track source positions accurately from a `Sources` stream (or any- instance of the new `UpdateSourcePos` class).-- * Text.Pandoc.Parsing-- + Export the modified Char parsers defined in Text.Pandoc.Sources- instead of the ones parsec provides. Modified parsers to use a- `Sources` as stream [API change].- + Improve include file functions [API change]. Remove old- `insertIncludedFileF`. Give `insertIncludedFile` a more general type,- allowing it to be used where `insertIncludedFileF` was.- + Add parameter to the `citeKey` parser from- Text.Pandoc.Parsing, which controls whether the `@{..}`- syntax is allowed [API change].-- * Text.Pandoc.Error: Modified the constructor `PandocParsecError` to take a- `Sources` rather than a `Text` as first argument, so parse error locations- can be accurately reported.-- * Fix source position reporting for YAML bibliographies (#7273).-- * Issue error message when reader or writer format is malformed- (#7231). Previously we exited with an error status but (due to a bug)- no message.-- * Smarter smart quotes (#7216, #2103). Treat a leading `"` with no- closing `"` as a left curly quote. This supports the practice, in- fiction, of continuing paragraphs quoting the same speaker without an- end quote. It also helps with quotes that break over lines in line blocks.-- * Markdown reader:-- + Use MetaInlines not MetaBlocks for multimarkdown metadata fields.- This gives better results in converting to e.g. pandoc markdown.- + Implement curly-brace syntax for Markdown citation keys (#6026).- The change provides a way to use citation keys that contain- special characters not usable with the standard citation key syntax.- Example: `@{foo_bar{x}'}` for the key `foo_bar{x}`. It also allows- separating citation keys from immediately following text, e.g. `@{foo}A`.-- * RST reader:-- + Seek include files in the directory of the file- containing the include directive, as RST requires (#6632).- + Use `insertIncludedFile` from Text.Pandoc.Parsing- instead of reproducing much of its code.-- * Org reader: Resolve org includes relative to the directory containing the- file containing the INCLUDE directive (#5501).-- * ODT reader: Treat tabs as spaces (#7185, niszet).-- * Docx reader:-- + Add handling of vml image objects (#7257, mbrackeantidot).- + Support new table features (Emily Bourke, #6316): column- spans, row spans, multiple header rows, table description- (parsed as a simple caption), captions, column widths.-- * LaTeX reader:-- + Improved siunitx support (#6658, #6620).- + Better support for `\xspace` (#7299).- + Improve parsing of `\def` macros. We previously set "verbatim mode"- even for parsing the initial `\def`; this caused problems- for `\def` nested inside another `\def`.- + Implement `\newif`.-- * ConTeXt writer: improve ordered lists (#5016, Denis Maier).- Change ordered list from itemize to enumerate. Add new- itemgroup for ordered lists. Remove manual insertion of- width attributes. Use tabular figures in ordered list- enumerators.-- * HTML reader:-- + Don't fail on unmatched closing "script" tag (Albert Krenkel, #7282).- + Keep h1 tags as normal headers (#2293, Albert Krewinkel).- The tags `<title>` and `<h1 class="title">` often contain the same- information, so the latter was dropped from the document. However, as- this can lead to loss of information, the heading is now always- retained. Use `--shift-heading-level-by=-1` to turn the `<h1>`- into the document title, or a filter to restore the previous behavior.- + Handle relative lengths (e.g. `2*`) in HTML column widths (#4063).- See <https://www.w3.org/TR/html4/types.html#h-6.6>.-- * DocBook/JATS readers:-- + Fix mathml regression caused by the switch in XML libraries (#7173).- + Fix "phrase" in DocBook: take classes from "role" not "class" (#7195).-- * DocBook reader: ensure that first and last names are separated (#6541).-- * Jira reader (Albert Krewinkel, #7218):-- + Support "smart" links: `[alias|https://example.com|smart-card]` syntax.- + Allow spaces and most unicode characters in attachment links.- + No longer require a newline character after `{noformat}`.- + Only allow URI path segment characters in bare links.- + The `file:` schema is no longer allowed in bare links; these- rarely make sense.-- * Plain writer: handle superscript unicode minus (#7276).-- * LaTeX writer:-- + Better handling of line breaks in simple tables (#7272).- Now we also handle the case where they're embedded in other elements,- e.g. spans.- + For beamer output, support `exampleblock` and `alertblock` (#7278).- A block will be rendered as an `exampleblock` if the heading- has class `example` and an `alertblock` if it has class `alert`.- + Separate successive quote chars with thin space (#6958,- Albert Krewinkel). Successive quote characters are separated with- a thin space to improve readability and to prevent unwanted ligatures.- Detection of these quotes sometimes had failed if the second quote- was nested in a span element.- + Separate successive quote chars with thin space (#6958, Albert- Krewinkel).-- * EPUB Writer: Fix belongs-to-collection XML id choice (#7267, nuew).- The epub writer previously used the same XML id for both the book- identifier and the epub collection. This causes an error on epubcheck.-- * BibTeX/BibLaTeX writer: Handle `annote` field (#7266).-- * ZimWiki writer: allow links and emphasis in headers (#6605,- Albert Krewinkel).-- * ConTeXt writer:-- + Support blank lines in line blocks (#6564, Albert Krewinkel,- thanks to @denismaier).- + Use span identifiers as reference anchors (#7246, Albert Krewinkel).-- * HTML writer:-- + Keep attributes from code nested below `pre` tag (#7221,- Albert Krewinkel). If a code block is defined with `<pre><code- class="language-x">…</code></pre>`, where the `<pre>` element has no- attributes, then the attributes from the `<code>` element are used- instead. Any leading `language-` prefix is dropped in the code's- `class` attribute are dropped to improve syntax highlighting.- + Ensure headings only have valid attribs in HTML4 (#5944, Albert- Krewinkel).- + Parse `<header>` as a Div (Albert Krewinkel).-- * Org writer:-- + Inline latex envs need newlines (#7252, tecosaur).- As specified in https://orgmode.org/manual/LaTeX-fragments.html, an- inline \begin{}...\end{} LaTeX block must start on a new line.- + Use LaTeX style maths deliminators (#7196, tecosaur).-- * JATS writer (Albert Krewinkel):-- + Use either styled-content or named-content for spans (#7211).- If the element has a content-type attribute, or at least one class,- then that value is used as `content-type` and the span is put inside- a `<named-content>` element. Otherwise a `<styled-content>` element- is used instead.- + Reduce unnecessary use of `<p>` elements for wrapping (#7227).- The `<p>` element is used for wrapping in cases were the contents- would otherwise not be allowed in a certain context. Unnecessary- wrapping is avoided, especially around quotes (`<disp-quote>` elements).- + Convert spans to `<named-content>` elements (#7211). Spans with- attributes are converted to `<named-content>` elements instead of- being wrapped with `<milestone-start/>` and `<milestone-end>`- elements. Milestone elements are not allowed in documents using the- articleauthoring tag set, so this change ensures the creation of valid- documents.- + Add footnote number as label in backmatter (#7210). Footnotes in the- backmatter are given the footnote's number as a label. The- articleauthoring output is unaffected from this change, as footnotes- are placed inline there.- + Escape disallows chars in identifiers. XML identifiers must start- with an underscore or letter, and can contain only a limited set- of punctuation characters. Any IDs not adhering to these rules are- rewritten by writing the offending characters as `Uxxxx`,- where `xxxx` is the character's hex code.-- * Jira writer: use `{color}` when span has a color attribute- (Albert Krewinkel, tarleb/jira-wiki-markup#10).-- * Docx writer:-- + Autoset table width if no column has an explicit width (Albert- Krewinkel).- + Extract Table handling into separate module (Albert Krewinkel).- + Support colspans and rowspans in tables (Albert Krewinkel, #6315).- + Support multirow table headers (Albert Krewinkel).- + Improve integration of settings from reference.docx (#1209).- This change allows users to create a reference.docx that- sets `w:proofState` for spelling or grammar to `dirty`,- so that spell/grammar checking will be triggered on the- generated docx.- + Copy over more settings from reference.docx (#7240). From settings.xml- in the reference-doc, we now include: `zoom`, `embedSystemFonts`,- `doNotTrackMoves`, `defaultTabStop`, `drawingGridHorizontalSpacing`,- `drawingGridVerticalSpacing`, `displayHorizontalDrawingGridEvery`,- `displayVerticalDrawingGridEvery`, `characterSpacingControl`,- `savePreviewPicture`, `mathPr`, `themeFontLang`, `decimalSymbol`,- `listSeparator`, `autoHyphenation`, `compat`.- + Set zoom to 100% by default in settings.xml.- + Align math options more with current Word defaults (e.g. Cambria Math- font).- + Remove `rsid`s from default settings.xml. Word will add these- when revisions are made.-- * Ms writer: Handle tables with multiple paragraphs (#7288).- Previously they overflowed the table cell width. We now set line lengths- per-cell and restore them after the table has been written.-- * Markdown writer:-- + Use cleaner braceless syntax for code blocks with a- single class (#7242, Jan Tojnar).- + Add quotes properly in markdown YAML metadata fields (#7245).- This fixes a bug, which caused the writer to look at the *last*- rather than the *first* character in determining whether quotes- were needed. So we got spurious quotes in some cases and- didn't get necessary quotes in others.- + Use `@{..}` syntax for citations when needed.- + Use fewer unneeded escapes for `#` (see #6259).- + Improve escaping of `@`. We need to escape literal `@` before- `{` because of the new citation syntax.-- * Commonmark writer: Use backslash escapes for `<` and `|`...- instead of entities (#7208).-- * Powerpoint writer: allow `monofont` to be specified in metadata- (#7187).-- * LaTeX template:-- + Use non-starred names for xcolor color names (#6109).- This should make svgnames and x11names work properly.- + Fix bad vertical spacing after bibliography (#7234, badumont).- + List of figures before list of tables (#7235, Julien Dutant).- + Move CSL macro definitions before header-includes so they can be- overridden (#7286).- + Improve treatment of CSL `entry-spacing` (#7296).- Previously with the default template settings (`indent` variable- not set), we would get interparagraph spaces separating bib- entries even with `entry-spacing="0"`. On the other hand,- setting `entry-spacing="2"` gave ridiculously large spacing.- This change makes the spacing caused by `entry-spacing` a multiple- of `\parskip` by default, which gives aesthetically reasonable- output. Those who want a larger or smaller unit (e.g. because- they use `indent` which sets `\parskip` to 0) may- `\setlength{\cslentryspacingunit}{10pt}` in header-includes- to override the defaults.- + Move title, author, date up to top of preamble (#7295).- This allows header-includes to use them, and puts them- in a position where you can see them immediately.- + Define commands for zero width non-joiner character- (#6639, Albert Krewinkel). The zero-width non-joiner character- is used to avoid ligatures (e.g. in German).-- * ConTeXt template:-- + Define `enumerate` itemgroup (#5016, Denis Maier).- + List of figures before list of tables (#7235, Julien Dutant).-- * reveal.js template:-- + Support `toc-title` (#7171, Florian Kohrt).- + Use `hash: true` by default rather than `history: true` (#6968).-- * HTML-based slide shows: add support for `institute` (#7289, Thomas- Hodgson).-- * Text.Pandoc.Extensions: Add constructor `Ext_rebase_relative_paths` to- `Extensions` [API change].-- * Text.Pandoc.XML.Light: add Eq, Ord instances for Content,- Element, Attr, CDataKind [API change].-- * Text.Pandoc.MediaBag:-- + Change type to use a `Text` key instead of `[FilePath]`.- We normalize the path and use `/` separators for consistency.- + Export `MediaItem` type [API change].- + Change `MediaBag` type to a map from Text to MediaItem [API change].- + `lookupMedia` now returns a `MediaItem` [API change].- + Change `insertMedia` so it sets the `mediaPath` to a filename based on- the SHA1 hash of the contents. This will be used when contents- are extracted.-- * Text.Pandoc.Class.PandocMonad:-- + Remove `fetchMediaResource` [API change]. Use `fetchItem` to get- resources in `fillMediaBag`.- + Add informational message in `downloadOrRead` indicating what path- local resources have been loaded from.-- * Text.Pandoc.Logging:-- + Remove single quotes around paths in messages.- + Add LoadedResource constructor to LogMessage [API change].- This is for INFO-level messages telling where image data has been- loaded from. (This can vary because of the resource path.)-- * Text.Pandoc.Asciify: simplify code and export `toAsciiText` [API change].- Instead of encoding a giant (and incomplete) map, we now- just use unicode-transforms to normalize the text to- a canonical decomposition, and manipulate the result.-- * App: allow tabs expansion even if file-scope is used (Albert Krewinkel,- #6709). Tabs in plain-text inputs are now handled correctly, even if- the `--file-scope` flag is used.-- * Add new internal module Text.Pandoc.Writers.GridTable (Albert Krewinkel).-- * Text.Pandoc.Highlighting: Change type of `languagesByExtension`, adding- a parameter for a `SyntaxMap` [API change] (Jan Tojnar, #7241).- Languages defined using `--syntax-definition` were not recognized by- `languagesByExtension`. This patch corrects that, allowing the writers- to see all custom definitions. The LaTeX writer still uses the default- syntax map, but that's okay in that context, since- `--syntax-definition` won't create new listings styles.-- * Text.Pandoc.Citeproc:-- + Ensure that CSL-related attributes are passed on to a Div with id- 'refs'. Otherwise things like `entry-spacing` won't work when- such Divs are used.- + Use metadata's `lang` for the lang parameter of citeproc, overriding- `localeLanguage`.- + Recognize locators spelled with a capital letter (#7323).- + Add a comma and a space in front of the suffix if it doesn't start- with space or punctuation (#7324).- + Don't detect math elements as locators (#7321).-- * Remove Text.Pandoc.BCP47 module [API change]. Use types and functions- from UnicodeCollation.Lang instead. This is a richer implementation- of BCP 47.-- * Text.Pandoc.Shared:-- + Fix regression in grid tables for wide characters (#7214).- In the translation from String to Text, a char-width-sensitive- `splitAt'` was dropped. This commit reinstates it and uses it to make- `splitTextByInstances` char-width sensitive.- + Add `getLang` (formerly in the now-removed BCP47) [API change].-- * Text.Pandoc.SelfContained: use `application/octet-stream`- for unknown mime types instead of halting with an error (#7202).-- * Lua filters: respect Inlines/Blocks filter functions in `pandoc.walk_*`- (Albert Krewinkel).-- * Add text as build-depend for trypandoc (#7193, Roman Beránek).-- * Bump upper-bounds for network-uri, time, attoparsec.-- * Use citeproc 0.4.-- * Use texmath 0.12.3.-- * Use jira-wiki-markup 1.3.5 (Albert Krewinkel).-- * Require latest skylighting (fixes a bug in XML syntax highlighting).-- * Use latest xml-conduit.-- * Use latest commonmark, commonmark-extensions, commonmark-pandoc.-- * Use haddock-library-1.10.0 (Albert Krewinkel).-- * Allow compilation with base 4.15 (Albert Krewinkel).-- * MANUAL:-- + Add information about `lang` and bibliography sorting.- + Add info about YAML escape sequences, link to spec (#7152,- Albert Krewinkel).- + Note that `institute` variable works for HTML-based slides.- + Update documentation on citation syntax.- + Add citation example for locators and suffixes (Tristan Stenner)-- * Updated and fixed typos in documentation (Charanjit Singh,- Anti-Distinctlyminty, Tatiana Porras, obcat).-- * Add instructions for installing pandoc-types before compiling filter.-- * INSTALL: add note that parallel installations should be avoided- (#6865).-- * Remove `biblatex-nussbaum.md` test. It is basically the same- as `biblaetx-quotes.md`.-- * Command tests: fail if a file contains no tests---and fix a- test that failed in that way!-- * Use smaller images in tests, reducing the size of the source tarball by 8 MB.---## pandoc 2.13 (2021-03-21)-- * Support `yaml_metadata_block` extension for `commonmark`, `gfm` (#6537).- This supported is a bit more limited than with pandoc's- `markdown`. The YAML block must be the first thing in the input,- and the leaf notes are parsed in isolation from the rest of- the document. So, for example, you can't use reference- links if the references are defined later in the document.-- * Fix fallback to default partials when custom templates are used.- If the directory containing a template does not contain the partial,- it should be sought in the default templates, but this was not- working properly (#7164).-- * Handle `nocite` better with `--biblatex` and `--natbib` (#4585).- Previously the nocite metadata field was ignored with these formats.- Now it populates a `nocite-ids` template variable and causes a- `\nocite` command to be issued.-- * Text.Pandoc.Citeproc: apply `fixLinks` correctly (#7130). This is code- that incorporates a prefix like `https://doi.org/` into a following link- when appropriate.-- * Text.Pandoc.Shared:-- + Remove `backslashEscapes`, `escapeStringUsing` [API change]. Replace- these inefficient association list lookups with more efficient escaping- functions in the writers that used them (for a 10-25% performance boost- in org, haddock, rtf, texinfo writers).- + Remove `ToString`, `ToText` typeclasses [API change]. These were needed- for the transition from String to Text, but they are no longer used and- may clash with other things.- + Simplify `compactDL`.-- * Text.Pandoc.Parsing:-- + Change type of `readWithM` so that it is no longer polymorphic- [API change]. The `ToText` class has been removed, and now that we've- completed the transition to Text we no longer need this to operate- on Strings.- + Remove `F` type synonym [API change]. Muse and Org were defining their- own `F` anyway.-- * Text.Pandoc.Readers.Metadata:-- + Export `yamlMetaBlock` [API change].- + Make `yamlBsToMeta`, `yamlBsToRefs` polymorphic on the parser state- [API change].-- * Markdown reader: Fix regression with `tex_math_backslash` (#7155).-- * MediaWiki reader: Allow block-level content in notes (ref) (#7145).-- * Jira reader (Albert Krewinkel):-- + Fixed parsing of autolinks (i.e., of bare URLs in the text).- Previously an autolink would take up the rest of a line, as spaces- were allowed characters in these items.- + Emoji character sequences no longer cause parsing failures. This was- due to missing backtracking when emoji parsing fails.- + Mark divs created from panels with class "panel".-- * RST reader: fix logic for ending comments (#7134). Previously comments- sometimes got extended too far.-- * DocBook writer: include Header attributes as XML attributes on- section (Erik Rask). Attributes with key names that are not allowed- as XML attributes are dropped, as are attributes with invalid values- and `xml:id` (DocBook 5) and `id` (DocBook 4).-- * Docx writer:-- + Make `nsid` in `abstractNum` deterministic. Previously we assigned- a random number, but we don't need random values, so now we just- assign a value based on the list marker.- + Use integral values for `w:tblW` (#7141).-- * Jira writer (Albert Krewinkel):-- + Block quotes are only rendered as `bq.` if they do not contain a- linebreak.- + Jira writer: improve div/panel handling. Include div attributes in- panels, always render divs with class `panel` as panels, and- avoid nesting of panels.-- * HTML writer: Add warnings on duplicate attribute values.- This prevents emitting invalid HTML. Ultimately it would be good to- prevent this in the types themselves, but this is better for now.-- * Org writer: Prevent unintended creation of ordered list items (#7132,- Albert Krewinkel). Adjust line wrapping if default wrapping would cause- a line to be read as an ordered list item.-- * JATS templates: support 'equal-contrib' attrib for authors (Albert- Krewinkel). Authors who contributed equally to a paper may be marked- with `equal-contrib`.-- * reveal.js template: replace JS comment with HTML (#7154, Florian Kohrt).-- * Text.Pandoc.Logging: Add `DuplicateAttribute` constructor to `LogMessage`.- [API change]-- * Use `-j4` for linux release build. This speeds up the build dramatically- on arm.-- * cabal.project: remove ghcoptions. Move flags to top level, so they can- be set differently on the command line.-- * Require latest texmath, skylighting, citeproc, jira-wiki-markup.- (The latest skylighting fixes a bad bug with Haskell syntax highlighting.)- Narrow version bounds for texmath, skylighting, and citeproc, since- the test output depend on them.-- * Use doclayout 0.3.0.2. This significantly reduces the time and memory- needed to compile pandoc.-- * Use `foldl'` instead of `foldl` everywhere.-- * Update bounds for random (#7156, Alexey Kuleshevich).-- * Remove uses of some partial functions.-- * Don't bake in a larger stack size for the executable.-- * Test improvements:-- + Use `getExecutablePath` from base, avoiding the dependency on- `executable-path`.- + Factor out `setupEnvironment` in Helpers, to avoid code duplication.- + Fix finding of data files by setting teh `pandoc_datadir` environment- variable when we shell out to pandoc. This avoids the need to use- `--data-dir` for the tests, which caused problems finding `pandoc.lua`- when compiling without the `embed_data_files` flag (#7163).-- * Benchmark improvements:-- + Build `+RTS -A8m -RTS` into default ghc-options for benchmark.- This is necessary to get accurate benchmark results; otherwise we- are largely measuring garbage collecting, some not related to the- current benchmark.- + Allow specifying BASELINE file in 'make bench' for comparison- (otherwise the latest benchmark is chosen by default).- + Force `readFile` in benchmarks early (Bodigrim).-- * CONTRIBUTING: suggest using a `cabal.project.local` file (#7153,- Albert Krewinkel).-- * Add ghcid-test to Makefile. This loads the test suite in ghcid.---## pandoc 2.12 (2021-03-08)-- * `--resource-path` now accumulates if specified multiple- times (#6152). Resource paths specified later on the command line are- prepended to those specified earlier. Thus,- `--resource-path foo --resource-path bar:baz` is equivalent to- `--resource-path bar:bas:foo`. (The previous behavior was- for the last `--resource-path` to replace all the rest.)- `resource-path` in defaults files behaves the same way: it- will be prepended to the resource path set by earlier- command line options or defaults files. This change- facilitates the use of multiple defaults files: each can- specify a directory containing resources it refers to- without clobbering the resource paths set by the others.-- * Allow defaults files to refer to the home directory, the- user data directory, and the directory containing the defaults file- itself (#5871, #5982, #5977). In fields that expect file paths- (and only in these fields),-- + `${VARIABLE}` will expand to the value of the environment variable- `VARIABLE` (and in particular `${HOME}` will expand to the path- of the home directory). A warning will be raised for undefined- variables.- + `${USERDATA}` will expand to the path of the user data- directory in force when the defaults file is being processed.- + `${.}` will expand to the directory containing the defaults file.- (This allows default files to be placed in a directory containing- resources they make use of.)-- * When downloading content from URL arguments, be sensitive to- the character encoding (#5600). We can properly handle UTF-8 and latin1- (ISO-8859-1); for others we raise an error. Fall back to latin1 if- no charset is given in the mime type and UTF-8 decoding fails.-- * Allow abbreviations that don't end in a period to be- specified using `--abbreviations` (#7124).-- * Add new unexported module Text.Pandoc.XML.Light, as well- as Text.Pandoc.XML.Light.Types, Text.Pantoc.XML.Light.Proc,- Text.Pandoc.XML.Light.Output. (Closes #6001, #6565, #7091).-- This module exports definitions of `Element` and `Content`- that are isomorphic to xml-light's, but with Text- instead of String. This allows us to keep most of the code in existing- readers that use xml-light, but avoid lots of unnecessary allocation.-- We also add versions of the functions from xml-light's- Text.XML.Light.Output and Text.XML.Light.Proc that operate on our- modified XML types, and functions that convert xml-light types to our- types (since some of our dependencies, like texmath, use xml-light).-- We export functions that use xml-conduit's parser to produce an- `Element` or `[Content]`. This allows existing pandoc code to use- a better parser without much modification.-- The new parser is used in all places where xml-light's parser was- previously used. Benchmarks show a significant performance improvement- in parsing XML-based formats (with docbook, opml, jats, and docx- almost twice as fast, odt and fb2 more than twice as fast).-- In addition, the new parser gives us better error reporting than- xml-light. We report XML errors, when possible, using the new- `PandocXMLError` constructor in `PandocError`.-- These changes revealed the need for some changes in the tests. The- docbook-reader.docbook test lacked definitions for the entities it used;- these have been added. And the docx golden tests have been updated,- because the new parser does not preserve the order of attributes.-- * DocBook reader:-- + Avoid expensive tree normalization step, as it is not necessary- with the new XML parser.- + Support `informalfigure` (#7079) (Nils Carlson).-- * Docx reader:-- + Use Map instead of list for Namespaces. This gives a speedup of- about 5-10%. With this and the XML parsing changes, the docx reader- is now about twice as fast as in the previous release.-- * HTML reader:-- + Small performance tweaks.- + Also, remove exported class `NamedTag(..)` [API change]. This was just- intended to smooth over the transition from String to Text and is no- longer needed.- + As a result, the functions `isInlineTag` and `isBlockTag`- are no longer polymorphic; they apply to a `Tag Text` [API change].- + Do a lookahead to find the right parser to use. This takes- benchmarks from 34ms to 23ms, with less allocation.- + Fix bad handling of empty `src` attribute in `iframe` (#7099).- If `src` is empty, we simply skip the `iframe`.- If `src` is invalid or cannot be fetched, we issue a warning- nd skip instead of failing with an error.-- * JATS reader:-- + Avoid tree normalization, which is no longer necessary given the- new XML parser.-- * LaTeX reader:-- + Don't export `tokenize`, `untokenize` [API change]. These are internal- implementation details, which were only exported for testing.- They don't belong in the public API.- + Improved efficiency of the parser. With these changes the reader- is almost twice as fast as in the last release in our benchmarks.- + Code cleanup, removing some unnecessary things.- + Rewrite `withRaw` so it doesn't rely on fragile assumptions- about token positions (which break when macros are expanded)- (#7092). This requires the addition of `sEnableWithRaw` and- `sRawTokens` in `LaTeXState`, and a new combinator `disablingWithRaw`- to disable collecting of raw tokens in certain contexts.- Add `parseFromToks` to Text.Pandoc.Readers.LaTeX.Parsing.- Fix parsing of single character tokens so it doesn't mess- up the new raw token collecting. These changes slightly increase- allocations and have a small performance impact.- + Handle some bibtex/biblatex-specific commands that used to be- dealt with in pandoc-citeproc (#7049).- + Optimize `satisfyTok`, avoiding unnecessary macro expansion steps.- Benchmarks after this change show 2/3 of the run time and 2/3 of the- allocation of the Feb. 10 benchmarks.- + Removed `sExpanded` in state. This isn't actually needed and checking- it doesn't change anything.- + Improve `braced'`. Remove the parameter, have it parse the- opening brace, and make it more efficient.- + Factor out pieces of the LaTeX reader to make the module smaller.- This reduces memory demands when compiling. Created- Text.Pandoc.Readers.{LaTeX,Math,Citation,Table,Macro,Inline}.- Changed Text.Pandoc.Readers.LaTeX.SIunitx to export a command map- instead of individual commands.- + Handle table cells containing `&` in `\verb` (#7129).-- * Make Text.Pandoc.Readers.LaTeX.Types an unexported module [API change].-- * Markdown reader:-- + Improved handling of mmd link attributes in references (#7080).- Previously they only worked for links that had titles.- + Improved efficiency of the parser (benchmarks show a 15% speedup).-- * OPML reader:-- + Avoid tree normalization, which is no longer necessary with the- new XML parser.-- * ODT reader:-- + Finer-grained errors on parse failure (#7091).- + Give more information if the zip container can't be unpacked.-- * Org reader:-- + Support `task_lists` extension (Albert Krewinkel, #6336).- + Fix bug in org-ref citation parsing (Albert Krewinkel, #7101).- The org-ref syntax allows to list multiple citations separated by- comma. Previously commas were accepted as part of the citation id,- so all citation lists were parsed as one single citation.-- * RST reader:-- + Use `getTimestamp` instead of `getCurrentTime` to fetch timestamp.- Setting `SOURCE_DATE_EPOCH` will allow reproducible builds.- + RST reader: fix handling of header in CSV tables (#7064).- The interpretation of this line is not affected by the delim option.-- * Jira reader:-- + Modified the Doc parser to skip leading blank lines. This fixes- parsing of documents which start with multiple blank lines (Albert- Krewinkel, #7095).- + Prevent URLs within link aliases to be treated as autolinks (Albert- Krewinkel, #6944).-- * Text.Pandoc.Shared-- + Remove formerly exported functions that are no longer used in the- code base: `splitByIndices`, `splitStringByIndicies`, `substitute`,- and `underlineSpan` (which had been deprecated in April 2020)- [API change].- + Export `handleTaskListItem` (Albert Krewinkel) [API change].- + Change `defaultUserDataDirs` to `defaultUserDataDir` [API- change]. We determine what is the default user data directory- by seeing whether the XDG directory and/or legacy- directory exist.-- * BibTeX writer:-- + BibTeX writer: use doclayout and doctemplate. This change allows- bibtex/biblatex output to wrap as other formats do,- depending on the settings of `--wrap` and `--columns` (#7068).-- * CSL JSON writer:-- + Output `[]` if no references in input, instead of raising a- PandocAppError as before.-- * Docx writer:-- + Use `getTimestamp` instead of `getCurrentTime` for timestamp.- Setting `SOURCE_DATE_EPOCH` will allow reproducible builds.-- * EPUB writer:-- + Use `getTimestamp` instead of `getCurrentTime` for timestamp.- Setting `SOURCE_DATE_EPOCH` will allow reproducible builds (#7093).- This does not suffice to fully enable reproducible in EPUB, since- a unique id is still being generated for each build.- + Support `belongs-to-collection` metadata (#7063) (Nick Berendsen).-- * JATS writer:-- + Escape special chars in reference elements (Albert Krewinkel).- Prevents the generation of invalid markup if a citation element- contains an ampersand or another character with a special meaning- in XML.-- * Jira writer:-- + Use Span identifiers as anchors (Albert Krewinkel).- + Use `{noformat}` instead of `{code}` for unknown languages (Albert- Krewinkel). Code blocks which are not marked as a language supported- by Jira are rendered as preformatted text via `{noformat}` blocks.-- * LaTeX writer:-- + Adjust hypertargets to beginnings of paragraphs (#7078).- Use `\vadjust pre` so that the hypertarget takes you to the beginning- of the paragraph rather than one line down.- This makes a particular difference for links to citations using- `--citeproc` and `link-citations: true`.- + Change BCP47 lang tag from `jp` to `ja` (Mauro Bieg, #7047).- + Use function instead of map for accent lookup (should be- more efficient).- + Split the module to make it easier to compile on low-memory- systems: added Text.Pandoc.Writers.LaTeX.{Util,Citation,Lang}.-- * Markdown writer:-- + Handle math right before digit. We insert an HTML comment to- avoid a `$` right before a digit, which pandoc will not recognize- as a math delimiter.- + Split the module to make it easier to compile on low-memory- systems: added Text.Pandoc.Writers.Markdown.{Types,Inline}.-- * ODT writer:-- + Use `getTimestamp` instead of `getCurrentTime` for timestamp.- Setting `SOURCE_DATE_EPOCH` will allow reproducible builds.- + Update default ODT style (Lorenzo). Previously, the "First paragraph"- style inherited from "Standard" but not from "Text body." Now- it is adjusted to inherit from "Text body", to avoid some ugly- spacing issues. It may be necessary to update a custom `reference.odt`- in light of this change.-- * Org writer:-- + Support `task_lists` extension (Albert Krewinkel, #6336).-- * Pptx writer:-- + Use `getTimestamp` instead of `getCurrentTime` for timestamp.- Setting `SOURCE_DATE_EPOCH` will allow reproducible builds.-- * JATS templates: tag `author.name` as `string-name` (Albert Krewinkel).- The partitioning the components of a name into surname, given names,- etc. is not always possible or not available. Using `author.name`- allows to give the full name as a fallback to be used when- `author.surname` is not available.-- * Add default templates for bibtex and biblatex, so that- the variables `header-include`, `include-before`, `include-after`- (or alternatively the command line options- `--include-in-header`, `--include-before-body`, `--include-after-body`)- may be used.-- * LaTeX template:-- + Update to iftex package (#7073) (Andrew Dunning)- + Wrap url colours in braces (#7121) (Loïc Grobol).-- * revealjs template: Add 'center' option for vertical slide centering.- (maurerle, #7104).-- * Text.Pandoc.XML: Improve efficiency of `fromEntities`.-- * Text.Pandoc.MIME-- + Add exported function `getCharset` [API change].-- * Text.Pandoc.UTF8: change IO functions to return Text, not String- [API change]. This affects `readFile`, `getContents`, `writeFileWith`,- `writeFile`, `putStrWith`, `putStr`, `putStrLnWith`, `putStrLn`.- `hPutStrWith`, `hPutStr`, `hPutStrLnWith`, `hPutStrLn`, `hGetContents`.- This avoids the need to uselessly create a linked list of characters- when emiting output.-- * Text.Pandoc.App-- + Add `parseOptionsFromArgs` [API change, new exported function].- + Add fields for CSL options to `Opt` [API change]:- `optCSL`, `optbibliography`, `optCitationAbbreviations`.-- * Text.Pandoc.Citeproc.BibTeX-- + `Text.Pandoc.Citeproc.writeBibTeXString` now returns- `Doc Text` instead of `Text` (#7068).- + Correctly handle `pages` (= `page` in CSL) (#7067).- + Correctly handle BibLaTeX `langid` (= `language` in CSL, #7067).- + In BibTeX output, protect foreign titles since there's no language- field (#7067).- + Clean up BibTeX parsing (#7049). Previously there was a messy code- path that gave strange results in some cases, not passing through raw- tex but trying to extract a string content. This was an artefact of- trying to handle some special bibtex-specific commands in the BibTeX- reader. Now we just handle these in the LaTeX reader and simplify- parsing in the BibTeX reader. This does mean that more raw tex will- be passed through (and currently this is not sensitive to the- `raw_tex` extension; this should be fixed).-- * Text.Pandoc.Citeproc.MetaValue-- + Correctly parse "raw" date value in markdown references metadata.- (See jgm/citeproc#53.)-- * Text.Pandoc.Citeproc-- + Use https URLs for links (Salim B, #7122).-- * Text.Pandoc.Class-- + Add `getTimestamp` [API change]. This attempts to read the- `SOURCE_DATE_EPOCH` environment variable and parse a UTC time- from it (treating it as a unix date stamp, see- https://reproducible-builds.org/specs/source-date-epoch/). If the- variable is not set or can't be parsed as a unix date stamp, then the- function returns the current date.-- * Text.Pandoc.Error-- + Add `PandocUnsupportedCharsetError` constructor for- `PandocError` [API change].- + Export `renderError` [API change].- + Refactor `handleError` to use `renderError`. This allows us render- error messages without exiting.-- * Text.Pandoc.Extensions-- + `Ext_task_lists` is now supported by org (and turned- on by default) (Albert Krewinkel, #6336).- + Remove `Ext_fenced_code_attributes` from allowed commonmark attributes- (#7097). This attribute was listed as allowed, but it didn't actually- do anything. Use `attributes` for code attributes and more.-- * Lua subsystem:-- + Always load built-in Lua scripts from default data-dir (Albert- Krewinkel). The Lua modules `pandoc` and `pandoc.List` are now always- loaded from the system's default data directory. Loading from a- different directory by overriding the default path, e.g. via- `--data-dir`, is no longer supported to avoid unexpected behavior- and to address security concerns.- + Add module "pandoc.path" (Albert Krewinkel, #6001, #6565).- The module allows to work with file paths in a convenient and- platform-independent manner.- + Use strict evaluation when retrieving AST value from the stack- (Albert Krewinkel, #6674).-- * Text.Pandoc.PDF-- + Disable `smart` extension when building PDF via LaTeX.- This is to prevent accidental creation of ligatures like- `` ?` `` and `` !` `` (especially in languages with quotations like- German), and similar ligature issues. (See jgm/citeproc#54.)-- * Text.Pandoc.CSV:-- + Fix parsing of unquoted values (#7112). Previously we didn't allow- unescaped quotes in unquoted values, but they are allowed- in CSV.-- * Test suite:-- + Use a more robust method for testing the executable. Many- of our tests require running the pandoc executable. This- is problematic for a few different reasons. First,- cabal-install will sometimes run the test suite after- building the library but before building the executable,- which means the executable isn't in place for the tests.- One can work around that by first building, then building- and running the tests, but that's fragile. Second, we- have to find the executable. So far, we've done that using- a function `findPandoc` that attempts to locate it- relative to the test executable (which can be located- using findExecutablePath). But the logic here is delicate- and work with every combination of options. To solve both- problems, we add an `--emulate` option to the- `test-pandoc` executable. When `--emulate` occurs as the- first argument passed to `test-pandoc`, the program simply- emulates the regular pandoc executable, using the rest of- the arguments (after `--emulate`). Thus, `test-pandoc- --emulate -f markdown -t latex` is just like `pandoc -f- markdown -t latex`. Since all the work is done by library- functions, implementing this emulation just takes a couple- lines of code and should be entirely reliable. With this- change, we can test the pandoc executable by running the- test program itself (locatable using `findExecutablePath`)- with the `--emulate` option. This removes the need for the- fragile `findPandoc` step, and it means we can run our- integration tests even when we're just building the- library, not the executable. [Note: part of this change- involved simplifying some complex handling to set- environment variables for dynamic library paths. I have- tested a build with `--enable-dynamic-executable`, and it- works, but further testing may be needed.]- + Print accurate location if a test fails (Albert- Krewinkel). Ensures that tasty-hunit reports the location- of the failing test instead of the location of the helper- `test` function.-- * Documentation: Update URLs and use `https` where possible (#7122,- Salim B).-- * Add `doc/libraries.md`, a description of libraries that support pandoc.-- * MANUAL.txt-- + MANUAL: block-level formatting is not allowed in line blocks (#7107).- + Clarify `tex_math_dollars` extension. Note that no blank lines- are allowed between the delimiters in display math.- + Add MANUAL section on reproducible builds.- + Document no template fallback for absolute path (#7077, Nixon- Enraght-Moony.)- + Improve docs for cite-method.- + Update README and man page.-- * Makefile: in `make bench`, create CSV files for comparison and compare- against previous benchmark run. Add timestamp to CSV filenames.-- * cabal.project: don't explicitly set -trypandoc.- If we do, this can't be overridden on the cabal command line.-- * doc/lua-filters.md: improve documentation for- `pandoc.mediabag.insert`, `pandoc.mediabag.fetch`,- `directory`, `normalize` (Albert Krewinkel).-- * Allow base64-bytestring-1.2.* (Dmitrii Kovanikov)-- * Require jira-wiki-markup 1.3.3 (Albert Krewinkel)-- * Require citeproc 0.3.0.8, which correctly titlecases when titles- contain non-ASCII characters.-- * Use skylighting 0.10.4. This version of skylighting uses xml-conduit- rather than hxt. This speeds up parsing of XML syntax definitions- fourfold, and removes four packages from pandoc's dependency graph:- hxt-charproperties, hxt-unicode, hxt-regex-xmlschema, hxt.-- * Add script `tools/parseTimings.pl` to help pin down which- modules take the most time and memory to compile.-- * Avoid unnecessary use of NoImplicitPrelude pragma (#7089) (Albert- Krewinkel)-- * Benchmarks-- + Use the lighter-weight tasty-bench instead of criterion.- + Run writer benchmarks for binary formats too.- + Alphabetize benchmarks.- + Don't run benchmarks for bibliography formats- (yet; we need a special input for them).- + Show allocation data- + Clean up benchmark code.- + Allow specifying patterns using `-p blah'.-- * trypandoc: add 2 second timeout.-- * Use `-split-sections` in creating linux release binary.- This reduces executable size significantly (by about 30%).-- * Remove `weigh-pandoc`. It's not really useful any more, now that our- regular benchmarks include data on allocation.-- * Improve linux package build process and add script to- automate building an arm64 binary package.---## pandoc 2.11.4 (2021-01-22)-- * Add `biblatex`, `bibtex` as output formats (closes #7040).-- * Recognize more extensions as markdown by default (#7034):- `mkdn`, `mkd`, `mdwn`, `mdown`, `Rmd`.-- * Implement defaults file inheritance (#6924, David Martschenko).- Allow defaults files to inherit options from other defaults files by- specifying them with the following syntax:- `defaults: [list of defaults files or single defaults file]`.-- * Fix infinite HTTP requests when writing epubs from URL source (#7013).- Due to a bug in code added to avoid overwriting the cover image- if it had the form `fileX.YYY`, pandoc made an endless sequence- of HTTP requests when writing epub with input from a URL.-- * Org reader:-- + Allow multiple pipe chars in todo sequences (Albert Krewinkel, #7014).- Additional pipe chars, used to separate "action" state from "no further- action" states, are ignored. E.g., for the following sequence, both- `DONE` and `FINISHED` are states with no further action required:- `#+TODO: UNFINISHED | DONE | FINISHED`.- + Restructure output of captioned code blocks (Albert Krewinkel, #6977).- The Div wrapper of code blocks with captions now has the class- "captioned-content". The caption itself is added as a Plain block- inside a Div of class "caption". This makes it easier to write filters- which match on captioned code blocks. Existing filters will need to be- updated.- + Mark verbatim code with class `verbatim` (Dimitri Sabadie, #6998).-- * LaTeX reader:-- + Handle `filecontents` environment (#7003).- + Put contents of unknown environments in a Div when `raw_tex` is not- enabled (#6997). (When `raw_tex` is enabled, the whole environment is- parsed as a raw block.) The class name is the name of the environment.- Previously, we just included the contents without the surrounding Div,- but having a record of the environment's boundaries and name can be- useful.-- * Mediawiki reader:-- + Allow space around storng/emph delimiters (#6993).-- * New module Text.Pandoc.Writers.BibTeX, exporting- writeBibTeX and writeBibLaTeX. [API change]-- * LaTeX writer:-- + Revert table line height increase in 2.11.3 (#6996).- In 2.11.3 we started adding `\addlinespace`, which produced less dense- tables. This wasn't an intentional change; I misunderstood a comment in- the discussion leading up to the change. This commit restores the earlier- default table appearance. Note that if you want a less dense table, you- can use something like `\def\arraystretch{1.5}` in your header.-- * EPUB writer:-- + Adjust internal links to identifiers defined in raw HTML sections- after splitting into chapters (#7000).- + Recognize `Format "html4"`, `Format "html5"` as raw HTML.- + Adjust internal links to images, links, and tables after splitting into- chapters. Previously we only did this for Div and Span and Header- elements (see #7000).-- * Ms writer:-- + Don't justify text inside table cells.-- * JATS writer:-- + Use `<element-citation>` if `element_citations`- extension is enabled (Albert Krewinkel).- + Fix citations (Albert Krewinkel, #7018). By default- we use formatted citations.- + Ensure that `<disp-quote>` is always wrapped in `<p>` (#7041).-- * Markdown writer:-- + Cleaned up raw formats. We now react appropriately- to `gfm`, `commonmark`, and `commonmark_x` as raw formats.-- * RST writer:-- + Fix bug with dropped content from inside spans with a class in- some cases (#7039).-- * Docx writer:-- + Handle table header using styles (#7008). Instead of hard-coding- the border and header cell vertical alignment, we now let this- be determined by the Table style, making use of Word's- "conditional formatting" for the table's first row. For- headerless tables, we use the tblLook element to tell Word- not to apply conditional first-row formatting.-- * Commonmark writer:-- + Implement start number on ordered lists (#7009). Previously they always- started at 1, but according to the spec the start number is respected.-- * HTML writer:-- + Fix implicit_figure at end of footnotes (#7006).-- * ConTeXt template: Remove `\setupthinrules` from default template.- The width parameter this used is not actually supported,- and the command didn't do anything.-- * Text.Pandoc.Extensions:-- + Add `Ext_element_citations` constructor (Albert Krewinkel).-- * Text.Pandoc.Citeproc.BibTeX: New unexported function- `writeBibtexString`.-- * Text.Pandoc.Citeproc:-- + Use finer grained imports (Albert Krewinkel).- + Factor out and export `getStyle` [API change].- + Export `getReferences` [API change, #7106].- + Factor out getLang.-- * Text.Pandoc.Parsing: modify `gridTableWith'` for headerless tables.- If the table lacks a header, the header row should be an empty- list. Previously we got a list of empty cells, which caused- an empty header to be emitted instead of no header. In LaTeX/PDF- output that meant we got a double top line with space between.-- * ImageSize: use `viewBox` for SVG if no length, width attributes (#7045).- This change allows pandoc to extract size information from more SVGs.-- * Add simple default.nix.-- * Use commonmark 0.1.1.3.-- * Use citeproc 0.3.0.5.-- * Update default CSL to use latest chicago-author-date.csl.-- * CONTRIBUTING.md: add note on GNU xargs.-- * MANUAL.txt:-- + Update description of `-L`/`--lua-filter`.- + Document use of citations in note styles (#6828).--## pandoc 2.11.3.2 (2020-12-29)-- * HTML reader: use renderTags' from Text.Pandoc.Shared (Albert Krewinkel).- A side effect of this change is that empty `<col>` elements are written- as self-closing tags in raw HTML blocks.-- * Asciidoc writer: Add support for writing nested tables (#6972, timo-a).- Asciidoc supports one level of nesting. If deeper tables are to be- written, they are omitted and a warning is issued.-- * Docx writer: fix nested tables with captions (#6983).- Previously we got unreadable content, because docx seems- to want a `<w:p>` element (even an empty one) at the end of- every table cell.-- * Powerpoint writer: allow arbitrary OOXML in raw inline elements- (Albert Krewinkel). The raw text is now included verbatim in the- output. Previously is was parsed into XML elements, which prevented- the inclusion of partial XML snippets.-- * LaTeX writer: support colspans and rowspans in tables (#6950,- Albert Krewinkel). Note that the multirow package is needed for- rowspans. It is included in the latex template under a variable,- so that it won't be used unless needed for a table.-- * HTML writer: don't include p tags in CSL bibliography entries- (#6966). Fixes a regression in 2.11.3.-- * Add `meta-description` variable to HTML templates (#6982). This- is populated by the writer by stringifying the `description`- field of metadata (Jerry Sky). The `description` meta tag will- make the generated HTML documents more complete and SEO-friendly.-- * Citeproc: fix handling of empty URL variables (`DOI`, etc.).- The `linkifyVariables` function was changing these to links- which then got treated as non-empty by citeproc, leading- to wrong results (e.g. ignoring nonempty URL when empty DOI is present).- See jgm/citeproc#41.-- * Use citeproc 0.3.0.3. Fixes an issue in author-only citations when- both an author and translator are present, and an issue with- citation group delimiters.-- * Require texmath 0.12.1. This improves siunitx support in math,- fixes bugs with `\*mod` family operators and arrays, and avoids- italicizing symbols and operator names in docx output.-- * Ensure that the perl interpreter used for filters with `.pl`- extension (wuffi).-- * MANUAL: note that textarea content is never parsed as Markdown- (Albert Krewinkel).---## pandoc 2.11.3.1 (2020-12-18)-- * Added some missing files to extra-source-files and data- files, so they are included in the sdist tarball. Closes #6961.- Cleaned up some extraneous data and test files, and added- a CI check to ensure that the test and data files included- in the sdist match what is in the git repository.-- * Use citeproc 0.3.0.1, which avoids removing nonbreaking- space at the end of the `initialize-with` attribute. (Some- journals require nonbreaking space after initials, and this- makes that possible.)--## pandoc 2.11.3 (2020-12-17)-- * With `--bibliography` (or `bibliography` in metadata), a- URL may now be provided, and pandoc will fetch the resource.- In addition, if a file path is provided and it is not- found relative to the working directory, the resource- path will be searched (#6940).-- * Add `sourcepos` extension for `commonmark`, `gfm`, `commonmark_x`- (#4565). With the `sourcepos` extension set set, `data-pos`- attributes are added to the AST by the commonmark reader. No other- readers are affected. The `data-pos` attributes are put on elements- that accept attributes; for other elements, an enlosing Div or Span- is added to hold the attributes.-- * Change extensions for `commonmark_x`: replace `auto_identifiers`- with `gfm_auto_identifiers` (#6863). `commonmark_x` never actually- supported `auto_identifiers` (it didn't do anything), because the- underlying library implements gfm-style identifiers only. Attempts- to add the `auto_identifiers` extension to `commonmark` will now- fail with an error.-- * HTML reader:-- + Split module into several submodules (Albert Krewinkel). Reducing- module size should reduce memory use during compilation.- + Support advanced table features (Albert Krewinkel):- block level content in captions, row and colspans,- body headers, row head columns, footers, attributes.- + Disable round-trip testing for tables. Information for cell- alignment in a column is not preserved during round-trips (Albert- Krewinkel).- + Allow finer grained options for tag omission (Albert Krewinkel).- + Simplify list attribute handling (Albert Krewinkel).- + Pay attention to `lang` attributes on body element (#6938).- These (as well as `lang` attributes on the html element) should update- lang in metadata.- + Retain attribute prefixes and avoid duplicates (#6938).- Previously we stripped attribute prefixes, reading `xml:lang` as- `lang` for example. This resulted in two duplicate `lang`- attributes when `xml:lang` and `lang` were both used. This commit- causes the prefixes to be retained, and also avoids invald- duplicate attributes.-- * Commonmark reader:-- + Refactor `specFor`.- + Set input name to `""` to avoid clutter in sourcepos output.-- * Org reader:-- + Parse `#+LANGUAGE` into `lang` metadata field (#6845, Albert- Krewinkel).- + Preserve targets of spurious links (#6916, Albert- Krewinkel). Links with (internal) targets that the reader doesn't- know about are converted into emphasized text. Information on the- link target is now preserved by wrapping the text in a Span of class- `spurious-link`, with an attribute `target` set to the link's- original target. This allows to recover and fix broken or unknown- links with filters.-- * DocBook reader:-- + Table text width support (#6791, Nils Carlson).- Table width in relation to text width is not natively supported- by docbook but is by the docbook `fo` stylesheets through an XML- processing instruction, `<?dbfo table-width="50%"?>`.-- * LaTeX reader:-- + Improve parsing of command options (#6869, #6873).- In cases where we run into trouble parsing inlines til the- closing `]`, e.g. quotes, we return a plain string with the- option contents. Previously we mistakenly included the brackets- in this string.- + Preserve center environment (#6852, Igor Pashev).- The contents of the `center` environment are put in a `Div`- with class `center`.- + Don't parse `\rule` with width 0 as horizontal rule. These are- sometimes used as spacers in LaTeX.- + Don't apply theorem default styling to a figure inside (#6925).- If we put an image in italics, then when rendering to Markdown- we no longer get an implicit figure.-- * Dokuwiki reader:-- + Handle unknown interwiki links better (#6932).- DokuWiki lets the user define his own Interwiki links. Previously- pandoc reacted to these by emitting a google search link, which is- not helpful. Instead, we now just emit the full URL including the- wikilink prefix, e.g. `faquk>FAQ-mathml`. This at least gives users- the ability to modify the links using filters.-- * Markdown writer:-- + Properly handle boolean values in writing YAML metadata (#6388).- + Ensure that a new csl-block begins on a new line (#6921).- This just looks better and doesn't affect the semantics.-- * RST writer:-- + Better image handling (#6948). An image alone in its paragraph- (but not a figure) is now rendered as an independent image, with an- `alt` attribute if a description is supplied. An inline image that- is not alone in its paragraph will be rendered, as before, using a- substitution. Such an image cannot have a "center", "left", or- "right" alignment, so the classes `align-center`, `align-left`, or- `align-right` are ignored. However, `align-top`, `align-middle`,- `align-bottom` will generate a corresponding `align` attribute.-- * Docx writer:-- + Keep raw openxml strings verbatim (#6933, Albert Krewinkel).- + Use Content instead of Element. This allows us to inject- raw OpenXML into the document without reparsing it into an- Element, which is necessary if you want to inject an open- tag or close tag.- + Fix bullets/lists indentation, so that the first level is slightly- indented to the right instead of right on the margin (cholonam).- + Support bold and italic in "complex script" (#6911).- Previously bold and italics didn't work properly in LTR- text. This commit causes the w:bCs and w:iCs attributes- to be used, in addition to w:b and w:i, for bold and- italics respectively.-- * ICML writer:-- + Fix image bounding box for custom widths/heighta (Mauro Bieg, #6936).-- * LaTeX writer:-- + Improve table spacing (#6842, #6860).- Remove the `\strut` that was added at the end of minipage- environments in cells. Replace `\tabularnewline` with- `\\ \addlinespace`.- + Improve calculation of column spacing (#6883).- + Extract table handling into separate module (Albert Krewinkel).- + Fix bug with nested `csl-` display Spans (#6921).- + Improve longtable output (#6883). Don't create minipages for- regular paragraphs. Put width and alignment information in the- longtable column descriptors.-- * OpenDocument writer:-- + Support for table width as a percentage of text width- (#6792, Nils Carson).- + Implement Div and Span ident support (#6755, Nils Carson).- Spans and Divs containing an ident in the Attr will become bookmarks- or sections with idents in OpenDocument format.- + Add two extensions, `xrefs_name` and `xrefs_number` (#6774, Nils- Carlson). Links to headings, figures and tables inside the- document are substituted with cross-references that will use the- name or caption of the referenced item for `xrefs_name` or the- number for `xrefs_number`. For the `xrefs_number` to be useful- heading numbers must be enabled in the generated document and- table and figure captions must be enabled using for example the- `native_numbering` extension. In order for numbers and reference- text to be updated the generated document must be refreshed.-- * JATS writer:-- + Support advanced table features (Albert Krewinkel).- + Support author affiliations (#6687, Albert Krewinkel).-- * Docbook writer:-- + Use correct id attribute consistently (Jan Tojnar).- DocBook5 should always use `xml:id` instead of `id`.- + Handle admonition titles better (Jan Tojnar).- Docbook reader produces a `Div` with `title` class for `<title>`- element within an “admonition” element. Markdown writer then turns- this into a fenced div with `title` class attribute. Since fenced- divs are block elements, their content is recognized as a- paragraph by the Markdown reader. This is an issue for Docbook- writer because it would produce an invalid DocBook document from- such AST – the `<title>` element can only contain “inline”- elements. Handle this special case separately by unwrapping- the paragraph before creating the `<title>` element.- + Add XML namespaces to top-level elements (#6923, Jan Tojnar).- Previously, we only added `xmlns` attributes to chapter- elements, even when running with `--top-level-division=section`.- These namespaces are now added to part and section elements too,- when they are the selected top-level divisions.- We do not need to add namespaces to documents produced with- `--standalone` flag, since those will already have xmlns attribute on- the root element in the template.-- * HTML writer:-- + Fix handling of nested `csl-` display spans (#6921).- Previously inner Spans used to represent CSL display attributes were- not rendered as div tags as intended.-- * EPUB writer:-- + Include title page in landmarks (#6919).- Note that the toc is also included if `--toc` is specified.- + Add frontmatter type on body element for nav.xhtml (#6918).-- * EPUB templates: use preserveAspectRatio="xMidYMid" for cover image (#6895,- Shin Sang-jae). This change affects both the epub2 and the epub3- templates. It avoids distortion of the cover image by requiring that the- aspect ratio be preserved.-- * LaTeX template:-- + Include `csquotes` package if `csquotes` variable set.- + Put back `amssymb`. We need it for checkboxes in todo lists,- and maybe for other things. In this location it seems compatible- with the cases that prompted #6469 and PR #6762.- + Disable language-specific shorthands in babel (#6817, #6887).- Babel defines "shorthands" for some languages, and these can- produce unexpected results. For example, in Spanish, `1.22`- gets rendered as `122`, and `et~al.` as `etal`.- One would think that babel's `shorthands=off` option (which- we were using) would disable these, but it doesn't. So we- remove `shorthands=off` and add some code that redefines- the shorthands macro. Eventually this will be fixed in babel,- I hope, and we can revert to something simpler.-- * JATS template: allow array of persistent institute ids in `pid`- (Albert Krewinkel).-- * Text.Pandoc.Parsing: minor code and efficiency improvements.-- * Text.Pandoc.Extension:-- + Add `Ext_sourcepos` constructor for `Extension` [API change].- + Add `Ext_xrefs_name` and `Ext_xrefs_number` constructors for- `Extension` (Nils Carson) [API change].-- * Text.Pandoc.Citeproc:-- + Fix truncation of `[Citation]` list in `Cite` inside footnotes (#6890).- This affected author-in-text citations in footnotes. It didn't cause- problems for the printed output, but for filters that expected the- citation id and other information.- + Allow the use of both inline and external references (#6951),- as with pandoc-citeproc. References defined in the document's- metadata take priority over references with the same id defined in- an external bibliography.- + Use `fetchItem` to get external bibliography (#6940).- + Ensure that BCP47 lang codes can be used. We ignore the variants- and just use the base lang code and country code when passing off- to citeproc.- + Citeproc BibTeX parser: revert change in `getRawField`- which was made (for reasons forgotten) when transferring- this code from pandoc-citeproc. The change led to `--` in- URLs being interpreted as en-dashes, which is unwanted (#6874).-- * Text.Pandoc.ImageSize:-- + Default to DPI 72 if the format specifies DPI of 0 (#6880).- This shouldn't happen, in general, but it can happen with- JPEGs that don't conform to the spec. Having a DPI of 0- will blow up size calculations (division by 0).- + ImageSize: use JuicyPixels to determine size for png, jpeg, and- gif, instead of doing our own binary parsing (#6936). This- gives more reliable results.-- * Text.Pandoc.CSS:-- + Remove `foldOrElse` (internal module) (Albert Krewinkel).-- * Use skylighting 0.10.2 (#6625).-- * Use citeproc 0.3. This fixes issues with references with- duplicate ids (jgm/citeproc#36).-- * Use doctemplates 0.9. This fixes issues with boolean- metadata values in the Markdown writer (#6388)- and in `meta-json` (#6650). It also fixes- issues with nested for loops in templates.-- * Add translations zh-Hans.yaml and zh-Hant.yaml (#6904, #6909,- Kolen Cheung, taotieren).-- * Add tests: True to cabal.project.- This fixes some CI failures for cabal.-- * Normalize test/tables/*.native (#6888, Kolen Cheung).-- * Move executable to `app` directory to avoid problems with cabal repl.-- * CONTRIBUTING: add section "How can I help?" (#6892, Albert Krewinkel).- Also adds a paragraph aimed at highlighting the importance of feature- maintenance.-- * MANUAL: Document that --number-sections works in `ms` (#6935).---## pandoc 2.11.2 (2020-11-19)-- * Default to using ATX (`##`-style) headings for Markdown output- (#6662, Aner Lucero). Previously we used Setext (underlined) headings- by default for levels 1--2.-- * Add option `--markdown-headings=atx|setext`, and deprecate- `--atx-headers` (#6662, Aner Lucero).-- * Support `markdown-headings` in defaults files.-- * Fix corner case in YAML metadata parsing (#6823). Previously YAML- metadata would sometimes not get recognized if a field ended with a- newline followed by spaces.-- * `--self-contained`: increase coverage (#6854).- Previously we only self-contained attributes for certain tag names- (`img`, `embed`, `video`, `input`, `audio`, `source`, `track`,- `section`). Now we self-contain any occurrence of `src`,- `data-src`, `poster`, or `data-background-image`, on any tag; and- also `href` on `link` tags.-- * Markdown reader:-- + Fix detection of locators following in-text citations.- Prevously, if we had `@foo [p. 33; @bar]`, the `p. 33` would be- incorrectly parsed as a prefix of `@bar` rather than a suffix of- `@foo`.- + Improve period suppression algorithm for citations in notes- in note citation styles (#6835).- + Don't increment `stateNoteNumber` for example list references.- This helps with #6836 (a bug in which example list references- disturb calculation of citation note number and affect when- `ibid` is triggered).-- * LaTeX reader:-- + Move `getNextNumber` from Readers.LaTeX to Readers.LaTeX.Parsing.- + Fix negative numbers in siunitx commands. A change in pandoc 2.11- broke negative numbers, e.g. `\SI{-33}{\celcius}` or `\num{-3}`.- This fixes the regression.-- * DocBook reader: drop period in formalpara title- and put it in a div with class `formalpara-title`, so that- people can reformat with filters (#6562).-- * Man reader: improve handling of `.IP` (#6858). We now better handle- `.IP` when it is used with non-bullet, non-numbered lists, creating a- definition list. We also skip blank lines like groff itself.-- * Bibtex reader: fall back on `en-US` if locale for LANG not found.- This reproduces earlier pandoc-citeproc behavior (jgm/citeproc#26).-- * JATS writer:-- + Wrap all tables (Albert Krewinkel).- All `<table>` elements are put inside `<table-wrap>` elements, as the- former are not valid as immediate child elements of `<body>`.- + Move Table handling to separate module (Albert Krewinkel).- Adds two new unexported modules:- Text.Pandoc.Writers.JATS.Types, Text.Pandoc.Writers.JATS.Table.-- * Org writer:-- + Replace org #+KEYWORDS with #+keywords (TEC).- As of ~2 years ago, lower case keywords became the standard (though- they are handled case insensitive, as always).- + Update org supported languages and identifiers according to the- current list contained in- <https://orgmode.org/worg/org-contrib/babel/languages/index.html>- (TEC).-- * Only use `filterIpynbOutput` if input format is ipynb (#6841).- Before this change content could go missing from divs with class- `output`, even when non-ipynb was being converted.-- * When checking reader/writer name, check base name now that we permit- extensions on formats other than markdown.-- * Text.Pandoc.PDF: Fix `changePathSeparators` for Windows (#6173).- Previously a path beginning with a drive, like `C:\foo\bar`, was- translated to `C:\/foo/bar`, which caused problems.- With this fix, the backslashes are removed.-- * Text.Pandoc.Logging:-- + Add constructor `ATXHeadingInLHS` to `LogMessage` [API change].- + Add constructor `EnvironmentVariableUndefined` to- `LogMessage` [API change].-- * Fix error that is given when people specify `doc` output (#6834,- gison93).-- * LaTeX template: add a `\break` after parbox in `CSLRightInline`.- This should fix spacing problems between entries with numeric styles.- Also fix number of params on `CSLReferences`.-- * reveal.js template: Put quotes around `controlsLayout`,- `controlsBackArrows`, and `display`, since these require strings.- Add `showSlideNumber`, `hashOneBasedIndex`, `pause`.-- * Use citeproc 0.2. This fixes a bug with title case around parentheses.-- * pandoc.cabal: remove 'static' flag.- This isn't really necessary and can be misleading (e.g. on macOS,- where a fully static build isn't possible). cabal's new option- `--enable-executable-static` does the same. On stack you can add- something like this to the options for your executable in package.yaml:-- ld-options: -static -pthread-- * Remove obsolete bibutils flag setting in `linux/make_artifacts.sh`.-- * Manual:-- + Correct `link-citation` -> `link-citations`.- + Add a sentence about `pagetitle` for HTML (#6843, Alex Toldaiev).-- * INSTALL.md: Remove references to `pandoc-citeproc` (#6857).-- * CONTRIBUTING: describe hlint and how it's used (#6840, Albert- Krewinkel).--## pandoc 2.11.1.1 (2020-11-07)-- * Citeproc: improve punctuation in in-text note citations (#6813).- Previously in-text note citations inside a footnote would sometimes have- the final period stripped, even if it was needed (e.g. on the end of- 'ibid').-- * Use citeproc 0.1.1.1. This improves the decision about when- to use `ibid` in cases where citations are used inside- a footnote (#6813).-- * Support `nocase` spans for `csljson` output.-- * Require latest commonmark, commonmark-extensions.- This fixes a bug with `autolink_bare_uris` and commonmark.-- * LaTeX reader: better handling of `\\` inside math in table cells (#6811).-- * DokuWiki writer: translate language names for code elements- and improve whitespace (#6807).-- * MediaWiki writer: use `syntaxhighlight` tag instead of deprecated- `source` for highlighted code (#6810). Also support `startFrom`- attribute and `numberLines`.-- * Lint code in PRs and when committing to master (#6790,- Albert Krewinkel).-- * doc/filters.md: describe technical details of filter invocations (#6815,- Albert Krewinkel).---## pandoc 2.11.1 (2020-11-03)-- * DocBook Reader: fix duplicate bibliography bug (#6773, Nils Carlson).-- * HTML reader:-- + Parse contents of iframes (#6770).- + Parse inline svg as image unless `raw_html` is set in the reader (in- which case the svg is passed through as raw HTML) (#6770).-- * LaTeX reader:-- + Fix bug parsing macro arguments (#6796). If `\cL` is- defined as `\mathcal{L}`, and `\til` as `\tilde{#1}`, then- `\til\cL` should expand to `\tilde{\mathcal{L}}`, but- pandoc was expanding it to `\tilde\mathcal{L}`. This is- fixed by parsing the arguments in "verbatim mode" when the- macro expands arguments at the point of use.- + Properly support optional (cite) argument for- `\blockquote` from `csquotes` (#6802).-- * LaTeX writer: Improved calculation of table column widths.- We now have LaTeX do the calculation, using `\tabcolsep`.- So we should now have accurate relative column widths no- matter what the text width. The default template has been modified to load- the calc package if tables are used.-- * HTML writer: Fix duplicate "class" attribute for table- rows (Andy Morris).-- * Text.Pandoc.Filter: allow shorter YAML representation of Citeproc- (Albert Krewinkel). The map-based YAML representation of filters expects- `type` and `path` fields. The path field had to be present for all filter- types, but is not used for citeproc filters. The field can now be omitted- when type is "citeproc", as described in the MANUAL.-- * Text.Pandoc.Error: Add `PandocBibliographyError` constructor- for `PandocError` [API change]. This ensures that bibliography parsing- errors generate messages that include the bibliography file name --- otherwise it can be quite mysterious where it is coming from.-- * Citeproc: properly handle `csl` field with `data:` URI (#6783).- This is used with the JATS writer, so this fixes a regression- in pandoc 2.11 with JATS output and citeproc.-- * Allow `citation-abbreviations` in defaults file.-- * JATS templates: ensure `jats_publishing` output is valid- (Albert Krewinkel).-- * LaTeX template: Fix `CSLRightInline`, so that it does not- run over the right margin.-- * HTML template: default CSS tweaks (Mauro Bieg and John- MacFarlane).-- - Fix margin before codeblock- - Add `monobackgroundcolor` variable, making the background color- and padding of code optional.- - Ensure that backgrounds from highlighting styles take precedence over- monobackgroundcolor- - Remove list markers from TOC- - Add margin-bottom where needed- - Remove italics from blockquote styling- - Change borders and spacing in tables to be more consistent with other- output formats- - Style h5, h6- - Set font-size for print media to 12pt.- - Reduce interline space.- - Reduce interparagraph space.- - Reduce line width.- - Remove the special `line-height: 1` for table cells.- - Remove the special line-height for pre.- - Ensure that there is a bit more space before a heading- than after.- - Slightly reduced space after title header.- - Add CSS example to MANUAL-- * man template: Change comment that triggers `tbl` from- `.\"t` to `'\" t`, as specified in groff_man(7) (#6803).-- * Use latest commonmark, commonmark-extensions.- This fixes a bug with nested blocks in footnotes with the- `footnote` extension to `commonmark`. See jgm/commonmark-hs#63.-- * Citeproc: use comma for in-text citations inside footnotes.- When an author-in-text citation like `@foo` occurs in a footnote,- we now render it with: `AUTHOR NAME + COMMA + SPACE + REST`.- Previously we rendered: `AUTHOR NAME + SPACE + "(" + REST + ")"`.- This gives better results. Note that normal citations are still- rendered in parentheses.-- * Use latest citeproc:-- + citeproc no longer capitalizes notes, so we do it- in pandoc when appropriate.- + Closes #6783.-- * Clarify manual on `--track-changes` (#6801).-- * Add `doc/jats.md` to document pandoc's handling of JATS- (#6794, Albert Krewinkel).-- * Fix code example in lua-filters.md (#6795).--## pandoc 2.11.0.4 (2020-10-21)-- * Commonmark writer: fix regression with fenced divs (#6768).- Starting with 2.10.1, fenced divs no longer render with- HTML div tags in commonmark output. This is a regression- due to our transition from cmark-gfm. This commit fixes it.-- * Use released version of citeproc. (This fixes a mis-step- in the 2.11.0.3 release, which is now deprecated.)-- * Use latest sylighting, with support for `groovy`.-- * Document that --html-q-tags requires the smart extension on the reader- (#6766).--## pandoc 2.11.0.3 (2020-10-20)-- * Use latest citeproc (closes #6765). This fixes a problem with- author-in-text citations for references including both an author- and an editor. Previously, both were included in the text, but only- the author should be.-- * With `--citeproc`, ensure that the final period is removed when- citations that occur in notes in note-based styles get put in- parentheses. See jgm/citeproc#20.-- * Normalize rewritten image paths with `--extract-media` (#6761).- This change will avoid mixed paths like this one when- `--extract-media` is used with a Word file:- ``. Instead we'll get- ``.-- * Modify `--version` output. Use space more efficiently and report the- citeproc and ipynb versions, along with skylighting, texmath, and- pandoc-types. Drop the word "default" before "user data directory."-- * DocBook reader: bibliomisc and anchor support (#6754, Nils Carlson).- Also ensure that bibliodiv without a title no longer results in- an empty Header.-- * ConTeXt template: adds `\setupinterlinespace` to fonts larger- than normal (#6763, Denis Maier).-- * LaTeX template: Do not load amssymb if not needed (#6469, Angelo Peronio).- See <https://tex.stackexchange.com/a/549938>.-- * Relax upper bound on hslua, allow hslua-1.3.* (Albert Krewinkel).-- * MANUAL:-- + Improve explanation of "indent" variable (#6767, Cyrus Yip).- + Remove org from list of input formats supporting raw_tex (#6753,- Nick Fleisher).---## pandoc 2.11.0.2 (2020-10-15)-- * Fix handling of `xdata` in bibtex/biblatex bibliographies (#6752).-- * Fix some small typos in the API documentation (#6751, Michael Hoffmann).-- * Require citeproc 0.1.0.2. This fixes a regression from pandoc-citeproc- involving spacing between components of a reference in certain styles- (e.g. `cell.csl`).-- * Fix typos in comments, doc strings, error messages, and tests- (Albert Krewinkel, #6738).--## pandoc 2.11.0.1 (2020-10-13)-- * LaTeX reader: support more acronym commands (#6746):- `\acl`, `\aclp`, and capitalized versions of already- supported commands.-- * Commonmark reader: add `pipe_table` extension *after* defaults (#6739).- Otherwise we get bad results for non-table, non-paragraph- lines containing pipe characters.-- * Markdown writer: Fix autolinks rendering for gfm (#6740).- Previously, autolinks rendered as raw HTML, due to the- `class="uri"` added by pandoc's markdown reader.-- * LaTeX writer:-- + Escape option values in lstlistings environment (#6742).- + Fix handling of `lang` `pt-BR` (#2953). For polyglossia we now- use `\setmainlanguage[variant=brazilian]{portuguese}` and for babel- `\usepackage[shorthands=off,main=brazilian]{babel}`.-- * Depend on latest citeproc (0.1.0.1).-- + This fixes the citation number issue with ieee.csl and other- styles that do not explicitly sort bibliographies (#6741). (Pandoc- was numbering them by their order in the bibliography file,- rather than the order cited, as required by the CSL spec.)- + Fixes groupin/collapsing with citation items with prefixes.-- * default.latex: fix `CSLReference` macro definition.-- * Fix MANUAL.txt CSL JSON conversion examples.-- * Fix spelling errors in changelog, MANUAL.txt, `doc/org.md` (#6738).---## pandoc 2.11 (2020-10-11)-- * Add `--citeproc` (`-C`) option to trigger built-in citation processing.- It is no longer necessary to use the external `pandoc-citeproc`- filter. `--citeproc` behaves like a filter and can be positioned- relative to other filters as they appear on the command line.-- The new built-in citation processing uses the citeproc library,- a reimplementation of CSL citation processing that fixes many- of the shortcomings of pandoc-citeproc. In general, citation- processing should work much the same as it did with pandoc-citeproc,- but with greater fidelity to CSL styles and better performance.- (The tests from the pandoc-citeproc package have been carried- over to pandoc.) The following differences should be noted:-- - At this point, only some of the writers (HTML, ms, LaTeX) properly- interpret CSL display styles. You should get decent output in- all formats (at least as good as with pandoc-citeproc), but- indentation and block-alignment may not be right.-- - pandoc-citeproc searches the `~/.csl` directory for `.csl`- styles. Pandoc instead searches the `csl` subdirectory of- the pandoc user data directory (e.g., `~/.pandoc/csl` or- `~/.local/share/pandoc/csl`). Users who already keep- CSL styles in `~/.csl` may find it convenient to add a- symlink.-- - Some of the bibliography formats supported by pandoc-citeproc (via- hs-bibutils) are no longer supported: Copac, EndNote,- ISI, MEDLINE, MODS, and RIS. If you use one of these formats,- you may use the `bibutils` utility to convert to BibLaTeX.- We now support only BibTeX, BibLaTeX, CSL JSON,- and pandoc's YAML/Markdown analogue of CSL JSON.-- - pandoc-citeproc would always retrieve the independent parent- of a dependent style by doing an HTTP request. pandoc will- now first seek the independent parent locally (in the resource- path or in the `csl` subdirectory of the pandoc user data- directory) before resorting to HTTP. In addition, you may- omit the `.csl` extension, e.g. `--csl zoology`.-- - Using the `--bibliography` option (or including- `bibliography` in YAML metadata) no longer triggers- citation processing implicitly: one must always use the- `--citeproc` option if citation processing is wanted.-- * Add `csljson` as and input and output format. This allows pandoc- to convert between `csljson` and other bibliography formats- (e.g. `-f csljson -t markdown -s` or `-f bibtex -t csljson`),- and to generate formatted versions of CSL JSON bibliographies- (e.g., `pandoc -f csljson --citeproc pl.json -o pl.pdf`).-- * Added `bibtex`, `biblatex` as input formats. This allows pandoc- to convert between BibLaTeX and BibTeX and other bibliography formats,- and to generated formatted versions of BibTeX/BibLaTeX bibliographies- (e.g., `pandoc -f biblatex --citeproc pl.bib -o pl.pdf`).-- * Raise informative errors when YAML metadata parsing fails (#6730).- Previously the command would succeed, returning empty metadata,- with no errors or warnings.-- * Sort languages in `--list-highlight-languages` output (#6718,- Albert Krewinkel). Languages were previously sorted by their- long name, which leads to unexpected results).-- * Add CSS to default HTML template (#6601, Mauro Bieg). This- greatly improves the default typography in pandoc's HTML- output. The CSS is sensitive to a number of variables- (e.g. `mainfont`, `fontsize`, `linestretch`): see the manual for- details. To restore the earlier, more spartan output, you can- disable this with `-M document-css=false`.-- * Support `--toc-depth` option for ODT writer (#6696, niszet).-- * Fix issues with Windows UNC paths with some options (#5127).-- * Remove `fenced_code_blocks` and `backtick_code_blocks` from allowed- `commonmark` and `gfm` extensions. These shouldn't really be counted- as extensions, because they can't be disabled in commonmark.- Adjust markdown writer to check for the commonmark variant in addition- to extensions.-- * Add these extensions to `gfm` and `commonmark`:- `fenced_code_blocks`, `backtick_code_blocks`, `fenced_code_attributes`.- These can't really be disabled in the reader, but they need to be enabled- in the writer or we just get indented code.-- * Make sure proper set of extensions is recognized for `commonmark_x`.-- * Allow `gfm_auto_identifiers`, `ascii_identifiers` extensions for `docx`.-- * Markdown reader:-- + Add `Maybe FilePath` parameter to `yamlToMeta` [API change].- + Export `yamlToRefs` [API change], a version of `yamlToMeta`- specialized to references.- + Set `citationNoteNum` accurately in citations.- + Revise abbreviation support. Don't insert a nonbreaking space after a- potential abbreviation if it comes right before a note or citation.- This causes problems for citeproc's moving of note citations.-- * LaTeX reader:-- + Support missing siunitx commands (#6658).- + Support `squared`, `cubed`, `tothe` in siunitx (#6657).- + Improved uncertainty handling in slunitx.- + Factored out siunitx stuff into separate unexposed module.- + Fix improper empty cell filtering (#6689, Christian Despres).- + Fix parsing of "show name" in `\newtheorem` (#6734).- Previously we were just treating it as a string and- ignoring accents and formatting.- + Prevent wrong nesting of `\multirow` and `\multicolumn` table- cells (#6603, Laurent P. René de Cotret).- + Table cell parser not consuming spaces correctly (#6596,- Laurent P. René de Cotret).- + Change `SIRange` to `SIrange` (#6617, Emerson Harkin).- + Allow blank lines inside `\author` (#6324).-- * DocBook reader:-- + Don't squelch space at end of emphasis and other inline elements;- instead, move it outside the element (#6719).- + Implement table cell alignment (#6698, Nils Carlson).- + Implement column span support for tables (#6492, Nils Carlson).- + Update list of block level tags (#6610).--- * JATS reader:-- + Don't squelch space at end of emphasis and other inline elements;- instead, move it outside the element (#6719).-- * RST reader:-- + Apply `.. class::` directly to following Header rather than creating- a surrounding Div (#6699).-- * Docx reader:-- + Allow empty dates in comments and tracked changes (#6726, Diego- Balseiro).-- * Markdown writer:-- + Be less aggressive about using quotes for YAML values,- allowing e.g. a quotation mark or bracket as long as it's not at the- beginning of the line.- + Use double quotes for YAML metadata (#6727).- + Sort YAML metadata keys in Markdown output case-insensitive.--- * Asciidoc writer:-- + Support asciidoctor's block figures (#6538, argent0).-- * LaTeX writer:-- + Fix spacing issue with list in definition list.- When a list occurs at the beginning of a definition list definition,- it can start on the same line as the label, which looks bad.- Fix that by starting such lists with an `\item[]`.-- * HTML writer:-- + Support intermediate table headers (#5314, Albert Krewinkel).- + Support attributes on all table elements (Albert Krewinkel).- + Render table footers if present (#6314, Albert Krewinkel).- + Fix addition of `doc-biblioentry` role.- + Support colspans and rowspans in HTML tables (#6312, Albert Krewinkel).-- * ICML writer:-- + Support internal document links (#5541, Leonard Rosenthol).- + Changed default link state to invisible (#6676, Leonard Rosenthol).-- * Docx writer:-- + Better handle list items whose contents are lists (#5948, Michael- Hoffmann). If the first element of a bulleted or ordered list is- another list, then that first item would previously disappear if the- target format is docx.- + Separate adjacent tables (#4315). Word combines adjacent tables,- so to prevent this we insert an empty paragraph between two- adjacent tables.-- * Org writer:-- + Don't force blank line after headings (#6554).-- * OpenDocument writer:-- + Implement table cell alignment (#6700 Nils Carson, Mauro Bieg).- + New table cell support with row and column spans (#6682, Nils Carson).- + Syntax highlighting for inline code (#6711, niszet).-- * Add Text.Pandoc.Citeproc module, exporting `processCitations`- [API change]. This depends on several other, unexported- modules under Text.Pandoc.Citeproc.-- * Add module Text.Pandoc.Writers.CslJson, exporting `writeCslJson`.- [API change]-- * Add module Text.Pandoc.Readers.CslJson, exporting `readCslJson`.- [API change]-- * Add module Text.Pandoc.Readers.BibTeX, exporting `readBibTeX` and- `readBibLaTeX`. [API change]-- * Text.Pandoc.Filter: Add `CiteprocFilter` constructor to Filter.- [API change] This runs the processCitations transformation.- We need to treat it like a filter so it can be placed- in the sequence of filter runs (after some, before others).- In FromYAML, this is parsed from `citeproc` or `{type: citeproc}`,- so this special filter may be specified either way in a defaults file- (or by `citeproc: true`, though this gives no control of positioning- relative to other filters).-- * Add new exported module Text.Pandoc.Writers.AnnotatedTable [API change]- (#6655, Christian Despres). This module (which should generally- be imported qualified to avoid name conflicts) provides a- `Table` type that mirrors the structure of a pandoc `Table`,- but with added inferred information so that the writers do not have to- lay out tables themselves. The `toTable` and `fromTable` functions convert- between an annotated `Table` and a regular pandoc `Table`. In addition to- producing a `Table` with coherent and well-formed annotations, the- `toTable` function also normalizes its input table like the table- builder does. Tests ensure that `toTable` normalizes tables exactly- like the table builder, and that its annotations are coherent.-- * Text.Pandoc.Logging:-- + Remove unused `CouldNotParseYamlMetadata` constructor for `LogMessage`- [API change].- + Add `CiteprocWarning` constructor to `LogMessage` [API change].-- * Text.Pandoc.Readers.Metadata: export `yamlBsToRefs` [API change].- These allow specifying an id filter so we parse only references- that are used in the document.-- * Text.Pandoc.Parsing:-- + Export ParseError [API change].- + Add `stateInNote` and `stateNoteNumber` to `ParserState`- [API change]. These are used to populate note numbers for citation- processing.-- * Fix apparent typos in sample.lua (#6729, William Lupton).- Also make the writer less aggressive in escaping quotes.-- * Text.Pandoc.Options:-- + `defaultMathJaxURL`: use `tex-chtml-full` instead of `tex-mml-chtml`- (#6599, Kolen Cheung). This drops the MathML support (which we- don't need for HTML math rendering) and includes the full JavaScript,- which makes it possible to use `--self-contained` (though there may- still be issues if the required math fonts aren't available). This- change should also reduce latency in pages with lots of formulas.- + Add `/tex-chtml-full.js` to `defaultMathJaxURL` (#6593) Previously we- added this in processing command line options, but not in processing- defaults files, which was inconsistent.-- * epub.css: Fix cover page selectors and add note explaining their use- (#6649, a-vrma).-- * Add data files needed for Text.Pandoc.Citeproc: these include- `default.csl` in the data directory and a `citeproc` directory that- is only used at compile-time for biblatex localizations. Note that we've- added `file-embed` as a mandatory rather than a conditional- dependency, because of the biblatex localization files.-- * Lua filters:-- + Add SimpleTable for backwards compatibility (#6575, Albert Krewinkel).- A new type `SimpleTable` is made available to Lua filters. It is- similar to the `Table` type in pandoc versions before 2.10;- conversion functions from and to the new Table type are provided.- Old filters using tables now require minimal changes and can use, e.g.,-- if PANDOC_VERSION > {2,10,1} then- pandoc.Table = pandoc.SimpleTable- end-- and-- function Table (tbl)- tbl = pandoc.utils.to_simple_table(tbl)- …- return pandoc.utils.from_simple_table(tbl)- end-- to work with the current pandoc version.-- + Make `attr` argument optional in `Table` constructor (Albert Krewinkel).- This changes the Lua API. It is highly unlikely for this change to affect- existing filters, since the documentation for the new Table constructor- (and type) was incomplete and partly wrong before. The Lua API is now- more consistent, as all constructors for elements with attributes now- take attributes as the last parameter.-- * MANUAL.txt:-- * Add a dedicated Citations section which consolidates the information- the manual used to contain about citation processing, and incorporates- some information formerly found in the pandoc-citeproc man page.- + Add note about lualatex using `selnolig`.- + Remove duplicate `seriespage` (#6568, Blake Eryx).- + Remove lists of support extensions for markdown variants (#6604).- Instead, offer the advice to use `--list-extensions=FORMAT`.- + Fix position of attributes in header (Albert Krewinkel).- + Delete obsolete section on compact and loose lists (#6684).--- * doc/lua-filters.md:-- + Add info on how to debug Lua filters (#6732, Ian Max Andolina).- + Document Underline type and constructor (Albert Krewinkel).- + Document `body` field (Albert Krewinkel).- + Add missing header attribute- + Add missing Link.title field (Albert Krewinkel).- + Make the setting-the-date example conditional (the-solipsist).- This makes the example a bit more realistic.- + Remove outdated link table example.-- * doc/org.md:-- + Add section on tables (Albert Krewinkel).- + Add section on handling of unknown directives (Albert Krewinkel).-- * CONTRIBUTING.md: fix typo (#6584, Dmitry Volodin).-- * Use golden test framework for command tests. This means that- `--accept` can be used to update expected output.-- * Use the `smart` extension when generating pandoc's man page (#6613).-- * Release-candidate: don't build windows i386.- So far we haven't been able to figure out how to get- stack to use a 32-bit ghc.-- * Use `null` instead of deprecated `Builder.isNull`.-- * Makefile:-- + Fix macospkg target to fetch target from S3 artifacts.- + Fix pandoc-templates target to include all partials.-- * Remove duplicated dependency in pandoc.cabal (#6591, Felix Yan).-- * Sort build depends in pandoc.cabal alphabetically (#6691,- Albert Krewinkel).-- * Add .travis.yml for macos release candidate build (#6622).- We need to build the release candidate on Travis rather- than GitHub actions, because GH has macos 10.15, and- binaries compiled on that OS will not work with 10.13.- This build is only triggered on `rc/*` branches.-- * Remove instructions for building pandoc-citeproc from CI and- release binary build instructions. We will no longer distribute- pandoc-citeproc.-- * Fix math rendering in trypandoc (this broke after- commit d8ad766d17603784b86fc5c2e1b22864125d04d1).-- * Use latest versions of skylighting, commonmark (#6589),- comonmark-extensions, commonmark-pandoc, texmath.-- * Relax version bounds for hslua, hslua-module-text, bytestring.-- * Use released pandoc-types 1.22. This changes the JSON- encoding slightly for the new table types introduced- in 1.21, so they're more consistent with the rest.- Developers of libraries for pandoc filters will want- to take note.-- * Fix hlint suggestions, update hlint.yaml (#6680, Christian Despres).-- * Code cleanup (#6678, Joseph C. Sible).-- * Add haddocks to functions in Text.Pandoc.Writers.Shared (Albert- Krewinkel).-- * Remove duplicate `tshow` definition.-- * Linux release candidate build: use ghc-musl container. This simplifies- our build process (over using a customized alpine container).---## pandoc 2.10.1 (2020-07-23)-- * Add `commonmark_x` output format. This is `commonmark` with a number- of useful pandoc extensions enabled.-- * Many more extensions now work with `commonmark` and `gfm`.-- * Add generic `attributes` extension. This allows attributes to- be added to any block or inline element in a uniform way. Since- the Pandoc AST doesn't include attributes on each element type,- the attributes will sometimes be added by creating a surrounding- Div or Span container. Currently this extension is only- compatible with the `commonmark` and `gfm` readers.-- To add an attribute to a block-level element, e.g. a paragraph,- put it before the block:- ```- {#mypara}- This is a paragraph.- ```- Multiple attributes may be used and will be combined:- ```- {#mypara}- {.blue .warning key="val"}- This is a paragraph.- ```- To add an attribute to an inline-level element, put it- immediately after the element:- ```- *emphasized text*{.special}- ```-- * Support `--number-sections` for docx output (#1413).-- * LaTeX reader:-- + Support `\SIRange` reader (#6418, Emerson Harkin).- + Support table col-span and row-span (#6311, Laurent P. René de Cotret).- Supports `\multirow` and `\multicolumn`.- + Support amsthm: `\newtheorem`, `\theoremstyle`, and theorem and- proof environments, including labels and references. The only thing- that is unsupported is the second optional argument, which causes- numbering to be reset after the specified series is incremented.- + Moved some code to T.P.LaTeX.Parsing. We need to reduce the size- of the LaTeX reader to ease compilation on resource-limited systems.-- * RST reader:-- + Fix csv tables with multiline cells (#6549).- + Fix spurious newlines in some attributes from directives.- + Avoid extra newline in included code blocks.-- * Commonmark reader:-- + Switch from cmark-gfm to commonmark-hs for commonmark and gfm- parsing. This avoids depending on a C library- and allows us to support more pandoc extensions for- `commonmark` and `gfm`.-- * DocBook reader:-- + Parse releaseinfo as metadata (#6542).-- * Docx reader:-- + Only use `bCs/iCs` on runs with `rtl` or `cs` property (#6514, Nikolay- Yakimov).- + Code cleanup/refactoring (Nikolay Yakimov).-- * Org reader (Albert Krewinkel):-- + Respect export setting which disables entities- MathML-like entities, e.g., `\alpha`, can be disabled with the- `#+OPTION: e:nil` export setting (Albert Krewinkel).- + Respect export setting disabling footnotes. Footnotes can be removed- from the final document with the `#+OPTION: f:nil` export setting.- + Respect tables-excluding export setting. Tables can be removed from- the final document with the `#+OPTION: |:nil` export setting.-- * Markdown writer:-- + Move `asciify` out of `escapeString`. Otherwise `unsmartify`- doesn't catch quotes that have already been turned to entities.- + Add `writeCommonmark` (new exported function, API change).- + Use unicode super/subscript characters when possible if the- `superscript` or `subscript` extension or `raw_html` aren't available.- + Render caption as following paragraph when `table_caption` extension- is not enabled.- + Use numerical labels for reference links that are longer- than 999 characters or contain square brackets, for conformity- with commonmark (#6560).-- * Commonmark writer:-- + Instead of using cmark-gfm, use `writeCommonmark` from the- Markdown writer. This function calls the markdown writer- with appropriate extensions and a few small modifications- (e.g. not requiring backslashes before spaces inside- super/subscripts). With this change `comonmark` and- `gfm` output can be used with a wider selection of- extensions.-- * Jira writer: keep image caption as alt attribute (#6529, Albert- Krewinkel).-- * HTML writer:-- + Improve alt-text/caption handling for HTML5 (#6491, Albert Krewinkel).- Screen readers read an image's `alt` attribute and the figure caption,- both of which come from the same source in pandoc. The figure caption is- hidden from screen readers with the `aria-hidden` attribute. This- improves accessibility. For HTML4, where `aria-hidden` is not allowed,- pandoc still uses an empty `alt` attribute to avoid duplicate contents.-- * Ms writer:-- + Fix code highlighting with blank lines. Previously blank lines- were simply omitted from highlighted code.- + Escape starting periods in ms writer code blocks (#6505, Michael- Hoffmann). If a line of ms code block output starts with a period (.),- it should be prepended by `\&` so that it is not interpreted as a roff- command.-- * Text.Pandoc.Extensions:-- + Add `raw_markdown` extension (which only affects `ipynb`- input).- + Trim down `githubMarkdownExtensions`.- Previously it included all of the following, which make- sense for the legacy `markdown_github` but not for `gfm`,- since they are part of base commonmark and thus- can't be turned off in `gfm`:-- - `Ext_all_symbols_escapable`- - `Ext_backtick_code_blocks`- - `Ext_fenced_code_blocks`- - `Ext_space_in_atx_header`- - `Ext_intraword_underscores`- - `Ext_lists_without_preceding_blankline`- - `Ext_shortcut_reference_links`-- These have been removed from `githubMarkdownExtensions`, though- they're still turned on for legacy `markdown_github`.- + Add `Ext_attributes` constructor for `Extension` [API change].-- * LaTeX template: use selnolig to selectively suppress ligatures with- lualatex (#6534).-- * Benchmark bytestring readers (Nikolay Yakimov).-- * Documentation:-- + Update using-the-pandoc-api.md (favonia).- + Fix Typos in lua-filters.md (tajmone).- + Rewrite Raw HTML/TeX section in MANUAL.txt to avoid duplicate- headings for the extensions.- + Fix typo in MANUAL.txt (Benjamin Wuethrich).- + Remove duplicate 'titlepage' in MANUAL.txt (Blake Eryx).- + CONTRIBUTING.md: Advertise the official nightlies in GitHub actions.- Replaces #6500, thanks to @ickc.----## pandoc 2.10 (2020-06-29)-- * Use pandoc-types 1.21. This adds two things:-- + A native Underline constructor for Inline (#6277, Vaibhav Sagar).- + More expressive types for tables (#1024, Christian Despres).- Tables can now take attributes; and rowspans and colspans,- column headers, multiple row headers, table head and foot- can all be represented. (Note, however, that reader and- writer support for these features is still lacking, so- most users won't see any differences in table conversion- yet. These changes just lay the foundation for further- improvements.)-- * Support new Underline element in readers and writers (#6277,- Vaibhav Sagar).-- * Support new Table type (Christian Despres).- The Builder.simpleTable now only adds a row to the TableHead- when the given header row is not null. This uncovered an- inconsistency in the readers: some would unconditionally- emit a header filled with empty cells, even if the header- was not present. Now every reader has the conditional- behaviour. Only the XWiki writer depended on the header row- being always present; it now pads its head as necessary.-- * Add an option to disable certificate validation (#6156, Cédric Couralet,- Cécile Chemin, Juliette Fourcot). This commit adds the option- `--no-check-certificate`, which disables certificate checking when- resources are fetched by HTTP.-- * Unify defaults and markdown metadata parsers (#6328, Nikolay- Yakimov). Clean up code in Text.Pandoc.Readers.Metadata and- properly handle errors in `yamlToMeta`. This fixes parsing- of Boolean fields in metadata withinin defaults files and reduces- code duplication.-- * Docbook reader:-- + Implement `<procedure>` (#6442, Mathieu Boespflug).- + Implement `<phrase>` (#6438, Mathieu Boespflug).- + Treat envar and systemitem like code (#6435, Mathieu Boespflug).- + Implement `<replaceable>` (#6437, Mathieu Boespflug)- + Map `<simplesect>` to unnumbered section (#6436, Mathieu Boespflug).-- * JATS reader:-- + Handle "label" element in section title (#6288).- + Parse abstract element into metadata field of same name- (#6480, Albert Krewinkel).-- * Jira reader (Albert Krewinkel):-- + Resolve multiple parsing problems, including issues with empty- table cells, faulty recognition of closing emphasis characters, and- parsing of image attributes (#6212, #6219, #6220).- + Two consecutive markup chars are now parsed verbatim (#6343);- styled text must not be empty.- + Newlines are no longer allowed within styled text (#6325).- + Links to anchors are now parsed as links (#6407).- + Retain image attributes (#6234). Jira images attributes as in- `!image.jpg|align=right!` are retained as key-value pairs. Thumbnail- images, such as `!example.gif|thumbnail!`, are marked by a- `thumbnail` class in their attributes.- + Use Underline for inserted text (#6237). Previously, the span was- marked with the non-standard class `inserted`.- + Improve icon conversion for `(/)`, `(x)`, `(!)`, `(?)`- `(+)`, `(-)`, `(off)`, `(*)`. (#6236, #6264).- + Support citations, attachment links, and user links (#6231, #6238,- #6239).- + Resolve parsing issues of blockquote, color (#6233, #6235).-- * HTML reader:-- + Parse attributes into table attributes.- + Support `<bdo>` (#5794, Tristan de Cacqueray).- + Add `summary` to list of block-level HTML tags (#6385).- This improves support for summary/details inside Markdown.- NOTE: you need to include a blank line before the closing- `</details>`, if you want the last part of the content to- be parsed as a paragraph.- + Fix parsing unclosed th elements in a table (#6247).-- * Commonmark reader: Implement `implicit_figures` extension (#6350).-- * Markdown Reader:-- + Fix inline code in lists (#6284, Nikolay Yakimov).- Previously inline code containing list markers was sometimes- parsed incorrectly.- + Don't require blank line after grid table (#6481).- This allows grid tables to be enclosed in fenced divs with no- intervening blank lines.-- * LaTeX reader:-- + Don't parse beyond `\end{document}` (#6380).- This required some internal changes to `\subfile` handling.- + Better handling of `\lettrine`. SmallCaps instead of Span- for the part after the initial capital. Ensure that both- arguments are parsed, so that in Markdown both- are treated as raw LateX. (Closes #6258.)-- * Org reader (Albert Krewinkel):-- + Recognize images with uppercase extensions (#6472).- + Keep unknown keyword lines as raw org. The lines of unknown- keywords, like `#+SOMEWORD: value` are no longer read as metadata,- but kept as raw `org` blocks. This ensures that more information- is retained when round-tripping org-mode files; additionally,- this change makes it possible to support non-standard org- extensions via filters.- + Unify keyword handling. Handling of export settings and other- keywords (like `#+LINK`) has been combined and unified.- + Support `LATEX_HEADER_EXTRA` and `HTML_HEAD_EXTRA`- settings. These export settings are treated like their non-extra- counterparts, i.e., the values are added to the `header-includes`- metadata list.- + Allow multiple `#+SUBTITLE` export settings. The values of all- lines are read as inlines and collected in the `subtitle`- metadata field.- + Read `#+INSTITUTE` values as text with markup. The value is- stored in the `institute` metadata field and used in the- default beamer presentation template.- + The behavior of the `#+AUTHOR` and `#+KEYWORD` export- settings has changed: Org now allows multiple such lines- and adds a space between the contents of each line. Pandoc- now always parses these settings as meta inlines; setting- values are no longer treated as comma-separated lists.- Note that a Lua filter can be used to restore the previous- behavior.- + Read description lines as inlines (#6485). `#+DESCRIPTION` lines- are now treated as text with markup. If multiple such- lines are given, then all lines are read and separated by soft- linebreaks.- + Honor tex export option (#4070). The `tex` export option can be set- with `#+OPTION: tex:nil` and allows three settings:- `t` (the default) causes LaTeX fragments to be parsed as TeX or added- as raw TeX. `nil` removes all LaTeX fragments from the document.- `verbatim` treats LaTeX as text.--- * RST reader:-- + Pass arbitrary attributes through in code blocks (#6465).- Exceptions: name (which becomes the id), class (which becomes the- classes), and number-lines (which is treated specially to fit- with pandoc highlighting).- + Handle `date::` directive (#6276).-- * Textile reader: support `pre.` for code blocks (#6454).-- * Ipynb reader:-- + Implement `raw_markdown` extension (#5408). Specifying- `-f ipynb+raw_markdown` will cause Markdown cells- to be represented as raw Markdown blocks, instead of being- parsed. This is not what you want when going from `ipynb`- to other formats, but it may be useful when going from `ipynb`- to Markdown or to `ipynb`, to avoid semantically insignificant- changes in the contents of the Markdown cells that might- otherwise be introduced.- + Handle application/pdf output as image (#6430).- + Properly handle image/svg+xml as an image (#6430).-- * Docx reader:-- + Distinguish between docx parsing and docx container unpacking errors.-- * MediaWiki reader:-- + Fix `gfm_auto_identifiers` so that `-` is not replaced by `_` (#6335).-- * Vimwiki reader:-- + Add nested syntax highlighting (#6256, Vlad Hanciuta).- Nested syntaxes are specified like this:- ```- {{{sql- SELECT * FROM table- }}}- ```- The preformatted code block parser has been extended to check if the- first attribute of the block is not a `key=value` pair, and in that- case it will be considered as a class.--- * Jira writer (Albert Krewinkel):-- + Always escape braces (#6478). Braces are now always escaped, even- within words or when surrounded by whitespace. Jira and- Confluence treat braces specially.- + Convert Underline to inserted text (`+inserted+`).- + Add image attributes (#6234). Image attributes are added- to the output as image parameters. If the image has a- class "thumbnail", then a thumbnail image is generated;- all other attributes are discarded in this case.-- * LaTeX writer:-- + Ensure that `-M csquotes` works even in fragment mode (#6265).- + Escape `^` specially for listings (#6460).- + Create hypertarget for links with identifier (#6360).- + Distinguish between single and double quotes when using enquote- package (#6457, dbecher-ito).- + Add support for customizable alignment of columns in beamer (#6331,- andrebauer).- + Add support for customizable alignment of columns in beamer- (#4805, #4150, andrebauer).-- * HTML writer:-- + Use CSS in favor of `<br>` for display math (#6372)- Some CSS to ensure that display math is- displayed centered and on a new line is now included- in the default HTML-based templates; this may be- overridden if the user wants a different behavior.-- * Org writer:-- + Clean-up Div handling (Albert Krewinkel).-- * Docx writer:-- + Enable column and row bands for tables (#6371).- This change will not have any effect with the default style.- However, it enables users to use a style (via a reference.docx)- that turns on row and/or column bands.-- * OpenDocument (and ODT) writer:-- + Add custom-style "Abstract" in metadata abstract.- This ensures that the abstract is rendered with style Abstract.- + Enable custom-style attribute on a Div.- This allows you to apply a custom style to contained paragraphs.-- * DocBook writer:-- + Add id of figure to enclosed image.- + Add personname element to docbook author (#6244).-- * FB2 writer:-- + Properly handle cover-image containing spaces (#6391).-- * Markdown writer:-- + Ensure consistent padding for pipe tables (#6240).- + Avoid unnecessary escapes before intraword `_` when- `intraword_underscores` extension is enabled (#6296).-- * RST writer:-- + Properly handle images with same alt text (#6194).- Previously we created duplicate references for these in rendering RST.-- * AsciiDoc writer:-- + Add blank line after Div (#6308).-- * Haddock Writer:-- + Support Haddock tables (Joe Hermaszewski).- See this PR on Haddock for details on the table format:- <https://github.com/haskell/haddock/pull/718>.-- * PowerPoint writer (Jesse Rosenthal):-- + Write math input verbatim in speaker notes (#6301).- OMML in speaker notes would lead to corrupt PowerPoint output. We now- output the OMML verbatim as LaTeX in the speaker notes.-- * LaTeX template: Make polyglossia package options list-aware- (#6444, Frederik Elwert).-- * Reveal.js template:-- + Update template for reveal.js 4.0.0 (#6390, Salim B).- + Update template with newly available options (#6347, Jake Zimmerman).- + Use CDN version of revealjs v4 by default (#6408).-- * opendocument template: Add abstract and subtitle to opendocument- template (#6369).-- * reference.odt: clean up styles. Add Abstract.- Change Author, Date to centered paragraphs with no character- styling.-- * epub.css: wrap overlong lines in highlighted code blocks (#6242).- This fixes a problem in iBooks v2.4 with our earlier- horizontally scrolling code blocks. The problem seems to- be a bug in iBooks, not pandoc, but since iBooks is a major- target we're changing pandoc's default behavior so that- pandoc-produced epubs work on that platform.-- * Text.Pandoc.PDF:-- + Use `--enable-local-file-access` in invoking `wkhtmltopdf` (#6474).- `wkhtmltopdf` changed in recent versions to require this for- access to local files. This fixes PDF via HTML5 with `--css`.- + Send verbose output to stderr, not stdout (#6483).-- * Text.Pandoc.MIME: Fix MIME type for TrueType fonts in EPUBs- (#6464, Michael Reed).-- * Text.Pandoc.Shared:-- + `makeSections`: omit number attribute when unnumbered class- is present (#6339). Previously the attribute was included but given- an empty value, and this caused the table of contents creation- functions in Text.Pandoc.Writers.Shared to think these items had- numbers, which meant that they were included in the TOC even if the- `unlisted` class was used.- + Deprecate `underlineSpan` in Shared in favor of- `Text.Pandoc.Builder.underline` (Vaibhav Sagar).- + `renderTags'`: use self-closing tag for col element (#6295).-- * Text.Pandoc.UUID: Fix `getRandomUUID`, which previously would- return the same value twice in a row. Make `getRandomUUID`- polymorphic in PandocMonad. Remove `getUUID` (#6228, Joseph C. Sible).-- * Text.Pandoc.Class: Generalize `PandocIO` functions to `MonadIO`.-- * Fixed Katex standalone script (#6399, Lucas Escot).- Global macros are now persistent when using the HTML Writer with the- `--katex` option.-- * Lua subsystem (Albert Krewinkel):-- + Use new type PandocLua for all pandoc Lua operations (API change).- The new type `PandocLua` is an instance of the `PandocMonad` typeclass- and can thus be used in a way similar to `PandocIO`.- + Use PandocError for exceptions in Lua subsystem (API change).- The PandocError type is used throughout the Lua subsystem. All Lua- functions throw an exception of this type if an error occurs. The- `LuaException` type is removed and no longer exported from- `Text.Pandoc.Lua`. In its place, a new constructor `PandocLuaError`- is added to PandocError.-- * Lua filters: improve error messages for failing filters (#6332,- Albert Krewinkel). Print the Lua error properly instead of- displaying their `show` string.-- * Use latest skylighting. This fixes a bug with lua multiline- comments (and may improve handling of other syntaxes as well).- IT also adds `aria-hidden="true"` to the empty a elements, which- helps people who use screen readers.-- * Use latest texmath.-- * Require latest doctemplates 0.8.2.- This adds support for template pipes `first`, `rest`,- `last`, `allbutlast`.-- * Revert 0e48a02 and dependency on base-noprelude, which hasn't- been updated for ghc 8.10 (see #6187).-- * Dependency adjustments:-- + Allow haddock-library 1.9.x.- + Allow hslua 1.1 (#6243, Felix Yan).- + Allow base64-bytestring 1.1.- + Use latest jira-wiki-markup.- + Allow http-client 0.7.- + Allow tasty 1.3.x.- + Allow aeson 1.5 (#6400, Felix Yan).- + Remove unused dependency `vector` (#6462, Laurent P. René de Cotret).- + Bump QuickCheck upper bound.-- * Significant code cleanup and simplification (Joseph C. Sible, #6223,- #6209, #6225, #6229, #6226, #6340).-- * Remove unnecessary hlint ignores (#6341, Joseph C. Sible).-- * Remove obsolete RelaxedPolyRec extension (#6487, Nikolay Yakimov).-- * trypandoc improvements (Mike Tzou):-- + Add standalone option to the command text (#6210).- + Update third party libraries.-- * MANUAL.txt:-- + Clarify template partial naming (#6476, Mauro Bieg).- + Describe `jira` as "Jira/Confluence wiki markup" (#6351, Albert- Krewinkel). In the past, Jira's wiki markup was also used by -- and- could be imported into -- Atlassian Confluence.- + Add link to print-css.rocks (#6272, Mauro Bieg).- + Clarify pipe table column width adjustment (#6254).- + Fix ATX header syntax.- + Fix misleading note about image size conversions (#6353).- + Update links to reveal.js documentation (#6386, Salim B).- + Separate adjacent verbatim code blocks (#6307, tom-audm).-- * org.md:-- + Document behavior of `smart` extension (#4387, Albert Krewinkel).- + Describe all supported export options in detail.-- * lua-filters.md:-- + Fix description of BulletList Lua type (Levi Gruspe).- + Use pandoc.system module in TikZ example (Albert- Krewinkel). Showcase temporary directory handling with- `with_temporary_directory` and `with_working_directory`.-- * INSTALL.md: fix FreeBSD port link (#6422, Mo).- The FreeBSD port was renamed from pandoc to hs-pandoc in 2010.- The old pandoc port is still at version 1.5.1.1-- * Propagate `(DY)LD_LIBRARY_PATH` in tests (#6376, Lila).-- * Bump `cabal-version` to 2.2 (#6377).-- * Make it possible to compile using Stack on NixOS (#6439, Mathieu- Boespflug).-- * CI action to check for commit message length (Nikolay Yakimov, #6398).---## pandoc 2.9.2.1 (2020-03-23)-- * Markdown reader: Fix table alignment when heading begins with t (#6153).- Due to a typo (`t` instead of `\t`) we were center aligning column- headings that begin with a lowercase `t`!-- * Text.Pandoc.Readers.Roff:-- + Fix parsing of `\.` in man/ms readers (#6175).- Previously due to a typo it was being parsed as `` ` ``.- + Fix parsing of `\'` in man/ms readers (#6175). It was being parsed- as a backtick.-- * Jira reader (Albert Krewinkel):-- + Fix parsing of tables without preceding blankline (#6198).- A bug was fixed which caused faulty parsing if a table was not- preceded by a newline and the first table cell had no space- after the initial `|` characters.- + Fix parsing of strikeout, emphasis (#6196). A bug was fixed which- caused non-emphasized text containing digits and/or non-special- symbols (like dots) to sometimes be parsed incorrectly.- + Support colored inline text, indented lists (#6183, #6184).-- * Ms writer:-- + Fix definition lists so indent even when paragraph indent is- set to 0 (as is the default). Also ensure indent for display math- that falls back to TeX.- + Use `.QS/.QE` instead of `.RS/.RE` for block quotes.-- * EPUB writer: fix regression on detection of front/back/bodymatter- (#6170). This bug caused sections with epub:type `dedication` to be- misplaced in bodymatter instead of frontmatter as specified- in the manual. The same problem would affect other epub:types.- The pattern matching needed to be changed with the use of- `makeSection`.-- * AsciiDoc writer: remove redundant `otherwise` guard in- `inlineToAsciiDoc` (#6146, Ryan Scott).-- * Text.Pandoc.Class:-- + Fix missing import when data files are not embedded (Albert Krewinkel).- + Subdivide Text.Pandoc.Class into small unexported modules- and ensure that all functions have Haddock documentation (#6106,- Albert Krewinkel).- + Finer grained imports of Text.Pandoc.Class submodules (#6203, Albert- Krewinkel).-- * Text.Pandoc.XML: Add to list of HTML5 attributes:- `allow`, `autocapitalize`, `decoding`, `enterkeyhint`,- `imagesizes`, `imagesrcset`, `loading`.-- * Use implicit Prelude (#6187, Albert Krewinkel).- The previous behavior was introduced as a fix for #4464. It seems that- this change alone did not fix the issue, and `stack ghci` and `cabal- repl` only work with GHC 8.4.1 or newer, as no custom Prelude is loaded- for these versions. Given this, it seems cleaner to revert to the- implicit Prelude.-- * Always use custom prelude (#6187, Albert Krewinkel).- Previously, the custom prelude was used only with older GHC versions, as- a workaround for problems with ghci. The ghci problems are resolved by- replacing package `base` with `base-noprelude`, allowing for consistent- use of the custom prelude across all GHC versions.-- * Remove outdated checks for no longer supported base versions- (Albert Krewinkel).-- * PDF via wkhtmltopdf: put user-specified options last (#6171).- Certain options (e.g. `cover`) need to come after flags on- the command line.-- * Text.Pandoc.App: set resource path at the beginning so it can affect- things like include-in-header (#5982).-- * Change macOS release candidate CI process so that notarized- packages can be produced (#6169).-- * Make MANUAL more explicit about nonbreaking space handling by- `all_symbols_escapable` (#6154, Fabien Schurter).-- * trypandoc (Mike Tzou):-- + Add checkbox for standalone option (#6189).- + Use strict mode for JavaScript code (#6188).- + Fetch resources over https (#6188).- + Remove unnecessary attributes on style, script elements (#6188).-- * Use details tag to make GitHub releases changelog collapsible.-- * Update filter code in doc/filters.md so it works with latest pandoc- (#6185).-- * linux/Dockerfile: upgrade to alpine 3.11 (#6180, Albert Krewinkel).- This is used to build the static linux binaries.---## pandoc 2.9.2 (2020-02-15)-- * Add `csv` as an input format (#6100). The CSV table is converted into a- pandoc simple table. A new module Text.Pandoc.Readers.CSV- exports `readCSV` [API change].-- * Introduce new format variants for JATS writer (#6014, Albert Krewinkel):-- - `jats_archiving` for the "Archiving and Interchange Tag Set",- - `jats_publishing` for the "Journal Publishing Tag Set", and- - `jats_articleauthoring` for the "Article Authoring Tag Set."-- The `jats` output format is now an alias for `jats_archiving`.- The module Text.Pandoc.Writers.JATS now exports- `writeJatsArchiving`, `writeJatsPublishing`, and- `writeJatsArticleAuthoring`, as well as the legacy- `writeJATS` [API change].-- * `--defaults`: Support `bibliography` and `csl` fields.- Move `addMeta` from Text.Pandoc.App.CommandLineOptions to- Text.Pandoc.App.Opt (internal change).-- * Add timing info for filters in `--verbose` mode (#6112).- When verbose mode is specified (verbosity == INFO), print a- notice when running a filter and when a filter completes (including- timing).-- * LaTeX reader:-- + Allow `&` in LaTeX citation keys (#6110).- + Improve caption and label parsing.- + Don't emit empty Span elements for labels.- + Put tables with labels in a surrounding Div.- + Resolve `\ref` to table numbers (#6137).- + Skip comments in more places where this is needed (#6114).- + Allow beamer overlays for all commands in all raw tex (#6043).- This affects parsing of raw tex in LaTeX and in Markdown and- other formats.- + Improve parsing of raw environments (#6034). If parsing fails- in a raw environment (e.g. due to special characters like unescaped- `_`), try again as a verbatim environment, which is less sensitive to- special characters. This allows us to capture special environments- that change catcodes as raw tex when `-f latex+raw_tex` is used.-- * RST reader:-- + Add highlight directive (#6140, Lucas Escot).-- * MediaWiki writer:-- + Prevent triple `[[[` which confuses MediaWiki (#6119).-- * HTML reader:-- + Don't parse `data-id` as `id` attribute. And similarly don't- parse any `data-X` as `X` when `X` is a valid HTML attribute.-- * Org reader:-- + Simplify parsing of sub- and superscripts (#6127, Albert Krewinkel).- Speeds up parsing of single-word, markup-less sub- and superscripts.-- * LaTeX writer:-- + Group biblatex citations even with prefix and suffix (#5849, Ethan- Riley). Previously biblatex citations were only grouped if there- was no prefix. This patch allows them to be grouped in subgroups split- by prefixes and suffixes, which allows better citation sorting.- + Fix regression in handling of columns in beamer slides (#6033).- Columns in title slides were causing problems with- slide division.- + Fix duplicate frame classes in LaTeX/Beamer output (#6107).-- * HTML writer:-- + Fix duplicate attributes on headings (#6062), regression from 2.7.x.- + Fix `--number-offset` with HTML TOC. Eventually it would be worth- adding a parameter to `makeSections` so this could be done at that- level; then it would also affect other writers that construct- TOC manually.- + reveal.js: restore old behavior for 2D nesting (#6032).- The fix to #6030 actually changed behavior, so that the- 2D nesting occurred at slide level N-1 and N, instead of- at the top-level section. This commit restores the v2.7.3 behavior.- If there are more than 2 levels, the top level is horizontal- and the rest are collapsed to vertical.- + reveal.js: ensure that pauses work even in title slides (#5819).-- * Markdown writer:-- + Fix regression: spurious dots in markdown_mmd metadata output (#6133).-- * Docx writer:-- + Fix regression with Compact style on tight lists (#6072).- Starting in 2.8, the docx writer no longer distinguishes between tight- and loose lists, since the Compact style is omitted. This is a- side-effect of the fix to #5670, as explained in the changelog. This- patch fixes the problem by extending the exception currently offered to- Plain blocks inside tables to Plain blocks inside list items.-- * Jira writer:-- + Fix output of table headers (Albert Krewinkel, #6035).-- * Add Text.Pandoc.Image with unexported svgToPng.-- * Text.Pandoc.XML: Export `html5Attributes`, `html4Attributes`,- `rdfaAttributes` (formerly unexported in Text.Pandoc.Writers.HTML).- [API change]-- * Text.Pandoc.Shared: Export a new function `findM` (#6125,- Joseph C. Sible).-- * Text.Pandoc.Logging: Add `RunningFilter`, `FilterCompleted`- constructors to LogMessage [API change].-- * Text.Pandoc.CSV: fix bug in CSV parser; previously an extra blank record- would sometimes be inserted at the end.-- * LaTeX template: add space option to xeCJK with PassOptionsToPackage- (#6002). Otherwise we can get a clash with documentclasses that- already load the package.-- * Lua filters:-- + Allow filtering of element lists (#6038, Albert Krewinkel). Lists of- Inline and Block elements can now be filtered via `Inlines` and- `Blocks` functions, respectively. This is helpful if a filter- conversion depends on the order of elements rather than a single- element. For example, the following filter can be used to remove all- spaces before a citation:-- function isSpaceBeforeCite (spc, cite)- return spc and spc.t == 'Space'- and cite and cite.t == 'Cite'- end-- function Inlines (inlines)- for i = #inlines-1,1,-1 do- if isSpaceBeforeCite(inlines[i], inlines[i+1]) then- inlines:remove(i)- end- end- return inlines- end-- + Add methods `insert`, `remove`, and `sort` to pandoc.List- (Albert Krewinkel). Example of use:-- local numbers = pandoc.List {2, 3, 1}- numbers:sort() -- numbers is now {1, 2, 3}- + Make `pandoc.List` a callable constructor (Albert Krewinkel).- It is now possible to construct a new List via- `pandoc.List()` instead of `pandoc.List:new()`.- + Add tests for pandoc.List module (Albert Krewinkel).-- * Text.Pandoc.App.CommandLineOptions: Change `setVariable` to use `Text`- instead of `String`. This avoids some unnecessary unpacking.-- * Use versioned directory for windows release zipfile.- Also remove old `make-windows-installer.bat`, superseded by GitHub- actions workflow, and modify `pandoc.wxs` for new paths.-- * Extensive code cleanup (#6141, #6128, #6129, #6130, #6123,- #6105, 6102, #6117, #6124, #6115, #6116, #6111, Joseph C. Sible).-- * Fix hlint warnings (Albert Krewinkel).-- * Use latest doclayout, doctemplates (#6031). The new version of- doclayout fixes a memory leak that affected `--include-in-header` with- large files (and possibly other cases involving extremely long lines).-- * Use latest texmath.-- * Use latest skylighting and fix test suite (#6086).-- * sample.lua: Fix typo in descriptive comments (#6136, Caleb Maclennan).- Fix typo in error message (#6135).-- * Add Docker and GH Actions instructions/links to INSTALL.md.-- * Update filter documentation (#6065). Improve cabal v2 instructions.- Remove example using pandoc API directly (we have other- docs for that and it was outdated).-- * Lua filter docs:-- + Cross-link constructors and types (Albert Krewinkel).- Thanks to @bpj for the idea.- + Sort pandoc.List methods alphabetically (Albert Krewinkel).- + Unify, fix anchors and internal links (#6061, Albert Krewinkel).- Links and anchors now follow consistent conventions, like- lowercase-only anchor names. This breaks some links to specific- sections in the document, but will make it much easier to link- documentation in the future.- + Clarify filter function execution order (#6059, Albert Krewinkel).-- * In docs, update URLs and use `https:` wherever possible (#6090,- Salim B).--## pandoc 2.9.1.1 (2020-01-05)-- * Markdown reader:-- + Fix parsing bug affected indented code after raw HTML (#6009, #5360).-- * LaTeX writer:-- + Fix regression in beamer slide structure with certain slide levels- (#6030).- + Allow framebreaks for beamer's TOC (Heiko Schlittermann, #6012)- + Properly handle unnumbered headings level 4+ (#6018).- Previously the `\paragraph` command was used instead of- `\paragraph*` for unnumbered level 4 headings.-- * HTML writer:-- + Fix revealjs slide structure regression with certain slide levels- (#6030).- + Add newlines to make slide show output more readable.-- * Org writer:-- + Remove extra spaces from table cells (Albert Krewinkel, #6024).-- * JATS template: Update JATS dtd (Arfon Smith, #6020). Use the archiving- and interchange DTD rather than the more restrictive journal publishing- DTD (which doesn't permit ext-link as a valid child).-- * Text.Pandoc.PDF: Fix `runTeXProgram` so that the input source is always- overwritten (#6027). Previously it wasn't overridden if the file already- existed, which led to bad results on subsequent runs when- `pdf-engine-opt=-output-directory=` was used to specify an explicit temp- dir.-- * Text.Pandoc.BCP47: Change `getLang` to handle block-level contents- (#6008). Some readers (e.g. RST) will populate the `lang` metadata field- with block-level content. `getLang` has been modified to handle this.- Previously in these cases the LaTeX writer would not properly set the- "main language" of the document.-- * Fix `test/tables.org` (Albert Krewinkel).-- * Use HTTPS in copyright message (Felix Yan, #6010)---## pandoc 2.9.1 (2019-12-23)-- * Add Jira reader (Albert Krewinkel, #5556).-- * Jira writer: use jira-wiki-markup renderer (Albert Krewinkel,- #5926). The following improvements are included in this change:-- + non-jira raw blocks are fully discarded instead of showing- as blank lines;- + table cells can contain multiple blocks;- + unnecessary blank lines are removed from the output;- + markup chars within words are properly surrounded by- braces;- + preserving soft linebreaks via `--wrap=preserve` is- supported.-- Note that backslashes are rendered as HTML entities, as there- appears no alternative to produce a plain backslash if it is- followed by markup. This may cause problems when used with- confluence, where rendering seems to fail in this case.-- * Fix regression with `--number-sections`. Starting with 2.8,- `--number-sections` also had the effect of `--section-divs`,- even if `--section-divs` was not specified.-- * Improved table of contents generation in markdown, RTF,- commonmark, better handling cases where section headings are- enclosed in divs.-- * Ensure that later default file values for `variable` replace- earlier ones (5988).-- * HTML reader: Add `nav` to list of block-level tags.-- * Org reader (Albert Krewinkel):-- + Wrap named table in Div, using name as id (#5984).- Tables which are given a name via `#+NAME:` or `#+LABEL:`- are wrapped in an additional Div, with the name set as the- Div's ID.- + Report parsing errors properly.- + Fix parsing problem for colons in headline (#5993).-- * Text.Pandoc.PDF: Ensure UTF8 when printing source in- `--verbose` mode, avoiding an error on platforms that- default to something other than UTF-8 (#5997).-- * Text.Pandoc.Templates: Strip directory before trying to find- partial in data files (#5987).-- * Text.Pandoc.Shared: Improve `makeSections` so we don't get- doubled "number" attributes in EPUB output (or anywhere- else) (#5986).-- * Added tests for `--toc` and `--section-divs`.-- * Text.Pandoc.MIME: Added glsl MIME type for WebGL maps (#6000,- Jared Lander).-- * MANUAL: A bit clearer explanation for `--base-header-level`.- We now say exactly how to translate between the deprecated- `--base-header-level` and `--shift-heading-level-by`.-- * lua-filters.md:-- + Remove spurious dot in title (#5996, Mauro Bieg).- + Replace metadata example with image centering (#6004,- Albert Krewinkel). Thanks to @efx for proposing this filter.---## pandoc 2.9 (2019-12-11)-- * Text.Pandoc.Templates [API change]-- + Add Monad wrappers `WithDefaultPartials` and `WithPartials`.- Wrapping these around an instance of `PandocMonad` gives- us different instances of `TemplateMonad`, with different- search behavior in retrieving partials.- To compile a template and limit partial search to pandoc's- data files, use `runWithDefaultPartials (compileTemplate ...)`.- To compile a template and allow partials to be found locally- (either on the file system or via HTTP, in the event that- the main template has an absolute URL), ue- `runWithPartials (compileTemplate ...)`.- + Export `getTemplate`, which seeks a template locally,- or via HTTP if the template has an absolute URL, falling- back to the data files if not found.- + Export `compileDefaultTemplate` -- does `getDefaultTemplate`- and compiles the result, raising an error on failure.-- * Text.Pandoc.Class [API change]-- + Remove `TemplateMonad` instances for `PandocIO` and `PandocPure`.- These were too limiting and caused a bug whereby a local- partial could be used even when the default template was requested.- We now rely on instances provided in the Templates module.-- * Text.Pandoc.App.OutputSettings: Simplify template retrieval code.-- * ConTeXt template: Adjust to title formatting (#5949, Denis Maier).- Add `\setupinterlinespace` to `title`, `subtitle`, `date` and `author`- elements: otherwise longer titles that run over multiple lines will look- squashed as `\tfd` etc. won't adapt the line spacing to the font size.-- * reveal.js template: Add title-slide-attributes variable (#5981,- Frederik Elwert).-- * More informative JSON parse error (#5973).-- * Use external emojis package (forked from pandoc). Removed emoji data- in Text.Pandoc.Emoji.-- * Fix regression in `makeSections` (#5965).- Previously `hierarchicalize` (the ancestor of `makeSections`) would put- header attributes on the containing Div. In 2.8 this behavior changed,- which broke some tools depending on pandoc. Here we roll back this change,- so that attributes again migrate from the header to the containing Div when- `makeSections` is run. Note that attributes are retained on the header as- well (unlike before) -- with the exception of the `id` attribute, which of- course cannot be duplicated.-- * Fix `--toc-depth` regression in 2.8 (#5967).-- * Use doctemplates 0.8. Rename template 'filters' as 'pipes'- to avoid confusion with the other notion of filter used by pandoc.-- * Fix README.md so that relative links from manual become absolute.- Previously they'd be broken links when viewed on GitHub or Hackage.- So we add the base URL for the pandoc manual.-- * Document display math syntax in manual.--## pandoc 2.8.1 (2019-12-05)-- * Add `ascii_identifiers` as a supported extension for `markdown`.- This fixes a regression in 2.8.-- * Fix regression with behavior of `--variable` (#5962).- Previously `-Vfoo=1 -Vfoo=2` would produce a list value for foo;- with 2.8 it produced just `2`. This commit restores the earlier- behavior.-- * Roll back part of of `--shift-heading-level-by` change (#5957).- With positive heading shifts, starting in 2.8 this option- caused metadata titles to be removed and changed to regular- headings. This behavior is incompatible with the old- behavior of `--base-header-level` and breaks old workflows,- so we have rolled back the change. Note that there is now an- asymmetry in positive and negative heading level shifts:- With positive shifts, the metadata title stays the same and- does not get changed to a heading in the body, while with- negative shifts, a heading can be converted into the- metadata title.-- * Text.Pandoc.Shared: Fix `makeSections` so it doesn't turn- column Divs into sections.-- * HTML writer: add task-list class to ul if all elements are- task list items. This will allow styling unordered task- lists in a way that omits the bullet.-- * HTML-based templates: Add CSS to suppress bullet on unordered task lists.-- * ConTeXt template: Fix `\startcslreferences` and use ConTeXt syntax- conventions (#5945, Denis Maier). The old version had a too large- a skip at the beginning of the reference list.-- * LaTeX template: keep the `\author{}` command even if author is not- specified (#5961, Yihui Xie). Avoids a LaTeX warning.-- * Generate Emoji module with TH.-- + Add Text.Pandoc.Emoji.TH.- + Replace long literal list in Text.Pandoc.Emoji with one-liner- generating it from `emoji.json` using TH.- + Add Makefile target to download `emoji.json`.- + Remove `tools/emoji.hs`.-- * Increase GC allocation space for compilation in cabal.project.-- * Clean up manual on PDF generation backend options (#5940).-- * Update release checklist to include code signing step and update- Windows release-candidate builds (#5950).---## pandoc 2.8.0.1 (2019-11-26)-- * List `pdf` in `--list-output-formats`.- * EPUB writer: Fix regression with `--css` (#5937). In 2.8 `--css`- would not have an effect on EPUB output.- * RST writer: Use grid tables for one-column tables, since- simple tables clash with heading syntax in this case (#5936).- * Add unexported module Text.Pandoc.Readers.Metadata (see #5914).- * Use doctemplates 0.7.2, which adds the `nowrap` filter to- templates.- * Update default man template using `nowrap` for .TH heading (#5929).- * HTML templates: Add support for `toc-title` variable (#5930,- Alexandre Franke).- * Remove `grffile` (LaTeX package) requirement in MANUAL.txt- (#5927, Ian Max Andolina).- * Use skylighting 0.8.3.--## pandoc 2.8 (2019-11-22)-- * Improvements in templates system (from doctemplates):-- + Pandoc templates now support a number of new features that- have been added in doctemplates: notably, `elseif`, `it`,- partials, filters, and syntax to control nesting and reflowing of- text. These changes make pandoc more suitable out of the- box for generating plain-text documents from data in YAML- metadata. It can create enumerated lists and even tabular- structures.- + We now used templates parameterized on doclayout Doc types.- The main impact of this change is better reflowing of- content interpolated into templates. Previously,- interpolated variables were rendered independently and- interpolated as strings, which could lead to overly long- lines. Now the templates interpolated as Doc values which- may include breaking spaces, and reflowing occurs after- template interpolation rather than before.- + Remove code from the LaTeX, Docbook, and JATS writers that- looked in the template for strings to determine whether it- is a book or an article, or whether csquotes is used. This- was always kludgy and unreliable.- + Change template code to use new API for doctemplates.-- * Add `--defaults`/`-d` option. This adds the ability to specify- a collection of default values for options in a YAML file. For- example, one might define a set of defaults for letters,- and then do `pandoc -d letter myletter.md -o myletter.pdf`.- See the documentation of this feature in MANUAL.txt.-- * Raise error on unsupported extensions (#4338).-- * The `--list-extensions[=FORMAT]` option now lists only- extensions that affect the given FORMAT.-- * Add `-L` option as shortcut for `--lua-filter`.-- * Add `--shift-heading-level-by` option and deprecate- `--base-heading-level` (#5615). The new option does- everything the old one does, but also allows negative shifts.- It also promotes the document metadata (if not null) to a- level-1 heading with a +1 shift, and demotes an initial- level-1 heading to document metadata with a -1 shift. This- supports converting documents that use an initial level-1- heading for the document title.-- * Allow `--metadata-file` to be used repeatedly to include- multiple metadata files (Owen McGrath, #5702). Values in- files specified first will be overridden by those in later- files.-- * `--ascii` now uses numerical hex character references (#5718).-- * Allow PDF output to stdout (#5751). PDF output now behaves like other- binary formats: it will not be output to the terminal, but can be- sent to stdout using either `-o -` or a pipe. The intermediate format- will be determined based on the setting of `--pdf-engine`.-- * Make some writers sensitive to 'unlisted' class on headings (#1762).- If this is present on a heading with the 'unnumbered' class,- the heading won't appear in the TOC. This class has no- effect if 'unnumbered' is not also specified. This affects HTML-based- writers (including slide shows and EPUB), LateX (including beamer), RTF,- and PowerPoint. Other writers do not yet support `unlisted`.-- * Fix `gfm_auto_identifiers` behavior with emojis (#5813). Note that- we also now use emoji names for emojis when `ascii_identifiers`- is enabled.-- * When `--ipynb-output` is used with the default "best" format, strip- ANSI escape codes for non-ipynb output (#5633). These cause problems- in many formats, including LaTeX.-- * Don't look for template files remotely for remote input (#5579).- Previously pandoc would look for the template at a remote URL when a- URL was used for the input file, instead of taking it from the- data directory.-- * Allow combining `-Vheader-includes` and `--include-in-header` (#5904).- Previously `header-includes` set as a variable would be- clobbered by material included using `--include-in-header`.-- * Change merge behavior for metadata. Previously, if a document- contained two YAML metadata blocks that set the same field, the- conflict would be resolved in favor of the first. Now it is resolved- in favor of the second (due to a change in pandoc-types).- This makes the behavior more uniform with other things in pandoc- (such as reference links and `--metadata-file`).-- * Don't add a newline to fragment output if there's already one.-- * Change exit codes and document in MANUAL.txt:-- + `PandocAppError` was 1, is now 4- + `PandocOptionError` was 2, is now 6- + `PandocMakePDFError` was 65, is now 66-- * Switch to new pandoc-types and use Text instead of String [API change].- (Christian Despres, #5884).-- * HTML reader:-- + Better handling of `<q>` with cite attribute (#5798, Ole Martin Ruud).- If a `<q>` tag has a `cite` attribute, we interpret it as a Quoted- element with an inner Span.- + Add support for HTML `<samp>` element (#5792, Amogh Rathore).- The `<samp>` element is parsed as Code with class `sample`.- + Add support for HTML `<var>` element (#5799, Amogh Rathore).- The `<var>` element is parsed as Code with class `variable`.- + Add support for `<mark>` elements (Florian B, #5797). Parse- `<mark>` elements from HTML as Spans with class `mark`.- + Add support for `<kbd>` elements, parsing them as Span with class- `kbd` (Daniele D'Orazio, #5796).- + Add support for `<dfn>`, parsing this as a Span with class `dfn`- (#5882, Florian Beeres).-- * Markdown reader:-- + Headers: don't parse content over newline boundary (#5714).- + Handle inline code more eagerly within lists (Brian Leung, #5627).- + Removed some needless lookaheads.- + Don't parse footnote body unless extension enabled.- + Fix small super/subscript issue (#5878). Superscripts and subscripts- cannot contain spaces, but newlines were previously allowed- (unintentionally). This led to bad interactions in some cases- with footnotes. With this change newlines are also not allowed inside- super/subscripts.- + Use `take1WhileP` for `str`, table row. This yields a small but- measurable performance improvement.--- * LaTeX reader:-- + Fix parsing of optional arguments that contain braced text (#5740).- + Don't try to parse includes if `raw_tex` is set (#5673).- When the `raw_tex` extension is set, we just carry through- `\usepackage`, `\input`, etc. verbatim as raw LaTeX.- + Properly handle optional arguments for macros (#5682).- + Fix `\\` in `\parbox` inside a table cell (#5711).- + Improve `withRaw` so it can handle cases where the token string is- modified by a parser (e.g. accent when it only takes part of a Word- token) (#5686). This fixes a bug that caused the ends of- certain documents to be dropped.- + Handle `\passthrough` macro used by latex writer (#5659).- + Support tex `\tt` command (#5654).- + Search for image with list of extensions like latex does, if an- extension is not provided (#4933).- + Handle `\looseness` command values better (#4439).- + Add `mbox` and `hbox` handling (Vasily Alferov, #5586).- When `+raw_tex` is enabled, these are passed through literally.- Otherwise, they are handled in a way that emulates LaTeX's behavior.- + Properly handle `\providecommand` and `\provideenvironment` (#5635).- They are now ignored if the corresponding command or environment- is already defined.- + Support epigraph command in LaTeX Reader (oquechy, #3523).- + Ensure that expanded macros in raw LaTeX end with a space- if the original did (#4442).- + Treat `ly` environment from lilypond as verbatim (Urs Liska, #5671).- + Add `tikzcd` to list of special environments (Eigil Rischel).- This allows it to be processed by filters, in the same way that- one can do for `tikzpicture`.-- * Roff reader:-- + Better support for `while`.- + More improvements in parsing conditionals.- + Fix problem parsing comments before macro.- + Improve handling of groups.- + Better parsing of groups (#5410). We now allow groups- where the closing `\\}` isn't at the beginning of a line.-- * RST reader:-- + Keep `name` property in `imgAttr` (Brian Leung, #5619).- + Fixed parsing of indented blocks (#5753). We were requiring- consistent indentation, but this isn't required by RST.- + Use title, not admonition-title, for admonition title.- This puts RST reader into alignment with docbook reader.- + Don't strip final underscore from absolute URI (#5763).- + Avoid spurious warning when resolving links to internal anchors- ending with `_` (#5763).-- * Org reader:-- + Accept `ATTR_LATEX` in block attributes (Albert Krewinkel, #5648).- Attributes for LaTeX output are accepted as valid block attributes;- however, their values are ignored.- + Modify handling of example blocks (Brian Leung, #5717).- + Allow the `-i` switch to ignore leading spaces (Brian Leung).- + Handle awkwardly-aligned code blocks within lists (Brian Leung).- Code blocks in Org lists must have their `#+BEGIN_` aligned in a- reasonable way, but their other components can be- positioned otherwise.- + Fix parsing of empty comment lines (#5856, Albert Krewinkel).- Comment lines in Org-mode can be completely empty.-- * Muse reader (Alexander Krotov):-- + Add RTL support (#5551).- + Do not allow closing asterisks to be followed by `*`.- + Do not split series of asterisks into symbols and emphasis (#5821).- + Do not terminate emphasis on `*` not followed by space.-- * DokuWiki reader:-- + Parse markup inside monospace ('') (#5916, Alexander Krotov).-- * Docx reader:-- + Move style-parsing-specific code to a new unexported module,- Text.Pandoc.Readers.Docx.Parse.Styles (Nikolay Yakimov).- + Move StyleMap to docx writer (Nikolay Yakimov).- + Only use LTR when it is overriding BiDi setting (#5723, Jesse- Rosenthal). The left-to-right direction setting in docx is used- in the spec only for overriding an explicit right-to-left setting.- We only process it when it happens in a paragraph set with BiDi.- This is especially important for docs exported from Google Docs,- which explicitly (and unnecessarily) set `rtl=0` for every paragraph.- + Fix list number resumption for sublists (#4324).- The first list item of a sublist should not resume numbering- from the number of the last sublist item of the same level,- if that sublist was a sublist of a different list item.-- * Docbook reader:-- + Richer parse for admonitions (Michael Peyton Jones, #1234).- Instead of parsing admonitions as blockquotes, we now parse- them as Divs with an appropriate class. We also handle titles- for admonitions as a nested Div with the "title" class.- + Fix nesting of chapters and sections (#5864, Florian Klink,- Félix Baylac-Jacqué).- + Fix bug with entities in mathphrase element (#5885).-- * MediaWiki reader:-- + Skip optional `{{table}}` template (#5757).-- * LaTeX reader:-- + Fix dollar-math parsing to ensure that space is left between a- control sequence and a following letter (#5836).- + In `untokenize`, ensure space between control sequence- and following letter (#5836).- + Don't omit macro definitions defined in the preamble.- These were formerly omitted (though they still affected macro- resolution if `latex_macros` was set). Now they are included in- the document body.- + Parse macro definitions as raw LaTeX when `latex_macros` is- disabled. (When `latex_macros` is enabled, we omit them, since- pandoc is applying the macros itself.)- + Fix a hang/memory leak in certain circumstances (#5845).- + Text.Pandoc.Readers.LaTeX.Parsing: add `[Tok]` parameter to- `rawLaTeXParser`. This allows us to repeat retokenizing- unnecessarily in e.g. `rawLaTeXBlock`.- + Add KOMA-Script metadata commands (#5910, Andrew Dunning).- Add all titling commands to existing definition for `\dedication`.- + Parse `\micro` siunitx unit command (#5921, Jose Luis Duran).-- * Markdown writer:-- + Ensure proper nesting when we have long ordered list markers (#5705).- + Make `plain` output plainer (#5741). Previously we used the following- Project Gutenberg conventions for plain output: extra space before and- after level 1 and 2 headings, all-caps for strong emphasis,- underscores surrounding regular emphasis. Now these- conventions are used only when the `gutenberg` extension is- enabled. By default, Strong and Emph are rendered without- special formatting, and headings are rendered without- special formatting, and with only one blank line following.- To restore the former behavior, use `-t plain+gutenberg`.- + Prefer using raw_attribute when enabled (#4311).- The `raw_attribute` will be used to mark raw bits, even HTML- and LaTeX, and even when `raw_html` and `raw_tex` are- enabled, as they are by default. To get the old behavior,- disable `raw_attribute` in the writer.- + Prefer `pipe_tables` to raw HTML even when we must- lose width information (#2608, #4497).- + Improve escaping in list items (#5918).-- * AsciiDoc writer:-- + Don't include `+` in code blocks for regular asciidoc.- This is asciidoctor-specific.- + Handle admonitions (#5690).-- * LaTeX writer:-- + Add thin space when needed in LaTeX quote ligatures (#5684).- + Use `\hspace{0pt}` for 0-width space U+200B (#5756).- + Use `cslreferences` environment for csl bibliographies.- This allows bibliographies to receive special formatting.- The template now contains definition of this environment (enabled- only when CSL is used). It also defines a `\cslhangindent` length.- This is set to 2em by default when the bibliography style specifies- a hanging indent. To override the length, you can use e.g.- `\setlength{\cslhangindent}{7em}` in header-includes.- See jgm/pandoc-citeproc#410.- + Strip off `{}` around locator for biblatex/natbib output (#5722).- + Fix line breaks at start of paragraph (#3324).- Previously we just omitted these. Now we render them- using `\hfill\break` instead of `\\`. This is a revision- of a PR by @sabine (#5591) who should be credited with the idea.- + We no longer look in the template or header-includes to see if a- book or article documentclass is used, or to see whether the- `csquotes` package is used. To use `csquotes` for LaTeX, set- `csquotes` in your variables or metadata. To specify a book- style, use the `documentclass` variable or- `--top-level-division`.- + Fix horizontal rule (#5801). We change to use 0.5pt rather than- `\linethickness`, which apparently only ever worked "by accident"- and no longer works with recent updates to texlive.-- * ConTeXt writer:-- + Add option to include source files in ConTeXt PDFs (Tristan- Stenner, #5578). The metadata field or variable- (`includesource`) can be set to attach the source documents- to the resulting PDF.- + Customizable type of PDF/A for the ConTeXt writer (Karl- Pettersson, #5608). The `pdfa` variable may now be set in metadata.- Also updated color profile settings in accordance with ConTeXt wiki,- and made ICC profile and output intent for PDF/A customizable- using `pdfaiccprofile` and `pdfaintent`.- + Unit tests: adjust code property to avoid an irrelevant- failure involving inline code with two consecutive newlines.- + Set `csl-hanging-indent` variable if needed.- + Use special environment for CSL references.- + Use braces, not start/stop, for inline language tags.- This prevents unwanted gobbling of spaces.-- * HTML writer:-- + Use numeric character references with `--ascii` (#5718).- Previously we used named character references with html5 output.- But these aren't valid XML, and we aim to produce html5 that is- also valid XHTML (polyglot markup). (This is also needed for epub3.)- + Ensure that line numbers in code blocks get id-prefix (#5650).- + Ensure TeX formulas are rendered correctly (Philip Pesca,- #5658). The web service passed in to `--webtex` may render- formulas using inline or display style by default.- Prefixing formulas with the appropriate command ensures- they are rendered correctly.- + Render inline formulas correctly with `--webtex` (Philip- Pesca, #5655). We add `\textstyle` to the beginning of the- formula to ensure it will be rendered in inline style.- + Pass through `aria-` attributes to HTML5 (#5642).- + Render a Quoted element with an inner Span with- `cite` attribute using a `<q>` tag (#5798, Ole Martin Ruud).- + Render a Span with class `mark` using the `<mark>` element- (Florian Beeres, #5797).- + Render Span with class `dfn` using `<dfn>` element- (Florian Beeres, #5882).- + Render Span with class `kbd` using `<kbd>` element (Daniele- D'Orazio, #5796).- + Render Code with class `variable` using `<var>` element- (Amogh Rathore, #5799).- + Render Code with class `sample` using `<samp>` element- (Amogh Rathore, #5799).-- * EPUB writer:-- + Improve splitting into chapters (#5761), using `makeSection`.- + Avoid issuing warning multiple times when title not set (see #5760).- + Use svg tag wrapper for cover image (#5638). In addition, the- code generating the image has been moved to the template, to make it- more customizable. NOTE: Those who use custom EPUB- templates will need to adjust their templates, adding the- code to generate the cover image. (Previously this was just- inserted into 'body'.)- + Improve toChapters, making it work better if there are Divs- around sections.- + Add support for EPUB2 covers (blmage, #3992).- + Do not override existing "fileN" medias when writing to EPUB format- (blmage, #4206).- + Ensure that `lang` variable is set on all chapters (so that it- will add an `xml:lang` attribute on the `html` element).-- * RST writer:-- + Removed remnants of `admonition-title`.- + Fix handling of `:align:` on figures and images (#4420).- When the image has the `align-right` (etc.) class, we now use- an `:align:` attribute.- + Improve spacing for tables with no width information (#5899).- If a simple table would be too wide, we use a grid table.- + Fix backslash escaping after strings (Albert Krewinkel, #5906).- The check whether a complex inline element following a string must- be escaped, now depends on the last character of the string instead- of the first.- + Ensure there's a blank line before tables (#5898).-- * Dokuwiki writer:-- + Handle mixed lists without HTML fallback (#5107).-- * XWiki writer:-- + Fix multiline table (Zihang Chen, #5683).-- * Muse writer:-- + Add RTL support (Alexander Krotov, #5551).-- * Man writer:-- + Suppress non-absolute link URLs (#5770). Absolute URLs are- still printed in parentheses following the link text, but relative- URLs are suppressed (just as internal links starting with '#'- always have been).- + Improved definition list term output. Now we boldface code but- not other things. This matches the most common style in man pages- (particularly option lists).-- * Ms writer:-- + Use `.LP` instead of `.PP` for line block (#5588).- + Use boldface for definition terms in DefinitionLists.-- * JATS writer:-- + Do not emit empty `<fn-group>` (Mauro Bieg, #5595).- + Update template to v1.1dtd (#5632, Arfon Smith).- + Update `data/jats.csl` to avoid commas between editor- name-part elements. (#5629)- + Add `abstract` to template (Mauro Bieg).-- * TEI writer:-- + Don't strip hash from internal links (#5922).-- * Jira writer:-- + Remove escapeStringForJira for code blocks (Jan-Otto Kröpke).- + Remove extraneous newline after single-line block quotes- (#5858, Albert Krewinkel).- + Improve escaping of special characters, using backslash escapes- instead of HTML entities (#5858, Albert Krewinkel).-- * OpenDocument writer:-- + Avoid duplicate attributes (#4634). We use the innermost- attribute in nested cases.- + If `native_numbering` extension is set, use native OpenDocument- enumeration for figures and tables (Nils Carlson).- + Place caption before table (#5681, Dmitry Pogodin).-- * ODT writer:-- + Add a test for MathML formulas in ODT documents (blmage).- + Improve the parsing of frames in ODT documents (blmage).-- * Docx writer:-- + Make handling of styles more robust in localized versions- of Word (Nikolay Yakimov, #5523, #5052, #5074). We now use- style names, not ids, for assigning semantic meaning, since- the ids can change depending on the locale. Style name- comparisons are case-insensitive, since those are- case-insensitive in Word. Since docx style names can have- spaces in them, and pandoc-markdown classes can't, anywhere- when style name is used as a class name, spaces are- replaced with ASCII dashes `-`. Code styles, i.e. "Source- Code" and "Verbatim Char" now honor style inheritance. Docx- Reader now honours "Compact" style (used in- Pandoc-generated docx). The side-effect is that "Compact"- style no longer shows up in docx+styles output. Styles- inherited from "Compact" will still show up.- + Re-use Readers.Docx.Parse for StyleMap (#5766, Nikolay Yakimov).- + Internal improvements and code simplification (Nikolay Yakimov).- + Preserve built-in styles in DOCX with custom style (Ben Steinberg,- #5670). This change prevents custom styles on divs and spans- from overriding styles on certain elements inside them, like- headings, blockquotes, and links. On those elements, the- "native" style is required for the element to display correctly.- This change also allows nesting of custom styles; in order to do so,- it removes the default "Compact" style applied to Plain blocks,- except when inside a table.- + Add `proofState` to list of elements carried over from- settings.xml in the reference.docx (Krystof Beuermann, #5703).- + Change order of `ilvl` and `numId` in `document.xml` (Agustín- Martín Barbero, #5645). Also, make list para properties go first.- This reordering of properties shouldn't be necessary but- it seems Word Online does not understand the docx correctly otherwise.-- * PowerPoint writer:-- + Code formatting is now context dependent (Jeroen de Haas, #5573).- This commit alters the way in which the Powerpoint writer treats- inline code and code blocks. Inline code is now formatted at- the same size as the surrounding text. Code blocks are now given- a margin and font size according to their level.- Furthermore this commit allows changing the font with which code is- formatted via the `monofont` option.- + Start numbering at appropriate numbers (Jesse Rosenthal, #5709).- Starting numbers for ordered lists were previously ignored. Now- we specify the number if it is something other than 1.-- * Text.Pandoc.Parsing:-- + Add `manyChar`, `many1Char`, `manyTillChar`, `many1TillChar`,- `many1Till`, `manyUntil`, `mantyUntilChar`: these are like their- unsuffixed counterparts but pack some or all of their output- (Christian Despres, #5884).- + Add `stateAllowLineBreaks` to `ParserState` [API change].- + Fix inline parsing in grid table cells (#5708).- + Change type of `setLastStrPos` so it takes a `Maybe SourcePos`- rather than a `SourcePos` [API change].- + Make `parseFromString'` and `gridTableWith` and- `gridTableWith'` polymorphic in the parser state,- constraining it with `HasLastStrPosition` [API change].- + `parseFromString'`: reset `stateLastStrPos` to `Nothing` before parse.- + Rename takeWhileP -> take1WhileP and clean it up.- (It doesn't match the empty sequence.)-- * Text.Pandoc.PDF:-- + For PDFs via HTML, ensure temp file is deleted even if the pdf- program is not found (#5720).- + Better detection of a Cygwin environment (#5451).- + Don't assume tex log file is UTF8-encoded (#5872).- Fall back to latin1 if it can't be read as UTF-8.-- * Text.Pandoc.Extensions:-- + Export new function `getAllExtensions`, which returns the- extensions that affect a given format (whether enabled by default- or not) [API change].- + Change type of `parseFormatSpec` from- `Either ParseError (String, Extensions -> Extensions)`- to `Either ParseError (String, [Extension], [Extension])`- [API change].- + Add `Ext_gutenberg` constructor to `Extension` [API change].- + Add `Ext_native_numbering` constructor to `Extension` [API change]- (Nils Carlson).-- * Text.Pandoc.Readers, Text.Pandoc.Writers:-- + Change type of `getReader` and `getWriter` so they return- a value in the PandocMonad instance rather than an Either- [API change]. Exceptions for unknown formats and unsupported- extensions are now raised by these functions.-- * Text.Pandoc.App-- + Change `optMetadataFile` type from `Maybe FilePath` to `[FilePath]`- (Owen McGrath, #5702) [API change].-- * Text.Pandoc.Logging:-- + Add `CouldNotDeduceFormat` constructor to `LogMessage` [API change].- Issue this warning when we're falling back to markdown or- html because we don't recognize the extension of the input or- output files.- + Clarify warning for missing title (#5760).- + Add `UnusualConversion` constructor to `LogMessage` [API change]- (Mauro Bieg, #5736). Emit warning on `-f latex -o out.pdf`.-- * Lua filters:-- + Improve function documentation (Albert Krewkinkel).- + Traverse nested blocks and inlines in correct order (Albert- Krewinkel, #5667). Traversal methods are updated to use the new- Walk module so that sequences with nested Inline (or Block) elements- are traversed in the order in which they appear in the linearized- document.- + New unexported module `Text.Pandoc.Lua.Walk` (Albert Krewinkel).- Lua filters must be able to traverse sequences of AST- elements and to replace elements by splicing sequences back- in their place. Special `Walkable` instances can be used for- this; those are provided in a new module- `Text.Pandoc.Lua.Walk`.- + `Attr` values can now be given as normal Lua tables (Albert- Krewinkel, #5744). This can be used as a convenient alternative- to constructing `Attr` values with `pandoc.Attr`. Identifiers- are taken from the `id` field, classes must be given as- space separated words in the `class` field. All remaining fields- are included as attributes. With this change, the following lines- now create equal elements:- ```- pandoc.Span('test', {id = 'test', class = 'a b', check = 1})- pandoc.Span('test', pandoc.Attr('test', {'a','b'}, {check = 1}))- ```- This also works when using the *attr* setter:- ```- local span = pandoc.Span 'text'- span.attr = {id = 'test', class = 'a b', check = 1}- ```- Furthermore, the *attributes* field of AST elements can now be a- plain key-value table even when using the `attributes` accessor:- ```- local span = pandoc.Span 'test'- span.attributes = {check = 1} -- works as expected now- ```- + Export `make_sections`, remove `hierarchicalize`. Lua filters that- use `hierarchicalize` will need to be rewritten to use- `make_sections`.- + Add a `clone()` method to all AST elements (Albert Krewinkel, #5568).- + Fix Lua function names in pandoc.system (niszet). Change- `get_current_directory` to `get_working_directory` and- `with_temp_directory` to `with_temporary_directory`, to- conform to the manual.-- * Text.Pandoc.Error:-- + Add constructors `PandocUnknownReaderError`,- `PandocUnknownWriterError`, `PandocUnsupportedExtensionError`.- [API change].- + Better message for `PandocShouldNeverHappenError`.- + Better message for `PandocTemplateError`.-- * Text.Pandoc.Emoji:-- + Update emoji list (#5666). Done using new `tools/emojis.hs`,- which uses the list from the gem GitHub uses. Future updates- can be done with this tool.-- * Text.Pandoc.PDF:-- + Pass value of `--dpi` to `rsvg-convert` when converting SVG to PDF- in the process of creating a PDF (#5721).-- * Text.Pandoc.Shared:-- + Replace `Element` and `makeHierarchical` with `makeSections`.- Now that we have Divs, we can use them to represent the- structure of sections, and we don't need a special Element type.- `makeSections` reorganizes a block list, adding Divs with class- `section` around sections, and adding numbering if needed.- This change also fixes some longstanding issues recognizing section- structure when the document contains Divs (#3057, see also #997).- + Remove `Element` type [API change]- + Remove `makeHierarchicalize` [API change]- + Add `makeSections` [API change]- + Export `deLink` [API change]- + Make `filterIpynbOutput` strip ANSI escapes from code in output- for non-ipynb formats, when the default "best" option is used with- `--ipynb-output` (#5633).- + Fix `camelCaseToHyphenated` so it handles `ABCDef` better.- + Improve `isTight` (#5857). If a list has an empty item,- this should not count against its being a tight list.- + Export `htmlSpanLikeElements` [API change] (Daniele D'Orazio, #5796).- This is a mapping of HTML span-like elements that are internally- represented as a Span with a single class.- + Change the implementation of `htmlSpanLikeElements` to retain- classes and attributes (#5882, Florian Beeres).-- * Text.Pandoc.Slides: recognize content in Divs when determining- slide level.-- * Text.Pandoc.SelfContained:-- + Omit content-type on type attribute for `<style>` (#5725).- It doesn't seem to be valid for HTML5, and as a result Chrome- ignores the style element.-- * Text.Pandoc.Pretty has been removed [API change].- We now use the new external doclayout module instead.-- * Text.Pandoc.Writers.Shared:-- + Remove `metaToJSON`, `metaToJSON'` [API change].- + Modify `addVariablesToContext`, `defField`, `setField`, `getField`,- `resetField` to work with Context rather than JSON values. [API change]- + Export new function `endsWithPlain` [API change].- + Change `gridTables` so it does better at keeping the widths of- columns (#4320) and does better at figuring out column widths- when no widths are given (#5899).-- * Text.Pandoc.Options-- + Change type of `writerTemplate` to `Maybe Template` instead- of `Maybe String`.- + Change To/FromJSON instances for `HTMLMathMethod`, `CiteMethod`,- `ObfuscationMethod`, `TrackChanges`, `WrapOption`,- `TopLevelDivision`, `ReferenceLocation`, `HTMLSlideVariant` (#5790).- In each case we use lowercase (or hyphenated lowercase) for- constructors to line up more closely with command-line option- values. This is a breaking change for those who manually decode or- encode JSON for these data types (e.g. for `ReaderOptions` or- `WriterOptions`).-- * Text.Pandoc.Filters:-- + Add `FromYAML` instance for `Filter`.- + `applyFilters`: Add and apply filters in order (not reversed)- This changes `applyFilters` from Text.Pandoc.Filter so- that it does a left fold rather than a right fold, applying- the filters in the order listed.-- * Text.Pandoc.XML:-- + Change `toEntities` to emit numerical hex character references- (#5718).-- * Text.Pandoc.Highlighting:-- + Add additional listings languages (Wandmalfarbe).-- * Text.Pandoc.MediaBag:-- + Some of the types using Strings were switched to use FilePath instead- (Christian Despres, #5884).-- * Text.Pandoc.Templates:-- + Don't import/export `varListToJSON` [API change]. It is removed in- doctemplates >= 0.3.- + Change type of `renderTemplate'` [API change]. Return value is- now Text rather than being polymorphic. This makes room for- upcoming removal of the `TemplateTarget` class from doctemplates.-- * Text.Pandoc.App.Opt [API changes]:-- + More convenient To/FromJSON instances. Make the field names- like `strip-empty-paragraphs` rather than `optStripEmptyParagraphs`.- Anyone who is using JSON serialization of Opt will need to adjust- things accordingly.- + Change `optHighlightStyle` to a `Maybe String` instead of- `Maybe Style`. Do the parsing/loading of themes later, after- option parsing.- + Remove `optBaseHeaderLevel` from `Opt`. We now just use- `optShiftHeadingLevelBy`, to avoid redundancy.- + Change `optShiftHeadingLevel` to `optShiftHeadingLevelBy` to- match the option.- + Custom FromJSON instance for `LineEnding`, so either `CRLF`- or `crlf` will work.- + Change `optVariables` from `[(String, String)]` to `Context Text`.- + Change `optMetadata` to `Meta`, to allow structured values.- The current behavior of the `--metadata` option stays the same.- + Rename `optReader`, `optWriter` as `optFrom`, `optTo`.- + Add `FromYAML` instances to `Opt` and to all subsidiary types.- + Rename `optMetadataFile` to `optMetadataFiles`.- + Rename `optPDFEngineArgs` to `optPDFEngineOpts`.- + Rename `optWrapText` to `optWrap`.- + Add `IpynbOutput` enumerated type: use this instead of- a string for `optIpynbOutput`.- + Change optInputFiles to a `Maybe [FilePath]` (#5888) [API change].- `Nothing` means: nothing specified.- `Just []` means: an empty list specified (e.g. in defaults).- + List fields in Opt so they aren't reversed (#5881) [API change].- Previously `optIncludeInHeader`, etc. were in reverse order.- + The `sourcefile` variable is now always a list. It used to be- sometimes a string, sometimes a list (when there was more than one).-- * Template changes:-- + default.latex: added code for `cslreferences` environment,- to be used for pandoc-citeproc references. A `csl-hanging-indent`- variable (set automatically if there is a `hanging-ident`- class on the references Div) controls whether contents of this- environment receive a hanging indent.- + default.latex: Add `space` as default option for xeCJK, so that- spaces between words are preserved (#5855, jeongminkim-islab).- This is necessary for Korean.- + default.latex: Remove include of `grffile` (#5848).- This package used to be needed for proper handling of image filenames- containing periods (in addition to the period before the extension).- It no longer works with the latest LaTeX kernel and graphicx,- so we have removed it. Future versions of graphicx will handle- these filenames without the need for `grffile`.- + default.context: add a saner default for page numbers.- Previously they appeared centered at the top of the page;- now we put them centered at the bottom, unless the `pagenumbering`- variable is set.- + default.context: define a start-stop-pair `cslreferences` to- allow for hanging indents in the bibliography (#5875, Denis Maier).- + default.ms: update defaults. Use Palatino font, use slightly- wider interparagraph space, don't indent paragraphs,- and put page numbers on the bottom. This brings ms output- closer to default LaTeX output.- + default.revealjs: add navigationMode (Mauro Bieg, #5657).- + default.muse: handle multiple authors better.- + docbook4, docbook5 templates: add indentation to body.- + HTML-based templates: use `styles.html` partial to avoid- code duplication.- + HTML-based templates: change indentation of styles in template.-- * reference.docx (#5820):-- + Change Block Text (block quote) style so that the same font- is used as in the body text, and the block text is indented- left and right.- + All headings now have a uniform color.- + Level-1 headings no longer set `w:themeShade="B5"`.- + Level-2 headings are now 14 point rather than 16 point.- + Level-3 headings are now 12 point rather than 14 point.- + Level-4 headings are italic rather than bold.-- * epub.css: Add CSS for hanging-indent div to support pandoc-citeproc's- new hanging indents.-- * pandoc.cabal:-- + Repeat ghc-options in all stanzas.- + Remove conditionals for ghc < 8 (Albert Krewinkel, #5693).- + Compile with `-Wcpp-undef` and `-fhide-source-paths` when possible- (Albert Krewinkel).- + Add cabal.project to extra-source-files (Albert Krewinkel).- + Add dependency on skylighting-core (#5729). Even though it shouldn't- be needed, some tools require it.- + Require latest pandoc-types, texmath, skylighting, haddock-library.- + Ensure TemplateHaskell is added to other-extensions when it is- used (Vanessa McHale, #5728).- + Remove `derive_json_via_th` flag; always use TH. This cuts down- on code duplication and reduces the chance for errors. See #4083.-- * Makefile:-- + Add ghci target.- + Add ghcid target.- + Remove references to obsolete flag (#5694).-- * Benchmarks: fix failure on ipynb.-- * Use MathJax 3 (zorkow).-- * KaTeX math: respect `classoption=fleqn` variable,- bump KaTeX version to 0.11.1 (#5815, Mauro Bieg).-- * Fix redundant constraint compiler warnings (Pete Ryland, #5625).-- * Use throwError instead of fail when appropriate.-- * Use Prelude.fail to avoid ambiguity with fail from GHC.Base.-- * Add `diff-zip.sh` to tools (John MacFarlane, Agustín Martín Barbero).- This is intended to make it easier to test differences in zip- containers, like epub, docx, or odt.-- * Add `.gitattributes` (#5747). This ensures that the golden files- in `test/fb2/reader/` don't have newlines converted. This should fix- a test failure on GitHub CI with Windows.-- * Reorder options in `--help`.-- * Revise code for HsYAML-0.2.0.0 (@vijayphoenix, #5704).-- * Remove blank line in code example in Haddocks (Leif Metcalf, #5679).-- * Fix trypandoc with `getReader`/`getWriter` changes.-- * Allow building pandoc with GHC 8.8.-- * linux tarball: add architecture `-amd64` to filename.- Now it will be: `pandoc-VERSION-linux-ARCH.tar.gz`.-- * MANUAL.txt:-- + Add section for exit codes.- + Document some pptx limitations in slide show section:- No incremental display (#5689). No pause with `. . .` (#5701).- + reveal.js flags (Mauro Bieg, #5653).- + Document addition of `data-` prefix to unknown attributes in HTML5.- + Link to YAML spec (Mauro Bieg, #5687).- + Fix capitalization of "Linux" (#5859, Marcus Stollsteimer).- + Use a table for exit codes.- + Put all template variable docs into one section.- + Use ATX headers consistently.- + Add fuller documentation of templates (#5779), including- new template syntax, partials, etc.- + Add documentation for the variable `hyperrefoptions` (Wandmalfarbe).- + Clarify when macro definitions are passed as raw latex.- In Markdown input, they are always passed through. In LaTeX, only if- `latex_macros` is disabled.- + Clarify that `--dpi` provides a default and doesn't override- dpi values specified in the images themselves (#5721).- + Document how to use custom writers with `--standalone` (#5866).- + Clarify `--preserve-tabs` default.-- * INSTALL.md:-- + Fix instructions for libicu.- + Add Void Linux instructions (Volodymyr Kozachnyskyi).-- * CONTRIBUTING.md:-- + Add information on tests (Agustín Martín Barbero, #5652).- + Add information about command test naming to CONTRIBUTING (Florian B).-- * Fix typos in changelog and comments (#5896, Brian Wignall).-- * doc/lua-filters.md:-- + Fix mistakes in mediabag module docs (#5851, Albert Krewinkel).- + Improve metadata replacement example in lua-filters doc (#5851).- + Mention which Lua version is shipped with pandoc (Albert Krewinkel,- #5892).--## pandoc 2.7.3 (2019-06-11)-- * Add `jira` (Atlassian's Jira wiki markup) as output format (#2497,- Albert Krewinkel).-- * Add `tex_math_dollars` to `multimarkdownExtensions` (#5512).- This form is now supported in multimarkdown,- in addition to `tex_math_double_backslash`.-- * Fix `--self-contained` so it works when output format has extensions.- Previously if you used `--self-contained` with `html-smart` or- `html+smart`, it wouldn't work.-- * Add template variable `curdir` with working directory- from which pandoc is run (#5464).-- * Markdown reader: don't create implicit reference for empty header- (#5549).-- * Muse reader: allow images inside link descriptions (Alexander Krotov).-- * HTML reader: epub related fixes.-- + With epub extensions, check for `epub:type` in addition to `type`.- + Fix problem with noteref parsing which caused block-level- content to be eaten with the noteref.- + Rename `pAnyTag` to `pAny`.- + Refactor note resolution.- + Trim definition list terms (Alexander Krotov).-- * LaTeX reader:-- + Add braces when resolving `\DeclareMathOperator`- (#5441). These seem to be needed for xelatex but not pdflatex.- + Allow newlines in `\mintinline`.- + Pass through unknown listings language as class (#5540).- Previously if the language was not in the list of languages supported- by listings, it would not be added as a class, so highlighting- would not be triggered.- + `rawLaTeXInline`: Include trailing `{}`s in raw latex commands (#5439).- This change affects the markdown reader and other readers that allow raw- LaTeX. Previously, trailing `{}` would be included for unknown- commands, but not for known commands. However, they are sometimes used- to avoid a trailing space after the command. The chances that a `{}`- after a LaTeX command is not part of the command are very small.-- * MediaWiki reader: handle multiple attributes in table row (#5471,- chinapedia).-- * Docx reader: Add support for `w:rtl` (#5545). Elements with this- property are put into Span inlines with `dir="rtl"`.-- * DocBook reader: Issue `IgnoredElement` warnings.-- * Org reader (Albert Krewinkel):-- + Fix planning elements in headers level 3 and higher- (#5494). Planning info is now always placed before- the subtree contents. Previously, the planning info was placed after- the content if the header's subtree was converted to a list, which- happens with headers of level 3 and higher per default.- + Omit, but warn about unknown export options. Unknown export- options are properly ignored and omitted from the output.- + Prefer plain symbols over math symbols (#5483).- Symbols like `\alpha` are output plain and unemphasized, not as math.- + Recognize emphasis after TODO/DONE keyword (#5484).-- * FB2 reader:-- + Skip unknown elements rather than throwing errors (#5560).- Sometimes custom elements are used (e.g. `id` element- inside `author`); previously the reader would halt with an error.- Now it skips the element and issues an `IgnoredElement` warning.- + Parse notes (#5493, Alexander Krotov).- + Internal improvements (Alexander Krotov).-- * OpenDocument writer: Roll back automatic figure/table numbering- (#5474). This was added in pandoc 2.7.2, but it makes it impossible- to use pandoc-crossref. So this has been rolled back for now,- until we find a good solution to make this behavior optional- (or a creative way to let pandoc-crossref and this feature- to coexist).-- * New module Text.Pandoc.Writers.Jira, exporting `writeJira` [API- change] (Albert Krewinkel).-- * EPUB writer:-- + Don't include 'landmarks' if there aren't any.- Previously we could get an empty ol element, which caused- validation errors with epubcheck.- + Ensure unique ids for styleesheets in content.opf (#5463).- + Make stylesheet link compatible with kindlegen (#5466,- Eric Schrijver). Pandoc omitted `type="text/css"` from both- `<style>` and `<rel="stylesheet">` elements in all templates, which- is valid according to the spec. However, Amazon’s kindlegen software- relies on this attribute on `<link>` elements when detecting- stylesheets to include.-- * HTML writer:-- + Output video and audio elements depending on file- extension of the image path (Mauro Bieg).- + Emit empty alt tag in figures (#5518, Mauro Bieg).- The same text is already in the <figcaption> and- screen-readers would read it twice, see #4737.- + Don't add variation selector if it's already there.- This fixes round-trip failures.- + Prevent gratuitous emojification on iOS (#5469).- iOS chooses to render a number of Unicode entities, including '↩', as- big colorful emoji. This can be defeated by appending Unicode- VARIATION SELECTOR-15'/'VARIATION SELECTOR-16'. So we now append this- character when escaping strings, for both '↩' and '↔'. If other- characters prove problematic, they can simply be added to- `needsVariationSelector`. + Add `class="heading"` to level 7+ Headers- rendered as `<p>` elements (#5457).-- * RST writer: treat Span with no attributes as transparent (#5446).- Previously an Emph inside a Span was being treated as- nested markup and ignored. With this patch, the Span- is just ignored.-- * LaTeX writer:-- + Include inline code attributes with `--listings` (#5420).- + Don't produce columns environment unless beamer (#5485).- + Fix footnote in image caption. Regression: the fix for #4683 broke- this case.- + Don't highlight code in headings (#5574). This causes- compilation errors.- + Use `\mbox` to get proper behavior inside `\sout` (#5529).-- * EPUB writer: Fix document section assignments (#5546).- For example, introduction should go in bodymatter, not frontmatter, and- epigraph, conclusion, and afterward should go in bodymatter, not- backmatter. For the full list of assignments, see the manual.-- * Markdown writer:-- + Add backslashes to avoid unwanted interpretation of- definition list terms as other kinds of block (#554).- + Ensure the code fence is long enough (#5519).- Previously too few backticks were used when the code block- contained an indented line of backticks. (Ditto tildes.)- + Handle labels with integer names (Jesse Rosenthal, #5495).- Previously if labels had integer names, it could produce a conflict- with auto-labeled reference links. Now we test for a conflict and- find the next available integer. This involves adding a new state- variable `stPrevRefs` to keep track of refs used in other document- parts when using `--reference-location=block|section`-- * Textile writer: fix closing tag for math output (Albert Krewinkel).- Opening and closing tag for math output match now.-- * Org writer: always indent src blocks content by 2 spaces (#5440, Albert- Krewinkel). Emacs always uses two spaces when indenting the content of- src blocks, e.g., when exiting a `C-c '` edit-buffer. Pandoc used to- indent contents by the space-equivalent of one tab, but now always uses- two spaces, too.-- * Asciidoc writer:-- + Use `` `+...+` `` form for inline code.- The old `` `a__b__c` `` yields emphasis inside code in asciidoc.- To get a pure literal code span, use `` `+a__b__c+` ``.- + Use proper smart quotes with asciidoctor (#5487).- Asciidoctor has a different format for smart quotes.- + Use doubled ## when necessary for spans (#5566).- + Ensure correct nesting of strong/emph (#5565): strong- must be the outer element.-- * JATS writer:-- + Wrap elements with p when needed (#5570). The JATS spec restricts- what elements can go inside `fn` and `list-item`. So we wrap other- elements inside `<p specific-use="wrapper">` when needed.- + Properly handle footnotes (#5511) according to "best practice."- (Group them at the end in `<fn-group>` and use `<xref>` elements- to link them.)- + Fix citations with PMID so they validate (#5481). This includes- an update to data/jats.csl.- + Ensure validity of `<pub-date>` by parsing the date and- extracting year, month, and day, as expected. Also add an- iso-8601-date attribute automatically.- + Don't use `<break>` element for LineBreak. It is only- allowed in a few special contexts, and not in `<p>` elements.- + Don't make `<string-name>` a child of `<string>`, which is illegal.-- * FB2 writer:-- + Do not wrap note references into `<sup>` and brackets- (Alexander Krotov). Existing FB2 readers, such as FBReader, already- display links with type="note" as a superscript.- + Use genre metadata field (#5478).-- * Muse writer: do not escape empty line after `<br>` (Alexander Krotov).-- * Add unicode code point in "Missing character" warning (#5538).- If the character isn't in the console font, the message is pretty useless,- so we show the code point for anything non-ASCII.-- * Lua: add Version type to simplify comparisons (Albert Krewinkel).- Version specifiers like `PANDOC_VERSION` and `PANDOC_API_VERSION` are- turned into `Version` objects. The objects simplify version-appropriate- comparisons while maintaining backward-compatibility.- A function `pandoc.types.Version` is added as part of the newly- introduced module `pandoc.types`, allowing users to create version- objects in scripts.-- * pandoc lua module (Albert Krewinkel):-- - Fix deletion of nonexistent attributes (#5569).- - Better tests for Attr and AttributeList.-- * pandoc.mediabag lua module (Albert Krewinkel):-- + Add function `delete` for deleting a single item.- + Add function `empty` for removing all entries.- + Add function `items` for iterating over mediabag.-- * Text.Pandoc.Class: Fix handling of `file:` URL scheme in- `downloadOrRead` (#5517, Mauro Bieg). Previously `file:/`- URLs were handled wrongly and pandoc attempted to make HTTP- requests, which failed.-- * Text.Pandoc.MIME: add `mediaCategory` [API change] (Mauro Bieg).-- * Text.Pandoc.Shared:-- + Add `onlySimpleTableCells` [API change]- (Mauro Bieg) and use this to consolidate simple-table detection- (#5524). This fixes an inconsistency in the HTML reader, which did not- treat tables with `<p>` inside cells as simple.- + `metaToJSON`: treat digits starting with 0 as a string, not a number- (#5479). This fixes a regression in YAML metadata in pandoc 2.7.2.-- * Text.Pandoc.Logging: Add `IgnoredElement` constructor for- `LogMessage`. `SkippedConetnt` doesn't work for some XML-based- readers which don't have access to parsec source positions.-- * Text.Pandoc.Asciify: Add Turkish undotted-i (#5433, Mauro Bieg).-- * Improve output of Lua tests (#5499, Albert Krewinkel).- This makes use of tasty-lua, a package to write tests in Lua- and integrate the results into Tasty output. Test output becomes- more informative: individual tests and test groups become visible- in test output. Failures are reported with helpful error messages.-- * Lua: add `pandoc.system` module (#5468, Albert Krewinkel).- The `system` Lua module provides utility functions to interact with the- operating- and file system. E.g.- `print(pandoc.system.get_current_directory())`- or- ```lua- pandoc.system.with_temporary_directory('tikz', function (dir)- -- write and compile a TikZ file with pdflatex- end)- ```-- * LaTeX template: Add pdflang to hypersetup if lang is set (#5443).-- * beamer template: Fix using Beamer with geometry (#5505, Daniel Maslowski).- Beamer already loads geometry, so we need to use the `\geometry`- command to set geometry options.-- * EPUB2/3 templates: Move inline styles to default epub.css (#5466).- NOTE: Those who use a custom CSS stylesheet with EPUB should- add these lines:-- code{ white-space: pre-wrap; }- span.smallcaps{ font-variant: small-caps; }- span.underline{ text-decoration: underline; }- q { quotes: "“" "”" "‘" "’"; }- div.column{ display: inline-block; vertical-align: top; width: 50%; }-- * reveal.js template:-- + Updates for revealjs 3.8.0 (#5435, ebiim).- + Remove reference to head.min.js (#5448, Winnie Hellmann).- NOTE: users will need to update reveal.js to at least 3.8.0- for their presentations generated with this version of pandoc- to work correctly.-- * Text.Pandoc.PDF:-- + Replace `</>` with literal `/` (#5451).- We use forward-slash for a directory separator in tmpDir,- even on Windows (because that's what tex likes). So we- should not put a backslash between the tmpDir and the- filename on Windows. This is harmless enough in normal- Windows setups, but it breaks on Cygwin.- Thanks to @cc2x for noticing and diagnosing the problem.- + Allow use of `-output-directory` in `--pdf-engine-opt` (#5462).- This is currently possible with `mklatex` and `-outdir`, but- was not yet possible with xelatex and `-output-directory`.- + For PDF via ms/pdfroff, make TOC appear at beginning and in- PDF bookmarks (#5553). Previously the TOC appeared at the end- of the document, and was not bookmarked. To keep it at the end,- add `--pdf-engine-opt=--no-toc-relocation` to your command line.-- * Fix broken links in documents (#5473, Shim Myeongseob).- Also, use absolute links to pandoc.org when possible, so that- the links can be followed by people viewing these documents- on GitHub.-- * Improved sample lua tikz filter in lua-filters docs (#5445,- Matthew Doty). There are three changes:-- + It only processes elements which begin with `\begin{tikzpicture}`- + It uses pdf2svg instead of imagemagick to preserve fidelity- + The images produced have transparent backgrounds-- * MANUAL.txt:-- + Add note about `title-meta`, `author-meta`, `date-meta` (#5486).- + Fix typo (#5489, Christian Krause).-- * add test/tables.xwiki to git and pandoc.cabal (#5498, Mauro Bieg).-- * Disable missing-home-modules warning in `stack.yaml`.- Otherwise `stack ghci` fails.---## pandoc 2.7.2 (2019-04-05)-- * Add XWiki writer (#1800, Derek Chen-Becker).- Add `Text.Pandoc.Writers.XWiki`, exporting `writeXWiki` [API change].-- * Dokuwiki Reader: parse single curly brace (#5416, Mauro Bieg).-- * Vimwiki reader: improve handling of internal links (#5414).- We no longer append `.html` to link targets, and we add a title- `wikilink`. This mirrors behavior of other wiki readers. Generally- the `.html` extension is not wanted. It may be important for output- to HTML in certain circumstances, but it can always be added using a- filter that matches on links with title `wikilink`.-- If your workflow requires the current behavior, here is a lua filter- that will add the `.html` extension:-- ```lua- function Link(el)- if el.title == 'wikilink' then- el.target = el.target .. ".html"- end- return el- end- ```- * ipynb reader:-- + Use format `ipynb` for raw cell where no format given.- + Avoid introducing spurious `.0` on integers in metadata.-- * Markdown reader: fenced div takes priority over setext header.-- * HTML reader: read `data-foo` attribute into `foo` (#5392).- The HTML writer adds the `data-` prefix for HTML5 for nonstandard- attributes. But the attributes are represented in the AST without- the `data-` prefix, so we should strip this when reading HTML.-- * LaTeX reader: Improve autolink detection (#5340).-- * PowerPoint writer (Jesse Rosenthal):-- + Expand builtin reference doc to model all layouts.- The previous built-in reference doc had only title and content- layouts. Add in a section-header slide and a two-content slide, so- users can more easily modify it to build their own templates.- + Always open up in slide view. When editing a- template/reference-doc, the user might be in Master view, but when- producing a slide show, it is assumed that slide view will be- desired.- + Remove `handoutsMasterList` from template presentation.xml- + Fix numerous errors in templating (#5402). Previously, some templates- produced by Office 365 (MacOS) would not render with `--reference-doc`- correctly. We now apply correct shapes for content, and build- shape trees correctly.- + Make default placeholder type for template lookup.- + Apply speaker notes to metadata slide if applicable.- + Test for speaker notes after breaking header.- + Correctly handle notes after section-title header.- Previously, if notes came after a section-title header (ie, a level-1- header in a slide-level=2 presentation), they would go on the next- slide. This keeps them on the slide with the header.- + Internal improvements.-- * ipynb writer:-- + Use format `ipynb` for raw cell where no format given.- According to nbformat docs, this is supposed to render in every- format. We don't do that, but we at least preserve it as a raw- block in markdown, so you can round-trip.- + Consolidate adjacent raw blocks. Sometimes pandoc creates two- HTML blocks, e.g. one for the open tag and one for a close tag.- If these aren't consolidated, only one will show up in output cell.- + Fixed carry-over of nbformat from metadata.- + Preserve `nbformat_minor` if it's given. This helps with round-tripping.-- * LaTeX writer:-- + Avoid inadvertently creating ?` or !` ligatures (#5407).- These are upside down ? and !, resp.- + Fix footnotes in table caption and cells (#5367). This fixes a- bug wherein footnotes appeared in the wrong order, and with- duplicate numbers, when in table captions and cells.- We now use regular `\footnote` commands, even in the table- caption and the minipages containing cells. Apparently- longtable knows how to handle this.-- * HTML writer: Don't add data- prefix to RDFa attributes (#5403).-- * JATS writer: Ensure that plain strings go inside `<pub-id>` tag (#5397).-- * Markdown writer:-- + Better rendering of numbers (#5398). If the number is integral,- we render it as an integral not a float.- + Proper rendering of empty map in YAML metadata (#5398). Should- be `{}`, not empty string.- + Properly escape attributes in Markdown writer (#5369).- + Be sure implicit figures work in list contexts (#5368).- Previously they would sometimes not work: e.g., when they- occurred in final paragraphs in lists that were originally- parsed as Plain and converted later using PlainToPara.-- * Docx writer: Use `w:br` without attributes for line breaks (#5377).- We previously added the attribute `type="textWrapping"`, but- this causes problems on Word Online.-- * LaTeX template (Andrew Dunning):-- + Ensure correct heading/table order (#5365). Improve workaround- (#1658) for tables following headings. The new solution works whether- or not the `indent` variable is enabled.- + Remove `subparagraph` variable. The default is now to use run-in- style for level 4 and 5 headings (`\paragraph` and `\subparagraph`).- To get the previous default behavior (where these were formatted as- blocks, like `\subsubsection`), set the `block-headings` variable.- + Add pandoc to PDF metadata (#5388).- + Group graphics-related code (#5389).- + Move `\setstretch` after front matter (#5179). Ensures that- `\maketitle`, `\tableofcontents`, and so forth are not affected by- changes to line spacing.-- * Update data/jats.csl to avoid commas between name-part elements- (#5397).-- * Add support for golang (`go`) with `--listings` (#5427).-- * Text.Pandoc.Shared - improve `metaToJSON` behavior with numbers.- We now do a better job marshalling numbers from MetaString- or MetaInlines into JSON Number.-- * Text.Pandoc.Writers.Shared: `metaValueToJSON`: use Number Values for- integers. Pandoc's MetaValue doesn't have a distinguished number type,- so numbers are put in MetaStrings. If the MetaString consists- entirely of digits, we convert it to a Number. We should probably- consider adding a MetaNumber constructor to MetaValue, for better- round-tripping with JSON etc. This change aids round-tripping in- ipynb metadata fields, like `toc_depth`.-- * Text.Pandoc.Class: `fetchItem`: don't treat UNC paths as- protocol-relative URLs (#5127). These are paths beginning `//?/UNC/...`.-- * Text.Pandoc.ImageSize: Improve `pdfSize` so it handles- a wider range of PDFs (#4322, with help from Richard Davis).-- * Text.Pandoc.Pretty: avoid stack overflow by using strict sum (#5401).-- * Fix harmless error in file-scope code (#5422).-- * MANUAL.txt:-- + Improve 'header' and 'heading' usage (#5423, Andrew- Dunning). The term 'header' was being used where 'heading'- is more appropriate.- + Add paragraph on options affecting markdown in ipynb.-- * stack.yaml - remove -Wmissing-home-modules- This seems to cause problems with stack ghci. Remove RTS options.-- * Add ghc-options to cabal.project.-- * appveyor.yml - use ghc 8.6.4. Fixes segfault issues on Windows (#5037).-- * linux build process: Remove clone of pandoc-citeproc (#5366).- It wasn't being used; cabal.project specifies the version to use.--## pandoc 2.7.1 (2019-03-14)-- * Add tectonic as an option for --pdf-engine (#5345, Cormac Relf).- Runs tectonic on STDIN instead of a temporary .tex file, so that it- looks in the working directory for `\include` and `\input` like the rest- of the engines. Allows overriding the output directory- args with `--pdf-engine-opt=--outdir --pdf-engine-opt="$DIR"`.-- * Allow `-o/--output` to be used with `--print-default-data-file`,- `--print-highlighting-style`, `--print-default-template`.- Note that `-o` must occur BEFORE the `--print*` command on the command- line (this is documented, #5357).-- * LaTeX reader:-- + Support `\underline`, `\ul`, `\uline` (#5359, Paul- Tilley). These are parsed as a Span with class `underline`, as- with other readers.- + Ensure that `\Footcite` and `\Footcites` get put in a note.-- * ipynb reader:-- + Remove sensitivity to `raw_html`, `raw_tex` extensions.- We now include every output format. Pruning is handled by- `--ipynb-output`.- + Better handling of cell metadata. We now include even complex cell- metadata in the Div's attributes (as JSON, in complex cases, or- as plain strings in simple cases).-- * ipynb writer:-- + Recurse into native divs for output cell data (#5354).- + Render cell metadata fields from div attributes.-- * Docx writer: avoid extra copy of abstractNum and num elements- in numbering.xml. This caused pandoc-produced docx files to- be uneditable using Word Online (#5358).-- * Markdown writer: improve handling of raw blocks/inline.- We now emit raw content using `raw_attribute` when no more- direct method is available. Use of `raw_attribute` can be- forced by disabling `raw_html` and `raw_tex`.-- * LaTeX writer: Add classes for frontmatter support (#5353, Andrew Dunning)- and remove frontmatter from `scrreprt`.-- * LaTeX template:-- + Improve readability (#5363, Andrew Dunning).- + Robust section numbering removal (#5351, Andrew Dunning).- Ensures that section numbering does not reappear with custom- section levels. See <https://tex.stackexchange.com/questions/473653/>.- + Better handling of front/main/backmatter (#5348).- In pandoc 2.7 we assumed that every class with chapters would accept- `\frontmatter`, `\mainmatter`, and `\backmatter`. This is not so (e.g.- report does not). So pandoc 2.7 breaks on report class by including an- unsupported command. Instead of the `book-class` variable, we use two- variables, `has-chapters` and `has-frontmatter`, and set these- intelligently in the writer.-- * Text.Pandoc.Shared: Improve `filterIpynbOutput`. Ensure that- images are prioritized over text. `best` should include everything- for ipynb.-- * Tests.Old: specify `--data-dir=../data` to ensure tests can find- data files even if they haven't been installed. Remove old- `pandoc_datadir` environment variable, which hasn't done anything for a- long time.-- * MANUAL.txt: Add recommendation to use `raw_attribute` with ipynb (#5354).-- * Use cmark-gfm-hs 0.1.8 (note that 0.1.7 is buggy).-- * Use latest pandoc-citeproc, texmath.---## pandoc 2.7 (2019-03-03)-- * Use XDG data directory for user data directory (#3582). Instead of- `$HOME/.pandoc`, the default user data directory is now- `$XDG_DATA_HOME/pandoc`, where `XDG_DATA_HOME` defaults to- `$HOME/.local/share` but can be overridden by setting the- environment variable. If this directory is missing, then- `$HOME/.pandoc` is searched instead, for backwards compatibility.- However, we recommend moving local pandoc data files from- `$HOME/.pandoc` to `$HOME/.local/share/pandoc`. On Windows the- default user data directory remains the same.-- * Slide show formats behavior change: content under headers- less than slide level is no longer ignored, but included in- the title slide (for HTML slide shows) or in a slide after- the title slide (for beamer). This change makes possible- 2D reveal.js slideshows with content in the top slide on- each stack (#4317, #5237).-- * Add command line option `--ipynb-output=all|none|best` (#5339).- Output cells in ipynb notebooks often contain several different- versions of an output, with different MIME types, e.g. an HTML- table and a plain-text fallback. Specifying `--ipynb-output=best`- (the default) ensures that the best version for the output format- is used. `all` includes all versions, and `none` suppresses them- all, leaving output cells empty.-- * `asciidoctor` is now an output format separate from `asciidoc`,- to accommodate some minor implementation-specific differences- (currently just in the treatment of display math).-- * Add `latexmk` as an option for `--pdf-engine` (#3195).- Note that you can use `--pdf-engine-opt=-outdir=bar` to specify- a persistent temp directory.-- * Markdown reader:-- + Improve tight/loose list handling (#5285). Previously the- algorithm allowed list items with a mix of Para and Plain, which- is never wanted.- + Add newline when parsing blocks in YAML (#5271). Otherwise last- block gets parsed as a Plain rather than a Para. This is a- regression in pandoc 2.x. This patch restores pandoc 1.19- behavior.- + Make `yamlToMeta` respect extensions (#5272, Mauro Bieg).- This adds a `ReaderOptions` parameter to `yamlToMeta` [API change].- + Fix bug parsing fenced code blocks (#5304). Previously parsing- would break if the code block contained a string of backticks of- sufficient length followed by something other than end of line.-- * LaTeX reader: don't let `\egroup` match `{`. `braced` now actually- requires nested braces. Otherwise some legitimate command and- environment definitions can break.-- * Docx reader (Jesse Rosenthal):-- + Rename `getDocumentPath` as `getDocumentXmlPath`.- + Use field notation for setting `ReaderEnv`.- + Figure out `document.xml` path once at the beginning of parsing, and- add it to the environment, so we can avoid repeated lookups.- + Dynamically determine main document xml path (#5277).- The desktop Word program places the main document file in- `word/document.xml`, but the online word places it in- `word/document2.xml`. This file path is actually stated in the root- `_rels/.rels` file, in the `Relationship` element with an- `http://../officedocument` type.- + Fix paths in archive to prevent Windows failure (#5277).- Some paths in archives are absolute (have an opening slash) which, for- reasons unknown, produces a failure in the test suite on MS- Windows. This fixes that by removing the leading slash if it exists.- + Add comments to aid code readability.- + Trim space inside the last inline (#5273).- + Unwrap sdt elements in footnotes and comments (#5302).-- * Muse reader (Alexander Krotov):-- + Test that block level markup does not break `<verbatim>`.- + Add secondary note support.-- * ipynb reader: handle images referring to attachments. Previously- we didn't strip off the attachment: prefix, so even though the- attachment was available in the mediabag, pandoc couldn't find it.-- * JATS reader:-- + Fix parsing of figures (#5321). This ensures that a figure- containing a single image is parsed as a pandoc "implicit- figure" (i.e., a Para with a single Image whose title attribute- begins with `fig:`). More complex figures will still be parsed- as divs.- + Support `fig-group` block element (#5317).- + Handle citations with multiple references (#5310). The `rid`- attribute can have a space-separated list of ids.-- * AsciiDoc Writer: Add `writeAsciiDoctor` [API change, Tarik Graba].- Handle display math appropriately for Asciidoctor.-- * JATS writer: wrap figure caption in `<p>` to fix validation (#5290,- Mauro Bieg).-- * HTML writer:-- + Implement WAI-ARIA roles for (end)notes, citations, and- bibliography (#4213). Note that doc-biblioref is only used when- link-citations produces links, since it belongs on links.- + Include content (including speaker notes) in title slides- (#4317, #5237).-- * ipynb writer:-- + Ensure final newline.- + Only include metadata under `jupyter` field.- + Don't create attachments for images with absolute URIs,- including data: URIs (#5303).- + Keep plain text fallbacks in output even if a richer format is- included (#5293). We don't know what output format will be needed.- See the `--ipynb-output` command line option for a way to control- what formats are included in the output.-- * Markdown writer: use `markdown="1"` when appropriate for Divs:- when `native_divs` and `markdown_in_html_blocks` are disabled- but `raw_html` and `markdown_attribute` are enabled.-- * LaTeX writer:-- + Use right fold for `escapeString`. This is more elegant than- the explicit recursive code we were using.- + Avoid `{}` after control sequences when escaping.- `\ldots{}.` doesn't behave as well as `\ldots.` with the latex- ellipsis package. This patch causes pandoc to avoid emitting- the `{}` when it is not necessary. Now `\ldots` and other- control sequences used in escaping will be followed by either- a `{}`, a space, or nothing, depending on context.- + For beamer, include contents under headers superordinate to- slidelevel (#4317). Currently we keep the fancy title slide, and- add a new slide with the same title and whatever content was- under the header.-- * Powerpoint writer (Jesse Rosenthal): support underlines.- Use span with single class "underline" as in docx writer.-- * Muse writer: escape secondary notes (Alexander Krotov).-- * FB2 writer: add section identifiers support (#5229, John KetzerX).-- * Make `--fail-if-warnings` work for PDF output (#5343).-- * Lua filters (Albert Krewinkel):-- + Load module `pandoc` before calling `init.lua` (#5287). The file- `init.lua` in pandoc's data directory is run as part of pandoc's- Lua initialization process. Previously, the `pandoc` module was- loaded in `init.lua`, and the structure for marshaling was- set up after. This allowed simple patching of element- marshaling, but made using `init.lua` more difficult. Now, all- required modules are now loaded before calling `init.lua`. The- file can be used entirely for user customization. Patching- marshaling functions, while discouraged, is still possible via- the `debug` module.- + All Lua modules bundled with pandoc, i.e., `pandoc.List`,- `pandoc.mediabag`, `pandoc.utils`, and `text` are re-exported from the- `pandoc` module. They are assigned to the fields `List`, `mediabag`,- `utils`, and `text`, respectively.-- * Text.Pandoc.Lua (Albert Krewinkel):-- + Split `StackInstances` into smaller Marshaling modules.- + Get `CommonState` from Lua global. This allows more control over- the common state from within Lua scripts.-- * LaTeX template:-- + Support the `subject` metadata variable (#5289, Pascal Wagler).- + Add `\frontmatter`, `\mainmatter`, `\backmatter`- for book classes (#5306).-- * epub3 template: Add titlepage class to section (#5269).-- * HTML5 template: Add ARIA role `doc-toc` for table of contents (#4213).-- * Make `--metadata-file` use selected extensions (#5279, #5272, Mauro Bieg).-- * Text.Pandoc.Shared:-- + Remove `withTempDir` [API change].- + Add new exported function `defaultUserDataDirs` [API change].- + Add `filterIpynbOutput` [API change].- + `compactify`: Avoid lists with a mix of Plain and Para elements- (#5285).-- * Text.Pandoc.Translations: reorder alphabetically and remove `Author`- (#5334, Mauro Bieg).-- * Text.Pandoc.Extensions:-- + More carefully groom ipynb default extensions.- + Add `all_symbols_escapable` to `githubMarkdownExtensions`.-- * Text.Pandoc.PDF:-- + Use system temp directory when possible (#1192). Previously we- created temp dirs in the working directory, partly (a) because- there were problems using the system temp directory on Windows,- when their pathnames included tildes, and partly (b) because- programs like `epstopdf.pl` would not be allowed to write to- directories outside the working directory in restricted mode. We- now (a) use the system temp dir except when the path includes- tildes, and (b) set `TEXMFOUTPUT` when creating the PDF, so that- subsidiary programs can use the system temp directory. This- addresses problems that occurred when pandoc was used in a- synced directory (such as Dropbox).- + Change types of subsidiary functions to PandocIO, to allow- warnings to be threaded through (#5343).-- * Text.Pandoc.MIME: add WebP (#5267, Mauro Bieg).-- * Tests: avoid calling `findPandoc` multiple times.-- * Old tests: remove need for temp files by using `pipeProcess`.-- * Added simple ipynb reader/writer tests (#5274).-- * Rearrange `--help` output in a more rational way, with common- options at the beginning and options grouped by function (#5336).-- * trypandoc: Add JATS and other missing formats (Arfon Smith, #5291).-- * Add missing copyright notices and remove license boilerplate (#4592,- Albert Krewinkel).-- * Use latest basement/foundation on 32bit windows.-- * Use latest skylighting (#5328). Custom syntax definitions no- longer try to load `language.dtd`.-- * Require texmath 0.11.2.1-- * Use latest pandoc-citeproc (0.16.1.1).-- * MANUAL.txt:-- + Clarify variable substitution indentation in templates (#5338,- Agustín Martín Barbero).- + Reorder custom-styles section (#5324, Mauro Bieg).--## pandoc 2.6 (2019-01-30)-- * Support ipynb (Jupyter notebook) as input and output format.-- + Add `ipynb` as input and output format (extension `.ipynb`).- + Added Text.Pandoc.Readers.Ipynb [API change].- + Added Text.Pandoc.Writers.Ipynb [API change].- + Add `PandocIpynbDecodingError` constructor to Text.Pandoc.Error.Error- [API change].- + Depend on ipynb library.- + Note: there is no template for ipynb.-- * Add DokuWiki reader (#1792, Alexander Krotov). This adds- Text.Pandoc.Readers.DokuWiki [API change], and adds `dokuwiki`- as an input format.-- * Implement task lists (#3051, Mauro Bieg). Added `task_lists`- extension. Task lists are supported from markdown and gfm input.- They should work, to some degree, in all output formats, though in- most formats you'll get a bullet list with a unicode character for- the box. In HTML, you get checkboxes and in LaTeX/PDF output, a- box is used as the list marker. API changes:-- + Added constructor `Ext_task_lists` to `Extension`.- + Added `taskListItemFromAscii` and `taskListItemToAscii` to- Text.Pandoc.Shared.-- * Allow some command line options to take URL in addition to FILE.- `--include-in-header`, `--include-before-body`, `--include-after-body`.-- * HTML reader:-- + Handle empty `start` attribute (see #5162).- + Treat `textarea` as a verbatim environment (#5241) and preserve- spacing.-- * RST reader:-- + Change treatment of `number-lines` directive (Brian Leung,- #5207). Directives of this type without numeric inputs should- not have a `startFrom` attribute; with a blank value, the- writers can produce extra whitespace.- + Removed superfluous `sourceCode` class on code blocks (#5047).- + Handle `sourcecode` directive as synonynm for `code` (#5204).+## pandoc 3.10 (2026-06-03)++ * Add `--typst-input` CLI option (#11588). This allows one to+ pass parameters to typst, which are available at `sys.inputs`,+ just as `typst` itself does with its `--input` option.++ * Avoid trailing spaces in `--help` output (#11623).++ * Make groff the default pdf-engine for `ms` output (#11558).+ Formerly it was pdfroff.++ * Set default User-Agent request header to `pandoc/VERSION`.+ This can be overridden using the `--request-header` option.++ * Markdown reader:++ + Allow grid tables to be indented (#11671, Johan Larsson). Like+ the other table syntaxes (pipe, simple, and multiline tables)+ and block-level constructs generally, a grid table may now be+ indented by up to three spaces and still be recognized as a+ table. Previously the grid-table parser required the table to+ begin at the left margin, so an indented grid table was parsed+ as a paragraph.+ + Fix calculation of column widths for default columns in grid tables+ (#11664). This fixes a bug which produced too-narrow columns in some+ cases.+ + Don't produce empty Raw element with `--strip-comments` (#11625).+ + Fix quotes in inline notes (#11613, Andrew Dunning).+ + Allow spaces inside attributes in super/sub (#11589).+ + Simplify `checkNotes`, remove dead code+ + Various small performance optimizations.++ * HTML reader:++ + Parse aside as a Div with class "aside" (instead of using+ raw HTML) (#11626).+ + Add "header" class to Divs created from headers.++ * Docx reader:++ + Fix bug in bitmask checking (#8299). This led to some table rows+ being wrongly considered header rows.+ + Improve treatment of `tblHeader` element (#8299).+ If `tblHeader` exists but has `w:val="0"`, then don't consider+ the element a header.+ + With `citations` extension, prefer `citation-key` as the key for+ item data, if it is defined (#11581; cf. #10366, #11567). The `id` key+ used by Zotero is not exposed by their API and is generally not what+ is wanted when converting to biblatex.+ + Don't look to `ext` tags for image extent (#11580).+ This reverts a change from 7ff1b798c4e6681ef9050899442d80883116573a.+ The change was mistaken and could cause images to be parsed with+ the wrong sizes.++ * Man reader:++ + Support `auto_identifiers`, `gfm_auto_identifiers`, and+ `ascii_identifiers` extensions (#8852, Meher Chaitanya).+ Section headings parsed from .SH and .SS macros now receive+ auto-generated id attributes when the extension is enabled (as+ it is by default). This enables `--toc` to produce working anchor links.+ + Better handling of `.TP` macro (#11668). We parse these as+ DefinitionList items, but we previously sometimes stopped prematurely+ in including material in the definition. We should include everything+ until we hit a new indentation-changing macro.++ * Roff reader:++ + Handle `\` line continuation in table cells (#11635).++ * LaTeX reader:++ + Evaluate theorem name when used rather than evaluating it when+ the `\newtheorem` command is encountered (#11608). It may include+ macros only defined later.+ + Put identifier from label on table attributes rather than adding+ an enclosing Div (#11604).++ * Typst reader:++ + Fix issue parsing figure inside rotate or box (#11598).+ + Implement "rotate" as pass-through (#11531). Information about the+ angle is encoded in an attribute of an enclosing span or div.++ * RTF reader:++ + Fix tables parsed as deeply nested tables (#11682).++ * Docx writer:++ + Fix display of paragraph with just inline math (#11674).+ Word displays a paragraph containing just one inline math+ element as if it were display math. We don't want that,+ so we add a zero-width space to defeat this behavior.+ + Fix FirstParagraph style lost after heading with footnote (#11573).+ + Fix empty keywords in core document properties (#11666, Sai Asish Y).++ * OpenDocument/ODT writer:++ + Use predefined styles (#9316, #5086, #2747, #3426, #7336).+ Previously the OpenDocument writer emitted a fresh automatic+ style (L1..Ln, P1..Pn, T1..Tn) for nearly every list, list-item+ paragraph, block quote, preformatted block, and inline text+ style. This commit teaches the writer to reference the+ predefined styles that LibreOffice ships and that pandoc's+ reference.odt now exports:++ - Bullet lists use `List_20_1`; ordered lists with default start and+ decimal format use `Numbering_20_1`. Non-default ordered lists+ generate a single named override style (`Pandoc_Numbering_N`)+ memoised by (ListNumberStyle, ListNumberDelim); a non-default start+ value with the default format is expressed via `text:start-value`+ on the `text:list` element instead of a new style.+ - List-item paragraphs use `List_20_Bullet[_Tight]` and+ `List_20_Number[_Tight]`. The Tight variants are pandoc-specific+ (zero top/bottom margin) and are injected into the user's+ reference.odt if missing, just like the Skylighting token styles.+ - Block quotes use the predefined `Quotations` paragraph style+ directly. Nested block quotes use a single automatic style that+ inherits from Quotations and only adds extra margin-left, so a list+ inside a block quote now inherits its container's indent (#2747).+ - Preformatted blocks use `Preformatted_20_Text` directly.+ - Emphasis, Strong, Strikeout, Subscript, Superscript and Code spans+ use the predefined `Emphasis`, `Strong_20_Emphasis`, `Strikeout`,+ `Subscript`, `Superscript` and `Source_20_Text` text styles.+ - `paraStyle`/`paraStyleFromParent` no longer emit a wrapper automatic+ style when its only attribute would be `parent-style-name`; the+ parent name is returned directly.++ * EPUB writer:++ + Support multiple EPUB versions for raw content (#11628,+ nibras shami). This change ensures that raw content marked `epub2`+ will appear in (only) EPUBv2 output and content marked `epub3` will+ appear in (only) EPUBv3 output.++ * Typst writer:++ + Add zero-width space before a Span label if otherwise the label+ doesn't come after anything (#11568). (In this case typst will+ raise an error.)+ + Add newline after `#set text` directive (#11583). This ensures that+ blocks such as lists are parsed correctly after a `set text`.++ * LaTeX writer:++ + Fix `fr-CA` babel language mapping (#11575, Christophe+ Dervieux). Map fr-CA to `french` instead of deprecated `canadien`.+ The babel-french package's `canadien.ldf` is deprecated and+ broken: it never calls `\ldf@finish`, so `\bbl@main@language` is+ left undefined, causing babel to crash at `\begin{document}`.+ Since `canadien` was always just an unconditional alias for+ `french`, use `french` directly.++ * MediaWiki writer:++ + Handle some technically malformed URLs (#11562).+ + Fix escaping to avoid accidental lists (#11563).++ * Markdown writer:++ + Fix spacing issues with definition lists.+ - Properly handle the case where the first item is an indented+ code block (#11542).+ - Use correct indentation when `four_space_rule` extension is+ disabled.+ + Escape `:::` to avoid triggering unintended divs (#11571).++ * Man writer:++ + Don't run together successive definitions in a tight definition list+ with multiple definitions after a term (#11547).++ * Text.Pandoc.Writers.Shared:++ + `htmlAttrs`: use `data-` prefix when needed (#11680). This now+ behaves like the HTML writer, adding the `data-` prefix for+ custom attributes. This will affect, e.g., the mediawiki writer.++ * Text.Pandoc.Error:++ + Display IOError without stack trace (#11676).+ + Use single quotes around paths and format names (#11645) in+ displayed messages.++ * Text.Pandoc.App.Opt:++ + Opt has a new field `optTypstInputs` [API change].++ * Text.Pandoc.Options:++ + Change `defaultMathJaxURL` to use MathJax v4 (#11669).+ + ReaderOptions has a new field `readerTypstInputs` [API change].++ * Text.Pandoc.Citeproc.BibTeX:++ + Prevent wrong combination of `subtitle` and `titleaddon` with+ `maintitle` (#11677, Amir Dekel). When `maintitle` is present, `subtitle`+ should not be added to `title`, but only to `volume-title`.+ + BibLaTeX `inbook` should be CSL `book`, not `chapter` (#11552).+ + Allow `doi` field in bibtex (input and output) (#11617, Thomas Hodson).++ * Text.Pandoc.Translations:++ + Find lang-script type translations (#11648).+ E.g. for `zh-Hant-TW` look for (in order) `zh-Hant-TW.yaml`,+ `zh-Hant.yaml`, `zh.yaml`.++ * Text.Pandoc.Parsing:++ + Various small optimizations.+ + Fix bug in `extractIdClass` to ensure that both `id` and+ `class` are stripped from key/value attributes..++ * Text.Pandoc.Shared:++ + Various small optimizations.++ * ODT reference doc: demonstrate predefined styles (310327).+ This mirrors the demonstration content already present in+ the Word reference doc.++ * HTML templates:++ + Include pandoc-version in generator meta tag (#11624).+ + Styles: make screen-only CSS conditional (#11524, Keenan Brock).++ * EPUB templates:++ + Add dir attribute to html element (#11554).++ * LaTeX template: Define `\xmpquote` if not defined (#11528).+ `\xmpquote` is defined by the hyperref driver hyperxmp; we need a+ fallback for those who aren't using that.++ * Lua subsystem:++ + Add constructor `pandoc.TableBody`.++ * doc/lua-filters.md: Re-indent definition list items+ (Albert Krewinkel).++ * wasm/index.js: include filter to embed images for pdf-via-typst.+ Auto-inject `embed_images` filter for PDF via Typst. Otherwise+ conversion fails because we can't write the images in a temporary+ directory in the WASM sandbox. See jgm/pandoc#11584.++ * Fix test suite parallel execution failures (#11566).++ * linux/make_artifacts.sh: add `loong64` support (#11597,+ Olivier Benz).++ * `bash_completion.tpl`: add `groff` to `--pdf-engine` completions (#11555).++ * MANUAL.txt:++ + Improve description of reference links (#11643).+ + Update instructions for modifying reference.docx+ (#11600, Dan Jacobson). Mention LibreOffice as an alternative.+ + Clarify indentation rules for definition lists (#11542).+ + Move `--sandbox` to general options.+ + Reword restrictions on YAML metadata in commonmark (#11561).++ * Bump upper bound for time, tls, aeson.++ * Use latest releases of doclayout, asciidoc, texmath, typst,+ typst-symbols, pandoc-types, citeproc, commonmark, commonmark-pandoc,+ commonmark-extensions.++ * Add missing NAME heading to pandoc-lua, pandoc-server man pages (#11634).++## pandoc 3.9.0.2 (2026-03-19)++ * Typst template: fix regression introduced in 3.9.0.1 (#11538).++## pandoc 3.9.0.1 (2026-03-17)++ * WASM GUI:++ + Don't block everything while pandoc.wasm loads.+ + Fix bug with Unicode filenames (#11447).+ + Catch errors loading pandoc.++ * Docx reader:++ + Recognize media inside textboxes (#11053, Raymond Berger).+ + Properly handle media stored with packaged-rooted paths+ such as `/media` (#11518). This can be produced by the online version of Word.+ With this change, media stored at an absolute path will be stored+ with its original name and not given a SHA1-based name.+ + Preserve non-textbox content when unwrapping textboxes (#11510, #6893,+ #11412, #5394, #9633). Treat text inside a textbox containing an image+ as a figure caption.+ + Support `w:gridBefore` table row property (#11464, Jan Tojnar).++ * Typst reader:++ + Handle bibliography command (#11460). If this is present, a+ bibliography section is added to the document and the bibliography+ paths are added to `bibliography` in the metadata. This sets things+ up for using `--citeproc`.++ * Textile reader:++ + Handle block content in cells (#11455).++ * LaTeX reader:++ + Support `\footnotemark` and `\footnotetext` (#11450).+ These commands allow separating the footnote mark from its content, useful+ in tables, minipages, and other contexts where \footnote cannot be used+ directly.+ + Support supertabular environment (#11523, bodigrim).++ * ODT Reader:++ + Fix relative linked images (#11369, Tuong Nguyen Manh).+ + Recognize `Preformatted_20_Text` style Jan Tojnar+ This is used by LibreOffice, and we will switch to that as well.+ + Add block smushing logic (Jan Tojnar).+ + Support Preformatted Text style (#4841, Jan Tojnar).++ * Markdown reader:++ + Fix bug with `lists_without_preceding_blankline` (#11534).++ * Typst writer:++ + Don't add a carriage return after `\` for hard break (#11446).+ They are not necessary. Note that they can still be included+ if you use `--wrap=preserve` and add a newline in your source document.+ + Improve handling of data: URIs in images. Instead of using an+ SVG with a link containing the data URI (the solution of #10460),+ we can now simply produce a `bytes` object with the requisite bytes.+ Typst figures out the format automatically.+ + Fix escaping of quotes (#11463).+ + Include alt attributes on images (mcanouil).+ + Properly escape `.` after bracketed argument (#11511).++ * Docx writer:++ + Don't depend on `extractTarget` from Docx reader.+ + Fix section breaks with `--top-level-division` (#11482, #10578).++ * EPUB writer:++ + Add cover metadata for EPUB3 (#11479). This allows+ file managers to show cover thumbnails for EPUB3 files as well.+ + Update allowed values for EPUB3 metadata `identifier.scheme` (#11481,+ Pascal Wagler).++ * ODT writer:++ + Rename inline source class to match LibreOffice (#3390, Jan Tojnar).+ Rename the text style we use to represent `Code` inlines from+ `Source_20_Text` to `Source_Text`. This is the same name LibreOffice+ Writer uses so it will be recognized by the Character Styles section+ of the Styles menu.+ + Remove font size from inline source class (Jan Tojnar). This matches+ what LibreOffice Writer is doing. Also fixes literals inside+ headings being too small.+ + Modernize `Preformatted Text` & `Source Text` styles (Jan Tojnar).+ Presumably, `font-family-generic` and `font-pitch` will allow to find a+ replacement on systems that do not have `Courier New`.++ * Markdown writer:++ + Fix rendering of alerts (#11479). We only properly handled the case+ where the alert started with a paragraph, but it can start with a list+ or other block type.+ + Escape literal `&` that would trigger entity (#11490).++ * HTML writer:++ + For revealjs, default `scrollProgress` to `auto` (Christophe Dervieux).++ * PPTX writer:++ + Register content type for embedded fonts (#11492).++ * MediaWiki writer:++ + Use appropriate syntax for external images (#11494).+ Note that they will only be rendered as images if an option+ `$wgAllowExternalImages` is enabled in the MediaWiki instance.++ * ICML writer:++ + Support for image object styles (#11498, massifrg).+ This change allows users to style images in InDesign bysetting the+ `object-style` attribute in a pandoc Image, which is mapped to the+ AppliedObjectStyle attribute in the Rectangle element around an Image+ element in the resulting ICML.++ * JATS writer:++ + Improve representation of Divs (Albert Krewinkel). The writer now+ checks if the element used to represent (non-special) Divs has any+ `<boxed-text>` specific attributes. If it does, the writer keeps+ wrapping the Div contents in a `<boxed-text>`, as it did before.+ Otherwise, the writer falls back to the more appropriate `<p>` element+ or simply unwraps the Div if the wrapping element wouldn't have any+ attributes. The new behavior gives better semantic results in most cases,+ as `<boxed-text>` should be used for text that "is outside the flow of the+ narrative text", which doesn't apply to most divs.+ "Special" divs, like those used to mark sections, are not+ affected by this change.++ * Text.Pandoc.Writers.GridTable:++ + Normalize tables (#8102). Previously, if an invalid table was passed to+ `toTable`, an array index error could be raised. Normalizing the table+ forces it into a shape that won't allow this error.++ * Lua subsystem (Albert Krewinkel):++ + Add new function `pandoc.types.Sources` (#11441).++ * LaTeX template: properly handle keywords with commas.+ These need to be put in an `\xmpquote{..}` command. Closes #11528.++ * HTML styles template: avoid duplicate code selector.+ Consolidate two clauses. Closes #11484.++ * Revealjs template: fix type rendering of scroll-view options+ (Christophe Dervieux, #11486).++ * Typst template:++ + Use both place and block for title (Gordon Woodhull).+ Otherwise the title will be confined to the left column+ + Put title block in a conditional (#11529). This avoids an+ empty block for documents that lack metadata information.+ The empty block causes problems if `#set page` is used, as+ it will cause a page break.++ * Beamer template: add `logooption` variable (#11452, Sidney Mau).++ * Text.Pandoc.ImageSize:++ + Correctly handle percentage width, height on SVG (#11530).+ Previously we were getting image size of 0 when a percentage+ was specified for width or height on SVG. With this change,+ we simply ignore these percentages (becaues ImageSize doesn't+ know the size of the containing element).++ * Re-add `-threaded` to compile options in pandoc-cli.++ * Use released djot, asciidoc, texmath, typst.++ * Allow crypton 1.1, tls 2.2, http-client-tls 0.4.++ * Require auto-update >= 0.2.6 to fix server on macOS (#11488).++ * pandoc-cli.cabal: bump base min bound to 4.18 (same as pandoc).++ * MANUAL.txt:++ + Note that JSON may be used in YAML metadata blocks (#11525).+ + Update link for ICML in manual.+ + Fix outdated OPML spec URL in MANUAL.txt (#11504, Peter Briggs).++## pandoc 3.9 (2026-02-03)++ * Add support for compiling pandoc to WASM. (To build, `make+ pandoc.wasm`.) A stanza in `cabal.project` contains the+ necessary build modifications. We owe this almost entirely to+ TerrorJack, who created the original proof of context and+ came up with the necessary build flags and patches to some+ dependencies.++ `pandoc.wasm` has almost all the power of regular pandoc. The+ main limitations is that it operates in a WASM sandbox and thus+ cannot use HTTP to fetch resources and cannot run system commands.+ As a result, JSON filters cannot be used, `--embed-resources`+ works only with resources that have been explicitly provided in+ the WASM sandbox, and PDFs cannot be produced (since that requires+ running external commands). However, Lua filters can be used,+ as long as they do not run system commands.++ A JavaScript bridge module, `wasm/pandoc.js`, is provided; this+ handles the setup necessary to run `pandoc.wasm` in a browser.++ In addition, a full-featured GUI interface is provided in the+ `wasm` subdirectory. `make serve` from that directory and it+ will run locally, or visit <https://pandoc.org/app>. Note that+ once the relevant code has been downloaded by the browser, it runs+ entirely in the browser, and the conversions never touch a server.+ The GUI was developed in interaction with Claude Code. This app+ includes a WASM version of Typst and can produce PDF output via+ Typst.++ * Defaults files may now be either JSON or YAML (though a `.yaml`+ extension will still be assumed if the file has no extension).+ The structure of a JSON defaults file is isomorphic to that of+ a YAML defaults file.++ * Variable expansion now works even for the `defaults` field of+ defaults files (#8024, Jacob Larkin).++ * `--extract-media` will now create a zip archive containing the media+ (instead of a directory) if the path provided has a `.zip` extension.++ * Processing with `--citeproc` is now affected by a+ `reset-citation-positions` class on headings. When the+ `reset-citation-positions` class is added to a top-level+ heading, `--citeproc` will reset position information at that+ point in the document. This is needed in order to ensure that+ the first citation in a chapter to a work that has been cited+ in a previous chapter will not be in abbreviated form.++ * RST reader:++ + Fix definition lists where term ends with `-` (#11323).+ This reverts some old code giving special treatment to+ lines ending in hyphens; I don't understand why it was+ there, because rst2html does not seem to do this.++ * HTML reader:++ + Revert an earlier change that caused style tags in the body+ to be ignored (#10643, #11246).+ + Parse inline style elements as RawInline (#10643, #11246).++ * Markdown reader:++ + Fix parsing of inline math (`$...$`) (#11311, benniekiss).+ Do not allow blank lines before closing `$` delimiter. This brings the+ parser in line with the documentation.+ + Allow superscripted spans (#11409). These were being parsed as inline+ notes. Now we disallow an inline note followed by+ attributes, as this is almost certainly meant to be a span.+ + Support `alerts` extension for pandoc markdown (#9716). It is not+ enabled by default.++ * MediaWiki reader:++ + Add behavior switches support (#11354, Anton Melnikov).+ They add a field to metadata without producing any text.+ + Handle non-recognized tags as plain text (#11299).+ + Better handling of inline tags (#11299). `<mark>`, `<var>`,+ `<samp>`, and `<kbd>` now produce Code or Span elements with+ classes, which can be handled by multiple output formats,+ instead of simply being parsed as raw HTML tags.++ * RTF reader:++ + Ensure a new paragraph on `\pard` (#11361, Tuong Nguyen Manh). New+ paragraphs may start with `\pard` alone without an explicit paragraph+ break with `\par` preceding it.+ + Improve hyperlink parsing more (#10942, Tuong Nguyen Manh).+ Both the field instruction and its result may be ungrouped.+ + Fix bug where list items were incorporated into a following table+ (#11364).++ * ODT reader:++ + Add table row and column spans (#11366, Tuong Nguyen Manh).+ Parse the number-rows-spanned and number-columns-spanned attributes to+ create Cells for the Table.++ * DocBook reader:++ + Support "role" attribute (#11255, Yann Trividic). The `role`+ attribute is parsed and added to Pandoc AST elements, using a+ wrapper Div if needed.+ + Omit empty title when not required (#11422).+ This affects example and sidebar elements.+ + Fix adding wrong metadata (#11300, Tuong Nguyen Manh). Now+ keep track of the current element stack to only add metadata+ if inside an appropriate parent element.++ * DocBook/JATS reader:++ + Don't export surrounding space from inline elements (#11398). Previously+ we would export leading and trailing space inside elements like+ emphasis or ulink so they appeared outside the resulting pandoc Inline+ (Emph or Link). This is not really motivated; DocBook and XML in general+ treats leading and trailing whitespace in this context as significant.++ * Docx reader:++ + Handle tables without `tblGrid` (#11380).+ + Look inside v:rect as well as v:shape (#11412).++ * LaTeX reader:++ + Handle more quote macros from fontspec and ngerman babel (#6120).++ * Org reader:++ + Don't include 'example' class when parsing org example blocks (#11339).+ These are just unmarked code blocks.++ * Texinfo writer:++ + Improve handling of certain code blocks (#11312).+ MediaWiki, for example, will parse a code block containing+ formatting as a sequence of Code elements separated by+ LineBreaks. For this we now use a texinfo example block.++ * Typst writer:++ + Escape hyphens when needed (#11334).++ * HTML writer:++ + Include all classes on highlighted code elements (#11423). Previously,+ only the language class was included, and the others were dropped.+ + Slide formats: Make `. . .` pause work in nested blocks (#7201, #7582).+ + For revealjs, add idiomatic highlight.js support (#11420, Claude Opus 4.5).+ When using `--syntax-highlighting=idiomatic` with reveal.js output, pandoc+ now generates HTML compatible with reveal.js's built-in highlight.js plugin:+ Code blocks use `<pre><code class="language-X">` format.+ The template loads highlight.js CSS, JS, and RevealHighlight plugin.++ * Markdown writer:++ + Ensure that `\ ` line breaks are used for commonmark.+ + Use setext for headers containing line breaks for commonmark (#11341).+ + Allow display math to start/end with space (#11384).+ This reverts to earlier < 3.7 behavior.+ + Properly handle tables with footers (#11416).++ * JATS writer:++ + Fix XML output for nested figures (#11362, Albert Krewinkel).+ Subfigures are now wrapped inside a `<fig-group>` element. Furthermore,+ figure content that isn't allowed as children of `<fig>` elements, such as+ raw text, gets wrapped in `<p>` elements to ensure schema-conforming XML.++ * AsciiDoc writer:++ + Use doubled delims in more contexts (#11362). Also escape the `#` character.+ + Use a span with role for SmallCaps (#11374).+ + Export spaces inside delimited constructs like emph.++ * Docx writer:++ + Skip directory entries when building media overrides (#11379, You Jiangbin).+ Pandoc's docx writer was previously adding an `<Override>` for+ `/word/media/` in `[Content_Types].xml` when the reference doc contains+ media, which violates OPC rules and causes Word to report corruption.+ + Refactor the monolithic `writeDocx` into a number of smaller functions+ (Claude Opus 4.5).+ + Replace generic XML traversal with direct path navigation (Claude+ Opus 4.5). Instead of using Data.Generics `everywhere` to traverse the+ entire XML tree when setting language attributes, navigate directly to+ the known path `w:docDefaults/w:rPr/w:lang`. This is more efficient and+ removes the dependency on `Data.Generics`.++ * EPUB writer:++ + Don't use footnote backlinks for EPUBv3. Here we use aside elements,+ which are popups, and the backlinks are not needed; in some readers+ they cause a redundant number to appear, since the reader adds a note number.++ * MediaWiki writer:++ + Use Doc Text instead of Text for document construction (with Claude Open 4.5).+ This refactors the writer to use Text.DocLayout combinators (vcat, hcat,+ literal, blankline, cr, chomp) for building output, following the pattern+ used by other text format writers (RST, Markdown, Man). This enables+ better control over line spacing and paragraph separation.+ + Improve blank space around div elements (#11417). This is merely cosmetic.++ * PPTX writer:++ + Support notes field in metadata for title slide (#5844, Chris Callison-Burch).+ This adds support for a `notes` field in the YAML metadata block that will+ be used as speaker notes for the title slide in PowerPoint output.+ Previously, there was no way to add speaker notes to the title slide since+ it is generated from metadata rather than from content blocks.++ * LaTeX writer:++ + Add PDF standard support via DocumentMetadata (#11407, Gordon Woodhull+ with Claude Opus 4.5). The `pdfstandard` variable can be+ used to specify PDF standards (PDF/A, PDF/X, PDF/UA) in+ LaTeX output. This uses LaTeX's `\DocumentMetadata`+ command, which requires LuaLaTeX. PDF version requirements+ are automatically inferred, but can be explicitly overridden.+ Automatic tagging is added for standards that require it.++ * Typst template:++ + Fix keywords usage. (#11317, har7an).+ + Disable hyphenation for title, subtitle (#11375).+ + Improve accessibility of definition lists (#11436). Before this+ change, our show rule produced an error when typst was run with+ `--pdf-standard=ua1`.++ * HTML5 template:++ + Conditionally include lang attribute, instead of providing+ it with an empty value.++ * JATS template:++ + Fix author prefix placeholder (#11381, Christophe Dervieux).++ * Text.Pandoc.Citeproc:++ + Fix biblatex parsing of `@commentary` entries (#11322).+ + Fix typo affecting `jurisdiction` biblatex type (#11321).+ + Avoid adding an extra space at the beginning of a Cite.++ * Text.Pandoc.Shared:++ + Export `hasLineBreaks` [API change]. This was formerly+ defined in the DocBook writer but more generally useful.++ * Text.Pandoc.PDF:++ + Add `SOURCE_DATE_EPOCH` to verbose environment variable info.++ * Text.Pandoc.Class:++ + Factor out `openURL` into Text.Pandoc.Class.IO.HTTP (unexported module).++ * Lua subsystem (Albert Krewinkel):++ + Mark readers and writers with their types (#11367). The+ `pandoc.readers` and `pandoc.writers` maps now have string values+ instead of boolean values. The string signals the type of the+ reader/writer, `"text"` for TextReader/TextWriter and `"bytestring"`+ for ByteStringReader/ByteStringWriter.+ + Support equallity checks of LogMessage objects.+ + Add function `pandoc.with_state` (#10859). The function allows+ to run a callback with a modified pandoc state. This provides+ the ability to temporarily modify the resource path, the user+ data directory, and the HTTP request headers.+ + Let `pandoc.with_state` error on unknown options (#11376).+ + Add function `pandoc.utils.documentation` (#10999).+ This is now used to generate much of the Lua API documentation.++ * Text.Pandoc.App:++ + Remove redundant check for asciidoc in UnknownReader.++ * Text.Pandoc.Logging:++ + Add `pretty` field to ToJSON instance for LogMessage.+ This just reproduces the output of `logMessage`, for convenience for those+ who are using the JSON output outside of Haskell.++ * Text.Pandoc.Error:++ + Change PandocHttpError constructor to take a Text instead of an+ HttpException as the second argument (see #10980) [API change]+ Motivation: exposing HttpException in the public API makes it+ difficult to provide a version of pandoc that can be compiled+ to wasm, which currently can't handle the network libraries.+ + Define `displayException` for PandocError. This is a behavior change,+ not an API change, since there was already a definition that defaulted+ to using Show. The change here is that we use `renderError` for+ a more human-readable version.++ * Drop support for compilation with GHC versions < 9.6.++ * Use released citeproc 0.13, djot 0.1.3, skylighting-format-blaze-html+ 0.1.2 (see #11423), texmath 0.13.1, asciidoc 0.1.0.1, typst-0.9,+ hslua 2.5.++ * Add `-Wno-deriving-typeble` to cabal ghc-options for ghc >= 9.12.++ * Add `http` cabal flag (#10980). This allows pandoc to be+ compiled without support for making HTTP requests, which is+ useful when WASM is the target.++ * pandoc-lua-engine has a new build flag `repl`, allowing support+ for the Lua repl to be disabled for the wasm build.++ * We now sign Windows artifacts with a code signing+ certificate provided by SignPath.++ * Mention Excel in cabal description.++ * Makefile: remove some obsolete targets.++ * MANUAL.txt:++ + Fix typo about `--chunk-template` (#11358, Albert Lei).+ + Fix link for bbcode_steam (#11389).+ + Small rewrite of syntax-highlighting info.+ + Fix defaults.yaml example for `wrap`.++ * Fix a few mistakes in the contributing docs. (#11318, har7an).++ * Fix a couple small errors in `doc/lua-filters.md`,+ `doc/custom-writers.md`, and `doc/custom-readers.md`+ (#11408, #11388).++## pandoc 3.8.3 (2025-12-01)++ * Add `asciidoc` as an input format (#1456).++ * Add `xlsx` (Microsoft Excel) as an input format (Anton Antich).+ Each worksheet turns into a section containing a table.++ * Add `pptx` (PowerPoint) as new input format (Anton Antich).++ * Add `bbcode` as a new output format (#11242, reptee). Several variants+ of BBCode are also supported: `bbcode_fluxbb` (FluxBB), `bbcode_phpbb`+ (phpBB), `bbcode_steam` (Hubzilla), `bbcode_hubzilla` (Hubzilla),+ and `bbcode_xenforo` (xenForo).++ * New exported module Text.Pandoc.Readers.AsciiDoc,+ exporting `readAsciiDoc` [API change].++ * New module `Text.Pandoc.Readers.Pptx`,+ exporting `readPptx` (Anton Antich) [API change].++ * New module `Text.Pandoc.Readers.Xlsx`,+ exporting `readXlsx` (Anton Antich) [API change].++ * LaTeX reader:++ + Revert `\linebreak` as LineBreak (#11272). `\linebreak` is more+ of a hint, it shouldn't produce a hard break.+ + Better handling of `\makeatletter` in parsing raw LaTeX (#11270).+ + Fix spurious paragraph breaks in math environments (#11265,+ Emmanuel Ferdman). Previously, a math environment with extra+ space before the `\end` would get rendered with a blank line,+ which LaTeX treats as a paragraph break.+ + Change type on `rawLaTeXParser` in Text.Pandoc.LaTeX.Parsing.+ The preparser doesn't need to return a value.+ + Fix `rawTeXParser` (#11253). Make macro expansion in raw LaTeX+ depend on the setting of the `latex_macros` extension. Previously+ macros were always expanded, even in raw TeX in markdown. In+ addition, there was previously a bug that caused content to be+ garbled in certain cases.+ + Handle `ifstrequal` at a lower level, like the other `if`+ commands (#11253).+ + Move `ifstrequal`, `iftoggle`, etc., which were misplaced in+ `environments`, to `blockCommands`, so these commands work properly.++ * Docx reader:++ + Handle REF link instruction (#11296, Ezwal).+ + Check recursively for caption styles (Albert Krewinkel).+ The docx reader uses caption styles to identify figures and+ captioned tables. It now checks for known caption styles in the+ full styles hierarchy of a paragraph instead of just checking+ the style directly. This allows to recognize caption styles that+ are built on top of the basic *caption* style, as is sometimes+ the case in sophisticated styles.++ * Markdown reader:++ + Fix performance issue in links with `'` (#10880).++ * Typst reader:++ + Handle document metadata and `#title` (jgm/typst-hs#80).+ Note that previously, the typst reader never returned document+ metadata. Now it does, even if the typst document does not contain+ a `#title` function that would result in actually printing the+ title block.++ * Djot reader:++ + Add Space elements (#11250). Previously we just got big+ Str elements with spaces included. But many pandoc writers+ assume that breakable spaces will be Space elements, and this+ is also required for automatic wrapping.++ * RST reader:++ + Correctly handle intraword emphasis (#11309).++ * Text.Pandoc.Readers:++ + Export `readAsciiDoc`, `readXlsx`, `readPptx` [API change].++ * New module Text.Pandoc.Writers.BBCode, exporting+ `writeBBCode`, `writeBBCodeSteam`, `writeBBCodeFluxBB`,+ `writeBBCodePhpBB`, `writeBBCodeHubzilla`, `writeBBCodeXenforo`+ [API change].++ * LaTeX writer:++ + Make level 1-3 headings work inside blockquotes (#11281, James Barlow).+ + Remove `split` from list of math environments (#11274).+ + Improve handling of math environments in tex math (#11266).++ * HTML writer:++ + Add reveal.js `scroll` and `scrollSnap` options to writer and+ template (#10052, Asliddinbek Azizovich).+ + Use 'defer' when including mathjax script, as recommended in+ MathJax docs (#11292).++ * ANSI writer:++ + Apply row spans in tables (#10149, Tuong Nguyen Manh).+ The ANSI writer is now able to keep track of row spans and apply+ them in rows.++ * Pptx writer:++ + Handle reference doc without slides (#7536, Tuong Nguyen Manh).++ * AsciiDoc writer:++ + Add more table features (#11267, Tuong Nguyen Manh):+ Row span and column span, footer row, individual horizontal+ cell alignment.++ * Typst template:++ + Fix font for compatibility with typst 0.14, which doesn't+ permit an empty array for `font` (#11238).+ + Re-add `columns` to typst template (#11259), fixing a+ pandoc 3.8 regression.+ + Fix syntax for bibliography inclusion (#11233, Mickaël Canouil).+ Previously the syntax was wrong when multiple bibliography files+ were specified. Typst expects an array.++ * Text.Pandoc.Writers:++ + Export `writeBBCode`, `writeBBCodeSteam`, `writeBBCodeFluxBB`,+ `writeBBCodePhpBB`, `writeBBCodeHubzilla`, `writeBBCodeXenforo`+ [API change].++ * Text.Pandoc.Writers.Shared:++ + Add functions `insertCurrentSpansAtColumn`, `takePreviousSpansAtColumn`+ and `decrementTrailingRowSpans` for applying and keeping track of+ RowSpans over multiple rows (#10149, Tuong Nguyen Manh). [API change]++ * Text.Pandoc.Logging:++ + Change message for missing HTML title warning (#11307). Suggest+ setting the `pagetitle` variable instead of setting `title` in metadata.++ * Lua subsystem:++ + Preserve common state of custom Lua readers (Albert Krewinkel).+ The common state is transferred to Lua when calling a custom Lua+ reader, and is now also transferred back after the reader has+ finished. This ensures that info messages, warnings, and+ mediabag entries are available to the main program and all+ subsequent processing steps.++ * Text.Pandoc.PDF:++ + Avoid converting SVG to PDF when non-TeX PDF engine is used (#11275).+ This fixes a 3.8 regression, which caused documents with SVGs to+ raise an error when converted to PDF using WeasyPrint.+ + Fix a 3.8 regression with typst and smart quotes (#11256).+ Before 3.8, the default behavior when producing a PDF `-t typst`+ was to produce smart quotes according to typst's defaults.+ (This could be defeated by specifying `-t typst-smart`.)+ This behavior broke in 3.8 because of a change to Text.Pandoc.PDF.+ This change caused `smart` to be disabled for all formats when+ producing PDFs, when before it was only disable for TeX-based+ formats (to avoid bad ligatures). This commit restores the old+ behavior. Possibly the regression also other affects other+ non-TeX formats, e.g. HTML.++ * Text.Pandoc.Shared:++ + Add functions `allRowsEmpty` and `tableBodiesToRows` from the+ RST writer for reuse in other writers. (Tuong Nguyen Manh) [API+ change].++ * Text.Pandoc.Citeproc:++ + Allow formatting in locator to be transmitted to citeproc.+ We do this indirectly, by rendering the formatting using the+ HTML tags that citeproc recognizes. Fixes jgm/citeproc#68+ and jgm/citeproc#163. Note that formatting is only possible for+ locators given in the explicit form, surrounded by curly braces.+ It won't work for implicit locators, since these expect+ number-like expressions.++ * New non-exported module Text.Pandoc.Readers.OOXML.Shared+ containing functions factored out from+ Text.Pandoc.Readers.Docx.Util (Anton Antich).++ * Tests: The common file `nativeDiff` has been extracted from+ the Docx and Pptx text files and put in Tests.Helpers.++ * Use asciidoc 0.1, djot 0.1.2.4, texmath 0.13.0.2, typst 0.8.1,+ citeproc 0.12.++ * MANUAL.txt:++ + Improve `implicit_figure` documentation (#11082).+ + Give both forms of options when referring to them (#11306).++ * Update INSTALL.md (#11271).++## pandoc 3.8.2.1 (2025-10-20)++ * HTML reader: allow blank space between open and close `iframe`.++ * RTF reader: improve hyperlink parsing (#11211).++ * Org reader:++ + Parse parameter lists on unknown blocks (#11188, Albert+ Krewinkel). The reader tries to parse the rest of the opening+ line of a block, e.g., `#+begin_myblock …`, as a parameters+ list. It first assumes that the parameters are in lisp-style+ (`:key value`), then alternatively tries to read python-style+ key-value pairs (`key=value`) and falls back to reading the+ entire remaining line as a single `parameter` attribute.+ + Add support for dynamic blocks.++ * Docx writer: properly handle nested comment spans (#8189, #6959,+ mourino).++ * RST writer: Don't use simple tables with RowSpans (#11214,+ Tuong Nguyen Manh).++ * Typst writer: Escape open paren after non-space (#11210).+ This fixes an issue that occurs if an open paren comes+ right after e.g. `#strong[test]`.++ * Typst template: ensure that title block is properly centered (#11221).++ * LaTeX writer/template: small fix for unnumbered tables for+ compatibility with older LaTeX installations (#11201).+ Thanks to @priiduonu for the solution.++ * MANUAL.txt: Fixed missing backtick (#11209, FoxChillz).++ * Correct anchor references to `pandoc.text` module documentation (#11111,+ Emmanuel Ferdman).++ * Fixed golden test regeneration in Docx reader test.++ * Allow unicode-data 0.8.++ * Use citeproc 0.11. This fixes a significant performance+ regression in pandoc 3.8, which was due to a rewrite of the+ default chicago-author-date.csl file. Performance with `--citeproc`+ is now on par with what we had in pandoc 3.7, even with the+ revised Chicago styles.++## pandoc 3.8.2 (2025-10-05)++ * Markdown reader/writer: implement new `table_attributes` extension+ (#10884). When `table_attributes` is enabled (as it is by default for+ pandoc's Markdown), attributes can be attached to a table by+ including them at the end of the caption. Previously the writer+ would emit an identifier in this position, but the reader didn't+ handle it. Now arbitrary attributes are allowed, and they work in+ both the reader and writer.++ * Typst writer: don't add superfluous semicolons (#11196).+ Previously we added semicolons after inline commands not+ followed by spaces, but mainly this was to deal with one issue:+ the presence of a semicolon after an inline command, which+ would be swallowed as a command separator (#9252).+ This commits adopts an approach that should avoid so many+ superfluous semicolons: it escapes semicolons that might come+ right after a command.++ * Typst template: fix 3.8 regression in which links disappear+ (#11194). A template change in 3.8 added a show rule for links which+ causes them to disappear except in special cases.++ * Text.Pandoc.Parsing: rewrite `oneOfStrings` more efficiently.++ * LaTeX writer: Fix strikeout in links (#11192, Tuong Nguyen Manh).+ As in #1294 `\url` and `\href` need to be protected+ inside an mbox for `soul` commands.++ * Text.Pandoc.Extensions: Add `Ext_table_attributes` constructor for+ `Extension` [API change].++ * Use released texmath 0.13.0.1.++ * Update FSF contact information in COPYING (#11183, Bensun Muite).++ * MANUAL.txt: remove some redundancy (#11178, Reuben Thomas).++## pandoc 3.8.1 (2025-09-29)++ * New output format `vimdoc` (Vim documentation format) (#11132, reptee).++ + [API change] Added module Text.Pandoc.Writers.Vimdoc, exporting+ `writeVimdoc`.++ * Markdown reader:++ + Improve superscript/subscript/inline note parsing (#8652).+ We do not allow inline notes to be followed by `(` or `[`.+ Otherwise, we parse inline notes before superscripts.+ Also, the sub/superscript parsers have been adjusted so that they+ really exclude unescaped spaces (as they did not before, when the+ spaces occurred in nested inlines).+ + Fix simple table alignment (#11136, Tuong Nguyen Manh). Take wide+ characters into account when determining the alignment.++ * LaTeX reader:++ + Ignore `\pandocbounded` (#11140).++ * XML reader:++ + Parse `<MetaString>` (#11137, massifrg).++ * Typst reader:++ + Add support for reading typst pagebreak (#11101, Raymond Berger).+ The pagebreak is parsed as a HorizontalRule inside a wrapper Div+ with class `page-break`.++ * Docx reader:++ + Handle figures in indented paragraphs (#11028).+ + Change default for textwidth. This should only be used if `sectPr`+ is not found.+ + Properly calculate table column widths (#9837, #11147).+ Previously we assumed that every table took up the full text+ width. Now we read the text width from the document's `sectPr`.+ + Use Tasty.Golden for Docx reader tests. This way we can update+ them with `--accept`.++ * RST reader:++ + Fix regression in simple table parsing (#11150).+ + SkippedContent warning if table directive contains+ non-tabular content.+ + Simple tables: leading space in a cell should not cause the contents+ to be parsed as a block quote (#11146).+ + Parse `:alt:` on figure (#11140). Also give a better default if+ `alt` is not specified, using the stringified caption rather+ than the filename.+ + Support col spans for simple tables (Tuong Nguyen Manh).++ * Markdown writer:++ + Improve handling of implicit figures (#11140).+ Allow implicit figures when alt text differs from caption+ (in this case, we use an image attribute to add the alt).+ + Use approximate pipe tables when it's the only option (#11128).+ If we have a table with row/colspans that can rendered as an+ approximate pipe table (without row/colspans), and no other table+ format is enabled that could render the table, we fall back to+ an "approximate" pipe table, with no row/colspans.++ * RST writer:++ + Ensure blank line before directives (#11162).+ + Add col spans for simple tables (#10127, Tuong Nguyen Manh).++ * OpenDocument writer:++ + Add missing table elements (#10002, Tuong Nguyen Manh).+ Add missing header rows after the first one,+ footer rows as well as TableBody header rows.++ * Docx writer:++ + Fix regression (from 3.8) in highlighted code (#11156).++ * Powerpoint writer:++ + Handle single column (Tuong Nguyen Manh).++ * Typst writer:++ + Fix syntax highlighting (#11171, completes #10525).+ Previously the native typst highlighting was always used, regardless+ of the setting of `--syntax-highlighting`. With this change,+ `--syntax-highlighting=none` and `--syntax-highlighting=<stylename>`+ (with skylighting style) will work.++ * LaTeX writer:++ + Make beamer footnotes compatible with pauses (#5954).+ Previously they would appear before the content to which+ the note was attached, when there were pauses in a slide.+ + Avoid `\_` in bibliography variable (#11152).+ + Ensure that unlabelled tables don't increment counter (#11141).+ + Protect VERB in caption (#11139, Tuong Nguyen Manh).+ + Don't add links to TOC (#11124, Albert Krewinkel).+ + Fix strikeouts in beamer title (#11168, Tuong Nguyen Manh).++ * LaTeX template: Add `shorthands` variable for LaTeX output+ (#11160). If true, pandoc will allow language-specific shorthands+ when loading babel. (This is helpful, for example, in getting+ proper spacing around French punctuation.)++ * epub.css: Remove coloring for `a, a:visiting` (#11174).+ This was causing links in iOS books app not to be distinguished in+ any way (since underlining is not used there).++ * Text.Pandoc.Parsing:++ + [API chage] (Tuong Nguyen Manh). New functions `tableWithSpans`,+ `tableWithSpans'`, `toTableComponentsWithSpans` and+ `toTableComponentsWithSpans'` take a list of lists of+ (Blocks, RowSpan, ColSpan) to parse a Table with different RowSpan and+ ColSpan values accordingly. New helper functions `singleRowSpans` and+ `singleColumnSpans` help set all RowSpans or ColSpans to be 1 in case+ the table format only allows setting one or the other.++ * Text.Pandoc.Class:++ + Let `fetchItem` fail if the HTTP request is not+ successful (Albert Krewinkel). HTTP requests that don't return a 200+ error code are now treated as an error. This ensures that a warning is+ triggered when using `--embed-resources` or `--extract-media`.++ * Text.Pandoc.Writers.Shared:++ + Add new function `removeLinks` [API change] (Albert Krewinkel).+ The function converts links to spans. It is used, for example, to avoid+ nested links. The HTML writer used to put the description of nested links+ into small caps, but uses a simple *span* now.++ * Text.Pandoc.Highlighting: export typst functions+ [API change]. New exported functions `formatTypstBlock`,+ `formatTypstInline`, `styleToTypst`.++ * Text.Pandoc.XML:++ + Add `fetchpriority` to list of HTML attributes (#11176).++ * Allow unicode-data 0.7.++ * Use released djot 0.1.2.3. Fixes a bug in which indentation+ was swallowed in a code block inside a blockquote.+++## pandoc 3.8 (2025-09-06)++ * Add a new input and output format `xml`, exactly representing a Pandoc+ AST and isomorphic to the existing `native` and `json` formats (massifrg).+ XML schemas for validation can be found in `tools/pandoc-xml.*`.+ The format is documented in `doc/xml.md`. Pandoc now defaults to this+ reader and writer when the `.xml` extension is used.++ Two new exported modules are added [API change]:+ Text.Pandoc.Readers.XML, exporting `readXML`, and+ Text.Pandoc.Writers.XML, exporting `writeXML`.+ A new unexported module Text.Pandoc.XMLFormat is also added.++ * Add a new command line option `--syntax-highlighting`; this takes+ the values `none`, `default`, `idiomatic`, a style name, or a path to a+ theme file. It replaces the `--no-highlighting`, `--highlighting-style`,+ and `--listings` options, which will still work but with a deprecation+ warning. (Albert Krewinkel)++ * Create directory of output file if it doesn't exist (#11040).++ * Update `--version` copyright dates (#10961), and use a hardcoded+ string "pandoc" for the program name in `--version`, per GNU+ guidelines.++ * Add `smart_quotes` and `special_strings` extensions (Albert Krewinkel).+ Currently these only affect `org`. Org mode makes a distinction between+ smart parsing of quotes, and smart parsing of special strings like `...`.+ The finer grained control over these features is necessary to truthfully+ reproduce Emacs Org mode behavior. Special strings are enabled by default,+ while smart quotes are disabled.++ * Remove the old `compact_definition_lists` extension. This was+ neded to preserve backwards compatibility after pandoc 1.12+ was released, but at this point we can get rid of it.++ * Make `-t chunkedhtml -o -` output to stdout (as documented), rather+ than creating a directory called `-` (#11068).++ * RST reader: Support multiple header rows (#10338, TuongNM).++ * LaTeX reader:++ + Support soft hyphens (Albert Krewinkel).+ + Parse `\minisec` as unlisted level 6 headings (#10635, Albert Krewinkel).+ + Support `\ifmmode` (#10915).+ + Change handling of math environments (#9711, #9296).+ Certain environments in LaTeX will trigger math mode and can't+ occur within math mode: e.g., `align` or `equation`. Previously+ we "downshifted" these, parsing an `align` environment as a+ Math element with `aligned`, and an `equation` environment as a+ regular display math element. With this shift, we put these in+ Math inlines but retain the original environments.+ texmath and MathJax both handle these environments well.++ * Typst reader:++ + Fix addition of image path prefix to use posix separator.+ + Properly resolve image paths in included files (#11090).+ + Handle inline-level show rules on block content (#11017).+ Typst allows things like `smallcaps` to be applied to block-level+ content like headings. This produces a type mismatch in pandoc,+ so before processing the output of typst-hs, we transform it,+ pulling the block-level elements outside of the inline-level+ elements.++ * Org reader:++ + Improve sub- and superscript parsing (Albert Krewinkel).+ Sub- and superscript must be preceded by a string in Org mode. Some text+ preceded by space or at the start of a paragraph was previously parsed+ incorrectly as sub- or superscript.+ + Allow "greater block" names to contain any non-space char (#4287,+ Albert Krewinkel).+ + Accept quoted values as argument values (#8869, Albert Krewinkel).+ + Recognize "fast access" characters in TODO state definitions+ (#10990, Ryan Gibb).+ + Improve org-cite parsing: Handle global prefix and suffix properly.+ Use all and only the styles mentioned in oc-basic.el.+ Allow space after `;`.++ * HTML reader:++ + Don't drop the initial newline in a `pre` element (#11064).++ * DocBook reader:++ + Add rowspan support (#10981, Sean Soon).+ + Be sensitive to startingnumber attribute on ordered lists (#10912).++ * POD reader:++ + Fix named entity lookup (#11015, Evan Silberman).++ * Man reader:++ + Support header and footer reader (Sean Soon).++ * Markdown reader:++ + Don't confuse a span after an author-in-text citation with a+ locator. E.g. `@foo [test]{.bar}`.+ See https://github.com/jgm/pandoc/issues/9080#issuecomment-3221689892.+ + Make definition lists behave like other lists (#10889).+ If the `four_space_rule` extension is not enabled,+ figure out the indentation needed for child blocks dynamically,+ by looking at the first nonspace content after the `:` marker.+ Previously the four-space rule was always obeyed.+ + Fix tight/loose detection for definition lists, to conform to+ the documentation.++ * ODT reader:++ + Support `table-header-rows` (Tuong Nguyen Manh).++ * Docx reader:++ + Don't add highlighting if highlight color is "none" (#10900).+ + Handle strict OpenXML as well as transitional (#7691).+ + Fix `stringToInteger` (#9184). It previously converted things like+ `11ccc` to an integer; now it requires that the whole string be parsable+ as an integer.+ + Improve handling of AlternateContent. This fixes handling of+ one representation of emojis in Word (#11113).++ * LaTeX writer:++ + Control figure placement with attribute (#10369, Sean Soon).+ If a `latex-placement` attribute is present on a figure, it will be used+ as the optional positioning hint in LaTeX (e.g. `ht`). With implicit+ figures, `latex-placement` will be added to the figure (and removed from+ the image) if it is present on the image.+ + Include cancel package only if there is math that contains `\cancel`,+ `\bcancel`, or `\xcancel`.+ + Add braces around comments in `title-meta` (#10501). This is needed to+ prevent PDFs from interpreting this as a sequence of titles.+ + Set `pdf-trailer-id` if `SOURCE_DATE_EPOCH` envvar is set (#6539, Albert+ Krewinkel). The `SOURCE_DATE_EPOCH` environment variable is used to trigger+ reproducible PDF compilation, i.e., PDFs that are identical down to the+ byte level for repeated runs.+ + Be more conservative about using `\url` (#8802). We only use it when the+ URL is all ASCII, since the `\url` macro causes problems when used with+ some non-ASCII characters.+ + Support soft hyphens (Albert Krewinkel).+ + Change handling of math environments (#9711, #9296).+ When certain math environments (e.g. `align`) are found in Math+ elements, we emit them "raw" instead of putting them in `$..$`.++ * Typst writer:++ + Check `XID_Continue` in identifiers (Tuong Nguyen Manh).+ + Add escapes to prevent inadvertent lists due to automatic wrapping+ (#10047). Also simplify existing code that was meant to do this.+ + Add parentheses around typst-native year-only citations (#11044).+ + Add native Typst support for `nocite` (#10680, Albert Krewinkel).+ The `nocite` metadata field can now be used to supply+ additional citations that don't appear in the text, just as with citeproc+ and LaTeX's bibtex and natbib.+ + Set `lang` attribute in Divs (#10965).+ + Rename `numbering` variable to `section-numbering` (Albert Krewinkel).+ This is the name expected by the default template.+ + Add support for custom and/or translated "Abstract" titles (Albert+ Krewinkel, #9724).++ * Org writer:++ + Don't wrap link descriptions (#9000). Org doesn't reliable display+ these as links if they have hard breaks.+ + Disable smart quotes by default (Albert Krewinkel).++ * Markdown writer:++ + Better handling of pandoc-generated code blocks (#10926).+ Omit the wrapper sourceCode divs added by pandoc around code blocks.+ More intelligently identify which class to use for the one class+ allowed in GFM code blocks. If there is a class of form `language-X`,+ use `X`; otherwise use the first class other than `sourceCode`.+ + Use fenced divs even with empty attributes (#10955, Carlos Scheidegger).+ Previously fenced divs were not used in this case, causing the writer to+ fall back to raw HTML.+ + Match indents in definition items (#10890, Albert Krewinkel).+ Previously, the first line of a definition details item always used a+ colon and three spaces instead of respecting the tab-stop setting, which+ could lead to round-tripping issues. Likewise, the indentation of+ continuation paragraphs in definition lists now matches the+ two-characters leader of the first line for Markua output.++ * DocBook writer:++ + Use `startingnumber` instead of `override` for start numbers on ordered+ lists (#10912).++ * ANSI writer:++ + Make `--wrap=none` work properly (#10898).++ * Djot writer:++ + Fix duplicate attributes before section headings (#10984).++ * Docx writer:++ + Ensure that documents don't start with a section separator+ (#10578, Albert Krewinkel). Any leading section separator is removed from+ the result.++ * HTML writer:++ + Unwrap "wrapper" divs (#11014). Some of the readers (e.g. djot) add+ "wrapper" divs to hold attributes for elements that have no slot for+ attributes in the pandoc AST. The HTML reader now "unwraps"+ these wrappers so that the attributes go on the intended elements.++ * Asciidoc writer:++ + Handle lists with sublists following continuations (#11006).+ These require an additional blank line in some cases.++ * HTML styles template: prefix default styles with informative CSS comment+ (Albert Krewinkel, #8819).++ * Org template: add `#+options` lines if necessary (Albert Krewinkel).+ The default template now adds `#+options` lines if non-default settings+ are used for the `smart_quotes` and `special_strings` extensions.++ * LaTeX template:++ + Don't emit empty `linkcolor=` in hypersetup (#11098).+ + Add RTL support for LuaTeX engine (Reuben Thomas).++ * Typst template:++ + Add several new variables (Christopher T. Kenny, #9956):+ `thanks`, `abstract-title`, `linestretch`, `mathfont`, `codefont`,+ `linkcolor`, `filecolor`, `citecolor`.++ * `reference.docx`:++ + Don't left-align table header row (R. N. West, #11019).+ + Update East Asia font theme in `styles.xml` to `minorEastAsia` (TomBen).+ + Update language settings in `styles.xml` for East Asia to Simplified+ Chinese (TomBen).++ * Text.Pandoc.PDF:++ + `makePDF`: automatically embed resources from media bag in HTML+ before trying to convert it with weasyprint, etc. (#11099).+ This will give better results when converting from formats like docx.+ + Use `utf8ToText` for LaTeX log messages.+ + Make images from MediaBag available in tmp dir for every PDF engine,+ not just LaTeX/ConTeXt (#10911).+ + Improve error readability when pdf-engine is not supported (Albert+ Krewinkel). Each supported engine is now printed on a line of its own.+ + Allow `pdflatex-dev` and `lualatex-dev` as PDF engines (#10991, Albert+ Krewinkel). These are the development versions of the LaTeX binaries;+ installable, e.g., with `tlmgr install latex-base-dev`.+ + Clean up `makePDF` (Albert Krewinkel).+ + Avoid encoding errors when reading LaTeX logs (#10954).++ * Text.Pandoc.Readers:++ + Raise unknown reader error for `ods`, `odp`, `odf`, `xls`,+ `xslx`, `zip` extensions.++ * Text.Pandoc.App:++ + Recognize binary signatures and fail early (Repetitive). Fail early when+ receiving binary input with recognized signature: zip[-based], including+ OpenDocument and Microsoft formats, PDF, CFBF-based (old Microsoft formats+ including .doc and .xls), DjVu.+ + Remove code duplication around version info.+ Text.Pandoc.App.CommandLineOptions and `pandoc-cli/src/pandoc.hs`+ had similar code for generating version information.+ To avoid duplication, we now export `versionInfo` from+ Text.Pandoc.App [API change]. This function has three parameters that can+ be filled in when it is called by `pandoc-cli`.++ * Text.Pandoc.Parsing:++ + `tableWith` and `tableWith'` now return a list of lists of Blocks, rather+ than a list of Blocks, for the header rows, allowing for multiple header+ rows [API change] (#10338, TuongNM).++ * Text.Pandoc.Citeproc:++ + Don't move footnotes around em-dashes (#11046).+ + Allow `--citeproc` to put the bibliography in a Div with id `refs`+ even when `--file-scope` is used (#11072). When `--file-scope`+ is used, a prefix will be added based on the filename, so the Div+ will end up having an identifier like `myfile.md__refs`.+ Previously, this prevented the bibliography from being added to+ the marked Div. Now pandoc will add the bibliography to any Div+ with the id `refs` or any id ending in `__refs`.++ * Text.Pandoc.Citeproc.BibTeX: Protect case in periodical titles (#11048).+ Thus, for example, `{npj} Quantum Information` should translate as+ `[npj]{.nocase} Quantum Information`.++ * Text.Pandoc.ImageSize:++ + Detect more JPEG file signatures (R. N. West and John MacFarlane, #11049).+ + Unpack compressed object streams in PDFs and look inside for MediaBox+ information (#10902).+ + Add Point and Pica as constructors of ImageSize [API change] (#8957).+ This will prevent unnecessary conversion of units.+ + Add Avif constructor on ImageType [API change] and support avif images+ (#10979).++ * Text.Pandoc.Writers.Shared:++ + Amend docs of `lookupMeta...` functions (#10634, Albert Krewinkel).++ * Text.Pandoc.Options:++ + Add and export `defaultWebTeXURL` WebTeX URL [API change] (#11029,+ Sean Soon). This fixes the `webtex` option when used without+ parameter in a defaults file.+ + Add type `HighlightMethod` and patterns [API Change] (Albert Krewinkel).+ + The `writerListings` and `writerHighlightStyle` fields of the+ `WriterOptions` type are replaced with `writerHighlightMethod`+ [API change] (Albert Krewinkel, #10525).++ * Text.Pandoc.Extensions:++ + Remove `Ext_compact_definition_lists` constructor for+ `Extension` [API change].+ + Add `Ext_smart_quotes` and `Ext_special_strings` constructors.+ [API change].++ * Text.Pandoc.SelfContained:++ + Try fetching relative resources without query or fragment if the original+ fetch fails. This provides a fix for #1477 in a way that doesn't raise+ the problems mentioned in #11021.++ * Text.Pandoc.Highlighting:++ + Export `defaultStyle` [API Change] (Albert Krewinkel).+ This allows to be more explicit about using a default style, and+ providing a single point of truth for its value. The variable is+ an alias for `pygments`.++ * Text.Pandoc.Class:++ + `downloadOrRead`: do not drop fragment/hash for local file paths (#11021).+ With the previous behavior it was impossible to have an image+ file containing `#` or `?`.+ + Export function `runSilently` [API Change] (Albert Krewinkel).+ The function runs an action in the PandocMonad, but returns all log+ messages reported by that action instead of adding them to the main log.+ + Make CommonState opaque. Text.Pandoc.Class now exports CommonState as+ an opaque object, without its fields. [API change]+ The internal module Text.Pandoc.Class.CommonState still exports+ the fields.+ + Text.Pandoc.Class now exports the following new functions:+ `getRequestHeaders`, `setRequestHeaders`, `getSourceURL`,+ `getTrace`. [API change]+ + CommonState now has a `stManager` field. This allows us to cache the HTTP+ client manager and reuse it for many requests, instead of creating it again+ (an expensive operation) for each request. This fixes a memory leak and+ performance issue in files with a large number of remote images (#10997).++ * Lua subsystem (Albert Krewinkel):++ + Add function `pandoc.structure.unique_identifier`.+ + Add functions `pandoc.text.superscript` and `subscript`.+ + Use proper interface functions to access the CommonState.+ The `PANDOC_STATE` is no longer a userdata object, but a table that+ behaves like the old object. Log messages in `PANDOC_STATE.log` are now+ in temporal order.+ + Add function `pandoc.path.exists`.+ + Add `normalize` function to *Pandoc* objects (#10356).+ This function performs a normalization of Pandoc documents. E.g.,+ multiple successive spaces are collapsed, and tables are normalized such+ that all rows and columns contain the same number of cells.+ + Add more UTF-8-aware file operations to `pandoc.system`.+ Functions that expect UTF-8-encoded filenames should make it easier to+ write platform-independent scripts, as the encoding of the actual+ filename depends on the system. In addition, there is a new+ generalized method to run commands, and functions to retrieve XDG+ directory names. The new functions are `command`, `copy`, `read_file`,+ `remove`, `rename`, `times`, `write_file`, `xdg`.+ + Allow hslua-2.4.+ + Require lua-module-system 1.2.3. This provides List methods to the value+ returned by `pandoc.system.list_directory` (#11032).++ * MANUAL.txt:++ + Fix broken ConTeXt links (R. N. West, #11055).+ + Add `xml` as input/output format.+ + Fix minor capitalization typo (#11052, Albert Krewinkel).++ * `doc/lua-filters`:++ + Fix docs for `pandoc.Cite` (Albert Krewinkel).+ + Don't encourage returning tables of filters from Lua filters+ (R. N. West, #10995). Use the `Pandoc:walk` method instead.++ * doc/extras.md: Fix link to pandoc-mode (Erik Post).++ * doc/lua-filters.md: Add example on using pandoc.Table constructor (#10956,+ Sean Soon).++ * Update `default.csl` from new chicago-author-date.csl, which is now+ for the 18th edition.++ * Use latest releases of citeproc, typst-hs, texmath, doclayout,+ skylighting-core, skylighting.++## pandoc 3.7.0.2 (2025-05-28)++ * RST writer:++ + Don't emit alignment markers in grid tables (#10857).++ * Asciidoc writer:++ + Add support for sidebars (GHyman83).++ * LaTeX writer:++ + Include alt option in `\includegraphics` (#6095).++ * Markdown writer:++ + Preserve figure attributes (Nikolay Yakimov, #10867).+ Fixes a regression introduced by 0d2114e, which caused the+ Markdown writer to ignore attributes on the figure if it+ has class or key-value attributes set.++ * HTML writer:++ + Use the ID prefix in the ID for the footnotes section (Benjamin Esham).++ * Text.Pandoc.Writers.Shared:++ + `gridTable`: fix (3.7) regression with missing cell alignments (#10853).+ + `gridTable`: fix headings with colspans (#10855). If the heading+ contains a colspan, we still need to include information in the header+ line about the colspecs.+ + `gridTable`: fix headerless tables. The top line should encode+ colspan information.++ * Text.Pandoc.SelfContained:++ + Fix handling of empty script element (#10862). Previously in this+ case the closing tag was dropped.+ + Do not drop `data-` attributes in script tags (#10861).++ * Lua subsystem (Albert Krewinkel):++ + Add function `pandoc.mediabag.make_data_uri` (#10876).+ The function takes a MIME type and raw data from which it creates an+ RFC 2397 data URI.++ * `tools/update-lua-module-docs`: fix handling of wikilinks+ (Albert Krewinkel).++ * `doc/lua-filters.md`: add missing docs for `pandoc.Caption`+ (Albert Krewinkel).++ * Require texmath 0.12.10.3, typst 0.8.0.1++## pandoc 3.7.0.1 (2025-05-17)++ * Text.Pandoc.Shared.Writer: Fix numerous problems with `gridTable` and add+ tests (#10848). These fixes affect the Markdown, RST, and Muse writers.++ * Fix context writer/template to produce tagged PDFs (#10846).+ As before, the `tagging` extension must be enabled.+ We now add the command that tells ConTeXt to start tagging.++## pandoc 3.7 (2025-05-14)++ * Add new command-line option `--variable-json` (#10341).+ This allows non-string values (booleans, lists, maps) to be given to+ template variables on the command line.++ * The `--pdf-engine` option can now take `groff` as a value.++ * Markdown writer:++ + Avoid spaces after/before open/close delimiters (#10696).+ E.g. instead of rendering `x<em> space </em>y` as `x* space *y` we render+ it as `x *space* y`.+ + Handle row/colspans in grid tables, and expand cells when it isn't+ possible to lay them out without breaking string of non-whitespace.+ + Render a figure with Para caption as implicit figure (#10755).+ + When falling back to a Div with class `figure` for a figure that+ can't be represented any other way, include a Div with class+ `caption` containing the caption.+ + Improve use of implicit figures when possible (#10758).+ When the alt differs from the caption, but only as regards formatting, we+ still use an implicit figure.+ + Omit initial newlines in gfm `math` blocks to avoid an ugly blank line.+ * Support the `four_space_rule` extension for `plain` output (#10813,+ Manolis Stamatogiannakis).++ * RST writer:++ + Handle row/colspans in grid tables, and expand cells when it isn't+ possible to lay them out without breaking string of non-whitespace.++ * Muse writer:++ + Handle row/colspans in grid tables, and expand cells when it isn't+ possible to lay them out without breaking string of non-whitespace.++ * JATS writer:++ + Fix escaping for writing-review-editing role (#10744).++ * HTML writer:++ + Remove trailing slash from default revealjs URL (#8749). This+ avoids a double slash in the URL's path component.++ * LaTeX writer:++ + Make alignment work within `multirow` in tables (#10772).++ * Typst writer:++ + Support `mark` class on spans (#10747).+ + Add equation label if math contains `\label{..}` (#10805).++ * Roff format writers (man, ms):++ + Use the most compatible form for roff escapes (#10716).+ For example, `\(xy` instead of `\[xy]`. This was the original+ AT&T troff form and is the most widely supported. The+ bracketed form causes problem for some tools, e.g.+ `makewhatis` on macOS. And emit `e` followed by an escape+ for a unicode combining accent rather than the form `\[e aa]`,+ which works for groff but not e.g. on macOS's man.+ This change affects Text.Pandoc.RoffChar,+ Text.Pandoc.Writers.Roff, and the Man and Ms writers.++ * Docx writer:++ + Ensure that figures and tables with custom styles are not dropped+ (#10705).+ + Preserve Relationships for images from reference docx (#10759).+ This should allow one to include an image in a reference.docx and+ reference it in an openxml template.+ + Don't renumber rels (#10769). We used to renumber the+ Relationships so they didn't conflict with the set of fixed+ Relationships we imposed. We are now preserving the ids+ from the reference doc's document.xml.refs, so we shouldn't+ renumber them or references introduced by the user (e.g. in+ a template) will fail.++ * Ms writer:++ + Improve PDF TOC labels. We now use the plain writer to render these,+ so that Greek characters etc. will show up properly.+ + When no `pdf-engine` variable is specified, do not use the+ `.pdfhref` macros at all (#10738). This gives better results for links+ in formats other than PDF, since the link text would simply+ disappear if it exists only in a `.pdfhref` macro. When a PDF+ engine is specified, escape the argument of `.pdfhref O` in a way+ that is appropriate.++ * OpenDocument writer:++ + Fix character styles in footnotes (#10791). Character+ styles governing the position of the footnote reference+ should not be imposed on the footnote text.++ * Powerpoint writer:++ + Use reference-doc font for captions (#9896, R. N. West).++ * DocBook writer:++ + Use literallayout element for LineBlock (#10825).++ * MediaWiki reader/writer:++ + Allow definition on same line as term (#10708).++ * LaTeX reader:++ + Skip at most one argument to LaTeX tabular newline (#7512,+ Evan Silberman).+ + Disable ligatures inside `\texttt` (#10781).+ + Support more symbol commands (#10782).++ * Commonmark Reader:++ + Handle GFM math irregularity with braces (#10631). In GFM, you need+ to use `\\{` rather than `\{` for a literal brace.++ * DocBook reader:++ + Improve handling of literallayout (#10825). This is now only made+ a CodeBlock when there is a `monospaced` class. Otherwise it is made+ a LineBlock.++ * Org reader:++ + Add AVIF to Org Reader image extensions (#10736, Christian Christiansen).+ + Don't include newlines in inine code/verbatim (#10730).+ Convert newlines to spaces as we do in other formats.+ + Change handling of inline TeX (#10836). Previously inline+ TeX was handled in a way that was different from org's own export,+ and that could lead to information loss. This was particularly noticeable+ for inline math environments such as `equation`. Previously, an+ `equation` environment starting at the beginning of a line would create+ a raw block, splitting up the paragraph containing it (see+ #10836). On the other hand, an `equation` environment not+ at the beginning of a line would be turned into regular+ inline elements representing the math. (This would cause+ the equation number to go missing and in some cases degrade+ the math formatting.) Now, we parse all of these as raw+ "latex" inlines, which will be omitted when converting to+ formats other than LaTeX (and other formats like pandoc's+ Markdown that allow raw LaTex).++ * Beamer template: fix regression in 3.6.4, reverting the omission of+ `\date` when the document does not have a date. By default, beamer+ will display a date when no `\date` is present in the title block,+ so this was an unintended behavior change. The reverted+ change was motivated by the desire to include a custom+ `\date` in the frontmatter via header-includes. This can be+ achieved more simply by simply setting the `date` variable.+ In markdown you can even use `date` in metadata and put some+ raw LaTeX there.++ * Ms template:++ + Use T rather than P as default font family (#10738).+ + Put PDF-specific things under a conditional.+ Don't include them if `pdf-engine` isn't set.++ * Upgrade reveal.js URL to v5 (#10740, Kolen Cheung).+ v4 is no longer available on unpkg.com.++ * Text.Pandoc.PDF: Allow `groff` to be used as `--pdf-engine` with `ms`+ (#10738). When `groff` is used as a PDF engine, the `groff`+ extension to `ms` is automatically enabled. Limitations:++ - `groff` currently produces larger PDFs than `pdfroff`.+ - With `groff`, a table of contents produced with+ `--table-of-contents/--toc` will always be placed at the end of+ the document.+ - Certain characters (e.g. Greek characters) may be dropped in+ the PDF outline.++ * Text.Pandoc.Writers.Shared:++ + Export `delimited` [API change].+ + New version of `gridTable` (#6344) [API change]. This+ handles row and colspans. It also ensures that cells won't+ wrap text in places where it wouldn't normally wrap, even+ if this means making the cells wider than requested by the+ colspec (#9001, #7641). Because the parameters are+ different, this is a breaking API change.++ * Text.Pandoc.App: set `pdf-engine` variable.+ If `--pdf-engine` is specified or if a PDF is being produced, we set the+ `pdf-engine` variable. This allows writers and templates to behave+ differently depending on the PDF engine.++ * Text.Pandoc.Class and Text.Pandoc.URI:++ + Fix parsing of base64 data URIs to allow URI escapes and+ whitespace (which will be ignored) (#10704).+ + Handle percent encoding in `pBase64URI` instead of+ unescaping later, for efficiency (#10704).++ * Text.Pandoc.Citeproc.BibTeX:++ + Recognize `en` as a `langid` in biblatex bibliographies (#10764).++ * Text.Pandoc.MIME:++ + Add mime type and extension for `avif` (#10704).+ + Handle `apng`, `avif`, `jxl` (#10704).++ * Text.Pandoc.Readers.LaTeX.Math: export `inlineEnvironmentNames`.+ Internal module, not a change to the public API.++ * `reference.docx` (Andrew Dunning):++ + Remove extra spaces around text placeholders.+ + Add footnote block text sample.++ * Text.Pandoc.Class.Sandbox:++ + Add `sandboxWithFileTree` function [API change] (Albert Krewinkel).++ * Lua subsystem (Albert Krewinkel):++ + pandoc-lua-engine: add all test files to the cabal file.+ + Allow `pandoc.read` to be called in "sandbox" mode for added+ security (#10831). Readers running in a sandbox will not be+ able to access the network or file system. The sandbox is+ enabled if the fourth parameter is a list of files or+ filename/content pairs. The files are read and then made+ available in the sandbox via en ersatz file system.++ * Makefile:++ + Add target `release-checkist`.+ + Install @daisy/ace from npm if not present.+ + Use pandoc lua instead of lua.+ + Fix typo in `latex-package-dependencies` target.+ + Use `jq` instead of `json_reformat` in `validate-docx-golden-tests2`.++ * NiX infrastructure: new working `flake.nix` and simpler `shell.nix`.+ Removed old `default.nix`.++ * Require random >= 1.3 and use `splitGen`. `split` has been deprecated.++ * Use citeproc-0.9. Bump citeproc bounds for pandoc, pandoc-lua-engine.++ * Use texmath-0.12.10.1.++ * Use released typst 0.8 (partially supporting typst 0.13).++ * Use citeproc 0.9.0.1.++ * MANUAL.txt:++ + Fix default URL for revealjs.+ + Add note that `alerts` extension only works with commonmark (#9716).+ + Remove "Body Text Char" from list of Word styles that can be customized+ using a reference.docx (#10646). This doesn't seem to be present in+ pandoc-generated docx files, nor is it a Word default.+ + For pandoc lua, add note about the environment.+ + Improve documentation of `--variable` option.++ * `doc/typst-property-output.md`: Mention that `typst:no-figure` is a+ class, not an attribute (#10826, Niklas Eicker).++ * Change RELEASE-CHECKLIST to RELEASE-CHECKLIST-TEMPLATE.org. Use org-babel+ to automate many of the steps of the release.++ * INSTALL.md: update MacPorts information (#10719, Mohamed Akram).++ * COPYRIGHT: fix link to source code.++ * CONTRIBUTING.md: Fix link to discussion forum. (#10834, R. N. West).++## pandoc 3.6.4 (2025-03-16)++ * Disable `citations` extension in writers if `--citeproc` is used (#10662).+ Otherwise we get undesirable results, as the format's native+ citation mechanism is used instead of (or in addition to) the+ citeproc-generated citations.++ * Markdown reader:++ + Allow line break between URL and title of link (#10621).+ + Give better position information when YAML metadata parsing fails+ with a YAML exception (#10231).+ + Fixed `escapedChar'` parser (#10672). It should not accept+ escaped newlines.+ + Remove some misguided list fanciness (#9865, #7778, cf. #5628).+ Previously we tried to handle things like commented out list items:+ ```+ - one+ <!--+ - two+ -->+ - three+ ```+ and also things like:+ ```+ - one `and+ - two` and+ ```+ But the code we added to handle these cases caused problems with+ other, more straightforward things, like:+ ````+ - one+ - ```+ code+ ```+ - three+ ````+ So we are rolling back all the fanciness, so that the markdown+ parser now behaves more like the commonmark parser, in which+ indicators of block-level structure always take priority over+ indicators of inline structure.++ * HTML reader:++ + Skip MathJaX-introduced cruft (#10673).+ + Ignore style tags in the body (#10643).++ * LaTeX reader:++ + Better handle comments/whitespace in option lists and includes (#10659).+ + Support `\newline`, `\linebreak`.++ * Docx reader/writer:++ + Revert commit adding row heads+ (cbe67b9602a736976ef6921aefbbc60d51c6755a) (#10627).+ Word sets `w:firstColumn="1"` by default for tables. You have to find+ the Table Design tab and explicitly uncheck "First Column" to make this+ go away. In most cases, I don't think writers intend to designate+ the first column as a row head, so this commit is going to produce+ unexpected results. In addition, because of the table normalization+ done by pandoc-type's `tableWith`, any table containing a colspanned+ cell in the left-hand column will get broken if the first column is+ designated a row head. For these reasons it seems best to revert this+ change, which was made in response to #9495.++ * LaTeX writer and template:++ + Remove `selnolig-langs` (#9863). We now specify the language as+ a global option again, so we no longer need to specify it when+ invoking selnolig.+ + Use babel options `shorthands=off` (#6817).+ + Use `*` for multirow width when no colwidth specified (#10685).+ Otherwise the multirow will be excessively wide.+ + Protect `\phantomsection` (#10688, etclub).++ * Markdown writer:++ + Omit extra space after bullets (#7172). Those who want the old+ behavior can obtain it by using `-t markdown+four_space_rule`.+ + Treat `Emph [Emph ils]]` as `ils` (#10642). Otherwise we get+ `**content**` which means strong emphasis.++ * EPUB writer:++ + Use a nonbreaking space after section number in nav.xhtml.+ This seems to be required for iOS books app to display the space.++ * Typst writer:++ + Better heuristics for escaping potential list markers (#10650).+ + Ensure that `citation-style` works as well as `csl` (#10661).++ * Powerpoint writer:++ + Avoid extra blank lines before author when there is no+ subtitle (#10619).++ * JATS template:++ + Fix typo in author prefix in article.jats_publishing template+ (#10622, Tiago-Manzato).++ * Text.Pandoc.Parsing:++ + Smart quote parsing: ignore curly quotes (#10610). Previously we+ tried to match curly quotes as well as straight quotes,+ producing Quoted inlines. But it seems better just to assume+ that those who use curly quotes want them passed through+ verbatim. This also fixes an (unintended) bug whereby curly+ single left quotes would sometimes be changed to single right quotes.++ * Text.Pandoc.Shared:++ + `makeSections`: put some attributes on section element only.+ Certain `role` and `epub:type` attributes should only be on the section+ (and indeed, many `role`s give a validation error if left on the+ heading element).++ * Text.Pandoc.Logging:++ + Change NoTitleElement from WARNING to INFO (#10671). Users+ commonly complain about the warning when producing HTML+ documents without an explicit title. It seems that an info+ message is more appropriate, since pandoc's default here (using+ the input's base name) ensures compliance with the standard and+ many users are happy with that default. Those who want to make+ sure the message is seen can use `--verbose`.++ * Beamer template: only emit `\date` if set (#10687, josch).++ * Fix invalid OOXML in definition_list.docx test (#10394).++ * MANUAL.txt:++ + Correct typo: 'date' for doubled 'title' (#10654, Olivier Dossmann).+ + Add note about `template` variable for typst.+ + Change maxwidth default in MANUAL.txt (#10683).+ + Improve EPUB metadata documentation.+ + In Security section, alert readers to a threat relating to iframe in+ HTML, and add LaTeX, Typst to the list of formats that have an+ `include` (#10682).++ * `doc/lua-filters.md`: Add missing html_math_method 'katex' (R. N. West).++ * Use texmath 0.12.9.++ * Use typst 0.7. Fixes an issue with package loading, a regression+ in pandoc 3.6.3.++## pandoc 3.6.3 (2025-02-09)++ * Track wikilinks with a class instead of a title (Evan Silberman).+ Previously wikilinks were distinguished by giving them the `title`+ `wikilink`. Now that we have link attributes, it makes more sense+ to give them the `class` `wikilink`. This change affects all readers+ and writers that support wikilinks.++ * DocBook reader:++ + Handle title inside `orderedlist` (#10594). Also some other+ elements that allow title: `blockquote`, `calloutlist`, etc.+ + Better handle `informalequation` (#10592, tombolano). Include `id`+ attribute.+ + Better handle `formalpara`, `example`, and `sidebar` (#8666, tombolano).+ Include identifiers and titles in each case.++ * Markdown reader:++ + Simplify and fix normal citation parsing (#10584).+ This fixes a bug that causes some normal citations to be+ parsed as bracketed regular citations.++ * ODT reader:++ + Create Figure elements for images that are figures (#10567).+ + Avoid producing spurious blockquotes in list items (#9505).+ + Fix unwanted block quotes (#10575). Previously the reader created+ block quotes whenever a paragraph was marked indented (even though+ this just affects the first line). With this change we still+ generate block quotes for content that has an altered left margin,+ but not for indented paragraphs.++ * Docx reader:++ + Do not issue warning for comments with `+styles` (#10571, Stephen Reindl).++ * LaTeX reader:++ + Test \{,re}newcommand arguments (#4470, Evan Silberman).++ * Pod reader:++ + Consume blanks after =encoding in pod reader (#10537, Evan Silberman).++ * JATS writer:++ + Add CRediT roles to JATS (Charles Tapley Hoyt and Jez Cope, #10152).+ Enable annotating author roles using the Contribution Role Taxonomy+ (CRediT) and export this information in conformant JATS.++ * LaTeX writer/templates:++ + Improve babel support (#8283). Previously we used the `.ini`+ files for every language, but for European languages these tend to+ provide inferior results to the `.ldf` files used by classic+ Babel. Currently Babel documentation recommends using the classic+ system for European languages written in Latin and Cyrillic+ scripts and Vietnamese. So the LaTeX writer and template now+ follow this guidance.++ Main languages in the list of languages with good "classic" support+ are added to global documentclass options and will be automatically+ handled by Babel using the `.ldf` files.++ If the main language is not in this list, the `babeloptions` variable+ will be set to `provide=*`, which will cause support to be loaded from+ the `.ini` file rather than an `.ldf`. So, for example, setting+ `-V babeloptions=''` with a polytonic Greek document will cause the+ `.ldf` support to be used instead of the `.ini`.++ The default setting of this variable can be overwritten, but in most+ cases the default should give good results.++ + Allow `csquotesoptions` to be specified.+ + Fix indentation bugs in `font-settings.latex`.++ * Docx writer:++ + Repeat reference doc's `sectPr` for each new section (#10577).+ Previously we were only carrying over the reference doc's `sectPr`+ at the end of the document, so it wouldn't affect the intermediate+ sections that are now added if `--top-level-division` is `chapter`+ or `part`. This could lead to bad results (e.g. page numbering+ starting only on the last chapter).+ + Create section divisions with `--top-level-division=part` (#10576).+ + Improve title style in reference.docx; base Author and Date+ on Title; remove condensed spacing (Andrew Dunning, #10581).++ * Typst writer:++ + Brace tables with `typst:no-figure` and `typst:text` attributes (#10563,+ Gordon Woodhull).++ * Ms writer:++ + Fix escaping of `-` (#10536). `-` should now be escaped in man+ output but not in ms output (where `\-` is a unicode minus sign).++ * HTML styles: fix style of `hr` so it works when printed (#10535, Hendrik Erz).+ Previously `background-color` was used to style the hr, but this gets ignored+ when printing. This commit uses `border-top` instead.++ * Text.Pandoc.Shared:++ + Handle `<abbr>` as a span-like inline in `htmlSpanLikeElements`+ (#5793, Evan Silberman).++ * Text.Pandoc.MediaBag:++ + Prefer MIME type when determining extensions for MediaBag items (#10557,+ Max Heller). This should give different results for remote images+ that are served at URLs that do not contain misleading extensions+ (e.g. `shields.io`).++ * Text.Pandoc.Citeproc:++ + Fix moving punctuation before citation notes. This previously worked with+ regular citations, but not author-in-text citations. Now it works with both.++ * `doc/lua-filters.md`:++ + Correct luacheck URL (#10589, R. N. West).+ + Add static analysis paragraph to debugging section (#10568, R. N. West).+ + Add note about extensions handling in `read` and `write` (Albert Krewinkel).++ * `doc/extras.md`:++ + Add entry for pandoc-subfigs (R. N. West).+ + Update diagram Lua filter URL and description (R. N. West).++ * MANUAL.txt:++ + Add note on using typst to produce pdf/a-2b.+ + Document top-level-division functionality with Docx (#10579, Andrew Dunning).++ * Raise xml-conduit upper bound.++ * Depend on latest commonmark-pandoc, commonmark-extensions,+ citeproc, typst.++ * Makefile: make `make binpath` quiet.++## pandoc 3.6.2 (2025-01-12)++ * New input format: `pod` (Evan Silberman). Pod ("Plain old documentation")+ is a markup languaged used principally to document Perl modules and+ programs.++ * New reader module Text.Pandoc.Readers.Pod, exporting `readPod`+ [API change].++ * Docx reader:++ + Support row heads in tables (#9495). Reader: When `w:tblLook` has+ `w:firstColumn` set (or an equivalent bit mask), we set row heads = 1+ in the AST.+ + Read table styles as custom styles when `styles` extension+ is enabled (#9603).++ * HTML reader:++ + Add size information for font awesome SVG icons (#10134).+ If the icon has class `fa-fw` or `fa-w16` or `fa-w14`, we add a width+ attribute to prevent the icon from appearing full-width in PDF or+ docx output.++ * Djot reader:++ + Use a Span with class "mark" rather than "highlighted" for+ highlighted text, for consistency with the other pandoc readers and+ writers.++ * mandoc reader:++ + Add mdoc St for C23 (Evan Silberman).++ * RST reader:++ + Fix handling of underscores (#10497). Fixes a a regression+ introduced in 3.6.++ * Docx writer:++ + Support row heads in tables (#9495). Writer: set `w:firstColumn` in+ `w:tblLook` when there are row heads. (Word only allows one, so this+ is triggered by any number of row heads > 0.)++ * Djot writer:++ + Render a Span with sole class "mark" as highlighted text.++ * Asciidoc writer:++ + Don't emit the class in a span if it's just "mark" (#10511).+ The "mark" class is used for highlighting, and Asciidoc treats+ bare `#...#` with no attributes as highlighted text.+ + Improve escaping (#10385, #2337, #6424).++ * EPUB v2 writer:++ + Fix cover image (#10505). This is a regression introduced in 3.6.++ * Typst writer:++ + Fix handling of pixel image dimensions (#9945).+ These are now converted to inches as in the LaTeX writer.++ * Improve error message given when users specify `asciidoc` as input+ format (#8416, Santiago Zarate).++ * Allow random 1.3.++ * Use texmath 0.12.8.13 (typst improvements).++ * `lua-filters.md`: document `system.os` return values (#10523).++ * `MANUAL.txt`:++ + Improve manual's coverage of custom styles.+ + Replace LibreOffice PDF documentation link to latest so it links+ to the latest major release rather than a specific major release+ (which there are two of every year) (Stéphane Guillou).+ + Improve links and descriptions for `odt`, `opendocument` (#10518).++## pandoc 3.6.1 (2024-12-23)++ * Allow YAML bibliographies to be arrays of references (#10452).+ Previously, they had to be YAML objects with a `references` key.++ * Change `--template` to allow use of extensionless templates (#5270).+ The intent is to allow bash process substitution: e.g.,+ `--template <(echo "foo")`. Previously pandoc *always* added an+ extension based on the output format, which caused problems+ with the absolute filenames used by bash process substitution+ (e.g. `/dev/fd/11`). Now, if the template has no extension,+ pandoc will first try to find it without the extension, and+ then add the extension if it can't be found. So, in general,+ extensionless templates can now be used. But this has been+ implemented in a way that should not cause problems for+ existing uses, unless you are using a template `NAME.FORMAT`+ but happen to have an extensionless file `NAME` in the template+ search path.++ * Allow `--shift-heading-level-by=-1` to work in djot in the same way+ it works for other formats (with the top-level heading being+ promoted to metadata title) (#10459). This needed special+ treatment because of the way djot surrounds sections with Divs.++ * RST reader:++ + Handle explicit reference links (#10484, Evan Silberman).+ This case was missed when changing the reference link strategy for+ RST to allow a single pass. (It is a regression in pandoc 3.6.)++ * Markdown reader:++ + Use T.P.URI's `pBase64DataURI` in parsing data URIs (#10075,+ Evan Silberman and John MacFarlane).+ + More efficient base64 data URI parsing (#10075, Evan+ Silberman and John MacFarlane). This should yield dramatic+ performance improvements for markdown documents containing+ large data URIs in images.++ * HTML reader:++ + Don't canonicalize data: URIs (#10075). It can be very expensive+ to call network-uri's URI parser on these.++ * LaTeX reader:++ + Handle `figure*` environment as a figure (#10472).++ * MediaWiki reader:++ + Allow empty quoted attributes (#10490).+ + Allow cells starting with `+` (#10491).++ * Textile reader:++ + Improve parsing of spans (#9878). The span needs to be separated+ from its surroundings by spaces. Also, a span can have attributes,+ which we now attach.+ + Inline constructors shouldn't trigger if closer is preceded by+ whitespace (#10414).++ * Docx writer:++ + Put chapters in separate sections, and restart footnotes+ by section by default (#2773). The main effect of this change is that+ when `--top-level-division=chapter` is used, chapters will start on+ a new page and footnote numbering will restart for each chapter.+ Both of these defaults can be overridden in the reference.docx.+ + Use styleIds not styleNames for Title, Subtitle, etc.+ (#10282). This fixes a regression introduced in pandoc 3.5.+ This change affects the default openxml template as well as the+ OpenXML writer.++ * Markdown writer:++ + Avoid collapsing of initial/final newline in markdown raw blocks.+ This makes it easy to write a filter that adds extra blank lines+ before certain elements (#10477).++ * Mediawiki writer:++ + Escape line-initial characters that would otherwise be interpreted+ as list starts (#9700).++ * LaTeX writer:++ + Properly handle boolean value for `csquotes` variable (#10403).+ + Use displayquote for block quotes with `csquotes` (#10456).++ * HTML writer:++ + Avoid calling parseURIString for data URIs (#10075).+ This was done to determine the "media category," but we can+ get that directly from the mime component of data: URIs.++ * Typst writer:++ + Properly handle data URIs in images (#10460).++ * LaTeX/Beamer templates:++ + Fix default.beamer `nocite` location (Thomas Hodgson).+ It must be inside a frame or it is ignored (#10465).+ + Move nocites from LaTeX preamble to body (#10461, Thomas+ Hodgson). Putting `\nocite` in the preamble works only with biblatex.++ * Text.Pandoc.Parsing:++ + Correct example in comment on `charsInBalanced` (Evan Silberman).++ * Text.Pandoc.Error:++ + Mention typst in rendering `PandocUnknownWriterError` for `pdf`+ (Evan Silberman).++ * Text.Pandoc.MediaBag:++ + `insertMedia`: fast path for data URIs. Avoid the slow URI+ parser from network-uri on large data URIs (#10075).++ * Text.Pandoc.Class:++ + Add shortcut for base64 data URIs in `downloadOrRead` (#10075).+ This avoids calling the slow URI parser from network-uri on+ data URIs, instead calling our own parser.++ * Text.Pandoc.MIME:++ + Fix `extensionFromMimeType`. We had a few special cases encoded,+ but as previously written they wouldn't work properly with+ modifiers like `;charset=utf-8`.++ * Text.Pandoc.URI:++ + Export `pBase64DataURI`. Modify `isURI` to use this and avoid+ calling network-uri's inefficient `parseURI` for data URIs.++ * Text.Pandoc.PDF:++ + Fix temp file extension in `toPdfViaTempFile` (#10468).+ This fixes a regression in pandoc 3.6, which changed+ the extension from `html` to `source`. Apparently+ `wkhtmltopdf` needs it to be `.html`. So now we have added+ a parameter to `toPdfViaTempFile` that allows the extension+ to be specified in a way that is appropriate to the PDF engine+ used.++ * Lua (Albert Krewinkel):++ + Support more elements as input to `pandoc.utils.stringify`+ (#10450). Elements of type Caption, Cell, TableHead, and TableFoot+ can now be stringified.+ + Add `Caption` constructor to `pandoc` module.++ * Miscellaneous code quality improvements (Joseph C. Sible).++ * Depend on citeproc 0.8.1.2, skylighting and skylighting-core+ 0.14.5.++ * `doc/lua-filters.md: Fix links to constructors (Albert Krewinkel).+++## pandoc 3.6 (2024-12-07)++ * Add `mdoc` as input format (Evan Silberman). This change+ introduces a reader for mdoc, a roff-derived semantic markup+ language for manual pages. This reader has been developed almost+ exclusively against mandoc's documentation and implementation of+ mdoc as a reference, and the real-world manual pages tested+ against are those from the OpenBSD base system. Of ~3500 manuals+ in mdoc format shipped with a fresh OpenBSD install, 17 cause the+ mdoc reader to exit with a parse error. Any further chasing of+ edge cases is deferred to future work.++ * New module: Text.Pandoc.Readers.Mdoc, exporting `readMdoc` [API change].++ * Issue warnings for duplicate YAML metadata keys (#10312).++ * Ensure that `--sandbox` affects `--embed-resources`. Previously it+ did not (contrary to what was implied by the manual), which means+ that an image with URL `/etc/passwd` would leak an encoded version+ of that file to HTML output with `--self-contained` or+ `--embed-resources`, even if `--sandbox` was used. Thanks to+ Samuel Mortenson for pointing out the issue.++ * Text.Pandoc.App.OutputSettings: add `sandbox'` function.+ This computes the sandboxed files from Opt and avoids code repetition.++ * Docx reader:++ + Parse index references as empty spans with attributes (#10171).+ Attributes included are `entry`, and optionally `bold`, `italic`,+ `yomi`, `see`.+ + Don't create multiple paragraphs for title or subtitle (#10359).+ If there are multiple paragraphs with Title or Subtitle style,+ use only the first for metadata.+ + Handle case where Zotero `itemData` has different id from the+ `citationItem` id. In this case we use the `citationItemId`+ in the bibliography as well, overriding the `referenceId`+ in the itemData (#10366).++ * LaTeX reader:++ + Put parsed minipage in specially marked Div (#10266).++ * HTML reader:++ + Parse footnotes defined by dpub-aria roles (#5294).++ * MediaWiki reader:++ + Fix indented tables with caption (#10390).+ + Fix parsing of col/rowspan (#6992).++ * Typst reader:++ + Avoid generating empty paragraphs.+ + Support `underparen`, `overparen`.+ + Fix `#quote` attribution. If attribution is not present, don't print+ the `--` (#10320).+ + Fix typo in unicode code point for em dash (see #10320).++ * Commonmark reader:++ + `implicit_figures` should check for empty caption+ and not produce an implicit figure in this case (#10429).++ * RST reader:++ + Use a new one-pass parsing strategy. Instead of having an initial pass+ where we collect reference definitions, we create links with target+ `##SUBST##something` or `##REF##something` or `##NOTE##something`,+ and resolve these in a pass over the parsed AST. This allows us to handle+ link references that are not at the top level (#10281).+ + Ignore newlines in URL in explicit link (#10279).+ + Handle block level substitutions.+ + Support `:file:` on raw directive (#8584).+ + Implement option lists (#10318).+ + Avoid putting metadata in Para (#7766). Create MetaInlines when possible,+ just as with markdown input. MetaBlocks is still used when there are+ multiple paragraphs or non-paragraph content.+ This change also affects field lists.+ + Fix linked substitutions (#6588). E.g. `|Python|_`.+ + Support inline anchors (#9196).+ + Explicit links define references (#5081). For example,+ ``Go to `g`_ `g <www.example.com>`_.`` should produce two links to+ www.example.com.++ * EPUB writer:++ + Use standardized filename for cover image instead of the original name+ (#10404). This avoids problems with e.g. filenames containing spaces.++ * Markdown writer:++ + Issue INFO warning when not rendering table, e.g., when `raw_html` is+ disabled and the table can't be fit into a supported markdown table+ format (#10407).+ + Respect empty LineBlock lines in `plain` output (Evan Silberman).+ The plain writer behaved as a markdown variant with `Ext_line_blocks`+ turned off, and so empty lines in a line block would get eliminated.++ * LaTeX writer:++ Ensure that beamer footnotes go on frame, not column (#5769).++ * HTML writer:++ + Unwrap empty incremental divs (#10328, Albert Krewinkel).+ Divs are unwrapped if the only purpose of the div seems to be to control+ whether lists are presented incrementally on slides.++ * Typst writer:++ + Make template sensitive to a `page-numbering` variable (#10370).+ This can be set to an empty string (or, in metadata, to false) for+ no page numbers.+ + Make `smart` extension work (#10271). If `smart` is not enabled, a command+ in the default template will disable smartquote substitutions.+ When `smart` is enabled, render curly apostrophes as straight+ and escape straight apostrophes. When `smart` is disabled,+ render curly apostrophes as curly and don't escape straight+ apostrophes. Similarly for quotes, em and en dashes. This should+ give more idiomatic typst output, with fewer unnecessary+ escapes.++ * ANSI writer:++ + Respect empty LineBlock lines (Evan Silberman).++ * JATS writer:++ + Correct spelling of suppress attribute (#10350, Andreas Deininger).++ * Typst template:++ + Remove `definitions.typst` partial.+ + Remove unnecessary definition of `endnote`.+ + Incorporate the one remaining definition into `default.typst`.+ + Use typst 0.12 code for two column layout (#10294, Luis Rivera).+ + Note: the new templates presuppose typst 0.12; if you try to use an+ earlier version of typst, an error will be raised.++ * LaTeX/Beamer template:++ + Split `fonts.latex` partial into two parts: `fonts.latex` and+ `font-settings.latex`.+ + In beamer template, load beamer theme between `fonts.latex` and+ `font-settings.latex`. This allows a theme (such as metropolis)+ to set its own default font, while still allowing the user to+ override it. This fixes a regression in pandoc 3.5 (#10297).+ + Note: Users who have custom templates based on pandoc 3.5 templates will+ need to add `font-settings.latex()` after `fonts.latex()` in the+ latex template. In a beamer template, the beamer theme-setting+ code needs to be moved between these two partials.++ * ConTeXt template: Ensure that font names don't wrap (#10305).++ * `epub.css`: remove background-color (#10264, Suraj Patil).+ With this greyish background color, epubs look bad on a Kindle (#10263).++ * Text.Pandoc.ImageSize: add WebP support (Evan Silberman, #10397).+ Add `Webp` constructor on ImageType [API change].++ * Text.Pandoc.Readers.Roff and a new unexported module+ Text.Pandoc.Readers.Roff.Escape: parameterize Roff+ escaping (Evan Silberman) [API change]. This allows code to+ be reused between the mdoc and man readers, despite the+ differing Token types.++ * Text.Pandoc.PDF:++ + PDF via LaTeX: always do max runs if `toc` is present (#10308).+ The old method (checking to see if toc hash had changed) is not+ completely reliable.+ + Use `.source` extension, not `.html`, in `toPdfViaTempFile` (#10314).++ * Text.Pandoc.Logging: add `YamlWarning` constructor to `LogMessage`+ [API change] (#10312).++ * Text.Pandoc.Format: remove duplicate typst entry (#10388, Caleb Mclennan).++ * Fix a typo in the `ua.yaml` localization for 'See' (Jens).++ * Lua subsystem (Albert Krewinkel):++ + Remove prefixes from Lua type names (#8574). Lua type names were+ inconsistent with regard to the use of prefixes; all prefixes+ are removed now, and Lua types now have the same name as the+ Haskell types. The use of app-specific prefixes is suggested by+ the Lua manual to avoid collisions. However, this shouldn't be a+ problem with pandoc, as it cannot be used as a Lua package.++ * doc/libraries.md: Add newly developed Haskell packages.+ Sort list alphabetically (Albert Krewinkel).++ * doc/lua-filters.md: document `pandoc.List:iter` method (Albert Krewinkel).+ List objects have a new function `iter` that returns an iterator+ function that returns the next list item on each call.++ * MANUAL.txt:++ + Clarify what the example of YAML EPUB metadata shows (#10405).+ + Fix typo in template syntax (#10265, Pascal Wagler).+ + Update manual with information on openxml template (#10273).+ + Clarify that `--variable` can only assign string values (#10298).++ * Fix comments in TEI writer referring to DocBook (#10430, Evan Silberman).++ * Fix several typos in documentation (#10349, Andreas Deininger).++ * Allow Diff 1.0.++ * Add font-settings.latex partial to pandoc.cabal (#10379).++ * Bump upper bound for data-default.++ * Use latest typst, texmath, pandoc-lua-marshal, commonmark-pandoc,+ commonmark-extensions, skylighting, skylighting-format-blaze-html.+++## pandoc 3.5 (2024-10-04)++ * Add command-line options `--list-of-figures/--lof` and+ `--list-of-tables/--lot` (#10029, Akash Patel).+ Only docx, latex, and context are affected by these options currently.+ Setting the `lof` and `lot` variables will also work for the formats+ that are currently supported.++ * Defaults files: interpolation of environment variables now+ works for `to` and `from` fields (#8024). This is needed because+ these files can contain paths of custom readers/writers.++ * Docx reader:++ + Reset lists after headers in same list `numId` (#10258).+ To accomplish this, we add a Heading constructor to BodyPart and+ include on it all the information list items have.++ * DocBook reader:++ + Parse id, class, and tabstyle on tables (#10181, Erik Rask).+ Add parsing of id (xml:id), class, and tabstyle XML attributes+ for table and informaltable in the DocBook reader.+ The tabstyle value is put in the 'custom-style' attribute.++ * Dokuwiki reader:++ + Be more forgiving about misaligned lists, like dokuwiki itself (#8863).+ + Improve blockquote parsing in dokuwiki. Allow for quoted code blocks.+ + Enable smart extension.+ + Properly parse `--` and `---` as dashes.+ + Fix block quote behavior (#6461). Blockquotes are not really block+ containers in DokuWiki; the lines are interpreted literally (so,+ e.g., you can't start a list), and line breaks are added at the ends.++ * EPUB reader:++ + Fix links to other files in the EPUB, making them internal links+ to a fragment derived from the filename (#10207). There was+ already code to handle links like `#foo`, but not to handle links+ like `ch0001.html#foo`.++ * LaTeX reader:++ + Add em, ex, px, mu to list of units for dimension args (#10212).++ * ANSI writer:++ + Fix subscripts (Evan Silberman).++ * DokuWiki writer:++ + Don't emit `<HTML>` tags (#7413). The use of these tags is now+ strongly discouraged for security reasons, and will be removed.+ We previously used them as a fallback for lists that could not+ be represented using DokuWiki syntax, e.g. ordered lists with+ fancy numbers or lists with multiple blocks in their items.+ We also used them for block quotes with multiple blocks as+ their contents. We now use the `<WRAP>` syntax (from the optional+ WRAP plugin) to handle lists with multiple blocks as their contents.+ A new method of handling block quotes with complex contents+ has the side benefit of also handling nested block quotes,+ which weren't supported before.+ `<HTML>` and `<html>` tags are only for raw HTML blocks and+ inlines, and only if the `raw_html` extension is enabled. (It is+ now a valid extension for `dokuwiki`, though off by default.)++ * Docx writer:++ + Support `--list-of-figures` and `--list-of-tables` (or `lof` and+ `lot` variables) (Akash Patel).++ * HTML writer:++ + Don't emit missing title/lang warnings if templates does not+ contain the `pagetitle` or `lang` variables respectively (#9370).++ * LaTeX writer:++ + Better fix for lists in definition lists (#10241).+ In commit a26ec96d89ccf532f7bca7591c96ba30d8544e4a we added an+ empty `\item[]` to the beginning of a list that occurs first+ in a definition list, to avoid having one item on the line with+ the label. This gave bad results in some cases (#10241) and there+ is a more idiomatic solution anyway: using `\hfill`.+ + Avoid error on `refs` div with empty citations (#10185).+ If there are no citations, don't emit an empty CSLReferences environment.++ * RST writer:++ + Change bullet list hang from 3 to 2. This accords with the style in+ the RST reference docs.+ + Handle cases where indented context starts with block quote (#10236).+ In these cases we emit an empty comment to fix the point from+ which indentation is measured; otherwise the block quote is not+ parsed as a block quote. This affects list items and admonitions.+ + Don't enclose the list table in a `.. table::`; this leads to+ doubled captions (#10226).+ + Fix alignment of list table items corresponding to cells (#10227).++ * JATS template:++ + Support `floats-group` (Albert Krewinkel, see #10196).+ The content of the `floats-group` variable is now rendered in a+ `<floats-group>` element when using the *publishing* or *archiving* tag+ sets.++ * LaTeX and Beamer templates:++ + Split old default.latex into two templates, `default.latex` and+ `default.beamer`, factoring common parts into partials:+ `fonts.latex`, `common.latex`, `passoptions.latex`,+ `hypersetup.latex`, `after-header-includes.latex`.+ + Make `default.beamer` the default template for beamer.+ + Add `shorttitle`, `shortsubtitle`, `shortauthor`, `shortinstitute`,+ `shortdate` variables to beamer template (#10248, Thomas Hodgson).+ + Make `--number-sections` work with beamer (#12045, Thomas Hodgson).+ + Support a list of images for `titlegraphic` in beamer template+ (#10246, Thomas Hodgson). Title graphic options will be+ applied to each title graphic. Images will be separated by `\enspace`.+ + Beamer theme options (#10243)+ + Add theme options to beamer template: `colorthemeoptions`,+ `fontthemeoptions`, `innerthemeoptions`, `outerthemeoptions` (#10243,+ Thomas Hodgson).+ + Don't load amsmath, amssym in beamer template. These are loaded by+ beamer automatically.++ * Text.Pandoc.SelfContained:++ + Improve handling of links to remote CSS (#10261).++ * Text.Pandoc.Class:++ + Allow extracting `data:` URIs even in PandocPure (`--sandbox`)+ (#10249).+ + Export `extractURIData` [API change].++ * Text.Pandoc.PDF:++ + Read `.toc` and `.log` files from output directory (#10186).+ When this is different from the input directory, this is+ where `.toc` and `.log` files are written.++ * Text.Pandoc.Shared:++ + Modify `addPandocAttributes` for changes in commonmark-pandoc.+ The new commonmark-pandoc version automatically adds the+ attribute `wrapper="1"` on all Divs and Spans that+ are introduced just as containers for attributes that belong+ properly to their contents. So we don't need to add the+ attribute here. This gives much better results in some cases.+ Previously the wrapper attribute was being added even for+ explicit Divs and Spans in djot, but it is not needed in these cases.++ * Text.Pandoc.Options:++ + Add `writerListOfFigures` and `writerListOfTables` fields+ to `WriterOptions` (#8245, Akash Patel). [API change]++ * Text.Pandoc.App:++ + Add `optListOfFigures` and `optListOfTables` to `Opt` (#8245)+ [API change].++ * Lua subsystem (Albert Krewinkel):++ + Update List module (#9835). The module now comes with a method+ `:at(index[, def])` that allows to access indices, accepts+ negative indices to count from the end, and will return the+ `def` value as a default if the list has no item at the given position.+ Furthermore, the list constructor `pandoc.List` now accepts iterators.+ E.g., `pandoc.List(text:gmatch '%S+')` returns the list of words+ in `text`.+ + Support character styling via `pandoc.layout`. The `Doc` values+ produced and handled by the `pandoc.layout` module can now+ be styled using `bold`, `italic`, `underlined`, or `strikeout`. The+ style is ignored in normal rendering, but becomes visible when+ rendering to ANSI output. The `pandoc.layout.render` function+ now takes a third parameter that defines the output style,+ either *plain* or *ansi*.+ + It is now possible to return a single filter from a filter file, e.g.+ ``` lua+ -- Switch single- and double quotes+ return {+ Quoted = function (q)+ elem.quotetype = elem.quotetype == 'SingleQuote'+ and 'DoubleQuote' or 'SingleQuote'+ return elem+ end+ }+ ```+ The filter must not contain numerical indexes, or it might be treated+ as a list of filters.+ + Add `list_of_figures` and `list_of_tables` to writer options+ (Akash Patel).++ * Use latest releases of commonmark, commonmark-pandoc, texmath, djot.++ * Stop depending on package SHA (Albert Krewinkel). Use `crypton` instead.++ * `linux/make_artifacts.sh`: add riscv64 support (Olivier Benz).++ * Fix invalid XML in `test/docx/normalize.docx` (#10242).++ * `doc/lua-filters.md`: list functions in `pandoc.utils` alphabetically+ (Albert Krewinkel).++ * MANUAL.txt:++ + Clarify use of `beamerarticle` variable (#10250).+ + Add clarification to address user issues like #6704 (Yehuda Katz).++## pandoc 3.4 (2024-09-09)++ * New output format: `ansi` (for formatted console output) (Evan Silberman).+ Most Pandoc elements are supported and printed in a reasonable way, if+ not always ideally. This version does no detection of terminal+ capabilities, nor does it fall back to different output styles for+ less-capable terminals.++ * Add command line options `--table-caption-position` and+ `--figure-caption-position`. These allow the user to specify whether+ to put captions above or below tables and figures, respectively.+ The following output formats are supported: HTML (and related such+ as EPUB), LaTeX (and Beamer), Docx, ODT/OpenDocument, Typst.++ * Change default `--pdf-engine` via HTML to WeasyPrint (#10142).+ `wkhtmltopdf` is deprecated. `weasyprint` is the easiest-to-install,+ maintained alternative. For better results, one might prefer+ `pagedjs-cli`.++ * Org reader:++ + Fix parsing of src blocks with an `-i` flag (#10071, Albert Krewinkel).+ Tabs are now preserved in the contents of *src* blocks if the the block+ has the `-i` flag.++ * RTF reader:++ + Handle images inside `shp` contexts (#10145).++ * RST reader:++ + Improve simple table support (#10093). Multiline rows occur+ only when the *first* cell is empty; we were previously treating+ lines with *any* empty cell as row continuations. In addition, we+ no longer wrap multiline cells in Para if they can be represented+ as Plain. This is consistent with docutils behavior.++ * LaTeX reader:++ + Math environments don't have bracketed options (#10160).+ + Parse nested tabular environments (#4746).++ * Typst reader:++ + Change how "block" elements are handled. Previously they were+ always parsed as divs. But actually they can occur in some "inline"+ contexts. Now we first try to parse them as inlines, and only as+ blocks if that fails. A surrounding Div or Span element is added+ only if there is an identifier.++ * HTML reader:++ + Only parse main element's contents (if present) (#10140).+ If main has an id or class, we include a div with that id or class;+ otherwise just the contents.+ + Read TeX annotation in MathML content if present (#9971).+ + Better handle KaTeX-generated math (#9971). KaTeX emits the mathml+ followed by a span with an HTML fallback. Previously pandoc was+ converting both. We now ignore the HTML fallback span, marked+ with class `katex-html`.++ * Docx reader:++ + Add "SuppressAuthor" and "AuthorOnly" to citationMode+ when `+citations` is used (thomjur).++ * New module: Text.Pandoc.Writers.ANSI [API change] (Evan Silberman).++ * Docx writer:++ + Support `custom-style` attribute for docx table (Sebbones).+ + Support `--number-offsets`.+ + Make table/figure rendering sensitive to caption position settings.++ * OpenDocument writer:++ + Make table/figure rendering sensitive to caption position settings.++ * Typst writer/template:++ + Implement figure caption positions by triggering a show rule in+ the default template, which determines caption positions for+ figures and tables globally.+ + Don't include trailing semicolon after `@` style citations with suffixes+ (#10148).+ + Template: move header-includes before show doc (#9996, Gordon Woodhull).++ * LaTeX writer:++ + Make table/figure rendering sensitive to caption position settings (#5116).+ + Preserve locator labels with `--natbib` (#10057).++ * HTML writer/template:++ + Make `<figcaption>` placement sensitive to caption position+ settings. For tables, `<caption>` must be the first element, and+ positioning is determined by CSS, for here we set a variable+ which the default template is sensitive to.+ + Use `makeSectionsWithOffsets` for `writerNumberOffsets`,+ instead of the old, inefficient code.+ + Don't add doc-biblioref role to every link in a citation;+ only to links to the bibliography (#10156).+ + Add `data-` when rendering `label` attribute (#10048).++ * Markdown writer:++ + Avoid emitting markdown caption if table has fallen back to raw HTML,+ which will then contain a `<caption>` tag (#10094).+ + Make math sensitive to `tex_math_gfm` extension (#9121).+ This means that in GFM output, the "new style" math will be used+ by default, e.g.++ $`x=y`$++ ```math+ x = y+ ```++ To defeat this and get the older behavior, namely++ $x=y$++ $$x=y$$++ one could use `-t gfm-tex_math_gfm`.++ * AsciiDoc writer:++ + Add `link:` prefix when needed (#10105). AsciiDoc requires it+ except for `http`, `https`, `irc`, `mailto`, `ftp` schemes (#10105).+ + Preserve original base level (#10062). We used to normalize so+ that the base level is always 1, but asciidoc no longer seems+ to care about that, and the behavior creates difficulties when+ we are converting fragments.+ + Don't emit empty figure caption (#10047).++ * ODT writer:++ + Add TableCaption to styles.xml (#10058, Ian Max Andolina).++ * LaTeX template:++ + Fix wrong beamer color in (sub)section page (Jonathan).++ * Text.Pandoc.Options:++ + Add `CaptionPosition` and new `WriterOptions` fields+ `writerFigureCaptionPosition` and `writerTableCaptionPosition`+ [API change].++ * Text.Pandoc.Opt:++ + Change default for optNumberOffset to `[]`. This behaves the same as+ `[0,0,0,0,0]`.+ + Add `Opt` fields `optFigureCaptionPosition` and+ `optTableCaptionPosition` [API change].++ * Text.Pandoc.Format: change `formatFromFilePaths` so that it is+ smarter about URLs. URLs are parsed, and we take the format from+ the path component, if present (#10141). This means that+ `https://emacs.org/` will be treated as HTML, while+ `https://emacs.org/sample.org` will be treated as Org.++ * Text.Pandoc.URI:++ + Add unofficial `gemini:` to list of URI schemes (Pau RE).++ * Text.Pandoc.Shared:++ + Add `makeSectionsWithOffsets` [API change].+ + Remove `stripEmptyParagraphs [API change] (Albert Krewinkel).+ This function is no longer used.++ * Text.Pandoc.Highlighting: Expose `formatANSI` [API change]+ (Evan Silberman).++ * Text.Pandoc.Writers.Shared: export `to{Sub,Super}scriptInline`+ [API change] (Evan Silberman).++ * Remove use of partial functions (e.g. `head`) in code.++ * Use latest skylighting-core, skylighting, doclayout, texmath, typst.++ * pandoc-lua-engine: Add accessors for several writer options, including+ some that were added in previous releases.++ * pandoc-server: Initialize some missing fields in WriterOptions:+ `writerEpubTitlePage`, `writerChunkTemplate`, `writerListTables`,+ `writerFigureCaptionPosition`, `writerTableCaptionPosition`.++ * CONTRIBUTING.md: Summarize steps for adding a new cli option.++ * MANUAL.txt:++ + Clarify that the `--number-offset` option should only+ directly affect numbering of the first section heading in+ a document; subsequent headings will increment normally.+ + Fix asciidoc link (#10039).+ + Fix CSL Docs broken link (#10100, Tristano Ajmone).+ + Document the use of `luatexja` when CJKmainfont is used with lualatex+ (#3873, Kolen Cheung).+ + Add a `citations` (typst) section to the manual (#9127).+ + Clarify that `citations` affects both input and output for `org`.+ + Add note on `--citeproc` that you may need to disable `citations`+ extension on the output format (e.g., `-t markdown-citations`) to+ see the rendered citation (#9127, #10012).++ * INSTALL.md — reorganise info on static binaries and add conda-forge+ install options (#10098, #10069, Ian Max Andolina).++## pandoc 3.3 (2024-07-28)++ * New cli option: `--link-images`. This causes images to be linked+ rather than embedded in ODT.++ * Allow `--number-sections` to take an optional `true|false` argument.++ * RTF reader:++ + Handle `\*\shppict` without dropping image (#10025).++ * TWiki Reader:++ + Recognize WikiWords as internal links (#9941).+ + Avoid partial function.++ * Typst reader:++ + Ignore 'pad' and just parse its body (#9958).+ + Use typst 0.5.0.5. Fixes parsing of equations like `$1.$`.++ * Docx writer:++ + Fix regression with nested lists (#9994). The bug affects e.g.+ ordered lists with bullet sublists; after the sublist the top-level+ list reverts to bullets instead of being properly numbered.+ This is a regression introduced in version 3.2.1.++ * BibTeX writer:++ + Ensure that "literal" names are enclosed in braces (#9987).++ * Man writer:++ + Use default middle header when metadata does not include `header`+ (#9943). This change causes pandoc to omit the middle+ header parameter when `header` is not set, rather than+ emitting `""`. The parameter is optional and man will use+ a default based on the section if it is not specified.++ * HTML templates: don't load polyfill (#9918).+ This was added in a period when MathJaX required polyfill.+ MathJaX no longer recommends this and polyfill should no+ longer be necessary on any reasonably modern browser.++ * Translations:++ + Add `ua.yaml` (Jens Oehlschlägel).+ + Add a script (`tools/update-translations.py`) and Makefile+ target (`update-translations`) to update translation data+ automatically from babel and polyglossia upstream+ (Stephen Huan).+ + Use this script to update language data, increasing the number+ of languages we cover (Stephen Huan). Fix a few small bugs in+ existing translations.++ * Fix some mistakes with Japanese language code (#9938).+ In several places we were mistakenly assuming that the BCP 47 code for+ Japanese language was `jp`. It is `ja`.++ * Text.Pandoc.Options:++ + New field in WriterOptions: `writerLinkImages` [API change] (#9815).++ * Text.Pandoc.App.Opt:++ + New field in Opt: `optLinkImages` [API change] (#9815).++ * Lua subsystem:++ + Keep `lpeg` and `re` as "loaded" modules (Albert Krewinkel).+ The modules `lpeg` and `re` are now treated as if they had been+ loaded with `require`. Previously the modules were only assigned+ to global values, but could be loaded again via `require`,+ thereby allowing to use a system-wide installation. However, this+ proved to be confusing.++ The old behavior can be restored by adding the following lines to+ the top of Lua scripts, or to the `init.lua` in the data dir.++ debug.registry()['_LOADED'].lpeg = nil+ debug.registry()['_LOADED'].re = nil++ * `pandoc-cli`: Include pandoc copyright in Lua version info (Albert+ Krewinkel).++ * `pandoc-cli`: Refer printing of version info to the Lua interpreter+ (Albert Krewinkel). The Lua interpreter no longer terminates when+ called with `-v` or `--version` arguments, thus improving+ compatibility with the default `lua` interpreter program.++ * Avoid partial functions in JATS reader, DocBook writer, Haddock reader.++ * Allow tls 2.1.x.++ * MANUAL.txt:++ + Make documentation of extensions clearer (#9060).+ + Fix section level for two Extensions entries.++ * lua-filters.md: Partially autogenerate docs for module `pandoc`+ (Albert Krewinkel). The documentation system isn't powerful enough to+ generate the full documentation automatically.++## pandoc 3.2.1 (2024-06-24)++ * Fix `gfm_auto_identifiers` to replace emojis with their aliases,+ as documented (#9876).++ * CSV reader:++ + Turn line breaks into LineBreaks not SoftBreaks (#9797).++ * Docx reader:++ + Support task lists (#8211).+ + Fix a small bug in parsing delimiters in numbered lists,+ which led to the default delimiter being used wrongly in some cases.+ + Improve handling of captions.+ - Turn captioned images into Figure elements. Closes #9391.+ - Improve the logic for associating elements with captions (#9358).+ - Ensure that captions that can't be associated with an+ element aren't just silently dropped (#9610).+ + Support HorizontalRule. We support both pandoc-style and the style+ described on a Microsoft support page, an empty paragraph with+ a bottom border (#6285).+ + React to `"left"` value on `jc` attribute.+ + Handle column and cell alignments (#8551). We take the column alignments+ from the first body row.+ + Fix a bug that caused comments inside insertions or deletions+ to be ignored (#9833).++ * HTML reader:++ + Better handle non-`li` elements in `ul` and `ol` (#9809).+ For example, a `p` after a closed `li` will be incorporated into+ the previous `li`. This mirrors what browsers do with this+ invalid HTML.++ * LaTeX reader:++ + Fix parsing of dimensions beginning with `.`, e.g. `\kern.1pt` (#9902).++ * Markdown reader:++ + Allow author-only textual citations (#7219). E.g. `-@reese2002`+ outside of brackets.++ * RST reader:++ + Tighten up rules for when emphasis can start (#9805).+ + Support `:cite:` role with citeproc (#9904). A subset of the+ functionality of the sphinxcontrib-bibtex extension to Sphinx+ is supported.++ * Textile reader:++ + Don't let spans begin right after a symbol (#9878).++ * Typst reader:++ + Fix an incomplete pattern match (#9807).+ + Handle inline bodies ending in a parbreak. E.g.+ ```+ `#strong[+ test+ ]+ ```++ * ConTeXt template: remove `\setupbackend[export=yes]` (#9820).++ * Docx writer:++ + Allow OpenXML templates to be used with `docx` (#8338, #9069, #7256,+ #2928). The `--reference-doc` option allows customization of styles in+ docx output, but it does not allow one to adjust the content of the output+ (e.g., changing the order in which metadata, the table of contents,+ and the body of the document are displayed), or adding boilerplate+ text before or after the document body. For these changes, one can+ now use `--template` with an OpenXML template. (See the default+ `openxml` template for a sample.) `--include-before-body` and+ `--include-after-body` can also now be used with `docx` output.+ The included files must be OpenXML fragments suitable for+ inclusion in the document body.+ + New unexported module Text.Pandoc.Writers.Docx.OpenXML.+ + Omit `jc` attribute on table cells with AlignDefault (#5662).+ + Better formatting for task lists. Task lists are now properly+ formatted, with no bullet (#5198).+ + Replace an expensive generic traverse to remove Space elements,+ for better performance.+ + Wrap figures with `id` in a bookmark (#8662).+ + Add eastAsia font hints to `w:r` (#9817). We do this when the text+ in the run contains any CJK characters. This ensures that ambiguous+ code points (e.g. quotation marks) will be represented as "wide"+ characters when together with CJK characters.+ + Clean up Abstract Title and Subtitle in default reference docx.+ Center Subtitle, remove color.++ * HTML writer:++ + Ensure URI escaping needed for `html4` (#9905).+ Unicode characters need not be escaped for html5, and still won't be.+ + Don't emit unnecessary classes in HTML tables (#9325, Thomas Soeiro).+ Pandoc used to emit a `header` class on the `tr` element that forms+ the table header. This is no longer needed, because `head > tr` will+ do the same thing. Similarly, pandoc used to emit `even` and `odd`+ classes on `tr`s, allowing striped styling. This is no longer needed,+ because one can use e.g. `tbody tr:nth-child(2n)`.+ Compatibility warning: users who relied on these classes to style+ tables may need to adjust their CSS.++ * JATS writer:++ + Support `supplementary-material` in metadata for `jats_articlepublishing`+ (#9818).++ * LaTeX writer:++ + New method for ensuring images don't overflow (#9660).+ Previously we relied on graphicx internals and made global+ changes to Gin to force images to be resized if they exceed+ textwidth. This approach is brittle and caused problems+ with `\includesvg` (see #9660). The new approach uses a new macro+ `\pandocbounded` that is now defined in the LaTeX template.+ (Thanks here to Falk Hanisch in https://github.com/mrpiggi/svg/issues/60.)+ The LaTeX writer has been changed to enclose `\includegraphics`+ and `\includesvg` commands in this macro when they don't explicitly+ specify a width or height. In addition, the writer now adds+ `keepaspectratio` to the `\includegraphics` or `\includesvg`+ options if `height` is specified without width, or vice versa.+ Previously, this was set in the preamble as a global option.+ Users should attend to the following compatibility issues:+ - If custom templates are used with the new LaTeX writer, they will have+ to be updated to include the new `\pandocbounded` macro, or an error+ will be raised because of the undefined macro.+ - Documents that specify explicit dimensions for an image may render+ differently, if the dimensions are greater than the line width or+ page height. Previously pandoc would shrink these images to fit,+ but the new behavior takes the specified dimensions literally.+ In addition, pandoc previously always enforced `keepaspectratio`,+ even when width and height were both specified, so images with+ width and height specified that do not conform to their intrinsic+ aspect ratio will appear differently.+ + Task lists must be unordered (#9185).+ + Specify language option for `selnolig` and only include it if+ `english` or `german` is used (#9863). (This includes changes to the+ LaTeX template.) This should restore proper ligature suppression when+ lualatex is used.+ + Fix `--toc-depth` with beamer output (#9861). Previously only top-level+ sections were ever included in the TOC, regardless of the setting of+ `--toc-depth`.+ + Use `\linewidth` instead of `\columnwidth` or `\textwidth`+ for resizing figures, table cells, etc. in LaTeX (#9775).+ `\linewidth`, unlike the others, is sensitive to indented environments+ like lists.++ * LaTeX template: put `babel-lang` in options to beamer (#9868).+ This is required to make beamer use proper localized terms for+ things like "Section."++ * Markdown writer:++ + Don't print extra caption when using `implicit_figures`.+ + Ensure blank line after HTML blocks in commonmark-based formats (#9792).+ + Fix bug rendering block quotes in lists (#9908).++ * Texinfo writer:++ + Ensure proper escaping in all node/link contexts.+ + Target node rather than anchor when possible in internal links.+ + Remove illegal characters from internal link anchors (#6177).+ + Use two commas not one in `@ref`.+ + Don't add anchors to headings. We don't need them, now that we+ make internal links use the node.+ + Avoid duplicate node names.+ + Improve menus. Properly handle the case where the node name is+ different from the descriptive title.++ * Texinfo template: add variables for filename and version.++ * Typst writer:++ + Support '.typst:no-figure' and 'typst:figure:kind=kind' attributes+ (#9778, Carlos Scheidegger). This extends support for fine-grained+ properties in Typst. If the `typst:no-figure` class is present on a+ Table, the table will not be placed in a figure. If the+ `typst:figure:kind` attribute is present, its value will be used+ for the figure's `kind` (#9777). These features are documented in+ `doc/typst-property-output.md`.++ * Typst template:++ + Add subtitle (#9747, Mickaël Canouil).+ + Use content rather than string for title, author, date, email (#9823).+ This allows formatting in title, author, date, and email fields.+ Since the PDF metadata requires a string, and typst only+ converts the title to a string (not the authors), we use++ * Textile writer:++ + Get rid of header, odd, even classes on `tr` (#9376).++ * Text.Pandoc.Class:++ + `fillMediaBag`: Convert IOErrors to warnings when fetching absolute+ paths (#9859, Albert Krewinkel). This will allow many conversions that+ would have failed with an error to succeed (albeit without images or+ other needed resources).++ * Text.Pandoc.ImageSize:++ + Don't prefer exif width/height when they conflict with image+ width/height (#9871). That was a mistaken call in #6936.+ Usually when these values disagree, it is because the image+ has been resized by a tool that leaves the original exif values+ the same, so the width/height metadata are more likely to be+ correct that exif width/height.++ * Text.Pandoc.SelfContained:++ + Strip CRs from XML before base64 encoding for data URI+ (so tests can work on Windows).+ + Only create `<svg>` elements for SVG images when the image has+ the class `inline-svg`. Otherwise just use a `data` URI as we do+ with other images (#9787).++ * Lua subsystem (Albert Krewinkel):++ + Split Init module into more modules. The module has grown unwieldy and+ is therefore split into three internal Haskell modules, `Init`,+ `Module`, and `Run`.+ + Add function `pandoc.utils.run_lua_filter` (#9803).+ + Add function `pandoc.template.get` (#9854, co-authored by Carsten Gips).+ The function allows to specify a template with the same argument value+ that would be used with the `--template` command line parameter.+ + Keep CommonState object in the registry. The state is an internal+ value and should be treated as such. The `PANDOC_STATE` global is+ merely a copy; unsetting the global no longer breaks the Lua engine.+ + Allow passing an environment to `run_lua_filter`.+ The default is now to use a *copy* of the global environment when running+ a filter; this ensures better separation when `run_lua_filter` is used+ multiple times. A custom environment can be specified via the+ optional third parameter.+ + Set `pandoc.List` as default metatable for JSON lists (#9834).+ Lists created by `pandoc.json.decode` now behave like lists generated+ via `pandoc.List`. This also ensures that `pandoc.List` tables are+ encoded as JSON arrays when passed to `pandoc.json.encode`.++ * Text.Pandoc.Writers.Shared: export `toTaskListItem` [API change].++ * Add unexported module Text.Pandoc.Char. This exports `isCJK`.+ Use this instead of locally defined `isCJK` in T.P.Readers.MediaWiki.++ * MANUAL.txt:++ + Remove false claim that Lua mode does not support `-i` (#9757,+ Ian Max Andolina).+ + Use level-3 headings for extensions (to avoid gaps).+ + Add anchor for tagging extension.+ + Remove explicit referencess to generate anchors.+ These will be linkified automatically.+ + Fixed links to `option--reference-doc`.+ + Add a note that column widths aren't supported in pptx for Divs+ with class `columns` (#9890).+ + Fix alerts example (#9826, Ian Max Andolina).+ + Fix markup of `babelfonts` example code (Albert Krewinkel).++ * `doc/custom-writers.md`:++ + Fix usage of Template in example (Albert Krewinkel).+ + Document the separator arg of `Writer.Blocks` (Albert Krewinkel).++ * `doc/lua-filters.md` (Albert Krewinkel):++ + Fix outdated documentation for math and quoting functions and fields.+ + Autogenerate docs for module `pandoc.template` and `pandoc.layout`.+ + Document operators of the "Doc" type.++ * pandoc-lua-engine: depend on pandoc >= 3.2 (see #9755).++ * Allow crypton-connection 0.4, time 1.14.++ * Allow tasty-quickcheck 0.11.++ * Use latest emojis, skylighting, skylighting-core, citeproc, djot,+ commonmark-extensions, typst-hs++## pandoc 3.2 (2024-05-11)++ * Change to `--file-scope` behavior (#8741): previously a Div with an+ identifier derived from the filename would be added around the contents+ of each file. This caused problems for "chunking" files into chapters,+ e.g. in EPUB. We no longer add the surrounding Div. This cooperates+ better with chunking. Note, however, that if you have relied on the old+ behavior to link to the beginning of the contents of a file using+ its filename as identifier, that will no longer work.++ * Markdown reader:++ + Allow repeated labels in numbered example lists.+ Previously if you tried to use the same label as an earlier+ example list item, you'd get a new number, not the old one,+ and references to the label would go to the second occurrence.+ Now an existing label will be reused, and no new number will+ be generated. Caveat: this only works reliably when the+ re-used example list item occurs by itself in a list, or+ occurs in a list of previously used example list items that+ occur in exactly the same order as previously.+ + Fix `normalCite` so it doesn't consume past a closing `]` boundary+ (#9710). This was causing an exponential performance bug on long+ lists of links containing potential emphasis characters.+ + Generalize `inlinesInBalancedBrackets` to `inBalancedBrackets`,+ with a parameter for the inner parser.+ + Auto-close unclosed divs (#9635). This applies to both fenced and+ HTML-ish varieties. Otherwise we face an exponential performance+ problem with backtracking. A warning is issued when a div is+ implicitly closed.++ * RST reader:++ + Fix `figclass` and `align` annotations for figures (#7473, Gokul+ Rajiv).++ * LaTeX writer:++ + Use `polytonicgreek` instead of `polutonikogreek` with babel (#9698).+ `polutonikogreek` is outdated. Also recognize both in the LaTeX+ reader.+ + Improve treatment of math inside soul commands (#1294, #5529).+ soul commands (`ul`, `hl`, `st`) are very fragile and the math+ must be handled specially.++ * LaTeX reader:++ + Fix over-eager macro expansion in conditionals (#9676).+ + Parse `flalign`, `flalign*` math environments (#9679). We parse+ these as Math elements with an `aligned` environment. Semantically+ it's not exactly the same, but better than falling back to raw LaTeX.++ * LaTeX template: add `titlegraphicoptions` variable (#9207, Guilhem+ Saurel).++ * Docx reader:++ + Issue warning rather than error when we can't parse EndNote citations+ (see #8433).+ + Fix anchor in header after anchor (#9626, mbracke).++ * RTF reader:++ + Don't try to handle non-default code pages (#9683). Emit a warning+ instead.++ * OpenDocument writer:++ + Implement custom-style for spans (#9657).++ * Typst writer:++ + Add blank line in definition lists with multiple definitions (see+ #9704).+ + Property output (#9648, Gordon Woodhull). The Typst writer will pass+ on specially marked attributes as raw Typst parameters on selected+ elements. This allows extensive customization using filters.+ A separate document (`doc/typst-property-output.md`) has been added+ that provides extensive documentation and examples of the use of+ this feature.++ * Markdown writer:++ + Don't try to align columns in pipe tables with lines greater than+ COLUMNS. The alignment just reduces readibility when the lines+ soft wrap.+ + Don't use `raw_attribute` syntax for raw blocks, unless there is no+ other option (see #9677). Macros in a `raw_attribute` block don't+ get interpreted when it is read again by pandoc's markdown reader.++ * ConTeXt writer:++ + Replace depreciated `\sc` with `\setsmallcaps` (#9518, James P.+ Ascher).++ * Docx writer:++ + Use conventional styles/indents for Word bullet lists (#7280).++ * `reference.docx`:++ + Use current standard Word theme (#7280). This includes using the+ sans-serif font Aptos instead of the serif font Cambria, and+ default colors for headings.+ + Remove duplicate `DefaultParagraphFont` in `styles.xml`.++ * New module Text.Pandoc.Transforms [API change] (Albert Krewinkel).+ This module exports the following functions which were formerly+ exported from Text.Pandoc.Shared: `headerShift`,+ `filterIpynbOutput`, `eastAsianLineBreakFilter`, as well as some+ functions that were previously not exported.++ * Text.Pandoc.Shared:++ + `headerShift`, `filterIpynbOutput`, and `eastAsianLineBreakFilter`+ are no longer exported from this module; they are now exported+ from Text.Pandoc.Transforms (Albert Krewinkel).++ * Text.Pandoc.Error:++ + Improve reporting of unsupported extensions errors (#9247, Albert+ Krewinkel).++ * Text.Pandoc.App:++ + Move "transforms" after filters (#9664). This will mean that+ `--shift-heading-level-by` affects a heading added by+ `reference-section-title`.++ * Text.Pandoc.App.CommandLineOptions:++ + Simplify output for `OptVersion`. Omit the information about versions+ of dependencies. We no longer emit version info at this level anyway;+ `pandoc-cli` intercepts and handles `--version`. This code would+ only be called if someone used the pandoc library function+ `handleWithOptInfo` in their own program.++ * Text.Pandoc.ImageSize:++ + Export `ImageSize` datatype.++ * Text.Pandoc.SelfContained:++ + Merge class attribute when both img and svg specify it (#9652,+ Carlos Scheidegger).++ * Text.Pandoc.Logging:++ + Add `ScriptingInfo` constructor for `LogMessage` [API change]+ (Albert Krewinkel).+ + Make `DocxParserWarning` a WARNING, not INFO. [API change].+ + Add `UnsupportedCodePage` constructor to `LogMessage` [API change].+ + Add `UnclosedDiv` constructor for `LogMessage` [API change].++ * Lua subsystem (Albert Krewinkel:++ + Add a `pandoc.log` module.+ + Uupdate to pandoc-lua-marshal version 0.2.7 (#8916).+ This fixes counterintuitive behavior of the `content` property on+ BulletList and OrderedList items. Unmarshalling of that field now+ matches the behavior of the constructor.+ + Use newest zip module. This adds a `symlink` function to Entry objects,+ allowing to check if an entry represents a symbolic link.+ + Improve `pandoc.json.decode` docs.+ + Update and fix docs for `pandoc.types.Version` and `pandoc.utils.type`.+ + Add new module `pandoc.image` The module provides basic querying+ functions for image properties.+ + Bump pandoc-lua-engine to 0.2.1.4.++ * Use latest KaTeX CDN asset (#9707, Salim B).++ * `pandoc-cli`: ensure UTF8 when emitting version info.++ * tools/update-lua-module-docs.lua: improve script-internal docs, cleanup+ (Albert Krewinkel).++ * Allow network 3.2.++ * Use latest versions of texmath, djot, skylighting-core, skylighting.++ * Fix command test for #9652.++ * Fix some typos in code comments (#9638, guqicun).++ * Command tests: include regular PATH after directory with the test+ executable (ensures that DLLs will be found on Windows).++ * MANUAL.txt:++ + Document `handout` variable for beamer (#9742).+ + Document formats affected by `--slide-level` (#9745).+ + Update the list of required LaTeX packages (#9728, Albert Krewinkel).+ + Use more descriptive link text for ODT (#9673).+ + Add clarification about `toc-title` in `docx`, `pptx` (#9645).+ + Better document truthiness for conditionals (#9661).+ + Mention that `custom-style` works with ODT (Ian Max Andolina).+ + Harmonize typographic dashes (#9688, Salim B). Standardize on `---`+ with no space.++ * INSTALL.md: Minor tweaks (#9705, Leo Heitmann Ruiz).++## pandoc 3.1.13 (2024-04-07)++ * Org reader:++ + Fix treatment of `id` property under heading (#9639).++ * DocBook reader:++ + Add empty title to admonition div if not present (#9569).+ This allows admonition elements (e.g. `<note>`) to work with+ `gfm` admonitions even if the `<title>` is not present.++ * DokuWiki reader:++ + Link text cannot contain formatting (e.g., `//` is not italics) (#9630).+ + An explicitly empty link text (`[[url|]]`) works the same as an omitted+ link text (#9632).++ * Typst reader:++ + Support Typst 0.11 table features: col/rowspans, table head+ and foot (#9588).+ + Parse cell col/rowspans.++ * CSLJson writer:++ + Put `$` or `$$` around math in `csljson` output (#9616).++ * ConTeXt writer:++ + Fix options order with `\externalfigure`. The dimensions should+ come after the class if both are present.++ * Typst writer:++ + Put label after Span, not before. Labels get applied to preceding markup+ item.+ + Support Typst 0.11 table features (#9588): colspans, rowspans,+ cell alignment overrides, relative column widths,+ header and footer, multiple table bodies with intermediate headers.+ Row heads are not yet supported.+ + The default typst template has been modified so that tables+ don't have lines by default. As is standard with pandoc, we only+ add a line under a header or over a footer. However, a different+ default stroke pattern can easily be added in a template.+ + More reliable escaping in inline `[..]` contexts (#9586). For example,+ we need to escape `[\1. April]` or it will be treated as an ordered list.+ + Handle `unnumbered` on headings (#9585).++ * LaTeX writer:++ + Fix math inside strikeout (#9597).++ * Text.Pandoc.Writers.Shared:++ + Export `isOrderedListMarker` [API change].++ * Change lhs tests so they don't use `--standalone`.+ This will avoid test failures due to minor changes in+ skylighting versions, e.g. #9589.++ * Use latest texmath, typst.++ * Require pandoc-lua-marshal 0.2.6 (#9613, Albert Krewinkel).+ Fixes an issue arising when the value of `content` properties+ on *BlockQuote*, *Figure*, and *Div* elements was an empty list.++ * Update lua-filters.md (#9611, Carlos Scheidegger).+++## pandoc 3.1.12.3 (2024-03-17)++ * Markdown reader: Fix bug with footnotes at end of fenced div (#9576).++ * LaTeX reader:++ + Improve tokenization of `@` (#9555). Make tokenization sensitive to+ `\makeatletter`/`\makeatother`. Previously we just always treated+ `@` as a letter. This led to bad results, e.g. with the sequence `\@`.+ E.g., `a\@ b` would parse as "ab" and `a\@b` as "a".+ + Make `withRaw` work inside `parseFromToks` (#9517).+ This is needed for raw environments to work inside table cells.+ + Better handling of table colwidths (#9579). Previously the parser just+ failed if the column width specified in `p{}` wasn't a multiple of+ `\linewidth`. This led to cases where content was skipped.++ * Typst writer:++ + Add 'kind' parameter to figures with tables (#9574).+ + Avoid unnecessary box around image in figure (#9236).+ + Omit width/height in images unless explicitly specified (#9236).+ Previously we computed width/heigth for images that didn't have+ size information, because otherwise typst would expand the image+ to fit page width. This typst behavior has changed in 0.11.+ This change fixes a bug in which images would sometimes overflow+ page margins, depending on their intrinsic size.+ + Don't add hard-coded `inset` to tables (#9580). Instead, set this+ globally in the default template, allowing it to be customized.++ * LaTeX template: Fix block headings support for unnumbered paragraphs+ (#9542, #6018, Oliver Fabel).++ * HTML templates: Replace polyfill provider (#9537, @SukkaW).+ Replace polyfill.io with cdnjs.cloudflare.com/polyfill.+ polyfill.io has been acquired by Funnull, and the service has+ become unstable.++ * Korean translations: delete colon in translation for 'to'.+ This was invalid YAML, and not desired anyway, since a colon+ is added.++ * Use latest commonmark, commonmark-extensions.+ This fixes a 3.12 regression in parsing of commonmark/gfm autolinks+ (jgm/commonmark-hs#151).++ * Depend on djot 0.1.1.3, which fixes a serious parsing bug affecting+ regular paragraphs after lists.++ * Depend on latest skylighting, skylighting-core, typst-hs, texmath.++ * MANUAL.txt: Change broken link to IDML cookbook (#9563).++## pandoc 3.1.12.2 (2024-02-29)++ * Docx reader:++ + Ensure that table captions are counted (#9518).+ + Detect caption by style name not id (#9518).+ The styleId can change depending on the localization.+ + Avoid emitting empty paragraph where caption was.++ * Markdown reader: fix regression in link parsing with wikilinks extensions+ (#9481). This fixes a regression introduced in 3.1.12.++ * Org reader/writer: support admonitions (#9475).++ * Org writer: omit extra blank line at end of quote block.++ * Typst writer: ensure that `-`, `+`, etc. are escaped at beginning of block+ (#9478). Our recent relaxing of escaping (#9386) caused problems for+ things like emphasized `-` characters that were rendered using+ `#strong[-]#`. This now gets rendered as `#strong[\-]`.++ * LaTeX writer: fix bug when a language is specified in two different ways+ (#9472). If you used `lang: de-DE` but then had a span or div with+ `lang=de`, the preamble would try to load `ngerman` twice, leading+ to an error. This fix ensures that a language is only loaded once.++ * Docx writer: Don't copy over `footnotePr` in `settings.xml`+ from reference.docx (#9522).++ * EPUB writer: omit EPUB2-specific meta tag on EPUB3 (#9493).+ This caused a validation failure in epubs with cover images.++ * Lua: avoid crashing when an error message is not valid UTF-8 (Albert+ Krewinkel).++ * Text.Pandoc.SelfContained:++ + Add `role="img"` to svgs.+ + Add `aria-label` to svg elements with `alt` text if present.+ Screen readers ignore `alt` attributes on svg elements but do+ pay attention to `aria-label` (#9525).++ * Text.Pandoc.Shared: Fix regression in section numbering in+ `makeSections` (#9516). Starting with pandoc 3.1.12, unnumbered+ sections incremented the section number.++ * Text.Pandoc.Class: fix `openUrl` TLS negotiation (#9483).+ With the release of TLS 2.0.0, the TLS library started requiring+ Extended Main Secret for the TLS handshake. This caused problems+ connecting to zotero's server and others that do not support TLS 1.3.+ This commit relaxes this requirement.++ * Depend on djot 0.1.1.0 (fixes rendering on multiline block attributes).++ * Use new releases of skylighting-format-blaze-html (#9520).+ Fixes auto-wrapping of long source lines in HTML print media.++ * Use new commonmark-extensions (fixes issue with the+ `rebase_relative_paths` extension when used with commonmark/gfm.++ * Makefile: improve epub-validation target (#9493).+ Use `--epub-cover-image` to catch issues that only arise with that.++## pandoc 3.1.12.1 (2024-02-17)++ * EPUB writer: omit EPUBv3-specific accessibility features on epub2+ (#9469). Fixes a regression in 3.1.12.++ * More fixes for SVG ids with `--self-contained` (#9467).+ This generalizes the fix to #9420 so it applies to things like+ `style="fill(url(#..."` and should fix problems with SVGs including+ gradients.++ * Powerpoint writer: properly handle math in headings and tables (#9465).+ This ensures that paragraphs containing math are wrapped in+ a `mc:AlternateContent` node as required.++ * Makefile: make validate-epub check v2 output too.++## pandoc 3.1.12 (2024-02-14)++ * Add `djot` as input and output format. Djot is a light markup syntax+ (https://djot.net).++ + New module Text.Pandoc.Readers.Djot [API change]. The function+ `readDjot` is also exported by Text.Pandoc.Readers.+ + New module Text.Pandoc.Writers.Djot [API change]. The function+ `writeDjot` is also exported by Text.Pandoc.Writers.++ * `--number-sections` now uses the first digit for the number of+ the top-level section, no matter what its level. So if the top-level+ section is level-2, numbers will be `1`, `2`, etc. rather than+ `0.1`, `0.2`, as in the past (#5071). For some backwards compatibility,+ we revert to the old behavior when the `--number-offset` option is used.++ * DocBook reader:++ + Better handling of `<procedure>` and `<substeps>` (#9341):+ `<procedure>` now gets parsed as an ordered list, and+ `<substeps>` as a sublist.++ * Man reader:++ + Move spaces outside of emph/strong (#9445).++ * MediaWiki reader:++ + Don't make leading blanks underscores in image links (#9425).+ + Allow lowercase `image:` (#9424).++ * BibTeX reader:++ + Support `pagetotal` in converting BibLaTeX.++ * Markdown reader:++ + Fix wikilinks extensions to allow newlines in titles (#9454).++ * EPUB reader:++ + Don't put `#` characters in identifiers.++ * LaTeX reader:++ + Improve treatment of `\cref`, `\Cref` (#7463). Use the+ reference-type `ref+label` and `ref+Label`. Also, associate with+ `\vref` `ref` instead of `ref+page`.+ + Limited support for `\Cref` (#7463).+ + Generate relative widths for `\linewidth`, `\textheight` (#9388).++ * Typst reader:++ + Fix handling of `\overline` (#9294). Due to a typo, it was being+ incorrectly rendered as an `\underset`.+ + Improve handling of inline `#quote` (#9413).+ + Fix handling of `dot()`, `tilde()`, `ddot()` (jgm/typst-hs#38).+ + Fix character used for `norm` (jgm/typst-hs#38).++ * Typst writer:++ + Use reference form (e.g. `@jones2000[p. 30]`) for citations when+ possible.+ + Use `#ref` or `@` for links with `reference-type="ref"` (#7463).+ This attribute is added to LaTeX `\cref`, for example.+ + Improve citation support (#9452). Emit `form: "prose"` or `form: "year"`+ qualifiers if the citation is author-in-text or suppress-author.+ Strip initial comma from suffix, since typst will add an extra one.+ + Unescape URI escapes in image paths (#9389).+ + Handle labels and citaiton ids with spaces and other special+ characters (#9387). In these cases, we produce an explicit `label()`+ rather than using `<>` or `@`.+ + Avoid producing illegal labels (#9387).+ + Avoid unnecessary escapes (#9386).++ * LaTeX writer:++ + Make writer sensitive to `empty_paragraphs` extension (#9443).+ + Fix beamer highlighting (mh4ckt3mh4ckt1c4s).+ + Create valid table even when table is empty (#9350).+ + Set font fallback for babel main font (Max Heller).+ + Add some kerns where needed between quotes (#9371).++ * HTML writer:++ + Add suffix to multiple footnote section ids, so they are+ unique (Sam May). This is necessary when `--reference-location`+ is `block` or `section`.++ * EPUB writer:++ + Add ARA roles for accessibility (#9378, Iacobus1983).+ Footnote references are given role "doc-noteref", footnote text+ gets "doc-footnote", and nav gets "doc-toc".+ + Ensure that an alt attribute is always added (#9354). This seems to+ be required by iBooks; even an empty alt attribute will satisfy it.+ + Add `xml:lang` to package element (#9372).+ + Add accessibility metadata to EPUB metadata (#9372, #9400,+ Iacobus1983 and John MacFarlane). Reasonable default values are+ used to ensure that pandoc's EPUBs conform to the EU Accessibilty Act+ requirements, but values can be overridden using metadata.++ * Docx writer:++ + Restore ability to center-justify table (#9393). The fix to+ #5947 caused all tables to be left indented. This was necessary+ to avoid extra indentation in table cells when a table appeared+ in a list item. This change makes the changes conditional, so+ that they only affect tables in list items.++ * Man writer:++ + Fix bug with long URLs (#9458). URLs with more than 68 characters didn't+ display properly because of wrapping.+ + Support (limited) syntax highlighting in code blocks (#9446).+ Currently only boldface and italics are supported. The `monochrome`+ style might be of use for those generating man pages.++ * Org writer:++ + Escape special lines in code blocks (#9218, Albert Krewinkel).++ * Markdown writer:++ + Use different width fences for nested divs (#9450). Outer divs+ have longer fences. This aids clarity for the reader, making it+ easier to see where the div ends. It also makes the output+ compatible with some other implementations, e.g. micromark,+ which require different-width fences for nesting.+ + Fix output for pipe tables with a huge number+ of columns (#9346). Previously we got invalid pipe tables when the+ number of table columns exceeded the setting of `--columns`.++ * Powerpoint writer:++ + Fix regression in layout for slides with figures (#9442).+ + Use internal column widths in pptx writer tables (#5706,+ Tomas Dahlqvist). The table writer used to only divide all+ available width evenly for all columns. In this update the code+ uses the incoming widths if they are available. If they are not+ set the earlier even distribution is used. Some of the golden+ templates are adjusted slightly because of different rounding when+ using the new calculation model.++ * Custom writers:++ + Fix handling of common state (#9229, Albert Krewinkel).+ The CommonState (`PANDOC_STATE` in Lua) may change between the time that+ a custom writer script is first loaded and when the writer is run.+ However, the writer was always using the initial state, which led to+ problems, e.g. when the mediabag was updated in a filter, as those+ updates where not visible to the writer. The state is now updated+ right before the writer function runs.++ * Text.Pandoc.SelfContained:++ + Fix id replacements in SVGs with clipping paths (#9420).+ This fixes `--embed-resources` when SVGs have `clip-path` attributes.+ + Fix size of duplicated SVGs with `--embed-resources` (#9439).++ * ConTeXt template: support font fallback (#9361, Lawrence Chonavel).++ * Text.Pandoc.Shared:++ + `addPandocAttributes`: use `wrapper` attribute, not `wrap`, for+ Divs and Spans added as wrappers to hold attributes on elements+ that do not accept them.+ + `makeSections` behavior changes:+ - When the optional base level parameter is provided, we no+ longer ensure that the sequence of heading levels is gapless+ (#9398). Instead, we set the lowest heading level to+ the specified base level, and adjust the others accordingly. If+ an author wants to skip a level, e.g. from level 1 to level 3,+ they can do that. In general, the heading levels specified+ in the source document are preserved; `makeSections` only+ puts them into a hierarchical structure.+ - Section numbers are now assigned differently, as described above+ under `--number-sections` changes (#5071).+ + Improve `makeSections` code for section number calculation.++ * Text.Pandoc.Chunks:++ + Autogenerate unique ids for sections missing them (#9383).+ This is needed for TOC generation to work properly. We can't+ create TOC links if there are no ids. This fixes some EPUB validation+ issues we've been getting since switching over to Chunks for chunking.+ + Improve `fixTOCTreePaths`. We weren't adding ids for section headings+ that don't head a chunk, but these headings are needed for a TOC.++ * Lua: catch encoding error in `pandoc.read` (#9385, Albert Krewinkel).+ Fixed a bug that could lead to an un-catchable error and program+ termination when `pandoc.read` was called with invalid UTF-8 input.++ * LaTeX template: support font fallback (lawcho). This support is+ LuaLaTeX-specific. See MANUAL.txt for documentation.++ * Text.Pandoc.Readers: Add `readMan` to exports [API change] (George Stagg).++ * Text.Pandoc.PDF:++ + Reliably detect when TOC has changed (#9295). Sometimes the TOC+ changes but there are no warnings: this happens when no labels+ are present. In this case we must rerun LaTeX. So we now take the+ SHA1 hash of the TOC file and rerun LaTeX if it changes between runs.+ + Increase maximum number of LaTeX runs to 4 (#9299). On some documents,+ 4 runs are needed (e.g. when a LastPage reference is used).+ + Avoid `readFileLazy`, which caused improperly cleaned-up+ temp directories on Windows (#9460).++ * MANUAL.txt:++ + Harmonize spelling of Markdown and MultiMarkdown (#9402, Salim B).+ + Add `<pre>` to list of exceptions for `markdown_in_html_blocks`+ extension (#9305).+ + Add clarification to docs for `--resource-path` (#9417).++ * Makefile: Validate generated EPUB as part of prerelease checks.++ * Add validation for docx golden files to CI (Edwin Török).++## pandoc 3.1.11.1 (2024-01-05)++ * Docx reader:++ + Fix HYPERLINK with only switch and no argument (#9246).++ * Org reader:++ + Parse caption and label for grid tables (#9279).++ * MediaWiki reader:++ + Handle multiline math in list items (#9293).++ * OPML writer:++ + Respect `--wrap` options & `--columns` in contents of notes (#9297).++ * ODT/OpenDocument writers:++ + Properly handle highlighting styles (#9287). These styles were+ going into an `office:styles` element in `content.xml`, but this+ is invalid. Instead they must go in `styles.xml`. The variable+ `highlighting-styles` no longer has any effect on the default+ opendocument template, and highlighting styles are not included+ in `opendocument` output.++ * Markdown writer:++ + Add table identifier at end of caption if present (#9279).++ * Text.Pandoc.PDF:++ + Expand list of environment variables to display in verbose output+ (#9303).+ + Ensure that we find all the LaTeX warnings requiring a rerun (#9284).+ This should fix a regression from 3.1.9 that led to incorrect+ alignments in tables (and possibly other issues).++ * Docx writer:++ + Ensure that pandoc's output validates (Edwin Török, #9273, #9269,+ John MacFarlane, #9265, #9266, #9264).+ + Don't emit empty table rows, which seem to cause problems for+ Word (#9224).++ * LaTeX writer:++ + Omit superfluous page locator label when used with `--natbib` or+ `--biblatex` (#9275). These will treat a bare number as a+ page locator, and they will be able to localize it. Note that the+ recognition of the locator label is locale-sensitive; if `lang` is+ `de`, then `S. 33` is a page reference, and `p. 33` is not!++ * Text.Pandoc.Chunks: Fine tune `makeChunks` (#9281).++ + Ensure that chunks not based on sections (those with the+ "preamble" class) get unique identifiers, by appending chunk number.+ + This will also ensure that they get unique path names when+ the path is generated from the identifier.++ * Default HTML5 template: remove html5shiv (and support for IE < 9).++ * Makefile:++ + Fix `make quick-stack`: `j` was expecting a number (Edwin Török).+ + Run built pandoc (instead of pandoc in path).+ + Add `validate-epub` target, using `epubcheck` to test the golden files.+ + Add `validate-docx-golden-tests` target.++## pandoc 3.1.11 (2023-12-15)++ * Typst writer:++ + Emit `;` after typst code, unless followed by space (#9252).+ Otherwise there's the potential that the typst code will swallow+ up a following character.++ * Text.Pandoc.Logging:++ + Add `MakePDFWarning` constructor to LogMessage [API change].+ + Add `MakePDFInfo` constructor to LogMessage [API change].++ * Text.Pandoc.PDF:++ + LaTeX warnings are passed on to the user as warnings.+ + Use `report` with `MakePDFWarning` and `MakePDFInfo` to relay+ verbose information and warnings, instead of writing directly+ to stderr.+ + Parse logs to determine whether additional runs needed, instead of+ running a fixed number of times (#9255). (The number of times+ that was appropriate given pandoc's default templates didn't+ always work for custom templates, and thus pandoc 3.1.10's+ change in the number of runs led to some regressions in PDF+ production.)++ * Makefile: in `make prelease`, add checks that pandoc-cli and+ pandoc have the same version, that pandoc-cli depends on this+ exact version of pandoc, that there is an entry for this version+ in the changelog, and that the version numbers in the+ generated man pages are correct.++ * Regenerate man pages with pandoc 3.1.10. This properly escapes hyphens+ and fixes version numbers in man pages for `pandoc-server` and+ `pandoc-lua`.++ * Depend on texmath 0.12.8.6. This omits unneeded `lr`s in typst+ math output.++ * Depend on typst 0.5. This allows the typst reader to support+ multiline strings, the version type, and the `as`+ keyword with `import`.++## pandoc 3.1.10 (2023-12-12)++ * Link pandoc-cli version to pandoc version. Henceforth pandoc-cli's+ version will be synchronized with pandoc's, and pandoc-cli will+ depend on an exact pandoc version. This will avoid confusion by+ ensuring that `cabal install pandoc-cli-X.Y.Z` installs pandoc+ version X.Y.Z. It will make things more straightforward for+ upstream packagers (see #9232). This scheme does not follow the+ Haskell PVP, but that should cause no harm, because this package+ does not expose a library.++ * Add `alerts` markdown extension. This enables GitHub style markdown+ alerts as a commonmark extension. This extension is now default for+ `gfm`. It can't be used with `markdown`, only with `commonmark` and+ variants.++ * Markdown reader:++ + Preserve newlines in math instead of changing to spaces.+ Otherwise we can get unwanted results if there's+ a `%` comment (#9193).+ + Make attributes work with reference links (#9171).++ * HTML reader:++ + Improve handling of invalidly nested sublists (#9187, cf. #8150).++ * MediaWiki reader:++ + Allow attribute keys with hyphens (#9178).++ * ODT reader:++ + Support attr `text:continue-numbering` (#8979, Stephan Meijer).++ * Typst reader:++ + Allow references (e.g. `@foo`) to become citations+ if there is no corresponding label in the document.+ + Collapse adjacent `cite` elements.+ + Handle supplements in `cite`.+ + Change `cite` (only one key allowed, a label) (typst 0.9 breaking change).+ + Support `quote` element (typst 0.9).++ * LaTeX reader:++ + Handle otherlanguage environment and language-name environments like+ `\begin{french}...\end{french}` (#9202).+ + Fix theorem label parsing (#8872, Hikaru Ibayashi).++ * Docx reader:++ + Unwrap content of shaped textboxes (Stephan Meijer, #9214).+ + Improve handling of `w:sym` (#9220). We now look up symbols in symbol+ fonts using the table defined at Text.Pandoc.Readers.Docx.Symbols.+ + Add unexported module Text.Pandoc.Readers.Docx.Symbols. This gives us a+ table to use to resolve characters included in docx via `w:sym` element.++ * Man reader:++ + Properly handle `.sp` macro inside lists and block quotes (#9201).++ * LaTeX writer:++ + Fix bug with big footnotes inside emphasis (#8982, Hikaru Ibayashi).+ + Handle identifiers inside heading contents. `\phantomsection` can't+ be used in this case, so we need `\hypertarget` (#9209).++ * LaTeX template:++ + Include `bookmark` package unconditionally. This package+ produces better PDF bookmarks than `hyperref` and does it on the+ first pass.++ * Typst writer:++ + Use `quote` for block quotes.+ + Support `--toc-depth` as in other writers (#9242).+ + Put inline image dimensions on enclosing box, not image (#9104).+ + Better handling of tables with captions (#9194).+ We now put these in a figure with a caption argument.+ + Update typst writer to typst 0.9 citation format (#9188).++ * Typst template:++ + Remove custom definition of `blockquote` in default template.+ (We now use built-in `quote`.)+ + Support table of contents.+ + Support csl (#9186, Ian Max Andolina). Typst now supports CSL for its+ native citation engine, so pandoc should use a specified `csl`+ style in the template, falling back to `bibliographystyle` if+ `csl` is not specified.++ * Docx writer:++ + Use different style for block quotes in notes (#9243).+ Using "Footnote Block Text" for the style name, so it can be+ given a different font size if footnotes are.+ + Allow embedded fonts to be used in reference.docx (#6728).++ * HTML5 writer:++ + To conform to validator's expectations, `doc-footnote` role is used+ with `aside` and `doc-endnotes` with `section`.+ + `aside` is used only for notes at ends of sections or blocks;+ if all the notes come at the end of the document, `section` is+ used so we can have the `doc-endnotes` role.++ * JATS writer:++ + Handle case where there is material after refs div (#9166). Previously in+ such cases the references were not being moved to back matter.++ * Ms writer:++ + Don't do normal escapes in filename arguments for PSPIC etc.++ * T.P.RoffChar: escape `-` as `\-`. The `groff_man (7)` man page indicates+ that `-` characters will be treated as typographic hyphens and are not+ appropriate for cases where the output should be copy-pasteable as an+ ASCII hyphen-minus character. (E.g. in command line options.)+ However, until a recent update groff man did not actually do this;+ it treated `-` and `\-` the same. With the new update (1.23.0)+ the two are distinguished (see https://lwn.net/Articles/947941/+ for background), so now it is important that pandoc escape `-`.++ * Text.Pandoc.Extension: add `Ext_alerts` constructor [API change].++ * Text.Pandoc.PDF: We now default to running LaTeX only+ once in producing a PDF (instead of twice). This is made possible by the+ shift to the `bookmark` package, which does not require a second pass for+ PDF bookmarks. If a table of contents is present, we still have to run+ three times to get the page numbers, and if beamer is used we still do a+ minimum of two runs.++ * Text.Pandoc.Shared:++ + `renderTags'`: use minimized tag for `rect`.+ + Allow svg `path` element to be minimized.+ + Export `combineAttr` [API change].+ + Improve `isTightList` so that it recognizes an item containing only a list+ which is itself tight as potentially an item in a tight list (#9161).++ * Text.Pandoc.MIME: Ensure we use `.svg` not `.svgz` as extension+ for `image/svg+xml` mime type. This fixes issues with embedded+ SVG images in docx output, among other things (#9195).++ * Text.Pandoc.Class: `openURL` improvements for data uris.+ Only treat data URI as `base64` if ';base64' is specified.+ Otherwise treat as UTF-8 (not 100% reliable but should cover most+ other cases). Strip off `;base64` (or `;charset=...` or whatever)+ from mime type (#9195).++ * Text.Pandoc.SelfContained: Improve treatment of embedded SVGs+ (#9206, #8948).++ + Ensure unique ids for elements by prefixing SVG id.+ + Ensure SVG `id` attribute except when `use` element is used.+ + Remove `width`, `height` attributes from svg element when `use`+ element is used. Instead, add `width` and `height` 100% to the+ `use` element. This seems to get the sizing right.++ * Text.Pandoc.Citeproc: Don't link citations if+ `suppress-bibliography` specified, for there will be nothing to+ link to (#9163).++ * epub.css: add styling for sup and sub (#9160).++ * Switch from `base64` to `base64-bytestring` (#9233).++ * Use newest versions of commonmark, commonmark-extensions,+ commonmark-pandoc, texmath, typst, skylighting, skylighting-core.++ * Benchmark: use standalone documents for reader tests.+ Otherwise typst reader benchmark fails. Note: this means that we are now+ parsing longer documents, so bench results on readers won't be comparable+ to before.++ * MANUAL.txt: update defaults file docs for bibliography fields (#9173).+ Recommend using top-level `bibliography` `csl`, etc. instead+ of a nested `metadata` field. Reason: `${USERDATA}` and `${HOME}`+ are only expanded in these contexts, not in `metadata`.++ * Move man pages to pandoc-cli package (#9245).++## pandoc 3.1.9 (2023-10-27)++ * Make `reference-section-title` work with `jats+element_citations`+ (#9021).++ * Add `bits` as synonym of `jats` as input format.++ * JATS reader:++ + Modify JATS reader to handle BITS too (#9138, Julia Diaz).+ Add provision for title-group, book, book-part-wrapper, book-meta,+ book-part-meta, book-title, book-title-group, index, toc, legend,+ title, collection-meta+ + Fix handling of alt-text (#9130, Julia Diaz). Previously we were+ looking for an attribute that doesn't exist in JATS; alt-text is+ provided by a child element.++ * CommonMark reader:++ + Handle `Ext_tex_math_gfm` (#9121). Parse GFM-specific math+ constructions when `tex_math_gfm` enabled.++ * DokuWiki reader:++ + Allow autolinks to be avoided using e.g. `https:%%//%%...` (#9153).+ + Parse `<code>` and `<file>` as block-level code (#9154).+ Previously we treated them as inline code in some contexts,+ but that is not how DokuWiki works.++ * LaTeX reader:++ + Better handle spacing commands `\hfill`, `\vfill`, `\hskip`,+ `\vskip`, etc. (#9150).+ + Fix incorrect abbreviation for astronomical unit (#9125,+ Michael McClurg).++ * Markdown reader:++ + Fix blindspot with superscript in links (#8981).+ Previously `[^super^](#ref)` wasn't parsed as a link, due to+ code that was meant to prevent footnote markers from being+ recognized as reference links. This commit tightens up that+ code to avoid this bad effect. We have also added a new+ restriction on footnote labels: they cannot contain the characters+ `^`, `[`, or `]`. Though this is technically a breaking change, we+ suspect that the impact will be minimal, as it's very unlikely+ people would be using these characters in their note labels.+ + Don't apply `--default-image-extension` to data URIs (#9118).+ + More accurate check that a normalCite is not a link,+ bracketed span, or reference (#9080).++ * HTML reader:++ + Allow th to close td and vice versa (#9090).+ + Parse task lists using input elements (#9047, Seth Speaks).++ * Creole reader:++ + Handle empty cells correctly (#9141, Sascha Wilde).++ * Org writer:++ + Escape literal `*`, `|`, `#` at beginning of line with ZWS (#9159).++ * ICML writer:++ + Prevent doubled attributes (#9158).++ * Powerpoint writer:++ + Fix a corruption error caused when the document used both a+ regular png and a png in a data URI (#9113). (Similarly for any+ other image format.) The problem was that duplicate entries in+ `[Content Types].xml` were being created, one for the mime type+ `image/png`, one for `image/png;base64`.++ * LaTeX writer:++ + Fix rowspans in tables so they use the width of+ the column (`=` as the width parameter) (#9140).+ + Don't treat table as "simple" if they have col widths.+ This should help fix a problem wherein some grid tables with+ colspans were overly wide (#9140).+ + Fix uneven indents in line block output (#9088).++ * JATS writer: fix 3.1.4 regression in handling block-level metadata+ (#9092).++ * Ms writer: improvements in image handling (#4475).++ + PDFPIC is now used for PDF images in figures.+ + Inline images that are postscript or PDF are rendered using+ PSPIC or PDFPIC. This isn't ideal, because they will still be+ rendered as if in a separate paragraph, but it's probably+ better than just printing the image name.+ + Units are included in height.++ * HTML writer:++ + If raw format is an HTML side deck format, emit it (James J Balamuta).++ * Typst writer:++ + Add `#box` around image to make it inline. (#9104)+ An `#image` by itself in typst is a block-level element.+ To force images to be inline (as they are in pandoc), we need+ to add a box with an explicit width. When a width is not given+ in image attributes, we compute one from the image itself, when+ possible.+ + Don't allow long heading to wrap (#9132).+ + Escape `(` (#9137). If unescaped `(` occurs in+ certain contexts, it can be parsed as function application.++ * Man writer:++ + Fix some spacing issues around links (#9120).+ We need to use `\c` before a `.UR` or `.MT`, to avoid+ an extra space, and also after. To ensure that a space+ at the beginning of the following line doesn't get swallowed+ up, we escape it with `\`.+ + Use UR, MT macros for URLs, emails (#9120).++ * Text.Pandoc.Extensions:++ + Add `Ext_tex_math_gfm` constructor to Extension (#9121).+ [API change]. This handles two GitHub-specific syntaxes for math.+ This is now default for `gfm`, in addition to `tex_math_dollars`.+ + Remove duplicates for `Ext_raw_html` and `Ext_pipe_tables`+ in some of the lists (Tim Stewart).++ * Text.Pandoc.Metadata: Add helpful message on some metadata+ YAML errors (#9155).++ * Text.Pandoc.Shared:++ + `splitSentences`: don't split after initials.+ This improves the man and ms writer output, preventing+ sentence breaks after initials.+ + Add `addPandocAttributes` function [API change].+ This is meant to simplify addition of attributes to Pandoc+ elements: for elements that don't have a slot for attributes, an+ enclosing Div or Span is added to hold the attributes.++ * MANUAL.txt:++ + Clarify that formatting can't cross line boundaries+ in line blocks (#9119).+ + Fix legacy option for citation (#8737, 3w36zj6)++ * Update `et` translations (priiduonu).++ * Updated `no` translations (Stephan Daus).+ Renamed no.yaml (macrolanguage Norwegian) to nb.yaml (Norwegian Bokmål).+ Created soft symbolic link from no.yaml pointing to nb.yaml.++ * Lua subsystem: Use the newest LPeg version (lpeg-1.1.*) (#9107,+ Albert Krewinkel).++ * Default `epub.css`: Apply style to h6, format styles, and+ combine identical styles under shared selectors (samuel-weinhardt).++ * Update nix flake with dependencies (piq9117).++ * LaTeX template: fix `\CSLBlock` vertical space (John Purnell).++ * Allow tasty 1.5 and Diff 0.5.++ * Require commonmark-extensions 0.2.4, commonmark 0.2.4.++ * Require texmath 0.12.8.4. This should improve math in+ powerpoint, fixing empty boxes around roots in some cases.++ * Require typst 0.3.2.1++## pandoc 3.1.8 (2023-09-08)++ * JATS reader:++ + Ignore `<processing-meta>` element (#9057, Julia Diaz).+ + Fix conversion of date to ISO 8601 format (#8865).++ * LaTeX template:++ + Add code allow `\cite` to break across lines (#9050).+ + Fix regression with CSL `display="block"` (#7363).+ This restores the line break before the block.+ + Rewrite `CSLReferences` environment to avoid depending on+ `enumitem`, which plays badly with beamer. Instead we use+ a regular list environment. Thanks to @jpcirrus for the+ concept (#9053).+ + Restore the pre-3.1.7 format of the `CSLReferences`+ environment, which again has two parameters. The first+ determines whether a hanging indent is used (1 = yes, 0 = no),+ and the second is the entry line spacing (0 = none).+ + Add a strut to avoid inconsistencies in spacing (#9058).+ - Remove a break at the end of `CSLRightInline` to avoid+ inconsistencies in spacing. It shouldn't be necessary+ because the paragraph should extend to the right margin (#9058).++ * LaTeX writer:++ + Fix regression with figure labels (#9045). In 3.1.7, pandoc+ added two labels to LaTeX figure environments, one with a+ phantomsection.+ + Fix default citeproc entry-spacing. According to the CSL manual,+ the default entry spacing is 1. We were treating it as 0 (#9058).++ * HTML writer:++ + Use the ID prefix in the ID for the footnotes section (#9044,+ Benjamin Esham).+ + Fix CSL entry-spacing default (#9058).++ * Text.Pandoc.Citeproc: always include an `entry-spacing` attribute+ in the Div if the bibliography element contains an entry-spacing+ attribute (previously we omitted it when it was 0) (#9058).++ * Clean up pandoc's own man pages by regenerating with pandoc 3.1.7.++ * pandoc-lua-engine: bump lower bound for pandoc (#9046).++ * Depend on texmath 0.12.8.2, fixing binom in typst writer (#9063).++## pandoc 3.1.7 (2023-08-31)++ * Org reader:++ + Don't parse alphabetical lists unless the `fancy_lists` extension is+ enabled (#9042).+ + Allow escaping commas in macro arguments (Amneesh Singh).++ * JATS reader:++ + Support for `<permissions>` metadata (#9037, Julia Diaz).+ metadata objects with multiple fields are created, matching the+ structure in JATS.+ + Correct name of JATS element `attrib`.++ * Markdown reader:++ + Support images with wikilink syntax, e.g. `![[foo|bar]]`, when+ one of the `wikilinks` extension is enabled (#8853).+ + Allow a citation or reference link to be parsed after a `!` (#8254).+ + Fix dropped `!` before nonexistent reference (#9038).++ * LaTeX writer:++ + Fix regression in escaping URLs (#9043).+ + Use `\cite` and `\bibitem` to link up citations, even with citeproc.+ (#9031). This will give us better accessibility; when tagging is+ enabled, the citation can be linked to the bibliography entry.+ This changes some of the details of the layout and the default+ template. We now make `CSLReferences` a special enumitem list+ that will contain `\bibitem`s. Internal links inside citations to+ ids beginning in `ref-` are creating using `\cite` instead of+ `\hyperref`.+ + Use `\phantomsection` and `\label` instead of `\hypertarget` (#9022).+ + Use `\hyperref` for LaTeX internal links, `\hyperlink` for+ beamer (since `\hyperref` doesn't seem to work) (#9022).+ + Backslash-escape `%` and `#` in URLs (#9014).++ * JATS writer:++ + Fix placement of ref-list when no title is specified for the+ reference section (#9017). (In this case we place it in `back`+ with an empty title.)++ * Man writer:++ + Avoid a `.PP` right after a section heading (#9020).+ This is at best a no-op (in groff man and mandoc) and at worst+ (in some formatters) may create extra whitespace.+ + We revert the fanciness introduced in #7506, which employs a+ custom font name `V` and a macro that makes this act like boldface+ in a terminal and monospace in other formats. Unfortunately,+ this code uses a mechanism that is not portable (and does not+ work in mandoc) (#9020).+ + Instead of using `V` for inline code, we simply use `CR`.+ Note that `\f[CR]` is emitted instead of plain `\f[C]`,+ because there is no `C` font in man. (This produces warnings+ in recent versions of groff, #9020.)+ + For code blocks, we now use the `.EX` and `.EE` macros,+ together with `.IP` for spacing and indentation. This gives+ more standard code that can be better interpreted e.g. by mandoc+ (#9020).++ * Man template: don't emit `.hy`, regardless of setting of+ `hyphenate` variable (#9020).++ * LaTeX template: special redefinition of `\st` for CJK (#9019).+ soul's version raises on error on CJK text.++ * Use latest skylighting-format-blaze-html (#7248).+ This works around a longstanding iOS Safari bug that caused long+ lines to be displayed in a different font size in highlighted code.++ * Allow skylighting 0.14 (and require it in pandoc core).++ * Allow text 2.1.++## pandoc 3.1.6.2 (2023-08-22)++ * Org reader: allow example lines to end immediately after the colon+ (Brian Leung).++ * Docx reader:++ + Omit "Table NN" from caption (#9002).+ + Avoid spurious block quotes in list items (#8836).++ * JATS reader: Fix display of block elements (#8889, Julia Diaz).+ A number of block elements, like disp-quote, list, and disp-formula, were+ always treated as inlines if appearing inside paragraphs, even if their+ usage granted a separate block.++ * HTML reader: avoid duplicate id on header and div (#8991).++ * Typst writer:++ + Use `~` for nonbreaking space, and escape literal `~` (#9010).+ + Put the label in right place for Div, use `#block` (#8991).+ Previously we were putting the label at the beginning of+ the Div's contents, but according to the documentation such a+ label gets attached to the *preceding* element. We now use an+ explicit `#block` and add the label at the end.++ * LaTeX writer:++ + Improve escaping of URIs in href, url (#8992).+ + Improve internal links and targets (#8744). We no longer+ wrap section headings in a `\hypertarget`. This is unnecessary+ (hyperref creates an anchor based on the label) and it interferes with+ tagging. In addition, we now use `\hyperref` rather than `\hyperlink`+ for internal links. Currently `\hypertarget` is still being used for+ link anchors not on headings. Thanks to @u-fischer.++ * HTML format templates (style.html): Fix typo in clause for svg+ (Jackson Schuster).++ * Use lastest texmath, typst-symbols, typst. Targets typst 0.7.+++## pandoc 3.1.6.1 (2023-08-11)++ * HTML reader: properly calculate RowHeadColumns (#8984). This fixes a+ bug in the calculation of the number of header columns in table row.+ It also changes the algorithm for determining the table body's+ RowHeadColumns based on the numbers of head columns in each row.+ Previously we used the max, and #8634 switched to the min, which+ led to bad results. Now we only set RowHeadColumns to a non-zero value+ if *all* rows have the same number of head columns.++ * OpenDocument writer:++ + Implement syntax highlighting for inline and block code (#6710).+ + Support highlighted text in ODT/OpenDocument writers for Span+ with class `mark` (#8960). The color can be adjusted by+ modifying the Highlighted style.++ * Typst writer: escape `//` so it doesn't get interpreted as a comment+ (#8966).++ * ChunkedHTML writer: Fix regression including MathJax script (#8967).+ The fix for #8620 caused the script to be included when the table of+ contents but not the body text of a page contains math. But it broke the+ case where the table of contents doesn't contain math but the page does.+ This patch fixes the issue.++ * Text.Pandoc.SelfContained:++ + Retain attributes in SVG tag when referring to another+ SVG's content using `<use>` (#8969).+ + Allow units in width and height for SVG. Units are optional but allowed.+ + Don't coerce calculated SVG dimensions to Int.+ + fix calculation of SVG width and height. We were computing width and+ height from viewBox incorrectly (#8969).+ + Add clause for SVG to default CSS for HTML (#8969).+ + Ensure that width and height attributes don't get specified+ twice is both the img tag and the svg include them (#8965).+ + Omit unnecessary attributes xmlns, xmlns:xlink, and version on+ SVG element (#8965).+ + Use 20 character rather than 40 character hashes for generated IDs+ (#8965).++ * Use pandoc-types 1.23.1. This fixes a regression with toJSONFilter (#8976),+ which in 1.23.0.1 no longer worked on pure values of type `a -> [a]`.++ * Use ghc 9.6 for release builds (#8947).++ * Fix some links in FAQs (Diogo Almiro).+++## pandoc 3.1.6 (2023-07-20)++ * Fix CVE-2023-38745, a variant of the vulnerability in CVE-2023-35936.+ Guilhem Moulin noticed that the fix to CVE-2023-35936 was incomplete.+ An attacker could get around it by double-encoding the malicious+ extension to create or override arbitrary files.++ * `--embed-resources`: Use inline SVG instead of data uris for SVG+ images in HTML5 (#8948). Note that SelfContained does not have+ access to the writer name, so we check for HTML5 by determining+ whether the document starts with `<DOCTYPE! html>`. This means+ that inline SVG won't be used when generating document fragments.++ * Fix regression on short boolean arguments (#8956).+ In 3.1.5 boolean arguments were allowed an optional argument+ (`true|false`). This created a regression for uses of fused+ short arguments, e.g. `-somyfile.html`, which was equivalent+ to `-s -omyfile.html`, but now raised an error because+ pandoc attempted to parse `o` as a boolean `true` or `false`.+ This change allows the fused short arguments to be used again.+ Note that `-strue` will be interpreted as `-s` with an+ argument `true`, not as `-s -t -rue`. It is best to+ use long option names with the optional boolean values,+ to avoid confusion.++ * Make `--epub-title-page`'s argument optional. It takes a boolean+ argument, and now that all of our boolean flags take such an+ argument, we can make this one optional for consistency.++ * Improve errors for illegal output formats. Previously if you did+ `pandoc -s -t bbb`, it would give you an error about the missing+ `bbb` template instead of saying that `bbb` is not a+ supported output format.++ * Improve errors for incorrect command-line option values (#8879).+ Always give the name of the relevant argument.++ * Fix typo on error message for incorrect `--preserve-tabs` argument.+ Thanks @fsoedjede++ * Docx reader: use SVG version of image if present (#7244).+ Previously the backup PNG was exported even if an SVG was+ present, but the SVG should be preferred.++ * Typst reader: fix regression in recognition of display math (#8949).+ The last release caused all math to be parsed as inline math.++ * JATS writer: don't use `<code>` for inline code (#8889).+ It is intended for block-level code.++ * HTML writer: don't make line blocks sensitive to `--wrap` (#8952).++ * RST writer: fix figure handling (#8930, #8871).+ This fixes a number of regressions from pandoc 2.x.+ Properly handle caption, alt attribute in figures.+ No longer treat a paragraph with a single image in it as a figure+ (we have a dedicated Figure element now).++ * Docx writer: Copy "mirror margins" property from reference.docx (#8946).++ * Text.Pandoc.UTF8: Deprecate `decodeArg` which is now a no-op.+ This was needed for old base versions which we no longer support.++ * Use released skylighting, typst.++ * Allow latest commonmark-extensions. This allows entities in wikilinks.++ * Switch back to using ghc 9.2 for linux and Windows binary releases+ (#8947, #8955). With ghc 9.4+, we were getting AVX instructions+ in the amd64 binary, which aren't supported on older hardware.+ For maximum compatibility we switch back to ghc 9.2, which doesn't+ cause the problem. (As documented, ghc should not be emitting these+ instructions, so we aren't clear on the diagnosis, but the cure+ has been tested.)++ * Change Windows release build to use cabal instead of stack.++## pandoc 3.1.5 (2023-07-07)++ * Allow all boolean flags to take an optional `true` or `false` value+ (#8788, Sam S. Almahri). The default is true if no value is specified,+ so this is fully backwards-compatible.++ * Support `--id-prefix` for markdown output (#8878)++ * Markdown reader:++ + Add strictness annotations to fix a memory leak (#8762).++ * Typst reader:++ + Use typst-hs 0.3.0.0, which is more robust, fixes many bugs, and+ targets typst 0.6.+ + Package loading is now supported, as long as the package has been+ cached or is local.+ + Rewrite Typst reader in a way that makes it easier to extend.+ + Filter out CR in raw.+ + Handle block content for link element.+ + Handle block-level content in text element.+ + Handle style, align, place in inline contexts too.+ + Improve info message for skipped elements.++ * Add typst reader tests (#8942).++ * MediaWiki reader:++ + Revise treatment of "link trail." Previously we only included ASCII+ letters. That is correct for English but not for, e.g., Spanish (see+ comment in #8525). A safer approach is to include all letters except+ those in the CJK unified ideograph ranges.++ * AsciiDoc writer:++ + Make modern AsciiDoc the target for `asciidoc` (#8936).+ The AsciiDoc community now regards the dialect parsed by `asciidoctor`+ as the official AsciiDoc syntax, so it should be the target of our+ `asciidoc` format. The `asciidoc` output format now behaves like+ `asciidoctor` used to. `asciidoctor` is a deprecated synonym. For+ the old `asciidoc` behavior (targeting the Python script),+ use `asciidoc_legacy`. The templates have been consolidated. Instead of+ separate `default.asciidoctor` and `default.asciidoc` templates, there+ is just `default.asciidoc`.+ + Text.Pandoc.Writers.AsciiDoc API changes:+ - `writeAsciiDoc` now behaves like `writeAsciiDoctor` used to.+ - `writeAsciiDoctor` is now a deprecated synonym for `writeAsciiDoc`.+ - New exported function `writeAsciiDocLegacy` behaves like+ `writeAsciDoc` used to.+ + Update line-through for asciidoc writer to custom inline style (#8933,+ Kevin Broch).++ * Typst writer:++ + Support `unlisted` class in headings (#8941).+ + Consolidate bibliography files into one `#bibliography` command (#8937).+ + Improve handling of autolinks (#8931).++ * Docx writer:++ + Make relative widths work in tables. This didn't work before because we+ were missing an attribute that tells Word to used fixed widths rather+ than computing optimal ones.++ * DokuWiki writer: fix lists with Div elements (#8920).+ The DokuWiki writer doesn't render Divs specially, so their presence in+ a list (e.g. because of custom-styles) need not prevent a regular+ DokuWiki list from being used. (Falling back to raw HTML in this case is+ pointless because no new information is given.)++ * LaTeX writer:++ + Fix babel name for `fa` (should be `persian`).+ + Prevent babel language from being imported twice (#8925).++ * Text.Pandoc.Class:++ + Add `toTextM` [API change]. This is like `Text.Pandoc.UTF8.toText`,+ except:++ - it takes a file path as first argument, in addition to+ bytestring contents+ - it raises an informative error with source position if+ the contents are not UTF8-encoded++ This replaces `utf8ToText` whenever we have the filename and are+ in a PandocMonad instance. This will lead to more informative error+ messages for UTF8-encoding, indicating the file path and byte offset+ where the error occurs (#8884).++ * Remove invalid term "Subject" from Turkish translations (#8921).++ * stack.yaml: add pkg-config to nix packages (#8927, pacien).++ * Allow aeson 2.2.++ * MANUAL: Add clarification on --section-divs. Closes #8882.+++## pandoc 3.1.4 (2023-06-24)++ * Fix a security vulnerability in MediaBag and T.P.Class.IO.writeMedia.+ This vulnerability, discovered by Entroy C, allows users to write+ arbitrary files to any location by feeding pandoc a specially crafted+ URL in an image element. The vulnerability is serious for anyone+ using pandoc to process untrusted input. The vulnerability does+ not affect pandoc when run with the `--sandbox` flag. [CVE-2023-35936]++ * Allow `epub-title-page` to be used in defaults files (#8908).++ * Issue `Extracting` info message (in `--verbose` mode) when using+ `--extract-media` or extracting media temporarily in PDF production.++ * HTML reader: Update TableBody RowHeadColumns caculation (#8634,+ Ruqi). This change sets RowHeadColumns to the minimum value of each row,+ which gives better results in cases where rows have different numbers+ of leading th tags.++ * Dokuwiki reader: retain image query parameters as attributes (#8887, echo0).++ * Textile reader: Add support for link references (#8706, Stephen Altamirano).+ Textile supports what it calls "link alias", which are analogous to+ Markdown's reference-style links.++ * LaTeX reader: support alt text on images (#8743, Albert Krewinkel).++ * Commonmark reader: Make `implicit_figures` work again.+ Support for this (introduced in #6350) disappeared when we made an+ architectural change.++ * JATS reader:++ + Add footer and multiple body parsing to table reader (#8765, Noah Malmed).+ + Parse references title from ref-list (#8365).++ * JATS writer:++ + Make `--number-sections` work.+ + Include title in ref-list (#8364). Previously the reference title ended+ up in a separate section at the back of the body instead of in the ref-list+ in the back matter.++ * Mediawiki writer: allow highlighting to work for F# language+ (Adelar da Silva Queiróz).++ * LaTeX writer: Fix escaping of `&` in `\href` and `\url` (#8903).++ * Docx writer:++ + Fix localization of "Abstract" title (#8702).+ + Allow `abstract-title` to be specified in docx metadata (#8794).++ * ChunkedHTML writer: Make math work in top-level page (#8915).++ * Text.Pandoc.Logging: add new log message type `ScriptingWarning`+ [API change] (Albert Krewinkel).++ * Lua: report warnings from Lua scripts (Albert Krewinkel).+ Lua's warning system is plugged into pandoc's reporting architecture.+ Warnings that are raised with the Lua `warn` function are now reported+ together with other messages.++ * Use crypton-connection instead of connection (#8896, Felix Yan).+ Follows the change introduced in tls 1.7.0.++ * Bump versions for skylighting-core, skylighting.++ * Include lua/module/sample.svg in cabal extra-source-files (Felix Yan).++ * Add Nynorsk (New Norwegian) translations (Per Christian Gaustad).++ * Add tests for `fillMediaBag`/`extractMedia`.++ * INSTALL.md:++ + Mention alternatives to LaTeX to generate PDF (Norwid Behrnd).+ + Update Linux install links (harabat).++ * pandoc-extras.md: add to "Academic publishing workflows" (#8696,+ Vladimir Alexiev).++## pandoc 3.1.3 (2023-06-07)++ * New output format: `typst`.++ * New module: Text.Pandoc.Readers.Typst [API change].++ * DocBook reader:++ + Support more emphasis roles (Albert Krewinkel).+ The role "bf" is taken to indicate "bold face", i.e.,+ "strongly emphasized" text, while "underline" leads to+ underlined text.++ * JATS reader:++ + Improve title and label parsing in the JATS reader (#8718,+ Noah Malmed.)+ + Add rowspan, colspan and alignment to cells in jats table+ reader (#8408, Noah Malmed)++ * Org reader (Albert Krewinkel):++ + Require abstract environment to use lowercase.+ + Treat `#+NAME` as synonym for `#+LABEL` (#8578).++ * ODT reader:++ + Allow lists in table cells (#8892).+ + Allow frames inside spans (#8886).++ * RST reader:++ + Fix sorting on anonymous keys (#8877). This fixes a link+ resolution bug bug affecting RST documents with anonymous links.++ * HTML reader:++ + Fix iframe with data URI of an image (#8856).+ In this case we don't want to try to parse the data at the URL.+ Instead, create an image inside a div.++ * RTF reader:++ + Fix bug in table parsing (#8767). In certain cases, text before a+ table was being incorporated into the table itself.++ * Docx reader:++ + Introduce support for Intense Quote (Stephan Meijer).++ * Markdown reader:++ + Disallow escaping of `~` and `"` in `markdown_strict` (#8777,+ Albert Krewinkel). This matches the behavior of the legacy+ `Markdown.pl` as well as what is described in the manual.++ * LaTeX reader: ignore args to column type in `\multicolumn` (#8789).++ * HTML writer:++ + Use first paragraph in task item as checkbox label (#8729, Albert+ Krewinkel).++ * Ms writer:++ + Coerce titles to inlines (#8835). Block-level formatting is not+ allowed inside `.TL`.++ * LaTeX writer:++ + Fix width for multicolumn simple table (#8831).++ * Jira writer:++ + Use first code block class as highlighting language (#8814, Albert+ Krewinkel). The writer no longer searches the list of+ classes for a known programming language but always uses+ the first class in that list as the language identifier.++ * OpenDocument writer:++ + Handle row header column cells as header cells (#8764, Michael Stahl).+ + Fix invalid `text:p` inside `text:p` from meta (#8256).++ * ODT writer:++ + Don't add settings.xml (Michael Stahl). This will cause defaults+ to be used, which is what we want.+ + Don't add unnecessary Configurations2 directory (Michael Stahl).+ + Don't add thumbnail (Michael Stahl).+ + Put `manifest.version` on directory file-entry (Michael Stahl).+ See ODF 1.3 part 2, 4.16.14.1.+ + Stop validator complaints by producing ODF 1.3 (Michael Stahl).++ * MediaWiki writer:++ + Remove links from inside links in mediawiki writer (#8739,+ Wout Gevaert).++ * Typst writer:++ + Omit bibliography if `citations` not enabled (#8763).+ With this change, the typst writer will omit the `#bibliography`+ command when `citations` is not enabled. (If you want to use+ pandoc's own `--citeproc`, you should combine it with+ `-t typst-citations` to disable native typst citations.+ + Use `<..>` for labels, create internal links.+ + Use `#footnote` for notes (#8893).+ + Fix alignment issue in lists. It's an aesthetic issue+ only; the first line had an extra space indent after the+ list marker.++ * Commonmark writer:++ + Use shortcut reference links: commonmark supports these.++ * EPUB template: add `lang` attribute to `<html>` (Gabriel Lewertoski).++ * Template styles.html: fix task-list styling in reveal.js+ (#8731, Albert Krewinkel).++ * LaTeX template: Fix `\babelfont` (#8728).++ * Text.Pandoc.Parsing:++ + Remove unnecessary 'spaces' in `parseFromString`.++ * Text.Pandoc.ImageSize: Drop BOM at start of SVG if present.+ Otherwise our code can fail to determine image size.++ * Lua subsystem:++ + Fix value of PANDOC_SCRIPT_FILE for custom readers & writers+ (#8781, Albert Krewinkel). The value did not hold the actual+ file path for scripts in the *custom* folder of the datadir.++ * Fix YAML in translation files for `cs` and `pl` (#8787).++ * Fix pdf output via typst (#8754). One must now use `typst+ compile` rather than `typst`.++ * MANUAL.txt:++ + Added note that the user will need to create the user data+ dir (#8727).+ + Add `wikilinks` to non-default extensions (Ilona).+ + Update link to custom djot writer (Albert Krewinkel).+ + Better link to citation syntax.+ + Fix typo (sdhoward).+ + Note that `#` fancy list markers don't work with commonmark (#8772,+ William Lupton).+ + Add commonmark `fenced_div` note (#8773, William Lupton).+ + Move highlighting documentation, with minor adjustments+ (William Lupton).+ + Fix inaccurate statement about spaces and tabs in template+ syntax+ (Frank Seifferth).++ * Update documentation for org-mode (Christian Christiansen, #8716).++ * doc/lua-filter.md:++ + Fix typos (#8734, perro tuerto).+ + Fix anchor (Toni Dietze).+ + Use full field name in example (#8857, Matt Dodson).+ + Fix copy-paste error (#8798, thron7).++ * CONTRIBUTING.md: update info on ghc versions.++ * INSTALL.md:++ + Fix cabal install instructions (Albert Krewinkel).+ + Use more relevant link to NetBSD/pkgsrc entry (Charlotte Koch).+ + Fix Windows install instructions for winget (#8799).++ * Tests: Rename test/docx/block_quotes_parse_indent.native for+ consistency (Stephan Meijer).++ * Add `tls` constraint on cabal.project. This is needed to+ avoid problems caused by the transition to `crypton`.++ * Require texmath 0.12.8.+++## pandoc 3.1.2 (2023-03-26)++ * Add a Lua REPL (Albert Krewinkel). This can be started+ with `pandoc lua -i`. It is also possible to instruct a filter to+ open the REPL at a certain point, for debugging (see `pandoc.cli.repl`).++ * Support `typst` as a `--pdf-engine`.++ * Add typst writer (#8713). New module Text.Pandoc.Writers.Typst,+ exporting `writeTypst` [API change].++ * Org reader:++ + Allow zero width space as an escape character (#8716,+ Christian Christiansen). Allow the character U+200B to be used as+ an escape character as described in the Org-mode documentation+ (<https://orgmode.org/manual/Escape-Character.html>).++ * DocBook reader:++ + Handle "book" for xref references (#8712, Andres Freund)+ This also adds a test xref to book and part.+ + Handle `<part>` (#8712).++ * HTML reader:++ + Fix behavior with `-native_spans-raw_html` (#8711). Previously with+ this configuration, `<span>`s were not treated as inline elements at all.++ * HTML writer:++ + Avoid duplicate classes (#8705).+ + Use img element instead of embed for `.svg.gz` and `.png.gz` etc. (#8699).+ + HTML writer footnotes changes (#8695): when `--reference-location=section`+ or `=block`, use an `aside` element for the notes rather than a `section`.+ When `--reference-location=section`, include the `aside` element inside+ the section element, rather than outside. (In slide shows, this option+ causes footnotes on a slide to be displayed at the bottom of the slide.)++ * EPUB writer:++ + Use different structure for epub footnotes (#8676, see #8672, #5583).+ Many EPUB readers are thrown off by pandoc's current footnote+ output. Both the ol and the fact that the footnote backlink is+ at the end of the note seem to pose problems.+ With this commit, we now create a list of aside (or div) elements,+ instead of an ordered list. Each element begins with a note number+ that is linked back to the note reference. (So, the backlink occurs+ at the beginning rather than the end.) Thanks to @Porges and @lewer.++ * Docx writer:++ + Include abstract title (#8702). Uses localized term for abstract.++ * Markdown writer:++ + Use implicit figures if there's a caption but no alt (#8689,+ Albert Krewinkel).++ * Jira reader (Albert Krewinkel):++ + Add panel title as nested div (#8681).+ + Require jira-wiki-markup 1.5.1 (#8680). This fixes a bug in the parser+ that caused text between two exclamation marks to be parsed as an+ image. The first `!` of image markup must now be followed by a+ non-space character; otherwise, the enclosed text is parsed as+ normal content.++ * Ms writer:++ + Fix handling of Figure (#8660).++ * ICML writer:++ + Fix images with data (#8675). The Contents element+ should be inside Properties.++ * LaTeX writer:++ + Add Chinese to Babel languages.+ + Fix background image in Beamer when there are figure environments (#8671,+ Martín Pozo).++ * LaTeX template:++ + Add `babelfonts` variable to default LaTeX template.+ This allows specifying certain fonts to be used with+ certain babel languages. Thanks to Frederik Elwert.+ + Fix highlight/underline with lualatex (#8707). We need the lua-ul package+ instead of soul, which doesn't work with lualatex.++ * Lua (Albert Krewinkel):++ + Add `pandoc.cli.repl` function+ + Fix `json.encode` for nested AST elements. Ensures that objects with+ nested AST elements can be encoded as JSON.+ + Auto-generate docs for pandoc modules.+ + Load text module as `pandoc.text`. This only affects the name in the+ Lua-internal documentation. It is still possible to load the modules+ via `require 'text'`, although this is deprecated.+ + Move docs from module `text` to `pandoc.text`+ The latter is easier to use and more consistent with the other modules.+ + Keep the Lua stack clean A metatable used during initialization was+ not properly removed from the stack. Likewise, accessing the+ CommonState from Lua previously led to the pollution of the+ Lua stack with a left-over value.+ * Add function `pandoc.format.from_path`.+ + Allow to get the JSON encoding of log messages.++ * Text.Pandoc.Format: Add new function `formatFromFilePaths` [API change]+ (#8710, Albert Krewinkel).++ * The old Text.Pandoc.App.FormatHeuristics module has been removed.++ * In `--version`, use Windows `%APPDATA%` variable to describe+ user data dir (#8686, Pablo Rodríguez).++ * Text.Pandoc.App.CommandLineOptions: don't lowercase arg to `--from`/`--read`+ (Albert Krewinkel). This prevented users to use custom writers with+ uppercase characters in their filenames. Format-normalization,+ including lower-casing of format identifiers, happens during+ format parsing.++ * Documentation:++ + Add `doc/nix.md`.+ + Add `doc/extras.md`. This was formally in the website repo.+ + `doc/lua-filters.md`: improve docs for `pandoc.zip`.++ * Factor out `make_macos_release.sh` from the release candidate workflow.+ Use cabal instead of stack to build the macos binary.++ * Modify linux/make_artifacts.sh so it will work on cirrus.++ * Switch to hslua-2.3++ * Depend on latest releases of texmath, doclayout.++## pandoc 3.1.1 (2023-03-05)++ * EPUB reader: Give additional information in error if the epub+ zip container can't be unpacked.++ * TSV reader: don't gobble tabs as whitespace (#8661).++ * Org reader: accept empty tables (#8659).++ * LaTeX reader: fix multiplication syntax for tabular (#8658).+ We recognized `*{6}{...}` but not `*6{...}` or `*6c`.++ * Docx reader: parse image alt texts in LibreOffice generated files.+ LibreOffice tags images slightly differently than Word; this change lets+ the parses take that difference into account when looking for an image+ description (alt text).++ * DocBook reader:++ + Fix `<xref>` references to tables in DocBook files+ (#8626, Pavol Otto).+ + Parse `figure` as a Figure element in the AST (#8668).++ * JATS reader: avoid generating duplicate figure captions (#8669).++ * RST reader: align with spec in syntax for role names (#8653).+ In particular, we now allow colons in row names.++ * Add note on converting from .doc format to FAQs (#8654).++ * Trap error in getAppUserDataDirectory (#8648).+ This can raise an error if pandoc is run in a non-user environment.++ * LaTeX writer: do not use longtable foot with Beamer (#8638, Albert+ Krewinkel). The table foot is made part of the table body, as+ otherwise it won't show up in the output. The root cause for+ this is that longtable cannot detect page breaks in Beamer.++ * LaTeX template: Add CJKsansfont and CJKmonofont for XeLaTeX+ (#8656, Yudong Jin). `CJKsansfont` and `CJKmonofont` will be+ set for xelatex only if `CJKmainfont` is also provided.++ * URL style in ConTeXt (#8612, Thomas Hodgson). Previously, a+ URL like this would be in monospace text:+ `\useURL[url1][https://example.com]`. Now, it will match the+ main text unless the `linkstyle` variable is set, which+ controls the styling of all links. Closes #8602.++ * Asciidoc writer: Properly escape `|` in table cells (#8665).++ * asciidoc{,tor} template: fix revision date when author is unset+ (#8637, arcnmx). Revision line syntax is only valid in+ combination with an author line, so the date attribute must be+ set explicitly when the author is missing++ * HTML writer: allow "track" element to be treated as block-level HTML+ (#8629).++ * Include needed polyfill when MathJaX is used (#8625).++ * JATS writer: include alt-text in `<graphic>`,+ `<inline-graphic>` elements (#8631, Albert Krewinkel).++ * Chunked HTML writer: Retain metadata in processing sections+ for chunked HTML (#8620). Previously we suppressed metadata+ in all but the top page, in order to prevent the title block+ from being printed on every page. This prevented use of+ custom variables set by metadata fields. This commit moves+ to a better solution: a conditional in the default template+ restricts the title block to the top page.++ * Lua API:++ + Add new function `pandoc.system.cputime` (Albert+ Krewinkel). The function returns the CPU time consumed by+ pandoc and can be used to benchmark Lua computations.+ + Add module `pandoc.json` to handle JSON encoding (#8605,+ Albert Krewinkel).++ * Use pandoc-lua-marshal 0.2.1 (Albert Krewinkel).+ All major AST elements now have `__tojson` metamethods that return the+ JSON representation of an element. This allows to JSON-encode these+ elements with libraries that respect the `__tojson` metamethod,+ including dkjson.++ * Use latest zip-archive. This allows pandoc to open certain+ epubs that it could not open before.++ * Use commonmark-extensions 0.2.3.4. This fixes some bugs involving+ definition lists and inline formatting.++ * Use latest skylighting-format-context++ * MANUAL.txt:++ + Document chunk-template in defaults file.+ + Remove obsolete "raw content in a style" section.+ + Revise documentation for `--mathml` to reflect support in all major+ browsers (#8667).++ * docs/custom-readers.md: Update JSON parsing example. The example now+ uses the built-in `pandoc.json` library to parse the API output.++ * doc/press.md: Add article on CiTO in J Cheminform by @egonw.++ * doc/lua-filters.md: fix typo in `run_json_filter` (Morgan Willcock).+++## pandoc 3.1 (2023-02-09)++ * Fix regression with `--print-highlight-style` option (#8586).++ * Add new `--chunk-template` option (#8581), allowing more control+ over the filenames in chunked HTML output.++ * Text.Pandoc.App: Add `optChunkTemplate` constructor to Opt [API change].++ * Text.Pandoc.Options: add `writerChunkTemplate` constructor to+ `WriterOptions` [API change].++ * Text.Pandoc.Chunks: add Data, Typeable, Generic, ToJSON, FromJSON+ instances for `PathTemplate` [API change].++ * Text.Pandoc.Citeproc: Fix bug in `metaValueToReference` (#8611).+ This bug caused us to get some repeated content when converting+ MetaBlock to Inlines.++ * Textile reader:++ + Support footnote backlinks (#8585, Stephen Altamirano).+ + Don't allow brackets in URLs (#8582).++ * ODT reader: fix blockquote indent detection (#3437, Daniel Kessler).++ * LaTeX writer: include short figure/table caption if one is given+ (Albert Krewinkel). Short captions are used by LaTeX when generating+ the list of figures or list of tables. Adding a short caption will+ now overwrite the full caption in these lists.++ * Powerpoint writer: fix handling of simple figures (#8565,+ Albert Krewinkel). This ensures that simple figures are displayed+ in the same way as before the introduction of a dedicated `Figure`+ constructor in the AST.++ * Improve handling of `%` in bib(la)tex parsing (#8597, #8595).++ * Use released skylighting 0.13.2.1++ * INSTALL.md: direct people to cabal install pandoc-cli.++ * doc/lua-filters.md: document 'Figure' type and constructor (Albert+ Krewinkel). Fix typos (Martin Joerg).++ * Fix link in manual (#8583, Salim B).++## pandoc 3.0.1 (2023-01-25)++ * Fix use of extensions with custom readers (#8571).++ * Text.Pandoc.Writers.Shared: export `setupTranslations` [API change].+ Use this in HTML and OpenDocument writers, to ensure that+ translations are set up properly even when we don't go through+ `convertWithOpts`.++ * LaTeX reader: fix regression in macro resolution for environments (#8573).++ * Chunked HTML writer: Fix handling of images with absolute URLs (#8567).++ * HTML writer:++ + Don't omit newlines in task lists.+ + Don't disable checkboxes in task lists (#8562).++ * Ensure that automatically set variables `pandoc-version`, `outputfile`,+ `title-prefix`, `epub-cover-image`, `curdir`, `dzslides-core` can be+ overridden by `--variable` on the command line. Previously they would+ create lists in the template Context, which is not desirable.++ * Fix man page copying in `linux/make_artifacts.sh` (#8566).+ Previously we were copying the pandoc-server.1 pandoc page to pandoc-lua.1.++ * pandoc.cabal: remove pandoc.cabal, stack.cabal from extra-source-files+ (#8560). The problem is that if these are in extra-source-files, then they+ get put in the tarball, and then anyone trying to build the source+ from an unpacked tarball will run into the problem that cabal.project+ and stack.yaml refer to pandoc-server, pandoc-lua-engine, and+ pandoc-cli, which aren't in the tarball.++ * Require texmath 0.12.6 for better MathML output.++ * Fix typo in Lua filter documentation (Carlos Scheidegger).++ * Fix formatting of link in pandoc-server.md (James Scott-Brown).++ * Minor changelog fixups.++## pandoc 3.0 (2023-01-18)++ * Split pandoc-server, pandoc-cli, and pandoc-lua-engine+ into separate packages (#8309). Note that installing+ the `pandoc` package from Hackage will no longer give you the+ `pandoc` executable; for that you need to install `pandoc-cli`.++ * Pandoc now behaves like a Lua interpreter when called as+ `pandoc-lua` or when `pandoc lua` is used (#8311, Albert Krewinkel).+ The Lua API that is available in filters is automatically+ available to the interpreter. (See the `pandoc-lua` man page.)++ * Pandoc behaves like a server when called as `pandoc-server`+ or when `pandoc server` is used. (See the `pandoc-server` man page.)++ * A new command-line option `--list-tables`, causes tables to be+ formatted as list tables in RST (#4564, with Francesco Occhipinti).++ * New command line option: `--epub-title-page=true|false` allows+ the EPUB title page to be omitted (#6097).++ * `--reference-doc` can now accept a URL argument (#8535) and+ load a remote reference doc.++ * `--version` output no longer contains version info for dependent+ packages. Instead, it contains a "Features" line that indicates+ whether the binary was compiled with support for acting as a server,+ and for using Lua filters and Custom writers.++ * A new option `--split-level` replaces `--epub-chapter-level`+ and affects both EPUB and chunked HTML output. `--epub-chapter-level`+ will still work but is deprecated.++ * Multiple input files with `--file-scope`: fix case where the links+ are URL-encoded, e.g. with `%20` (#8467).++ * Produce error if `--csl` is used more than once (#8195, Prat).++ * Remove deprecated `--atx-headers` option.++ * Remove deprecated option `--strip-empty-paragraphs`.++ * In `--verbose` mode add message when running citeproc (as with+ other filters).++ * Add new `mark` extension for highlighted text in Markdown,+ using `==` delimiters (#7743).++ * Add new extensions `wikilinks_title_after_pipe` and+ `wikilinks_title_before_pipe` for `commonmark` and `markdown`.+ (#2923, Albert Krewinkel). The former enables links of style+ `[[Name of page|Title]]` and the latter `[[Title|Name of+ page]]`. Titles are optional in both variants, so this works+ for both: `[[https://example.org]]`, `[[Name of page]]`. The+ writer is modified to render links with title `wikilink` as+ a wikilink if a respective extension is enabled. Pandoc will+ use `wikilinks_title_after_pipe` if both extensions are+ enabled.++ * Add prefixes to identifiers with `--file-scope` (#6384).+ This change only affects the case where `--file-scope` is used+ and more than one file is specified on the command line.+ In this case, identifiers will be prefixed with a string+ derived from the file path, to disambiguate them. For example,+ an identifier `foo` in `contents/file1.txt` will become+ `contents__file1.txt__foo`. Links will be adjusted accordingly:+ if `file2.txt` links to `file1.txt#foo`, then the link will+ be changed to point to `#file1.txt__foo`. Similarly, a link+ to `file1.txt` will point to `#file1.txt`. A Div with an+ identifier derived from the file path will be added around+ each file's content, so that links to files will still work.++ * New output format: `chunkedhtml`. This creates a zip file+ containing multiple HTML files, one for each section,+ linked with "next," "previous," "up," and "top" links.+ (If `-o` is used with an argument without an extension,+ it is treated as a directory and the zip file is automatically+ extracted there, unless it already exists.) The top page will+ contain a table of contents if `--toc` is used. A+ `sitemap.json` file is also included. The option+ `--split-level` determines the level at which sections are+ to be split.++ * Support complex figures (Albert Krewinkel, Aner Lucero).+ There is now a dedicate Figure block constructor for+ figures. The old hack of representing a figure as+ `Para [Image attr [..alt..] (source, "fig:title")]`+ has been dropped. Here is a summary of figure support+ in different formats:++ + Markdown reader: paragraphs containing just an image are treated as+ figures if the `implicit_figures` extension is enabled. The identifier+ is used as the figure's identifier and the image description is also+ used as figure caption; all other attributes are treated as belonging+ to the image.+ + Markdown writer: figures are output as implicit figures if possible,+ via HTML if the `raw_html` extension is enabled, and as Div elements+ otherwise.+ + HTML reader: `<figure>` elements are parsed as figures, with the+ caption taken from the respective `<figcaption>` elements.+ + HTML writer: the alt text is no longer constructed from the caption,+ as was the case with implicit figures. This reduces duplication, but+ comes at the risk of images that are missing alt texts. Authors should+ take care to provide alt texts for all images. Some readers, most+ notably the Markdown reader with the `implicit_figures` extension,+ add a caption that's identical to the image description. The writer+ checks for this and adds an `aria-hidden` attribute to the+ `<figcaption>` element in that case.+ + JATS reader: The `<fig>` and `<caption>` elements are parsed into+ figure elements, even if the contents is more complex.+ + JATS writer: The `<fig>` and `<caption>` elements are used write+ figures.+ + LaTeX reader: support for figures with non-image contents and for+ subfigures.+ + LaTeX writer: complex figures, e.g. with non-image contents and+ subfigures, are supported. The `subfigure` template variable is set if+ the document contains subfigures, triggering the conditional loading+ of the *subcaption* package. Contants of figures that contain tables+ are become unwrapped, as longtable environments are not allowed within+ figures.+ + DokuWiki, Haddock, Jira, Man, MediaWiki, Ms, Muse, PPTX, RTF, TEI,+ ZimWiki writers: Figures are rendered like Div elements.+ + Asciidoc writer: The figure contents is unwrapped; each image in the+ the figure becomes a separate figure.+ + Classic custom writers: Figures are passed to the global function+ `Figure(caption, contents, attr)`, where `caption` and `contents` are+ strings and `attr` is a table of key-value pairs.+ + ConTeXt writer: Figures are wrapped in a "placefigure" environment+ with `\startplacefigure`/`\endplacefigure`, adding the features+ caption and listing title as properties. Subfigures are place in a+ single row with the `\startfloatcombination` environment.+ + DocBook writer: Uses `mediaobject` elements, unless the figure contains+ subfigures or tables, in which case the figure content is unwrapped.+ - Docx writer: figures with multiple content blocks are rendered as+ tables with style `FigureTable`; like before, single-image figures are+ still output as paragraphs with style `Figure` or `Captioned Figure`,+ depending on whether a caption is attached.+ + DokuWiki writer: Caption and "alt-text" are no longer combined. The+ alt text of a figure will now be lost in the conversion.+ + FB2 writer: The figure caption is added as alt text to the images in+ the figure; pre-existing alt texts are kept.+ + ICML writer: Only single-image figures are supported. The contents of+ figures with additional elements gets unwrapped.+ + OpenDocument writer: A separate paragraph is generated for each block+ element in a figure, each with style `FigureWithCaption`. Behavior for+ single-image figures therefore remains unchanged.+ + Org writer: Only the first element in a figure is given a caption;+ additional block elements in the figure are appended without any+ caption being added.+ + RST writer: Single-image figures are supported as before; the contents+ of more complex images become nested in a container of type `float`.+ + Texinfo writer: Figures are rendered as float with type `figure`.+ + Textile writer: Figures are rendered with the help of HTML elements.+ + XWiki: Figures are placed in a group.++ * Changes in custom readers/writers:++ + It is now possible to have a custom reader and a custom writer for+ a format together in the same file. The file may also define+ a custom template for the writer.+ + Pandoc now checks the folder `custom` in the user's data directory+ for a matching script if it can't find one in the local directory.+ Previously, the `readers` and `writers` data directories were+ searched for custom readers and writers, respectively. Scripts in+ those directories must be moved to the `custom` folder.+ + Custom readers used to implement a fallback behavior that allowed to+ consume just a string value as input to the `Reader` function. This+ has been removed, the first argument is now always a list of+ sources. Use `tostring` on that argument to get a string.++ * New module Text.Pandoc.Writers.ChunkedHTML,+ exporting `writeChunkedHtml` [API change].++ * We now set the `pandoc-version` variable centrally rather+ than in the writers. One effect is the man writer now emits+ a comment with the pandoc version.++ * pandoc-server:++ + Add simple CORS support to pandoc-server (#8427).+ + Print message to stderr when starting the server.++ * Docx reader:++ + Mark unnumbered headings with class `unnumbered` (#8148,+ Albert Krewinkel). This change ensures good conversion+ results when converting with `--number-sections`.+ + Support parsing of highlighted text.+ + Fix handling of `oMathPara` in `w:p` with other content (#8483).++ * ODT reader:++ + Fix relative links. ODT adds a `../` to relative links+ (see #3524); this needs to be removed when converting from ODT.+ + Handle "section" elements (#8409).+ + Rename Text.Pandoc.Readers.Odt -> Text.Pandoc.Readers.ODT,+ for consistency with Writers.ODT. Rename `readOdt` -> `readODT`.+ [API change]++ * DocBook reader:++ + Support href on link even in a fragment (#8437).+ (We now just look for an `href` attribute without+ worrying about the namespace.)+ + Parse title from imageobject/objectinfo (#8437).++ * JATS reader:++ + Handle uri element in references (#8270).++ * Ipynb reader:++ + Add cell id to attachment filename when storing in MediaBag (#8415).+ Otherwise attachments with the same name can overwrite each other.++ * LaTeX reader:++ + Skip parenthenized args of toprule, midrule, etc (#8242).+ + Handle `##` macro arguments properly (#8243).+ + Remove unused function `toksToString` in Parsing module.+ + Support more `soul` commands, including `\hl`.+ + Add `unnumbered` class for `\part*` (#8447)+ + Fix `TEXINPUTS` handling (#8392). If `TEXINPUTS` ends with `:`,+ then the system default `TEXINPUTS` is added. We handle this by+ just adding the working directory in this case.+ + Parse short table caption (see jgm/pandoc-types#103).+ This is not too useful yet, because writers don't do anything with+ the short caption.++ * MediaWiki reader:++ + Parse table cell with attributess, to support rowspan, colspan (#8231,+ Ruqi).+ + Refine "blending" rules for MediaWiki links (#8525, Ruqi).+ The rules for "blending" characters outside a link into the link are+ described here: https://en.wikipedia.org/wiki/Help:Wikitext#Blend_link+ These pose a problem for CJK languages, which generally don't have+ spaces after links. However, it turns out that the blending behavior, as+ implemented on Wikipedia, is (contrary to the documentation) only for+ ASCII letters. This commit implements that restriction, which fixes+ the problem for CJK.++ * HTML reader:++ + Fix regression for `<tt>` (#8330). It was no longer being parsed as+ Code (Justin Wood).++ * RST reader:++ + Support `mark` role for round-trip.++ * Textile reader:++ + Support linked images (#8541).+ + Fix strong emph ending with link (#8540).+ + Adding a Parser to look for ordered list start attribute numbers+ if any (#2465, vkraven).+ + Handle empty paragraphs (#8487). Also, if attributes are added+ explicitly to a paragraph, put it in a Div with the attributes.++ * Markdown reader:++ + Allow fenced code block "bare" language to be combined+ with attributes (#8174, Siphalor), e.g.+ ````+ ```haskell {.class #id}+ ```+ ````+ + Allow table caption labels to start with lowercase `t` (#8259).+ + Grid tables: allow specifying a table foot by enclosing it with+ part separator lines, i.e., row separator lines consisting only+ of `+` and `=` characters (#8257, Albert Krewinkel). E.g.:+ ```+ +------+-------++ | Item | Price |+ +======+=======++ | Eggs | 5£ |+ +------+-------++ | Spam | 3£ |+ +======+=======++ | Sum | 8£ |+ +======+=======++ ```+ + Fix `implicit_header_references` with duplicate headings (#8300).+ Documentation says that when more than one heading has the same text,+ an implicit reference `[Heading text][]` refers to the first one.+ Previously pandoc linked to the last one instead. This patch+ makes pandoc conform to the documented behavior.+ + Parse highlighted text inside `==..==` if `mark` extension enabled.++ * Org reader:++ + Allow org-ref v2 citations with `&` prefix (#8302).+ + Make `#+pandoc-emphasis-pre` work as expected (#8360, Amir Dekel).++ * BibTeX reader:++ + Fix handling of `%` in `url` field (#7678).+ `%` does not function as a comment character inside `url`+ (where URL-encoding is common).+ + Allow `url` field in `bibtex` as well as `biblatex` (#8287).+ This field is not officially supported for BibTeX, but many styles+ can handle it (<https://www.bibtex.com/f/url-field/>),+ and others will ignore it.+ + Support `software` type in biblatex <-> CSL conversions (#8504).+ + Make sure `version` field comes through in biblatex (#8504).++ * BibTeX writer:++ + Pass through `url` even for `bibtex` (#8287).++ * Org writer:++ + Pass through unknown languages in code blocks (#8278), instead+ of producing `begin_example`.+ + Use span attributes `tag-name` in headers as tags (#8513, Albert+ Krewinkel). This enables round-tripping of tags in Org headings.++ * EndNote reader:++ + Better error when parsing EndNote references fails.++ * DocBook writer:++ + Rename Text.Pandoc.Writers.Docbook -> Text.Pandoc.Writers.DocBook.+ Rename `writeDocbook` -> `writeDocBook`, for consistency with+ the DocBook reader's naming. [API change]+ + Fix position of textobject (#8437). It is a child of+ `inlinemediaobject`, not `imageobject`.+ + Add regression tests for #8437.+ + Render image alt text using textobject element (#8437).+ + Don't indent contents of title element.+ + Store "unnumbered" class in DocBook role attribute (#1402, lifeunleaded).++ * ConTeXt writer (Albert Krewinkel):++ + Support syntax highlighting for code.+ + Always use `\type` for inline code.+ Inline codes that contained curly braces where previously rendered+ with `\mono`; this led to unexpected results when the presentation+ of `\type` was customized, as those changes would not have+ been applied to code rendered with `\mono`.+ + Add support for unlisted, unnumbered headings (#8486).+ + Support `tagging` extension (Albert Krewinkel). Paragraphs+ are enclosed by `\bpar` and `\epar` commands, and `highlight` commands+ are used for emphasis. This results in much better tagging in PDF output.++ * LaTeX writer:++ + Do not repeat caption on headless tables (Albert Krewinkel).+ The caption of headless tables was repeated on each page that+ contained part of the table. It is now made part of the+ "first head", i.e. the table head that is printed only once.+ + Add separator line between table's body and its foot+ (Albert Krewinkel).+ + Ignore languages with no babel equivalent, instead of generating an+ invalid command in the preamble (#8325).+ + Use `\includesvg` for SVGs and include the `svg` package (#8334).+ + Use `soul` instead of `ulem` for strikeout, underline (#8411).+ This handles things like hyphenation, line breaks, and nonbreaking+ spaces better.+ + Use `\toprule\noalign{}` instead of `\toprule()` in tables,+ and similarly for `\midrule` and `\bottomrule` (#8223).+ This facilitates redefining `\toprule`, `\midrule`, and `\bottomrule`+ without needing to gobble the ()s. (Those who redefine these macros+ on the assumption that they will be followed by `()` may need to+ change their definitions.)+ + Support highlighted text for Span with class `mark`.++ * JATS writer:++ + Use `<break/>` for LineBreak in the limited contexts that accept it+ (#8344).+ + Officially deprecate `writeJATS` in favor of `writeJatsArchiving`.++ * RTF writer:++ + Add space after unicode escape commands (#8264). This fixes+ a bug that caused characters to disappear after unicode escapes.++ * RST writer:++ + Render tables as list tables when the `--list-tables` option is+ specified (`writerListTables`) (#4564, Francesco Occhipinti).+ + Improve inline escaping rules (#8380).+ + Use special `mark` role for Span with class `mark`.++ * Commonmark writer:++ + Ensure that we don't have blank lines in raw HTML (#8307).++ * HTML writer:++ + Only add role attribute in HTML5 (#8241). It is not valid in HTML4.+ + Avoid aria-hidden in code blocks for HTML4 (#8241).+ + Only treat `. . .` as a slide pause in slides, and not in regular+ HTML output (#8281).+ + Properly merge classes for headings of level > 6 (#8363).+ + Prevent `<a>` inside `<a>` (#7585). If a link text contains a link,+ we replace it with a span.+ + Replace deprecated aria roles for bibliography entries (#8354).+ `doc-biblioentry` -> `listitem`, `doc-bibliography` -> `list`.+ + Remove obsolete stuff about mathml-script.+ This was a shim we used to include for mathml support.+ We don't do anything with this any more, so this is dead code.+ + Include math links if there are raw commands or environments that+ can be interpreted as math e.g. by MathJax (#8469).+ + Add prooftree to list of math environments (#8462). This will cause+ raw LaTeX prooftree environments to be rendered appropriately when+ `--mathjax` is used.++ * HTML, Markdown writers: filter out empty class attributes (#8251).+ These should not be generated by any pandoc readers, but they+ might be produced programmatically.++ * Markdown writer:++ + Avoid HTML fallbacks in the generated TOC (Albert Krewinkel, #8131).+ The generated table of contents usually has IDs for each TOC link,+ allowing to link back to specific parts of the TOC. However, this+ leads to unidiomatic markup in formats like gfm, which do not support+ attributes on links and hence fall back to HTML. The IDs on TOC items+ are now removed in that case, leading to more aesthetic TOCs.+ + Escape `!` before `[` (#8254).+ + Support `mark` extension.++ * AsciiDoc writer:++ + In link text, only replace commas with entities when they're in+ Str elements. If a link contains an image, it may have attributes,+ and the commas there should not be converted (see #8437, #8070).++ * ODT writer:++ + Fix relative links (#3524).++ * Docx writer:++ + Better handling of tables in lists (#5947). Previously the content+ of each list cell was indented when the table belonged to a list+ item.+ + Indent tables in list items (#5947).+ + Adjust correct attribute on `lang` element (#7022). For East Asian+ languages, we need to adjust `w:eastAsia` rather than `w:val`.+ This allows normal fonts to be used for any Latin-font text.+ Similarly, for bidi languages, we need to adjust `w:bidi`+ rather than `w:val`. We treat `he` and `ar` as bidi languages,+ `zh`, `ja`, `ko` as East Asian languages.+ + Support relative image widths (Albert Krewinkel).+ Image widths given in percent are interpreted to be relative to+ the text width. Previously, percent widths were taken relative to+ the image's native size, inconsistently with other writers.+ + Avoid using 'error' for unassigned table cells (#8468). Instead,+ throw a regular pandoc error.+ + Render a Span with class `mark` as highlighted. Currently+ yellow is hardcoded.++ * MediaWiki writer:++ + Use the 'new' table structure, so that colspan and rowspan are+ supported (Wout Gevaert).++ * Man writer:++ + Use UTF-8 by default for non-ascii characters (#8507).+ Only use groff escapes if `--ascii` has been specified on the+ command line (`writerPreferAscii`).++ * ICML writer:++ + Use Contents element for images with raw data instead of a link+ with a data: uri (#8398).++ * EPUB writer:++ + Refactor to use Text.Pandoc.Chunks.+ + Refactored and simplified code.+ + Make title page optional (#6097).++ * Ms writer:++ + Properly format display equations (#8308).+ + Remove -C option on PSPIC. Some old versions don't support this+ option, and since it's the default it shouldn't be necessary.++ * XWiki writer:++ + Use template if it is specified (#8296). Previously+ templates were ignored.++ * LaTeX template:++ + Set fonts after Beamer theme (Jeremie Knuesel). Beamer themes+ such as metropolis and saintpetersburg change the default+ fonts. This change gives precedence to the user font settings+ by moving them after the loading of the Beamer theme.+ + Set `\babelfont` when `mainlang` and `lang` are specified and+ `pdflatex` is not being used (#8538). This is needed for good+ results in Arabic.+ + Add variable `urlstyle` (#8429, Amar Al-Zubaidi). This is set to+ `same` by default, so users should not experience any change.++ * HTML template:++ + Remove default font size, line height and font family in+ default inline css (#8423). `mainfont`, `fontsize`,+ and `linestretch` can still be used as before; the only difference+ is that we no longer provide opinionated defaults.+ This commit also adds a `maxwidth` variable that sets `max-width`;+ if not set, 36em is used as a default.+ + Add `code { hyphens: manual; }`.+ + Use `styles.citations.html` partial in `styles.html`.+ + Fix class name `hanging` -> `hanging-indent` in+ `styles.citations.html`.+ + Put Consolas before Lucida Console for code font (#8543).+ This is to prevent Lucida Console from being used on Windows, where+ it causes spacing issues in some applications, with boldface+ glyphs wider than regular ones.++ * EPUB CSS changes: Reduce the amount of inline CSS used for EPUBs+ (#8379). Almost everything is now in the default EPUB CSS+ (`data/epub.css`), which can be overridden either by+ putting `epub.css` in the user data directory or by using+ `--css` on the command line. Inline styles are only used+ for syntax highlighting (which depends on the style+ specified, and is only included on pages with highlighted+ code) and for bibliography formatting (which can depend on+ the CSL style, and is only used in the page containing the+ bibliography).++ Note that, for compatibility with older readers, we don't+ use flexbox to style `column/columns` divs by default, as+ we do in HTML. Instead, we use an older method which only+ works when there are two `column` divs inside a `columns`+ div. If you need more than two columns and aren't worried+ about support for older EPUB readers, you can modify the+ default CSS (there is a comment in the CSS telling you what+ to do).++ * Reveal.js template: prevent line-wrapping of parallax options+ (#8503, Albert Krewinkel).++ * reference.pptx: Remove unsupported element (#8342, #6338, Link Swanson).+ The default template contained text above the header, which can mislead+ users into thinking there is a way to put text there using pandoc.++ * Text.Pandoc.Readers.Metadata:++ + Fix metadata parsing corner case (#8465).+ + Don't fail on inline metadata beginning with newline (#8358).++ * Text.Pandoc.App:++ + Move initial input-to-Pandoc code to internal submodule (Albert+ Krewinkel).+ + Change `parseOptionsFromArgs` and `parseOptions` (#8406)+ They now return `Either OptInfo Opt`. [API change]+ + Add `OptInfo` type [API change].+ + Add `handleOptInfo` function. This performs the IO actions for+ things like `--version` that were previously done in+ `parseOptionsFromArgs` [API change].+ + `convertWithOpts`: add argument for a `ScriptingEngine` [API change].+ + Unify check for standalone output (Albert Krewinkel).+ + New `optEpubTitlePage` field on `Opt` [API change] (#6097).+ + Remove `optEpubChapterLevel`, add `optSplitLevel` [API change].+ + Export `IpynbOutput(..)` [API change].++ * Text.Pandoc.App.OutputSettings:++ + Remove unused field `outputWriterName` in `OutputSettings`.++ * Text.Pandoc.Citeproc:++ + Check both extension and mime type to determine bibliography type+ when the bibliography is fetched remotely (#7151).+ + CslJson: allow an object with `items` property in addition to+ an array of references. This is what is returned by e.g.+ `https://api.zotero.org/groups/904125/items?v=...&format=csljson`+ + Require a digit for an implicit "page" locator inside explicit+ locator syntax `{...}` (#8288). Previously a locator specified as+ `{}` would be rendered as `p.` with nothing after it.+ + Update `sub verbo` to `sub-verbo` (#8315). This is a change in+ the term's canonical name in citeproc. As a result of this change,+ `sub verbo` locators have not worked in pandoc since citeproc 0.7.+ + Text.Pandoc.Citeproc.MetaValue: remove unused function+ `metaValueToPath`.+ + Add internal module Text.Pandoc.Citeproc.Name (#8345). This exports+ `toName`, which previously had been part of T.P.Citeproc.BibTeX,+ and allows for cleaner module dependencies.++ * Export module `Text.Pandoc.Slides` [API Change] (Albert Krewinkel).++ * Add new module Text.Pandoc.Format [API change] (Albert Krewinkel).+ The module provides functions and types for format spec parsing and+ processing. The function `parseFormatSpec` was moved from+ Text.Pandoc.Extensions to the new module and renamed to+ `parseFlavoredFormat`. It now operates in+ a PandocMonad and is based on the updated types.++ * Text.Pandoc.Sources:++ + Add UpdateSourcePos instances for String and+ strict and lazy ByteString [API change].++ * Text.Pandoc.Extensions:++ + Fix JSON decoding of Extensions (#8352, Albert Krewinkel).+ + Add new exported function `readExtension` [API change].+ + Remove `parseFormatSpec` [API change]. This has been moved+ to Text.Pandoc.Format and renamed as `parseFlavoredFormat`+ (Albert Krewinkel).+ + Simpler implementation of Extensions based on Set+ (benchmarks show no performance penalty).+ + Add `CustomExtension` constructor to `Extension` [API change].+ + Remove `Bounded`, `Enum` instances for `Extension`.+ + Add `extensionsToList` function.+ + Revise `readExtension` so it can handle `CustomExtension`, and so+ that it returns a Text rather than `Maybe Text`.+ + Add `showExtension` [API change].+ + Add `Ext_mark` extension [API change].+ + Add `Ext_tagging` constructor [API change] (Albert Krewinkel).+ + Add `Ext_wikilinks_title_after_pipe`, `Ext_wikilinks_title_before_pipe`+ [API change] (Albert Krewinkel).++ * Text.Pandoc.PDF:++ + Fix `papersize` on PDF generation via ms (#8403).+ We need to set an option in pdfroff in addition to including+ a macro in the ms file. With this fix, `-Vpapersize=a4` should be+ sufficient to produce A4 PDF via ms.+ + Change default background color of PDFs generated via HTML (#8422,+ Marcin Serwin).++ * Text.Pandoc.MIME:++ + Base module on package `mime-types`, which+ is already a transitive dependency (#8277, Albert Krewinkel).+ + Remove deprecated overrides (#8292).++ * Text.Pandoc.XML:++ + Re-export `lookupEntity` from commonmark-hs [API change].++ * Text.Pandoc.Parsing:++ + Remove gratuitious renaming of Parsec types. We were exporting+ Parser, ParserT as synonyms of Parsec, ParsecT.+ There is no good reason for this and it can cause confusion.+ Also, when possible, we replace imports of Text.Parsec with+ Text.Pandoc.Parsing. The idea is to make it easier, at some point,+ to switch to megaparsec or another parsing engine if we want to.+ New (re-)exports: `Stream(..)`, `updatePosString`, `SourceName`,+ `Parsec`, `ParsecT`. Removed exports: `Parser`, `ParserT`+ [API change].+ + Export `errorMessages`, `messageString` [API change].+ + Export `fromParsecError`, which can be used to turn a parsec+ ParseError into a regular PandocParseError (#8382) [API change].+ + Remove `nested` [API change]. It was not being used, and in fact it+ was a bad idea from the beginning, as it had no hope of solving+ the problem it was introduced to solve.+ + Change `characterReference`, `charsInBalanced`. `characterReference`+ so they now return a Text (some named references don't correspond+ to a single Char). Use the the `lookupEntity` function from+ commonmark-hs instead of the slow one from tagsoup [API change].+ + `charsInBalanced` now takes a Text parser rather than a Char parser+ as argument [API change].++ * Text.Pandoc.Shared:++ + Export `textToIdentifier` [API change].+ + Remove deprecated `crFilter`. [API change]+ + Remove deprecated `deLink`. [API change]+ + Deprecate `notElemText`.+ + Deprecate `makeMeta`.+ + Remove `pandocVersion` (now available in Text.Pandoc.Version+ as `pandocVersionText`).+ + Remove `findM` [API change]. This was only used in one place, and+ can be replaced with simpler code.+ + Remove deprecated `makeMeta` [API change].+ + Remove `ordNub` [API change]. This is just `nubOrd` from+ Data.Containers.ListUtils.+ + Remove `mapLeft` [API change]. This is just a synonym for+ Bifunctor.first.+ + Remove `elemText`, `notElemText` [API change].+ + Drop export of `pandocVersion` and `pandocVersionText`,+ which are now exported by Text.Pandoc.Version.+ + Remove `escapeURI`, `isURI`. These are now exported by+ Text.Pandoc.URI, and removing them from Shared helps make+ the module structure more straightforward.+ + Use LineBreak as default block sep in `blocksToInlines`.+ (#8499, Albert Krewinkel). This change also affects the+ `pandoc.utils.blocks_to_inlines` Lua function.+ + `defaultUserDataDir` is no longer exported (it has been+ moved to T.P.Data) [API change].+ + New function `figureDiv`, offering offers a standardized way+ to convert a figure into a Div element (Albert Krewinkel) [API change].++ * Text.Pandoc.Writers.Shared:++ + Export `htmlAddStyle`, `htmlAlignmentToString` and `htmlAttrs`+ [API change] (Wout Gevaert).+ + Use 'literal tag' instead of 'text (T.unpack tag)' in `tagWithAttrs`+ (Wout Gevaert).+ + `toTableOfContents`: handle nested Divs better (#8402).++ * Rename Text.Pandoc.Network.HTTP -> Text.Pandoc.URI.+ This is still an unexported internal module.+ Export `urlEncode`, `escapeURI`, `isURI`, `schemes`, `uriPathToPath`.+ Drop exports of `schemes` and `uriPathToPath`.++ * Text.Pandoc.URI `isURI`: don't require non-ASCII characters to be+ escaped (#8508).++ * Rename Text.Pandoc.Readers.LaTeX.Types -> Text.Pandoc.TeX (internal+ module).++ * Text.Pandoc.Options:++ + WriterOptions now has a field `writerListTables`,+ specifying that list tables be used in RST output [API change].+ + New `writerEpubTitlePage` field on `WriterOptions` (#6097)+ [API change].+ + Remove `writerEpubChapterLevel`, add `writerSplitLevel` [API change].++ * Text.Pandoc.Filter:++ + Export `applyFilters` [API change].+ + Export `applyJSONFilter` [API Change] (Albert Krewinkel).+ + Parameterize `applyFilters` over scripting engine [API change] (Albert+ Krewinkel).++ * New exported module Text.Pandoc.Chunks [API change]. This+ module provides functions to split Pandoc documents into+ chunks to be rendered in separate files, e.g. one per+ section. Internal identifiers are rewritten appropriately to+ point to the new locations (#6122).++ * Text.Pandoc.Readers:++ + Change argument type of `getReader`, so it takes a `FlavoredFormat`+ instead of a `Text` [API change] (Albert Krewinkel).++ * Text.Pandoc.Writers:++ + Change argument type of `getWriter`, so it takes a `FlavoredFormat`+ instead of a `Text` [API change] (Albert Krewinkel).++ * Text.Pandoc.Templates:++ + Do not try to normalize input to `getDefaultTemplate` (Albert+ Krewinkel). The function `getDefaultTemplate` no longer splits off+ extension modifers from the given format, as that conflicts with+ using custom writers as formats. Haskell library users should use+ `getDefaultTemplate <=< (fmap formatName . parseFlavoredFormat)`+ if the input format can still contain extensions. The same is true+ for `compileDefaultTemplate`, which calls `getDefaultTemplate`+ internally+ + Add Wrapper type documentation (#8490, William Rusnack).++ * New exported module Text.Pandoc.Scripting (Albert Krewinkel).+ The module contains the central data structure for scripting engines+ (e.g., Lua) [API change].++ * Text.Pandoc.Error:++ + Add new PandocError constructor `PandocNoScriptingEngine` [API change]+ (Albert Krewinkel).+ + Add new PandocError constructor `PandocFormatError` [API change]+ (Albert Krewinkel). The new error is used to report problems with+ input or output format specifications.+ + Add new PandocError constructor `PandocNoTemplateError`+ (Albert Krewinkel).+ + Remove `PandocParsecError` constructor from `PandocError` (#8385).+ Henceforth we just use `PandocParseError`.++ * New module Text.Pandoc.Version, exporting `pandocVersionText`+ and `pandocVersion` [API change]. `pandocVersion` returns a `Version`+ instead of a `Text`, which is consistent with `pandocTypesVersion`.++ * Text.Pandoc.Class:++ + Make `getPOSIXTime`, `getZonedTime` sensitive to `SOURCE_DATE_EPOCH`+ environment variable if set (#7093). (`getTimestamp` was+ already sensitive.) This ensures that EPUB builds are reproducible.+ + Text.Pandoc.Class no longer exports `readDataFile`,+ `readDefaultDataFile`, `setTranslations`, and `translateTerm`+ [API change].+ + Text.Pandoc.Class now exports `checkUserDataDir` [API change].++ * T.P.Class.IO: export function `writeMedia` [API change] (Albert Krewinkel).+ This is useful for the `pandoc.mediabag` module.++ * Separate out Text.Pandoc.Data and Text.Pandoc.Translations from+ Text.Pandoc.Class (#8348). This makes Text.Pandoc.Class+ more self-contained.++ + Text.Pandoc.Data is now an exported module, providing `readDataFile`+ and `readDefaultDataFile` (both formerly provided by+ Text.Pandoc.Class), and also `getDataFileNames` (formerly+ unexported in Text.Pandoc.App.CommandLineOptions)+ and `defaultUSerDataDir` (formerly provided by+ Text.Pandoc.Shared). [API change]+ + Text.Pandoc.Translations is now an exported module (along with+ Text.Pandoc.Translations.Types), providing `readTranslations`,+ `getTranslations`, `setTranslations`, `translateTerm`,+ `lookupTerm`, `readTranslations`, `Term(..)`, and `Translations` [API+ change].++ * Text.Pandoc now exports Text.Pandoc.Data and `setTranslations`+ and `translateTerm` {API change].++ * Export module Text.Pandoc.Class.IO [API change].+ The module is useful when defining instances of class PandocMonad for+ types that are also instances of MonadIO.++ * Remove modules Text.Pandoc.Writers.Custom and Text.Pandoc.Readers.Custom+ [API Change] (Albert Krewinkel). The functions `writeCustom` and+ `readCustom` are available from module Text.Pandoc.Lua.++ * Text.Pandoc.Server:++ + Split this module into a separate package, `pandoc-server`,+ allowing the `pandoc` library to be compiled without server support.+ + Return object if JSON is accepted. Previously we just returned+ a JSON-encoded string. Now we return something like:+ ```+ {+ "output": "<p>hello</p>"+ "base64": false,+ "messages": [+ {+ "message": "Not rendering RawInline (Format \"tex\") \"\\\\noe\"",+ "verbosity": "INFO"+ }+ ],+ }+ ```+ This is a change in the pandoc-server JSON API.+ + Set translations in the writer based on `lang` metadata.+ + Return error in JSON object if response is JSON.+ + Remove `parseServerOpts`. [API change]++ * Text.Pandoc.Lua:++ + This module has been moved to a separate package,+ `pandoc-lua-engine`.+ + Export `applyFilter`, `readCustom`, and `writeCustom`.+ No longer export the lower-level function `runFilterFile` [API+ change].+ + Change type of `applyFilter` [API Change] (Albert Krewinkel).+ The module Text.Pandoc.Filter.Lua has been merged into+ Text.Pandoc.Lua. The function `applyFilter` now has type+ ``` haskell+ applyFilter :: (PandocMonad m, MonadIO m)+ => Environment-> [String]-> FilePath-> Pandoc-> m Pandoc+ ```+ where `Environment` is defined in Text.Pandoc.Filter.Environment.+ + Export new function `getEngine` [API Change].+ The function returns the Lua scripting engine.+ + Add unexported modules T.P.Lua.Reader, T.P.Lua.Writer.+ These contain the definitions of `readCustom` and `writeCustom`+ that were previously in T.P.Readers.Custom and T.P.Writers.Custom.+ + Cleanup module dependencies, for a cleaner module dependency graph.+ + The `writeCustom` function has changed to return a Writer and+ an ExtensionsConfig [API change]. This allows ByteString writers+ to be defined.+ + The `readCustom` function has changed to return a Reader and an+ ExtensionsConfig [API change].++ * Lua subsystem (Albert Krewinkel):++ + The whole Lua subsystem has been moved to a separate package,+ `pandoc-lua-engine`. `pandoc` does not depend on it.+ `convertWithOpts` has a new parameter that can be used to+ pass in the scripting engine defined in `pandoc-lua-engine`+ (or a different one, in theory).+ + Fix the behavior of Lua "Version" objects under equality+ comparisons (#8267).+ + Support running Lua with a GC-collected Lua state.+ + Ensure that extensions marshaling is consistent.+ + Produce more informative error messages for pandoc errors.+ Errors are reported in Lua in the same words in which they would be+ reported in the terminal.+ + Add new module `pandoc.format`. The module provides functions to+ query the set of extensions supported by formats and the set+ of extension enabled per default.+ + Add function `pandoc.template.apply`.+ + Add function `pandoc.template.meta_to_context`.+ The functions converts Meta values to template contexts; the intended+ use is in combination with `pandoc.template.apply`.+ + Allow Doc values in `WriterOptions.variables`.+ The specialized peeker and pusher function for `Context Text` values+ does not go via JSON, and thus keeps Doc values unchanged during+ round-tripping.+ + Fix rendering of Lua errors in Lua, so that the+ `Error running Lua` message is not prepended multiple times.+ + Add new module `pandoc.zip`.+ + Allow strings in place of compiled templates (#8321).+ This allows to use a string as parameter to `pandoc.template.apply`+ and in the WriterOptions `template` field.+ + Rename `reader_extensions`/`writer_extensions` globals as `Extensions`+ (#8390).+ + Add `pandoc.scaffolding.Writer` (#8377). This can be used to reduce+ boilerplate in custom writers.+ + Fix peeker for PandocError (Albert Krewinkel). String error messages+ were incorrectly popped of the stack when retrieving a PandocError.+ + Add functions `pandoc.text.toencoding`, `pandoc.text.fromencoding`+ (#8512, Albert Krewinkel).+ + Add `pandoc.cli` module. Allow processing of CLI options in Lua.+ + Support `-D` CLI option for custom writers.+ A new error `PandocNoTemplateError` (code 87) is thrown if a template+ is required but cannot be found.+ + Allow table structure as format spec. This allows to pass structured+ values as format specifiers to `pandoc.write` and `pandoc.read`.+ + Add function `pandoc.mediabag.write` (Albert Krewinkel).+ + Add module `pandoc.structure` (Albert Krewinkel). The function+ `make_sections` has been given a friendlier interface and moved to the+ new module; the old `pandoc.utils.make_sections` has been deprecated.++ * Custom writers:++ + The global variables `PANDOC_DOCUMENT` and `PANDOC_WRITER_OPTIONS`+ are no longer set when the writer script is loaded. Both variables+ are still set in classic writers before the conversion is started,+ so they can be used when they are wrapped in functions.+ + Deprecate classic custom writers.+ + Add function `pandoc.write_classic`. The function can be used to+ convert a classic writer into a new-style writer by setting it as+ the value of `Writer`:+ ``` lua+ Writer = pandoc.write_classic+ ```+ or to fully restore the old behavior:+ ``` lua+ function Writer (doc, opts)+ PANDOC_DOCUMENT = doc+ PANDOC_WRITER_OPTIONS = opts+ load(PANDOC_SCRIPT_FILE)()+ return pandoc.write_classic(doc, opts)+ end+ ```+ + Support extensions in custom writers. Custom writers can define the+ extensions that they support via the global `writer_extensions`.+ The variable's value must be a table with all supported extensions+ as keys, and their default status as values. For example,+ the below specifies that the writer supports the extensions `smart`+ and `sourcepos`, but only the `smart` extension is enabled by default:+ ``` lua+ writer_extensions = {+ smart = true,+ sourcepos = false,+ }+ ```+ + Custom writers can define a default template via a global `Template`+ function; the data directory is no longer searched for a default+ template. Writer authors can restore the old lookup behavior with+ ``` lua+ Template = function ()+ local template+ return template.compile(template.default(PANDOC_SCRIPT_FILE))+ end+ ```++ * Custom readers:++ + Support extensions in custom readers.+ Custom readers, like writers, can define the set of supported+ extensions by setting a global. E.g.:+ ``` lua+ reader_extensions = {+ smart = true,+ citations = false,+ }+ ```++ * Use latest versions of `commonmark-extensions`, `texmath`,+ `citeproc`, `gridtables`, and `skylighting`.++ * Use pandoc-types 1.23. This adds the `Figure` Block+ constructor and removes the `Null` Block constructor.++ * Require aeson >= 2.0.++ * Use jira-wiki-markup 1.5.0 (#8511, Albert Krewinkel). Fixes issues with+ icon-like sequences at the beginning of words.++ * Use doctemplates 0.11, avoiding a transitive dependency on HsYAML.++ * Use skylighting 0.13.1.2.++ * Allow mtl 2.3.1 (Alexander Batischev).++ * Use latest skylighting-format-context.++ * Allow building with mtl 2.3.++ * Remove `lua53` flag. We now only support Lua 5.4.++ * Add hie.yaml for haskell language server.++ * Add tools/latex-package-dependencies.lua.++ * Update default CSL with latest `chicago-author-date.csl`.++ * make_artifacts.sh: various small improvements.++ * Remove sample.lua from data files (#8356).++ * Documentation:++ + Deprecate `PANDOC_WRITER_OPTIONS` in custom writers (Albert Krewinkel).+ + Document `pandoc.write_classic` (Albert Krewinkel).+ + Document new table features (Albert Krewinkel).+ + Clarify what background-image does in reveal.js (#6450).+ + Documentation improvements for `blank_before_blockquote`+ (#8324, Pranesh Prakash).+ + Update grid table documentation (#8346).+ + Add note about MathJax fonts to `--embed-resources`.+ + Use cabal's --package-env more (#8317, Artem Pelenitsyn).+ + Modify Zerobrane instructions to use Lua 5.4 (#8353, Ian Max Andolina).+ + Fix documentation for highlight-style in `pandoc-server.md`.+ + Fix link to fedora package site (#8246, Akos Marton).+ + Rephrase paragraph on format extensions (#8375, Ilona Silverwood).+ + Update README.template (#8496, Sven Wick).+ + Fix a tiny typo in lua-filters.md (TomBen).+ + Clarify that `--css` should be used with `-s`.+ + Clarify font selection for pdf -t ms (#8421, nbehrnd).+ + Clarify docs for `--metadata-file` (#8459).+ + Fix typo in epub.md (Vladimir Alexiev).+ + Add missing backtick in filters.md (R. N. West).+ + `doc/lua-filters.md`: add documentation for `pandoc.format`+ (Albert Krewinkel).+ + Fix epub-embed-font documentation (#8455, Terence Eden).+ + Removed obsolete Templates section in CONTRIBUTING.md.+ + Add manual section on accessible PDFs, archiving standards (#8312,+ Albert Krewinkel).++ * Tests.Command: remove unused `runTest`.++ * Add pandoc-lua.1 man page.++ * Improve `shell.nix`.++ * Add `tools/moduledeps.lua` for inspecting the internal module+ dependency tree.++ * Fix macOS zip so pandoc-server is a symlink. This cuts its size by 2x.++ * CI: Improve CI speed by caching more, eliminating macos builds,+ and splitting benchmarks into a separate action, run by+ manual dispatch. (We still test that benchmarks build in+ the regular CI.) The cache can be expired manually by+ modifying the secret `CACHE_VERSION`.++ * Remove the unnecessary Setup.hs from pandoc.+ Cabal does not need this with build-type 'simple'.++ * Add pandoc-lua and pandoc-server (symlinks) and their man pages+ to releases.++ * Use hslua-cli package for pandoc-lua interface (Albert Krewinkel).++ * Add `server` flag to pandoc-cli, allowing it to be compiled without+ server support.++ * pandoc-cli: Allow building a binary without Lua support (Albert+ Krewinkel). Disabling the `lua` cabal flag will result in a+ binary without Lua.++ * Move `--version` handling to pandoc-cli. We need it here in order+ to print information about whether server and Lua support have been+ compiled in.++ * Move `nightly` flag from pandoc to pandoc-cli (#8339).++ * Makefile changes:++ - `make help` will now print all the targets and what they do.+ - Add targets: `coverage`, `weeder`, `moduledeps`, `prerelease`,+ `ghcid`, `repl`, `linecounts`, `hie.yaml`, `binpath`.+ - Note that you can `` alias pandoc=`make binpath` `` for+ convenient local testing of a build.+ - Rename `quick-cabal` -> `build`, `quick-test` -> `test`.+ - Exclude tests from `SOURCEFILES`.++ * Factor out xml-light into an internal library.++ * Add CITATION.cff (#8434).++ * Move trypandoc to a separate repository, jgm/trypandoc.++## pandoc 2.19.2 (2022-08-22)++ * Fix regression with data uris in 2.19.1 (#8239).+ In 2.19.1 we used the base64URL encoding rather than base64.++ * pandoc-server: handle `citeproc` parameter as documented (#8235).++ * Org reader: treat *emacs-jupyter* src blocks as code cells (#8236,+ Albert Krewinkel). This improves support for notebook-like org files+ that are intended to be used with emacs-jupyter package.++ * HTML writer and templates: revert to using `width` property for column+ widths (Albert Krewinkel). The default `flex` and `overflow-x` properties+ of a column are set to `auto`. In combination, these changes allow to+ get good results when using columns with or without explicit widths.++ * Org writer (Albert Krewinkel):++ + Add support for jupyter nodebook cells (#6367).+ + Prefix code language of ipynb code blocks with `jupyter-`.+ This is the convention used by the *emacs-jupyter* package.+ + Keep code block attributes as header args. This allows to keep more+ information in the resulting `src` blocks, making it easier to+ roundtrip from or through Org. Org babel ignores unknown header+ arguments.+ + Add code block identifier as `#+name` to src blocks.++ * Fix some typos in the codebase (luz paz).++ * Require hslua-module-path 1.0.3 (#8228, Albert Krewinkel).++## pandoc 2.19.1 (2022-08-18)++ * Add server capabilities.++ + New exported module Text.Pandoc.Server [API change].+ + The pandoc executable now starts up a web server when renamed or+ symlinked as `pandoc-server`, and functions as a CGI program when+ renamed or symlinked as `pandoc-server.cgi`. See the man page for+ `pandoc-server` for full documentation.++ * Text.Pandoc.App.Opts: Redo `FromJSON` for `Opt` so that optional+ values can be omitted (in which case the values from+ `defaultOptions` are used).++ * Org reader: treat "abstract" block as metadata (Albert Krewinkel, #8204).+ A block of type "abstract" is assumed to define the document's abstract.+ It is transferred from the main text to the metadata.++ * Org template: add abstract from metadata as block of type "abstract"+ (#8204).++ * HTML writer: use `flex` property for column widths+ (Albert Krewinkel, #8232).++ * LaTeX writer:++ + Add label to tables that have an identifier (Albert Krewinkel, #8219).+ Tables with an identifier are marked with a `\label`. A caption is+ always included in this case, even if the caption is empty.+ + Use `\textquotesingle` for straight quotes in text.+ + Fix widths of multicolumn cells (#8218).++ * LaTeX template: fix behavior of `colorlinks` variable (Albert+ Krewinkel, #8226). Fixes a regression in 2.19 that required the+ `boxlinks` variable to be set in addition to the usual link coloring+ variables. Otherwise links were never colored in LaTeX PDF output.++ * Text.Pandoc.Highlighting: Export `lookupHighlightingStyle`+ [API change]. Previously this lived in an unexported module+ Text.Pandoc.App.CommandLineOptions, under the name+ `lookupHighlightStyle`.++ * Text.Pandoc.App:++ + Remove unneeded MonadIO constraints in readSources.+ + Factor out `convertWithOpts'` from `convertWithOpts`.+ This runs in any PandocMonad, MonadIO, MonadMask instance.+ So far it is not exported, but it might find a use later.++ * Support `--strip-comments` in commonmark/gfm (#8222).+ This change makes the commonmark reader sensitive to+ `readerStripComments`.++ * Lua: add function `pandoc.utils.citeproc` (Albert Krewinkel).+ The function runs the *citeproc* processor on a Pandoc document.+ Exposing this functionality to Lua allows to make citation processing+ part of a filter or writer, simplifies the creation of multiple+ bibliographies, and enables the use of varying citation styles in+ different parts of a document.++ * Refactor `linux/make_artifacts.sh`.++ * Update INSTALL.md installation from source instructions.++ * Use base64 package instead of base64-bytestring. It is supposed to be+ faster and more standards-compliant.++ * trypandoc improvements:++ + Add dropdown with canned examples.+ + Add citeproc support.+ + Support csv, bibliographic and binary formats.+ + Add load from file.+ + Add permalink. Don't always reload page.+ + Use vanilla JS and CSS + the new `pandoc-server.cgi`.++ * Allow haddock-library-1.11.0.++ * Convert `tool/extract-changes.hs` to a Lua filter.+++## pandoc 2.19 (2022-08-03)++ * Add `--embed-resources` flag (Elliot Bobrow, #7331). This can be+ used to embed resources without implying `--standalone`.+ Deprecate `--self-contained` in favor of `--embed-resources --standalone`.++ * Allow environment variable interpolation in `highlight-style`+ and `pdf-engine` fields in defaults files+ (#8061; Jaehwang Jung, #8073).++ * Allow placing custom readers and writers in user data directory+ (Albert Krewinkel, #8112) (`readers` and `writers` subdirectories).++ * Add `tsv` (tab separated values) as an input format (#7974).+ [API change]: Text.Pandoc.Readers.CSV now exports `readTSV`.+ Internal change: In Text.Pandoc.CSV, `CSVOptions` has changed+ so that `csvQuote` takes a Maybe value.++ * Add `tex_math_dollars` to `gfm` default extensions (reflecting+ gfm's new support for math).++ * RST, Org, Markdown readers: support rowspans and colspans in grid tables+ (#8202, Albert Krewinkel). Note: the writers does not yet support these+ more complex grid table features, so these complex grid tables will+ not round-trip.++ * HTML, LaTeX, and MediaWiki readers: use `formatCode`+ (#8162, #8129, Elliot Bobrow). This moves formatting from inside inline+ code elements to the outside, since pandoc's Code element only takes string+ content.++ * Markdown reader:++ + Don't parse inline notes with blank lines inside (#8028).+ + Allow attributes in special spans (e.g. `smallcaps`, `underline`)+ (Albert krewinkel, #4102). These spans are parsed as+ SmallCaps or Underline elements, but any attributes are included+ in a wrapping Span.++ * HTML reader:++ + Allow sublists that are not marked as items (Albert+ Krewinkel, #8150). This is technically invalid HTML, but it can+ be found in the wild and browsers handle it.++ * Org reader (Albert Krewinkel):++ + Recognize absolute paths on Windows (Albert Krewinkel, #8201).+ + Recognize {webp,jxl} files as images (YI).+ + Allow attrs for Org tables (Albert Krewinkel, #8049). Tables with+ attributes are no longer wrapped in Div elements; attributes are added+ directly to the table element.+ + Support line selection in INCLUDE directives (Brian Leung, #8060).+ + Fix Post / Pre mixup when setting emphasis chars (Amir Dekel, #8134).++ * LaTeX reader:++ + Support `\includesvg` (#8027).+ + Unescape characters in `\lstinline` inside `\passthrough` (#8179).+ + Improve `mathEnvWith` (#8122). When converting e.g. an align+ environment to an aligned environment inside a Math element, we need+ to include a newline before the `\end{aligned}`, since the previous+ line might end in a comment.+ + Fix treatment of extensions for `\input` in LaTeX reader (#8092).+ Previously we required a `.tex` extension, but TeX+ allows any extension for `\input` (as opposed to `\include`).++ * RTF reader:++ + support `\nosupersub` (#8170).++ * TikiWiki reader:++ + Support underlined text++ * DocBook reader:++ + Improved reading `<xref>` elements (Frerich Raabe, #8065).++ * JATS reader:++ + Strip `ref-` prefix from ref id in xref (#8007).+ + Support edition in references (#8087).++ * RIS reader:++ + Make parser more forgiving (#8034). Allow blank lines after entries.+ Allow entries with no space after the `-`, provided they+ just have a newline, e.g. `DB -\n`.+ + Get right order of names (#8055).++ * MediaWiki reader:++ + Allow HTML comment after row start (#8110).++ * DokuWiki reader:++ + The `tex_math_dollars` extension is now supported for `dokuwiki`+ (but off by default) (#8178).+ + Content inside `<latex>...</latex>` is parsed as raw LaTeX inline,+ and inside `<LATEX>..</LATEX>` as raw LaTeX block (#8178).+ + The behavior of `<php>...</php>` is changed, so that instead of+ producing a code block, it produces raw HTML with `<?php ... ?>`.++ * LaTeX writer:++ + Improve grouping with autocites (#8088).+ + Extend list of book documentclasses (Wentau Han, #8053).+ + Fix width of multicolumn cells (Albert Krewinkel, #8090).+ Cells spanning multiple columns must be given an explicit width,+ calculated from the table properties.+ + Beamer: allow containsverbatim as alternative to fragile (#8080).++ * HTML writer:++ + Add 'footnotes' identifier to footnotes section (#8043).+ + Fix bug with `--number-offset`. This formerly caused section divs+ to be produced, even when `--section-divs` was not specified (#8097).+ + Use CSS flexboxes for columns (Albert Krewinkel). This allows+ an arbitrary number of columns, while the previous approach assumed+ exactly two columns.+ + Allow "spanlike" classes to be combined (see #8194). Previously+ classes like "underline" and "marked" had to be the first class+ in a span in order for the span to be interpreted as a "ul" or+ "mark" element. This commit allows these special classes to be+ "stacked," e.g. `[test]{.mark .underline}`; in addition, the+ special classes are no longer required to come first in the list+ of classes.+ + Avoid doubled style attribute when height and width are added to+ style because of an image, but the image already has a style attribute+ (#8047).+ + Do not include the deprecated doc-endnote role (#8030).+ doc-endnote was deprecated in DPUB-ARIA 1.1.+ + Remove extra soft break for tasklist (black-desk, #8142).+ Browser will display the extra newline character between checkbox and+ text as a space, which make tasklist items cannot be aligned.++ * EPUB writer:++ + Allow choice of math method for v3 (#8164). Previously we always+ used MathML for math in EPUB3, because the spec includes MathML.+ But this is not widely supported by readers, so it seems better+ to allow users to choose their math method as they can with+ EPUB2 or HTML. **NOTE:** Existing workflows that produce EPUBv3+ documents including math will be affected by this change. You+ must add `--mathml` to your command line if you want to continue+ producing MathML.++ * RST writer:++ + Fix missing spaces with nested inlines (#8182).+ + Always escape literal backslash (#8178).++ * Ms writer:++ + Add comment in preamble stating generator.+ + Fix roff ms syntax highlighting definitions (#8175, thanks to+ Branden Robinson).++ * ConTeXt writer:++ + Support complex table structures (Albert Krewinkel, #8116).+ The following table feature are now supported in ConTeXt:++ - colspans,+ - rowspans,+ - multiple bodies,+ - row headers, and+ - multi-row table head and foot.++ The wrapping `placetable` environment is also given a `reference` option+ with the table identifier, enabling referencing of the table from within+ the document.+ + Unify link handling (Albert Krewinkel, #8096).+ Autolinks, i.e. links with content that's the same as the linked URL,+ are now marked with the `\url` command. All other links, both internal+ and external, are created with the `\goto` command, leading to shorter,+ slightly more idiomatic code. As before, autolinks can still be styled+ via `\setupurl`, other links via `\setupinteraction`.+ + Use "sectionlevel" environment for headings (Albert Krewinkel, #5539).+ The document hierarchy is now conveyed using the+ `\startsectionlevel`/`\stopsectionlevel` by default. This makes it easy+ to include pandoc-generated snippets in documents at arbitrary levels.+ The more semantic environments "chapter", "section", "subsection", etc.+ are used if the `--top-level-division` command line parameter is set to+ a non-default value.++ * Docx writer:++ + Add `w:lang` to `rPr` for Span and Div with lang attribute, so+ that Word can know that "Apfel" is not a spelling error (#8026).+ + Prevent crashing when handling invalid tables (Albert Krewinkel, #8102).+ Tables with different numbers of cells per row would sometimes crash+ pandoc. This fix prevents this by cutting off overlong rows.++ * ICML writer:++ + Support custom-style attribute on Table (#8079).++ * AsciiDoc writer:++ + Fix commas in link text (#8070). Commas in link text trigger+ interpretation of attributes. To block this, we replace them with+ numeric entities.+ + Fix underline. We were rendering it as `+++text+++`; this is now+ changed to `[.underline]#text#`. See comment at+ <https://github.com/jgm/pandoc/issues/8070#issuecomment-1126883824>.++ * FB2 writer:++ + Fix handling of non-section Divs (#8123).++ * Markdown writer:++ + Disable soft wrapping when `hard_line_breaks` enabled (#8035).+ We were already doing this for `markdown`; this commit does+ the same thing for `markua` and `commonmark` and `gfm`.+ + Avoid excessive indentation on bullet lists for `commonmark`,+ `markua`, `gfm`. They are now nested by 2 spaces instead of 4 (#8011).++ * Text.Pandoc.Class:++ + Add new function `findFileWithDataFallback` [API Change]+ (Albert Krewinkel).+ + `fillMediaBag`: Keep attributes of original image on Span (Albert+ Krewinkel, #8099). Images that cannot be fetched are replaced with a+ Span that contains the image's description. The span now also retains+ all original image attributes and inherits all attributes of the image.+ Furthermore, the classes `image` and `placeholder` are added, and path+ and title are store in attributes `original-image-src` and+ `original-image-title`, respectively.++ * Text.Pandoc.Shared:++ + `makeSections`: don't make a section for a div with class "fragments"+ (#8098).+ + Ensure that Nulls are ignored by `makeSection` and in segmenting+ slides (#8155).+ + Add `formatCode` function to Text.Pandoc.Shared [API change]+ (Elliot Bobrow, #8129).+ + `taskListItemToAscii`: handle asciidoctor's characters (#8011).+ Asciidoctor uses different unicode characters for task+ lists; we should recognize them too and be able to convert+ them to ascii task lists in formats like gfm.+ + Deprecate `deLink` and mark for later removal.++ * Text.Pandoc.Writers.Shared:++ + `toTableOfContents`: Don't replace links with empty spans in TOC (#8020).++ * Text.Pandoc.Readers.Metadata:++ + Ensure that metadata values w/o trailing newlines are+ parsed as inlines, as the manual states.+ Previously, they were parsed as inlines if they would+ otherwise have been a single Plain or Para, but otherwise+ left unchanged. This led to some quirky results (e.g. #8143).+ We now use the general function `blocksToInlines` from T.P.Shared.++ * Text.Pandoc.Parsing:++ + Simplify `gridTableWith'`, `gridTableWith` [API Change] (Albert+ Krewinkel). The functions `gridTableWith` and `gridTableWith'` no+ longer takes a boolean argument that toggles whether a table head+ should be parsed: both, tables with heads and without heads, are+ always accepted now.++ * Lua subsystem (Albert Krewinkel):++ + Extend `pandoc.system` module (Albert Krewinkel, #8184).+ The module now has the additional functions `list_directory`,+ `make_directory`, and `remove_directory`. This makes it easier to write+ cross-platform scripts that need to inspect or modify the file system.+ + Require pandoc-lua-marshal 0.1.7. Adds a `clone` methods to+ Pandoc objects and allows to pass Blocks in instead of full+ Caption elements.+ + Add fields `pandoc.readers` and `pandoc.writers` (#8177).+ The set of supported input and output formats is made available to Lua+ users.+ + Ensure that tables marshaled via JSON arrays behave like Lists.+ This allows to invoke methods like `map` and `includes` on lists like+ `PANDOC_WRITER_OPTIONS.extensions`.+ + Require hslua-2.2.1, unless lua53 flag is set, and do not reset+ foreign encoding before running Lua. This fixes a problem where+ the encoding used for Lua filenames would sometimes mismatch the+ encoding used by the OS.+ + Simplify module loading code. Modules are now loaded directly;+ the special pandoc Lua package searcher is no longer necessary and+ has been removed.+ + Add function pandoc.mediabag.fill (#8104). The function allows to+ fill the mediabag with all images in a given document. Images that+ cannot be fetched are replaced with a Span containing the+ image description.++ * Populate mediabag after filters have run (Albert Krewinkel, #8099).+ The mediabag is filled with document resources after the filters have+ run. This allows, for example, filter authors to modify image paths+ before pandoc tries to fetch the images.+ Lua filters that rely on a filled mediabag can use the new+ `pandoc.mediabag.fill` function to perform that action in the filter.++ * Ms template: redefine rather than removing .CH macro (#8175).++ * JATS template (Albert Krewinkel, except as noted):++ + Include particles, prefix, suffix in names.+ + Mark authors with cor-id as corresponding authors.+ Corresponding authors are marked by setting the attribute+ `corresp="yes"` in their respective `<contrib>` element.+ + Unconditionally include permissions element (#8040).+ Fixes a bug that caused license information to be omitted when no+ copyright information was provided.+ + Follow JATS4R recommendation and PudMed Central for license URI+ (Castedo Ellerman, #8041).++ * LaTeX template:++ + Rename `\textormath` to `\TextOrMath` (Hos Es, #8036).+ + Fix links-as-notes (Albert Krewinkel, #8077).++ * HTML template styles:++ + Remove `span.underline` rule. This is superfluous now that we+ render Underline as `<u>`.+ + Improve CSS for task lists (#8151).++ * LaTeX template: Add `boxlinks` variable for LaTeX/PDF output (#8198).+ If `boxlinks` is set but `colorlinks` is not, then boxes will+ be printed around links (`hidelinks` will not be set in `hypersetup`).++ * `--self-contained`: Handle `url()` in `<style>` elements (#8193).++ * Text.Pandoc.PDF: use SHA1 hash of filename when converting SVG.+ The previous code threw away the directory component of+ the filename in constructing a new one. This led to+ surprising results if you had e.g. `foo/pic.svg` and `bar/pic.svg`;+ in the final PDF they'd be the same image, because the latter+ would overwrite the former in the temp directory.++ * Remove Muse reader round-trip tests. These are nondeterministic and have+ repeatedly failed on strange edge cases.++ * Update fonts MIME following IANA recommendation (Gabriel Lewertowski,+ #8127).++ * Future compat change for `liftA2` export from Prelude (Georgi Lyubenov,+ #8132).++ * Update `default.csl` from the latest chicago-author-date.csl.++ * Update manfilter.hs for greater portability (#8045).+ The tables in our man pages were not rendering correctly+ with mandoc, now used by default with macOS. mandoc doesn't+ allow man formatting inside table cells. For maximum portability,+ we now render the tables in plain format and include them as code+ blocks in the man page.++ * CI: update macos container version (#8197, Sukka).++ * Add `nightly` flag. This causes a `-nightly-COMPILEDATE`+ suffix to be added the the output of `--version` (#8016).+ This is used in the nightly CI builds.++ * Update dependencies (aeson, skylighting, pandoc-lua-marshall,+ citeproc, texmath).++ * Documentation improvements (thanks to Jiří Wolker,+ Castedo Ellerman, Albert Krewinkel, Bastien Dumont, Cezar Drożak, Benjamin+ Wuethrich, Ivan Panchenko, Sukil Etxenike, Masataka Ogawa).++## pandoc 2.18 (2022-04-04)++ * New input formats: `endnotexml` (EndNote XML bibliography),+ `ris` (RIS bibliography).++ * A RIS bibliography file may now be used with `--citeproc`.++ * Citeproc: Allow a formatted bibliography to be placed in metadata fields+ via a Div with class `refs` (#7969, #526). Thus, one can include a+ metadata field, say `refs`, whose content is an+ empty div with id `refs`, and the formatted bibliography will be put into+ this metadata field. It may then be interpolated into a template using the+ variable `refs`.++ * Ensure that you don't get PDF output to terminal. `-t pdf` now behaves+ like `-t docx` and gives an error unless the output is redirected.++ * `--version` now prints hslua version (#7929) and+ Lua version (#7997, Albert Krewinkel).++ * Change `--metadata-file` parsing so that, when the input format is not+ markdown or a markdown variant, pandoc's markdown is used (#6832, #7926).+ When the input format is a markdown variant, the same format is used.+ Reason for the change: it doesn't make sense to run the markdown parser+ with a set of extensions designed for a non-markdown format, and+ this dramatically limits what people can do in metadata files.++ * Trim whitespace from math in `--webtex` (#7892).+ This fixes problems with --webtex and markdown output,+ when display math starts or ends with a newline.++ * `--self-contained`: issue warning rather than failing with an error+ if a resource can't be found (#7904).++ * New exported module Text.Pandoc.Readers.EndNote, exporting+ `readEndNoteXML` and `readEndNoteXMLCitation` [API change].++ * New exported module, Text.Pandoc.Readers.RIS, exporting `readRIS` (#7894)+ [API change].++ * LaTeX reader:++ + Handle subequations as inline math environment (#7883).+ + Rudimentary support for `vbox` (#7939).+ + Support `\today` (#7905).+ + Handle `\label` and `\ref` for footnotes (#7930).+ + Allow inline groups starting with `\bgroup` (#7953).+ + Use custom TokStream that keeps track of whether macros are expanded.+ This allows us to improve performance a bit by avoiding unnecessary+ runs of the macro expansion code (e.g. from 24 ms to 20 ms on+ our standard benchmark).+ + Further optimizations for inline parsing.+ + Better handling of `\usepackage`. If the package is local but+ causes parse errors, parse everything up to the error and skip the+ rest. Issue a `CouldNotParseIncludeFile` warning indicating that+ parsing failed at that point.+ + Text.Pandoc.Readers.LaTeX.Parsing: Monoid and Semigroup instances for+ TokStream.++ * HTML reader:++ + Give warnings and emit empty note when parsing+ `<a epub:type="noteref">` and the identifier+ doesn't correspond to anything in the note table (#7884).+ Previously we just silently skipped these cases.+ + Fix parsing of epub footnotes (#7884).++ * DocBook reader:++ + Handle complete set of entities as specified at+ <https://www.w3.org/2003/entities/2007doc/byalpha.html> (#7938).+ + Handle abstract in info section (#7747).+ + Improve info parsing.+ + Simplify metadata parsing code (#7747).+ Handle abstract as block-level content.+ Report skipped info elements with `--verbose`.+ + Handle address and coyright in metadata (#7747).++ * DokuWiki reader:++ + Add DokuWiki table alignment (#5202, damon-sava-stanley).++ * RST reader:++ + Fix treatment of headerless simple tables (#7902).+ + Wrap math in Span to preserve attributes (#7998, Albert Krewinkel).+ Math elements with a name, classes, or other fields are wrapped in a+ `Span` with these attributes.++ * JATS reader:++ + Improve handling of fn-group elements (#6348, Albert Krewinkel).+ Footnotes in `<fn-group>` elements are collected and re-inserted into+ the document as proper footnotes in the place where they are referenced.+ + Handle `pub-date` (#8000).+ + Support PMID, DOI, issue in citations (#7995).+ + Improve refs parsing. Handle `issn` and `isbn`; use simpler form+ for issued date.+ + Strip 'ref-' from ref id in constructing CSL id. This allows better+ round-tripping, because the JATS writer adds the `ref-` prefix to+ the citation id to get the ref element's id.++ * Org reader:++ + Allow ":" in property drawer keys (Lucas V. R).+ Any non-space character is allowed as property drawer key, including ":"+ itself (so it is not really a delimiter). The real delimiter is a space+ character, so in a drawer like+ ```+ :PROPERTIES:+ ::k:ey:: value+ :END:+ ```+ ":k:ey:" is a key with value "value".++ + Allow comments above property drawer.+ + More flexible LaTeX environments (Lucas V. R).+ + Handle `#+bibliography:` as metadata so that it can work with+ `--citeproc`.+ + Parse `#+print_bibliography:` as Div with id `refs`.+ + Allow multiple `#+bibliography:`.++ * Markdown reader:++ + Allow one-column pipe tables with pipe on right (#7919).+ + Remove restriction on identifiers, so they no longer need to+ begin with a letter (#7920).++ * Docx reader:++ + Enable `citations` extension for docx reader (#7840).+ When enabled, Zotero, Mendeley, and EndNote citations embedded in+ a docx are parsed as native pandoc citations.+ (When disabled, the generated citation+ text and bibliography are passed through as regular text.)+ The bibliography generated by the plugin is suppressed.+ Instead, bibliographic data embedded in citation items is added+ to the `references` metadata field so that it can be used+ with `--citeproc`.++ * Docbook writer:++ + Interpret links without contents as cross-references (#7360, Jan Tojnar).+ Links without text contents are converted to `<xref>` elements. DocBook+ processors will generate appropriate cross-reference text when presented+ with an xref element.++ * Docx writer:++ + Single numbering ID for examples (#7895, mjfs).+ This change ensures that example list items all belong to a single+ number sequence, so that if items are added or deleted in a word+ processor, the other items will renumber automatically.+ + Add bookmark with table id to table (#7989, Nikolai+ Korobeinikov, #7285). This allows tables with ids to be linked to.++ * Ipynb writer:++ + Handle metadata better (#7928). Previously we used the markdown+ writer to render metadata. This had some undesirable consequences+ (e.g. en dash expanded to `--` when `smart` enabled), so now we use+ the plain writer.++ * LaTeX writer:++ + Avoid extra space before `\CSLRightInline` (#7932).+ + Add `scrreport` to `chaptersClasses` (#6168, ivardb).+ + Support `page`,`trim`,`clip` attributes on images (#7181).+ + Add `()` after booktabs rules (#8001). These commands take optional+ arguments with () and [], which can lead to problems if the content+ of the table cell begins with these characters.++ * RST writer:++ + Support all standard metadata ("bibliographic") fields.++ * HTML writer: performance improvements.++ * Org writer:++ + Stop indenting property drawers, quote blocks+ (#3245, Albert Krewinkel). This follows the current default org-mode+ behavior.++ * Markdown writer:++ + Move table-related code into submodule (Albert Krewinkel).+ + Don't produce redundant header identifier when the+ `gfm_auto_identifiers` extension is set (#7941).+ + Update escaping rules for `\`. We now escape `\` only if `raw_tex`+ is enabled or it is followed by a non-alphanumeric.++ * JATS writer:++ + Encode author "others" as `<etal/>` (Albert Krewinkel).+ Citeproc adopted the BibTeX convention to use the author name "others"+ when there are additional authors that are not named. JATS uses the+ `<etal>` element for this.+ + Avoid doubled ref-list element (#7990). Previously when generating JATS+ with the `element_citations` extension enabled, the references were+ put in a doubly-nested ref-list element (`<ref-list><ref-list>...`).+ + Keep edition info in element citations (#7993, Albert Krewinkel).+ + Fix handling of CSL variable 'page' (not 'pages' as we had before).+ It should go to 'lpage' and 'rpage', not 'page-range'.++ * EPUB writer: refactor for clarity (#7991, Jonathan Dönszelmann,+ Ola Wolska, Ivar de Bruin, Jaap de Jong).++ * Custom writer (Albert Krewinkel):++ + Support new-style Writer function (Albert Krewinkel).+ See the documentation for custom writers for details.+ + Produce stacktrace if Writer function fails++ * Text.Pandoc.Logging: add `CouldNotParseIncludeFile` constructor+ for `LogMessage` [API change].++ * Text.Pandoc.Shared:++ + Put id attributes on TOC entries (#7907, damon-sava-stanley).+ Naming scheme of id is "toc-" + id of linked to header/section.+ Effects HTML, Markdown, Powerpoint, and RTF.+ + Define `ordNub` as alias for `nubOrd` from containers package (#7963,+ Albert Krewinkel).+ + Export `ensureValidXmlIdentifiers`. This function changes identifiers+ that don't start with letters, and internal links to these identifiers,+ making them compatible with XML standards. The change+ is simple: we add `id_` to the front. There is potential+ for duplication if there are already `id_...` identifiers+ defined, but this seems rare enough not to worry too much+ about.++ * Ensure that valid XML identifiers are used in Docbook, EPUB, FB2,+ HTML4, S5, Slidy, Slideous, ICML, ODT, TEI writers.+ Thus, if you convert `[anchor]{#1} and [link to](#1)`,+ `id_1` will be used instead of `1` for the identifier.++ * Lua (Albert Krewinkel).++ + Add module `pandoc.layout` to format and layout text.+ + Move custom writer code into Lua hierarchy.+ + Use pandoc-lua-marshal 0.1.5.+ + Allow any type of callable object as argument to List+ functions `filter`, `map`, and `find_if`. These previously+ required the argument to be of type `function`, which was too+ restrictive.+ + Inline: the type of Image captions is now `Inlines` instead of `List`.+ + Allow passing `Sources` to `pandoc.read` (#8002).++ * Text.Pandoc.PDF:++ + Restore `wkhtmltopdf` as default pdf engine for HTML (Albert Krewinkel).+ + Allow custom writer as format if engine is explicitly specified (#7898,+ Albert Krewinkel). Note that it may be necessary to explicitly+ specify a template on the command line.++ * Text.Pandoc.MediaBag: improve detection of absolute paths (#7881).++ * Text.Pandoc.Extensions:++ + Remove `raw_tex` extension from list of commonmark extensions, and+ from the `commonmark_x` defaults. commonmark doesn't parse raw TeX,+ and it doesn't make sense to write it if we don't parse it.+ + Remove `native_divs` from allowed gfm extensions (#7965). This allows+ `<div>` to be suppressed using `-raw_html`. Previously `native_divs`+ was enabled but could not be suppressed, because it was not in the+ list of available extensions for commonmark-based formats.++ * Text.Pandoc.Parsing:++ + Partition module into (internal) submodules (#7962, Albert Krewinkel).+ + Unify grid table parsing (#7971, Albert Krewinkel).+ Grid table parsing in Markdown and RST are updated use the same+ functions. Functions are generalized to meet requirements for both+ formats. This change also lays the ground for further generalizations+ in table parsers, including support for advanced table features.+ [API change] in Text.Pandoc.Parsing:++ - Parse results of functions `tableWith'` and `gridTableWith'` are now a+ `mf TableComponents` instead of a quadruple of alignments, column+ widths, header rows and body rows.+ - Additional exports from Text.Pandoc.Parsing:+ `tableWith'`, `TableComponents`, `TableNormalization`,+ `toTableComponents`, `toTableComponents'`.++ * Text.Pandoc.XML.Light: add versions of the parsers that allow+ specifying a custom entity map. Exports new functions:+ `parseXMLElementWithEntities`, `parseXMLContentsWithEntities` [API change].++ * Text.Pandoc.Writers.GridTable: improve module documentation (Albert+ Krewinkel).++ * Text.Pandoc.Parsing.GridTable: simplify column handling code (Albert+ Krewinkel).++ * Text.Pandoc.MIME: Add mime type for mkv extension (#7181).++ * Text.Pandoc.Asciify: Fix regression with `ascii_identifiers` and Turkish+ undotted i (#8003).++ * Relax upper bound for hslua, allow hslua-2.2. (#7929)+ Lua 5.4 is used by default after this is merged. Packagers may still+ include Lua 5.3 instead by building pandoc with `--constraint='hslua <2.2'`.+ Differences between 5.3 and 5.4 should not generally affect pandoc Lua+ filters. See list of incompatible changes here:+ <https://www.lua.org/manual/5.4/manual.html#8.1>++ * JATS template: allow multiple licenses (Albert Krewinkel).++ * LaTeX template:++ + Skip `\babelprovide` if `babel-lang` is empty (#7945) to avoid an error.+ + Move hyperref near end of preamble (#5811). It now comes after+ header-includes and right before title, author, date, abstract.+ Note: Users who presuppose hyperref in their header-includes+ will now have to add `\usepackage{hyperref}` to their header-includes+ to make it available there. (The redundant `\usepackage` will+ do no harm in this case.)+ + Remove special redefinition of `\sout`. This used to be necessary to+ avoid problems with hyperref, when headings contain strikeout text,+ but it does not seem to be necessary any more (tested).++ * Tests: improve location reporting of failing tests (Albert Krewinkel).++ * Add tests for idempotency of `makeSections` (#7950).++ * Add armhf support in linux build script (#7944, Tony).++ * Use latest pandoc-types, so that toJSONFilter will work with+ Meta and MetaValue.++ * Use latest doclayout, texmath, commonmark, citeproc.++ * INSTALL.md: add reference to install via winget (#7951, Guriy Samarin).++ * MANUAL.txt:++ - Document way to get list in block quote in slide shows (#7916).+ - Minor changes to security section.+ - Note that `smart` works for html input.+ - Fix typos (#7934, Dimitris Apostolou).+ - Fix documentation for citations and org mode.+ - Remove claim that `--self-contained` does not work with `--mathjax`+ (#682).++ * doc/org.md: remove obsolete citations section.+ This mostly described citation formats we no longer support.++ * doc/lua-filters.md: Fix typo (#7981, Mario Lang).++ * Makefile: Use cabal for default build++ * Add `lua53` cabal flag. It is false by default. If set to true, compile+ with hslua 2.1 and Lua 5.3, otherwise hslua 2.2 and Lua 5.4.+++## pandoc 2.17.1.1 (2022-01-31)++ * Fix regression in 2.17.1 which caused problems finding+ default files in the default user data directory. (Reverts+ the item "logic bug in `fullDefaultsPath`", which was+ misguided.)++ * Sample custom writer: use single quotes for strings (#7487,+ Albert Krewinkel).++## pandoc 2.17.1 (2022-01-30)++ * Support `pagedjs-cli` as pdf engine (#7838, Albert Krewinkel).+ PagedJS is a polyfill and supports the Paged Media standards by the W3C.+ <https://www.pagedjs.org/>++ * CommonMark reader: fix source position after YAML metadata (#7863).++ * LaTeX reader:++ + Remove retokenizing in `rawLaTeXParser`.+ + Ensure that `\raggedright` doesn't gobble an argument (#7757).+ + Improve `descItem`. For some reason we were skipping+ arbitrary blocks before `\item`. This is now changed to "skip+ whitespace and comments."+ + Improve handling of `\newif`. Adding a pair of braces around the+ second argument of `\def` prevents LaTeX from an emergency stop+ on input like the following (#6096).+ ```+ \newif\ifepub+ \epubtrue+ \ifepub+ hi+ \fi+ ```++ * Docx reader: Parse both Zotero citation and bibliography as+ `FieldInfo` (#7840).++ * LaTeX writer:++ + Allow arbitrary frameoptions to be passed to a beamer+ frame, using the frameoptions attribute (#7869).+ + Add s and squeeze to recognized beamer frameoptions (#7869).++ * Markdown writer: handle explicit column widths with pipe tables (#7847).+ If a table has explicit column width information *and* the content+ extends beyond the `--columns` width, we need to adjust the+ widths of the pipe separators to encode this width information.++ * Docx writer: Separate tables even with RawBlocks between (#7724,+ Michael Hoffmann). Adjacent docx tables need to be separated by an+ empty paragraph. If there's a RawBlock between tables which renders+ to nothing, be sure to still insert the empty paragraph so that+ they will not collapse together.++ * Man writer: use custom font V for inline code (#7506).+ The V font is defined conditionally, so that it renders+ like CB in output formats that support that, and like B+ in those that don't (e.g. the terminal).+ Aliases also defined for VI, VB, VBI.++ * Asciidoc writer: Support checklists in asciidoctor writer (#7832,+ Nikolai Korobeinikov, ricnorr). The checklist syntax (similar to+ `task_list` in markdown) seems to be an asciidoctor-only addition.++ * HTML writer:++ + Avoid duplicate "style" attributes on table cells (#7871).+ + Don't break lines inside code elements. With the new (default)+ line wrapping of HTML, in conjunction with the default CSS which+ includes `code { whitespace: pre-wrap; }`, spurious line+ breaks could be introduced into inline code (#7858).++ * Custom writer: preserve order of element attributes (#7489, Albert+ Krewinkel). Attribute key-value pairs are marshaled as AttributeList,+ i.e., as a userdata type that behaves both like a list and a map. This+ allows to preserve the order of key-value pairs.++ * Switch to hslua-2.1 (Albert Krewinkel). This allows for some code+ simplification and improves stability.++ * Don't read files outside of user data directory (Even Brenden).+ If a file path does not exist relative to the working directory, and+ it does exist relative to the user data directory, but outside of+ of the user data directory, do not read it. This applies to+ `readDataFile` and `readMetadataFile` in PandocMonad and, by+ extension, any module that uses these by passing them relative paths.++ * Text.Pandoc.Class.`makeCanonical`: Correctly handle consecutive ".."s+ at the beginning of a path (Even Brenden). Prior to this commit,+ `../../file` would evaluate to `file`, when it should be unchanged.++ * Search for metadata files in `$DATADIR/metadata` (#7851, Even Brenden).+ If files specified with `--metadata-file` are not found in the working+ directory, look in `$DATADIR/metadata` (#5876).++ * Text.Pandoc.Class: export `readMetadataFile` [API change] (#5876).++ * Text.Pandoc.Error: export new `PandocCouldNotFindMetadataFileError`+ constructor for `PandocError` [API change] (#5876).++ * Avoid putting a frame around speaker notes in beamer (#7857).+ If speaker notes (a Div with class 'notes') occur right+ after a section heading, but above slide level, the+ resulting `\note{..}` caommand should not be wrapped in+ a frame, as that will cause a spurious blank slide.++ * CSS in HTML template: adjust #TOC and h1 on mobile (#7835, Mauro Bieg).++ * Text.Pandoc.Readers.LaTeX.Parsing: don't export `totoks`.+ Make the first param of `tokenize` a SourcePos instead of+ SourceName, and use it instead of `totoks`.++ * Text.Pandoc.Shared: Modify `stringify` so it ignores `[Citation]`+ inside `Cite` (#7855). Otherwise we'll sometimes get two copies of+ things, one from the `citationPrefix` or `citationSuffix` and another+ from the embedded fallback text. When there is no fallback text,+ we'll get no content. However, it really isn't an alternative to just+ rely on the result of running `query` on the embedded `Citation`s;+ this will result in a jumble of text rather than anything structured.++ * Omit `--enable-doc` in the cabal haddock invocation in+ `tools/build-and-upload-api-docs.sh`.++ * Text.Pandoc.App.Opt: fix logic bug in `fullDefaultsPath`.+ Previously we would (also) search the default user data directory+ for a defaults file, even if a different user data directory+ was specified using `--data-dir`. This was a mistake; if+ `--data-dir` is used, the default user data directory should+ not be searched.++ * Text.Pandoc.Shared: `defaultUserDataDir` behavior change (#7842).+ If the XDG data directory is not defined (e.g. because+ it's not supported in the OS or HOME isn't defined), we+ return the empty string instead of raising an exception.++ * Update command tests to distinguish stderr and test exit status.++ * MANUAL: add that speaker notes can be used with beamer (#7856).++ * Update `build-and-upload-api-docs.sh`.++ * Document `--trace` option.+ Document `no-check-certificate` in defaults files.+ Document 'sandbox' option for defaults files. (#7873).++ * Fix pattern syntax in sample readability custom reader.++ * doc/custom-readers.lua: add example for "readable HTML."++ * Fix message in man page about where code can be found.++ * `manfilter.lua`: remove extra indent in table cells with code blocks.++ * Fix lua-filters documentation for table column widths (#7864).++ * epub.doc: Update links to KindleGen (#7846, Benson Muite, Mauro Bieg).+ KindleGen has been deprecated and we need to link to archived versions.++ * Use tables in defaults files documentation, so each+ default option is paired with the corresponding command-line+ option (Carsten Allefeld).++ * Use skylighting 0.12.2.++ * Add pandoc-lua-marshal to Nix shell (#7849, Even Brenden).+++## pandoc 2.17.0.1 (2022-01-14)++ * Require pandoc-lua-marshal 0.1.3.1 (#7831, Albert Krewinkel).+ Fixes a problem with `List.includes` and `List.find` that caused a+ Lua stackoverflow and subsequent program crash.++ * HTML template: load header-includes before math (#7833, Kolen Cheung).+ MathJax expect the config comes before loading the MathJax script.+ This change of order allows one to config MathJax via+ header-includes, which loads before the MathJax script. Cf. #2750.++ * When reading defaults file, stop at a line `...`. This line signals+ the end of a YAML document. This restores the behavior we got with+ HsYaml. yaml complains about content past this line. See+ https://github.com/jgm/pandoc/issues/4627#issuecomment-1012438765++ * Text.Pandoc.Citeproc: allow `notes-after-punctuation` to work with+ numerical styles that use superscripts (e.g.+ american-medical-association.csl), as well as with note styles. The+ default setting of `notes-after-punctuation` is true for note styles+ and false otherwise. This restores a behavior of pandoc-citeproc+ that wasn't properly carried over to Citeproc (#7826, cf.+ jgm/pandoc-citeproc#384).++ * Use commonmark-pandoc 0.2.1.2 (#7769).++ * Add FAQ on images in ipynb containers (#7749, Kolen Cheung).++## pandoc 2.17 (2022-01-12)++ * Support `markua` as an output format (#1871, Tim Wisotzki and+ Saumel Lemmenmeier). Markua is a markdown variant used by Leanpub.++ * Add text wrapping for HTML output (#7764). Previously the HTML writer+ was exceptional in not being sensitive to the `--wrap` option. With+ this change `--wrap` now works for HTML. The default (as with other+ formats) is automatic wrapping. Note that the contents of `script`,+ `textarea`, and `pre` tags are always laid out with the `flush`+ combinator, so that unwanted spaces won't be introduced if these occur+ in an indented context in a template.++ * Don't read sources until in/out format are verified (#7797).++ * Issue error with `--list-extensions` for invalid formats (#7797).++ * Make `--citeproc` recognize `.yml` as well as `.yaml` extensions+ as YAML bibliography files (#7707, Jörn Krenzer).++ * Use latest version of KaTeX with `--katex`.++ * Fix parsing of footnotes in `--metadata-file` (#7813). Previously+ non-inline footnotes were not being parsed.++ * ODT reader:++ + Parse list-header as a list item (Tuong Nguyen Manh).++ * Commonmark reader:++ + Put sourcepos attribute on header, not enclosing div+ with `-f commonmark+sourcepos` (#7769).++ * Markdown reader:++ + Don't allow `^` at beginning of link or image label (#7723).+ This is reserved for footnotes. Fixes regression from 0a93acf.+ + Fix parsing of "bare locators" after author-in-text citations.+ Previously `@item [p. 12; @item2]` was incorrectly parsed as+ three citations rather than two. This is now fixed by ensuring+ that `prefix` doesn't gobble any semicolons.+ + Revert changes to `inlinesInBalancedBrackets` (commit fa83246),+ which caused regressions.+ + Improve detection of pipe table line widths (#7713). Fixed+ calculation of maximum column widths in pipe tables. It is+ now based on the length of the markdown line, rather than a+ "stringified" version of the parsed line. This should be+ more predictable for users. In addition, we take into account+ double-wide characters such as emojis.++ * Custom (Lua) readers:++ + First argument is now a list of sources instead of the+ concatenated text (Albert Krewinkel). The list+ structure can easily be converted to a string by applying+ `tostring`, but it is also possible to access the elements+ (each with a `text` and `name`). A small example is added+ to the custom reader documentation, showcasing its use in a+ reader that creates a syntax-highlighted code block for+ each source code file passed as input. Existing readers+ will still work through a fallback mechanism, issuing a+ deprecation notice.++ * Org reader:++ + Parse official org-cite citations (#7329). We also support the older+ org-ref style as a fallback. We no longer support the+ "markdown style" or "Berkeley style" citations.+ + Support alphabetical (fancy) lists (Lucas Viana). When the+ `fancy_lists` extension is enabled, alphabetical list markers are+ allowed, mimicking the behaviour of Org Mode when+ `org-list-allow-alphabetical` is enabled.+ + Support counter cookies in lists (Lucas Viana). Such cookies are+ used to override the item counter in ordered lists. In org it is+ possible to set the counter at any list item, but since Pandoc AST+ does not support this, we restrict the usage to setting an offset for+ the entire ordered list, by using the cookie in the first list item.+ + Allow trailing spaces after key/value pairs in directives (Albert+ Krewinkel). Ensures that spaces at the end of attribute directives like+ `#+ATTR_HTML: :width 100%` (note the trailing spaces) are accepted.++ * LaTeX reader:++ + Omit visible content for `\label{...}`. Previously we+ included the text of the label in square brackets, but this is+ undesirable in many cases. See discussion in+ <https://github.com/jgm/pandoc/issues/813#issuecomment-978232426>.+ + Improve references (#813). Resolve references to theorem environments.+ Remove the Span caused by "label" in figure, table, and theorem+ environments; this had an id that duplicated the environments' id.+ + Fix semantics of `\ref`. We were including the ams+ environment type in addition to the number. This is proper+ behavior for `\cref` but not for `\ref`. To support `\cref`+ we need to store the environment label separately.+ + Add babel mappings for Guajati (gu) and Oriya (or) (#7815).+ + Fix typo `panjabi` -> `punjabi` in babel mappings (#7814).++ * HTML reader:++ + Parse attributes on links and images (#6970).++ * Docx reader:++ + Handle multiple pic elements inside a drawing (#7786).+ + Change `elemToParPart` to return `[ParPart]` instead of `ParPart`.+ Also remove `NullParPart `constructor, as it is no longer+ needed. This will allow us to handle elements that contain+ multiple ParParts, e.g. `w:drawing` elements with multiple `pic:pic`.++ * DocBook reader:++ + Collapse internal spaces in literal and other similar tags (#7821),+ as the standard docbook toolchain does.+ + Be sensitive to spacing="compact" in lists (#7799). When+ `spacing="compact"` is set, Para elements are turned into Plain,+ so we get a "tight" list.++ * Markdown writer:++ + Add new exported function `writeMarkua` from Text.Pandoc.Writers.Markdown+ [API change] (#1871, Tim Wisotzki and Saumel Lemmenmeier).+ + Fix indentation issue in footnotes (#7801).+ + Avoid extra space before citation suffix if it already starts+ with a space.+ + Ensure semicolon between the locator and the next citation when an+ author-in-text citation has a locator and following citations.+ + Improve escaping for `#` (#7726).++ * Custom (Lua) writers:++ + Allow variables to be set via second return value of `Doc`+ (#6731, Albert Krewinkel). New templates variables can be added by+ giving variable-value pairs as a second return value of the+ global function `Doc`. Example:+ ```+ function Doc (body, meta, vars)+ vars.date = vars.date or os.date '%B %e, %Y'+ return body, vars+ end+ ```+ + Provide global `PANDOC_WRITER_OPTIONS` (#6731, Albert Krewinkel).+ + Assign default Pandoc object to global `PANDOC_DOCUMENT` (Albert+ Krewinkel). The default Pandoc object is now non-strict, i.e., only+ the parts of the document that are accessed will be marshaled to Lua.+ A special type is no longer necessary. This change also makes it+ possible to use the global variable with library functions such as+ `pandoc.utils.references`, or to inspect the document contents with+ `walk()`.++ * LaTeX writer:++ + Fix typo `panjabi` -> `punjabi` in babel mappings (#7814).++ * MediaWiki writer:++ + Remove redundant display text for wiki links (Jesse Hathaway).++ * Docx writer:++ + Handle bullets correctly in lists by not reusing numIds+ (#7689, Michael Hoffmann). This fixes a bug in which a Div in+ a list item would receive bullets on its contained paragraphs.++ * Org writer:++ + Fix list items starting with a code block or other non-paragraph+ content (#7810).+ + Avoid blank lines after tight sublists (#7810).+ + Fix extra blank line inserted after empty list item (#7810).+ + Don't add blank line before lists (#7810).+ + Support starting number cookies (Lucas Viana). This is necessary+ for lists that start at a number other than 1.+ + Support the new org-cite syntax (#7329).++ * Haddock writer:++ + Avoid blank lines after tight sublists (#7810).++ * Ipynb writer:++ + Ensure deterministic order of keys.+ + Handle cell output with raw block of markdown (#7563, Kolen Cheung).+ Write RawBlock of markdown in code-cell output. This is designed+ to fit the behavior of #7561, which makes the ipynb reader parse+ code-cell output with mime "text/markdown" to a RawBlock of markdown.+ This commit makes the ipynb writer writes this RawBlock of markdown+ back inside a code-cell output with the same mime, preserving this+ information in round-trip.+ + In choosing between multiple output options, always favor+ those marked with the output format over images (Kolen Cheung).+ Previously, both `fmt == f` case and Image have a rank of 1.++ * Ipynb reader & writer: properly handle cell "id" (#7728).+ This is passed through if it exists (in Nb4); otherwise+ the writer will add a random one so that all cells have an "id".++ * Ms writer:++ + Properly encode strings for PDF contents (#7731).++ * JATS writer:++ + Keep quotes in element-citations (Albert Krewinkel).+ Fixed a bug that lead to quote characters being lost in+ element-citations.++ * RTF writer:++ + Properly handle images in data URIs (#7771).++ * Commonmark writer:++ + Allow ')' delimiters on ordered lists.++ * RST writer:++ + Avoid extra blank line after empty list item (#7810).++ * HTML writer:++ + Make line breaks more consistent. With `--wrap=none`, we now+ output line breaks between block-level elements. Previously they+ were omitted entirely, so the whole document was on one line, unless+ there were literal line breaks in pre sections. This makes+ the HTML writer's behavior more consistent with that of+ other writers. Also, regardless of wrap settings,+ put newline after `<dd>` and after block-level elements in+ the footnotes section. And add a line break between an `img` tag+ and the associated `figcaption`.+ + reveal.js: Make sure images with `r-stretch` are not in p tags.+ They must be direct children of the section. There was previously+ code to make this work with the older class name `stretch`, but+ the name has changed in reveal.js.+ + reveal.js: don't add `r-fit-text` class to section. It must go on+ the header only.++ * AsciiDoc writer:++ + Improve detection of intraword emphasis (#7803).++ * OpenDocument writer:++ + Fix vertical alignment bug with display math (#7777). Previously some+ displayed formulas would be floated above a preceding text line.+ This is fixed by setting `vertical-rel` to `text` rather than+ `paragraph-content`.++ * JATS template (Albert Krewinkel):++ + Fix position of contrib affiliations in authoring set. Any+ `<aff>` element must come before any `<email>` element.+ + Fix affiliation tagging in `articleauthoring` output.+ Affiliations were `xlink`ed even in the articleauthoring tag set, but+ `<aff>` are not allowed as children of `contrib-group` elements in that+ tag set. Each affiliation must be listed directly in the contrib+ element.+ + Add support for article subtitles.++ * EPUB template:++ + Include abstract in default template.+ + Ensure that the essential styles needed by pandoc (`styles.html`+ partial) are included in the templates. This is important for correct+ formatting of CSL bibliographies. Note that much of the styling in+ `styles.html` will be ignored for EPUB, because of the conditional on+ `document-css`. Setting the `document-css` variable will cause it+ not to be ignored.++ * HTML template: Add abstract (#7588, Jannik Buhr, John MacFarlane).+ By default, a localized title (the word "Abstract") will be+ used, unless the variable `abstract-title` is set.++ * ConTeXt template: Make title appear in PDF title bar. This is+ recommended for accessibility reasons. Note: doesn't work with macOS+ Preview.app.++ * `reference.pptx`: change to use 16:9 aspect ratio, Powerpoint's default.++ * Text.Pandoc.Writers:++ + Do not export `writeCustom` [API change]. This ensures that all+ writers exported in T.P.Writers are parameterized and work with any+ `PandocMonad` type. This is consistent with T.P.Readers, as+ `readCustom` is not exported from that module either.++ * Text.Pandoc.Writers.Shared:++ + `endsWithPlain` now returns True if the list ends with a list+ that ends with a Plain, and so on recursively (#7810).++ * Text.Pandoc.Class.IO:++ + `writeMedia`: unescape percent-encoding in creating file path.+ This addresses a problem with spaces in image filenames+ when creating PDFs (#7819); it also affects `--extract-media`.++ * New internal module Text.Pandoc.Writers.Blaze, exporting `layoutMarkup`.+ This converts a blaze Html structure into a doclayout Doc Text.++ * Text.Pandoc.Extensions:++ + `parseFormatSpec`: cleaner error message for invalid extensions.++ * Text.Pandoc.MediaBag:++ + Fix bug in `extractMedia`, which caused the test for `..`+ in paths to fail, with the result that images with `..`+ in the path name could be extracted outside of the+ directory specified by `extractMedia`. It also led a check for+ `media` in resource paths to fail in the docx reader.++ * Text.Pandoc.Citeproc:++ + Avoid adding comma before an author-in-text citation in a note+ if it begins with a title (no author) (#7761).+ + Text.Pandoc.Citeproc.Locator now exports `toLocatorMap`,+ `LocatorInfo`, and `LocatorMap`. The type of `parseLocator`+ has changed, so it now takes a `LocatorMap` rather than a `Locale`+ as parameter, and returns a `LocatorInfo` instead of a tuple.+ + Fix citation locator detection for German. `toLocatorMap` now+ stores keys case-folded. We want to do a case-insensitive+ comparison when parsing locators, so that e.g. both+ `Chap.` and `chap.` work. Previously we case-folded terms+ when doing the lookup, but they weren't case-folded in the+ map itself, which led to locator-detection breaking for+ German (where the terms have uppercase letters).++ * Lua (Albert Krewinkel):++ + Allow single elements as singleton MetaBlocks/MetaInlines. Single+ elements should always be treated as singleton lists in the Lua+ subsystem.+ + Add `pandoc.template` module. The module provides a `compile`+ function to use strings as templates.+ + Add `pandoc.WriterOptions` constructor.+ + Add function `pandoc.write`.+ + Provide global `PANDOC_WRITER_OPTIONS` (#5221).+ + The function Text.Pandoc.Filter.applyFilters now takes a filter+ environment of type `Environment`, instead of a ReaderOptions value+ [API change].+ + The `Environment` type is exported from Text.Pandoc.Filter+ and allows to combine ReaderOptions and WriterOptions in a single+ value [API change].+ + Global, exported from Text.Pandoc.Lua, has a new type constructor+ `PANDOC_WRITER_OPTIONS` [API change].+ + Add constructors `pandoc.Blocks` and `pandoc.Inlines`.+ The functions convert their argument into a list of Block and Inline+ values, respectively. When applied to a string, they split the+ string into `Str` elements separated by `Space` or `SoftBreak`+ (#7712).+ + Support topdown traversals The traversal order of filters can now+ be selected by setting the key `traverse` of the filter to either+ `'topdown'` or `'typewise'`; the default remains `'typewise'`.+ Topdown traversals can be cut short by returning `false` as a+ second value from the filter function. No child-element of the+ returned element is processed in that case.+ + Marshal ReaderOptions field `extensions`, `track_changes` via JSON.+ Extensions are now available as a list of strings; the track-changes+ settings are given as the kebab-case representation used in JSON.+ + Allow binary (byte string) readers to be used with `pandoc.read`.+ + Use global state when parsing documents in `pandoc.read`.+ The function `pandoc.read` is updated to use the same state that was+ used while parsing the main input files. This ensures that log+ messages are preserved and that images embedded in the input are+ added to the mediabag.+ + Cleanup stack in `peekReadOptionsTable`. A ReaderOptions element was+ left on top of the stack when the `peekReadOptionsTable` function+ was invoked.+ + `walk` methods are added to `Pandoc`, `Block`, `Inline`,+ `Blocks`, `Inlines` values; the methods are similar to+ `pandoc.utils.walk_block` and `pandoc.utils.walk_inline`, but+ apply to filter to the element's contents.+ + Functions of name `Doc` are no longer accepted as alternatives for+ `Pandoc` filter functions. This functionality was undocumented.+ + Improve handling of empty caption, body by `from_simple_table`+ #7776). Create truly empty table caption and body when these are+ empty in the simple table.+ + Change representation of `TableHead`, `TableFoot`, and `Row` values+ (#7718). The objects now also follow the principle that element+ attributes are accessible through the `.attr` field. Rows in `TableHead`+ and `TableFoot` are available via the `.rows` field. Row objects have a+ `.cells` field, containing the list of table cells.+ + [Simplify](Simplify) code of `pandoc.utils.stringify`. Minor behavior change:+ plain strings nested in tables are now included in the result string.+ + Simplify and deprecate function `pandoc.utils.equals`. The function+ is no longer required for element comparisons; it is now an alias+ for the `==` operator.+ + Add function `pandoc.utils.references` (#7752).+ + Add new library function `pandoc.utils.type`. The function behaves+ like the default `type` function from Lua's standard library,+ but is aware of pandoc userdata types. A typical use-case would be+ to determine the type of a metadata value.+ + Fix return types of `blocks_to_inlines`, `make_sections`.+ Ensures the returned lists have the correct type (`Inlines` and+ `Blocks`, respectively).+ + Use more natural representation for Reference values+ Omit `false` boolean values, push integers as numbers.++ * Lua: use package pandoc-lua-marshal (#7719, Albert Krewinkel).+ The marshaling functions for pandoc's AST are extracted into a separate+ package. The package comes with a number of changes:++ + Pandoc's List module was rewritten in C, and error messages were+ improved.+ + Lists of `Block` and `Inline` elements are marshaled using the new+ list types `Blocks` and `Inlines`, respectively. These types+ currently behave identical to the generic List type, but give better+ error messages. This also opens up the possibility of adding+ element-specific methods to these lists in the future.+ + Elements of type `MetaValue` are no longer pushed as values which+ have `.t` and `.tag` properties. This was already true for+ `MetaString` and `MetaBool` values, which are still marshaled as Lua+ strings and booleans, respectively. Affected values:+ - `MetaBlocks` values are marshaled as a `Blocks` list;+ - `MetaInlines` values are marshaled as a `Inlines` list;+ - `MetaList` values are marshaled as a generic pandoc `List`s.+ - `MetaMap` values are marshaled as plain tables and no longer+ given any metatable.+ + `Cell` values are now marshaled as userdata objects; a constructor+ function for table cells is provided as `pandoc.Cell`.+ + The test suite for marshaled objects and their constructors has+ been extended and improved.+ + A bug in `Citation` objects, where setting a citation's suffix+ modified it's prefix, has been fixed.+ + Inlines, Blocks, and List objects now have an `__eq` metamethod,+ testing equality by comparing two lists element-wise.++ * Powerpoint tests: shorten lines by grouping tests (Albert+ Krewinkel). This makes the test output more pleasant to read+ in narrow terminal windows.++ * make check: check for unreleased dependencies.++ * Add `tools/build-and-upload-api-docs.sh`.++ * Update cabal description.++ * `MANUAL.txt`: Add section on EPUB styling.++ * `MANUAL.txt`: clarify "standard Markdown" as "original Markdown"+ (#7802, Martin Fischer).++ * `doc/custom-writers.md`: use filter to include source of example.++ * Add an example to `doc/custom-readers.md`.++ * Fix typo in `custom-readers.md` (#7722, Mauro Bieg).++ * `doc/jats.md`: add link to JATS documentation (Martin Fischer).++ * `doc/lua-filters.md`: many improvements (Albert Krewinkel,+ John MacFarlane).++ * Use commonmark-extensions 0.2.3. This allows a bare-word class attribute+ on fenced divs.++ * Use ipynb 0.2.++ * Use citeproc 0.6.0.1.++ * Use texmath 0.12.4.++ * Use doctemplates 0.10.0.1.++## pandoc 2.16.2 (2021-11-21)++ * Add interface for custom readers written in Lua (#7669).+ Users can now do `-f myreader.lua` and pandoc will treat the+ script `myreader.lua` as a custom reader, which parses an input+ string to a pandoc AST, using the pandoc module defined for+ Lua filters. A sample custom reader can be found in `data/creole.lua`.+ Also see documentation in `doc/custom-readers.md`.++ * New module Text.Pandoc.Readers.Custom, exporting `readCustom` [API change].++ * Allow `plain` to be used in raw attribute syntax.++ * Accept empty `--metadata-file` (#7675).+ This was a regression from 2.15 behavior.++ * Markdown reader: Improve `inlinesInBalancedBrackets`.+ This is just a small improvement in terms of performance, but it's simpler+ and more direct code. Also, we avoid parsing interparagraph spaces in+ balanced brackets, as the original did.++ * BibTeX reader: Properly handle commented lines in BibTeX/BibLaTeX (#7668).++ * RST reader: handle class attribute for for custom roles (#7699,+ willj-dev). Previously the class attribute was ignored, and the name+ of the role used as the class.++ * DocBook reader:++ + Add `<titleabbr>` support (Rowan Rodrik van der Molen).+ + Support for `<indexterm>` (#7607, Rowan Rodrik van der Molen).++ * LaTeX reader:++ + Add rudimentary support for `\autoref` (#7693).+ + Add 'uri' class when parsing `\url`, for consistency+ with treatment of autolinks in other formats (#7672).++ * JATS reader: Capture `alt-text` in figures (#7703, Aner Lucero).++ * MediaWiki writer: use HTML spans for anchors when header has id (#7697).+ We need to generate a span when the header's ID doesn't match+ the one MediaWiki would generate automatically. Note that MediaWiki's+ generation scheme is different from pandoc's (it uses uppercase letters,+ and `_` instead of `-`, for example). This means that in going from+ markdown to mediawiki, we'll now get spans before almost every heading,+ unless explicit identifiers are used that correspond to the ones MediaWiki+ auto-generates. This is uglier output but it's necessary for internal+ links to work properly.++ * Markdown writer: don't create autolinks when this loses information+ (#7692). Previously we sometimes lost attributes when rendering links+ as autolinks.++ * Text.Pandoc.Readers.Metadata: allow multiple YAML documents when parsing+ YAML for `yamlBsToRefs`. Some people use `---` as the end delimiter in+ YAML bibliography files, which causes the `yaml` library to emit an+ error unless we explicitly allow multiple YAML documents (and just+ consider the first).++ * JATS writer:++ + Ensure figures are wrapped with `<p>` in list items+ (Albert Krewinkel). This prevents the generation of invalid output.+ + Add URL to element citation entries (Albert Krewinkel).+ The URL of a reference, if present, is added in tag `<uri>` to+ element-citation entries.++ * HTML writer: Don't create invalid `data-` attribute for empty+ attribute key (#7546).++ * LaTeX writer:++ + Babel mappings: use `ancientgreek` for `grc`.+ + With `-t latex-smart`, don't generate `\ldots` from ellipsis (#7674).+ Instead just use unicode ellipsis.++ * JATS template: fix `equal-contrib` attribute (Albert Krewinkel).+ The standard requires the value to be either `yes` or `no`, but is was+ set to `true` for authors who contributed equally.++ * reveal.js template: Add `disableLayout` variable (Christophe Dervieux).++ * Text.Pandoc.Error: sort errors in `handleError` by exit code+ (Albert Krewinkel).++ * Text.Pandoc.Writers.Shared: Improve toLegacyTable (#7683,+ Christian Despres).++ * Lua subsystem:++ + Include lpeg module (#7649, Albert Krewinkel). Compiles the `lpeg`+ library (Parsing Expression Grammars For Lua) into+ the program. Package maintainers may choose to rely on package+ dependencies to make lpeg available, in which case they can compile+ the with the constraint `lpeg +rely-on-shared-lpeg-library`.+ `lpeg` and `re` are always made available in global variables,+ without the need for a `require`.++ + Set `lpeg` and `re` as globals; allow shared lib access via `require`.+ The `lpeg` and `re` modules are loaded into globals of the respective+ name, but they are not necessarily registered as loaded packages. This+ ensures that++ - the built-in library versions are preferred when setting the globals,+ - a shared library is used if pandoc has been compiled without `lpeg`,+ and+ - the `require` mechanism can be used to load the shared library if+ available, falling back to the internal version if possible and+ necessary.++ + Fix argument order in constructor `pandoc.Cite` (Albert Krewinkel).+ This restores the old behavior; argument order had been switched+ accidentally in pandoc 2.15.++ + Add Pushable instance for `ReaderOptions` (Albert Krewinkel).++ + Allow to pass custom reader options to `pandoc.read` as an+ optional third argument (#7656, Albert Krewinkel).+ The object can either be a table or a ReaderOptions value+ like `PANDOC_READER_OPTIONS`. Creating new ReaderOptions objects is+ possible through the new constructor `pandoc.ReaderOptions`.++ + Display Pandoc values using their native Haskell representation+ (Albert Krewinkel).++ + Require latest hslua (2.0.1) (#7661, #7657, Albert Krewinkel).+ This fixes issues with++ - misleading error messages when a required function parameter is+ omitted;+ - absent properties still being listed in the output of `pairs`; and+ - alias accessing leading to errors instead of returning `nil`, e.g.+ with `(pandoc.Str '').identifier`.++ + Add missing space in "package not found" message (#7658, Albert+ Krewinkel).++ * Update build files (#7696, Fabián Heredia Montiel).+ Drop old windows 32-bit constraints.+ Update cabal `tested-with` field to correspond to `ci.yml` matrix++ * Remove unneeded package dependencies from benchmark target.++ * Require ghc >= 8.6, base >= 4.12.+ This allows us to get rid of the old custom prelude and+ some crufty cpp. But the primary reason for this is that+ conduit has bumped its base lower bound to 4.12, making it+ impossible for us to support lower base versions.++ * Require Cabal 2.4. Use wildcards to ensure that all pptx tests are+ included (#7677).++ * Update `bash_completion.tpl` (S.P.H.).++ * Add `data/creole.lua` as sample custom reader.++ * Add `doc/custom-readers.md` and `doc/custom-writers.md`.++ * `doc/lua-filters.md`: add section on global modules, including lpeg+ (Albert Krewinkel).++ * `MANUAL.txt`: update table of exit codes and corresponding errors+ (Albert Krewinkel).++ * Use latest texmath.++## pandoc 2.16.1 (2021-11-02)+++ * Docx reader: don't let first line indents trigger block quotes (#7655).+ This fixes a regression introduced in pandoc 2.15.++ * Docx writer: use `getTimestamp` for modification times in+ reference.docx (#7654). This ensures that when `SOURCE_DATE_EPOCH` is+ set, the modification times of files taken from the reference.docx will+ be set deterministically, allowing for reproducible builds.++ * Lua subsystem (Albert Krewinkel):++ + Load module `pandoc.path` on startup (#7524). Previously the module+ always had to be loaded via `require 'pandoc.path'`.+ + Fix typo in SoftBreak constructor.+ + Re-add `content` property to Strikeout elements.+ Fixes a regression introduced in 2.15.+ + Be more forgiving when retrieving the Image `caption` property.+ Fixes a regression introduced in 2.15.+ + Display Attr values using their native Haskell representation.+ + Allow omitting the 2nd parameter in pandoc.Code constructor.+ Fixes a regression introduced in 2.15 which required users to always+ specify an Attr value when constructing a Code element.+ + Allow to compare, show Citation values. Comparisons of Citation+ values are performed in Haskell; values are equal if they represent+ the same Haskell value. Converting a Citation value to a string+ now yields its native Haskell string representation.+ + Restore List behavior of MetaList (#7650). Fixes a regression+ introduced in 2.16 which had MetaList elements lose+ the `pandoc.List` properties.+ + Restore `content` property on Header elements.+ + Ensure Block elements have all expected properties.+ + Ensure Inline elements have all expected properties.++ * Allow tasty-bench 0.3.x.++## pandoc 2.16 (2021-10-31)++ * Switch back from HsYAML to yaml for parsing YAML metadata (#6084).+ HsYAML is around 20 times slower in parsing large YAML bibliographies.+ In addition, HsYAML is not being actively maintained. This sets us back+ in our attempts to free ourselves from C dependencies (#4535). But I+ don't see a good alternative until a faster pure Haskell parser is available.+ Notes:++ + We've removed the FromYAML instances for all types that had them, since+ this is a HsYAML-specific typeclass [API change]. (The yaml package just+ uses From/ToJSON instead of having a dedicated From/ToYAML class.)+ + Unlike HsYAML (in the configuration we were using), yaml parses 'Y', 'N',+ 'Yes', 'No', 'On', 'Off' as boolean values. Users may need to quote these+ when they are meant to be interpreted as strings. Similarly, 'null' is+ parsed as a YAML null value (and will be treated as an empty string by+ pandoc rather than the string 'null'). Quoting it will force it to be+ interpreted as a string.+ + Some tests had to be adjusted accordingly.+ + Pandoc now behaves in a more useful way when the YAML metadata contains+ escaping errors: instead of just failng silently and falling back to+ some other interpretation of the section, it raises a YAML parsing error.++ * Markdown writer: Ensure that special values are quoted in YAML metadata.+ These include "Y", "yes", "on", and "off", which are now (with yaml library)+ considered boolean values, as well as "null".++ * Change JSON encodings of some types.++ + For LineEnding use lowercase constructors, e.g. `crlf`, `native`.+ + For HTMLSlideVariant use lowercase constructors.+ + For ReaderOptions use e.g. `default-image-extension`+ instead of `readerDefaultImageExtension` for field names.+ + For Extension, use e.g. `tex_math_dollars` instead of+ `Ext_tex_math_dollars` as constructor.+ + For Extensions, use an array of Extensions, instead of+ an object wrapping the tag `Extensions` and an integer.+ (The integer representation is not supposed to be part of the+ public API.)+ + For Opt, use field names like `tab-stop` instead of `optTabStop`.++ * Docx writer:++ + Add IDs to native_numbering test (Tristan Stenner).+ + Move ": " out of the caption bookmark (Tristan Stenner).+ This is needed so that native references to the figure are included as+ "As seen in Figure X, it is..." instead of "As seen in [Figure: X, it is..."++ * Lua (Albert Krewinkel, except as noted):++ + Use hslua module abstraction where possible.+ + Fix placement of tests for Block elements in pandoc module tests+ + Increase strictness when getting attribute keys+ + Re-add `t` and `tag` property to Attr values.+ Removal of these properties from Attr values was a regression.+ + Fix `pandoc.utils.stringify` regression. The `pandoc.utils.stringify`+ function returned empty strings when called with a string argument.+ + Fix a copy/paste bug in Lua marshalling code (John MacFarlane, #7639).+ This caused links to be changed to figures when Lua filters changed+ link properties.+ + Re-add `content` property to Link elements (#7647).+ This was a regression introduced in version 2.15.+ + Generate constants in module pandoc programmatically.+ + Marshal SimpleTable, ListAttributes, Citation, and Block values as+ userdata objects. Properties of Block values are marshalled lazily,+ which generally improves performance considerably. Script users may also+ notice the following differences:++ - Block element properties can no longer be accessed by numerical+ indexing of the `.c` field. The `.c` property now serves as an alias+ for `.content`, so some filter that used this undocumented method+ for property access may continue to work, while others will need to+ be updated and use proper property names.+ - The marshalled Block elements now have a `show` method, and a+ `__tostring` metamethod. Both return the Haskell string+ representation of the element.+ - Block values now have the Lua type `userdata` instead of `table`.++ * Add a short guide to pandoc's sources (Albert Krewinkel).++ * Fix epub files in epub reader tests, so that they are valid+ according to epubcheck (#7586).++ * Allow time 1.13.++ * Require latest skylighting (0.12.1).++ * Fix build on GHC 9.2 (Joseph C. Sible).++ * Fix trypandoc so it builds with aeson > 2.+++## pandoc 2.15 (2021-10-23)++ * Add `--sandbox` option (#5045).++ + Add sandbox feature. When this option is used, readers and writers+ only have access to input files (and other files specified directly on+ command line). This restriction is enforced in the type system.+ + Filters, PDF production, custom writers are unaffected. This+ feature only insulates the actual readers and writers, not+ the pipeline around them in Text.Pandoc.App.+ + Note that when `--sandboxed` is specified, readers won't have+ access to the resource path, nor will anything have access to+ the user data directory.++ * `--self-contained`: Fix bug that caused everything to be made a data+ URI (#7635, #7367). We only need to use data URIs in certain cases, but+ due to a bug they were being used always.++ * Pandoc will now fall back to latin1 encoding for inputs that can't be+ read as UTF-8. This is what it did previously for content fetched+ from the web and not marked as to content type. It makes sense to do+ the same for local files. In this case a `NotUTF8Encoded` warning+ will be issued, indicating that pandoc is interpreting the input as latin1.++ * Markdown reader:++ + Don't parse links or bracketed spans as citations (#7632).+ Previously pandoc would parse `[link to (@a)](url)` as a+ citation; similarly `[(@a)]{#ident}`. This is undesirable. One should+ be able to use example references in citations, and even if `@a` is+ not defined as an example reference, `[@a](url)` should be a link+ containing an author-in-text citation rather than a normal citation+ followed by literal `(url)`.+ + Fix interaction of `--strip-comments` and list parsing (#7521).+ Use of `--strip-comments` was causing tight lists to be rendered as+ loose (as if the comment were a blank line).+ + Fix parsing bug for math in bracketed spans and links (#7623).+ This affects math with unbalanced brackets (e.g. `$(0,1]$`)+ inside links, images, bracketed spans.+ + Fix code blocks using `--preserve-tabs` (#7573). Previously they+ did not behave as the equivalent input with spaces would.++ * DocBook reader:++ + Honor linenumbering attribute (Samuel Tardieu).+ The attribute DocBook `linenumbering="numbered"` on code blocks+ maps to the `numberLines` class internally.++ * LaTeX reader:++ + Implement siunitx v3 commands (#7614).+ We support `\unit`, `\qty`, `\qtyrange`, and `\qtylist`+ as synonyms of `\si`, `\SI`, `\SIrange`, and `\SIlist`.+ + Properly handle `\^` followed by group closing (#7615).+ + Recognize that `\vadjust` sometimes takes "pre" (#7531).+ + Ignore (and gobble parameters of) CSLReferences environment (#7531).+ Otherwise we get the parameters as numbers in the output.+ + Restrict `\endinput` to current file (Simun Schuster).++ * RST reader: handle escaped colons in reference definitions (#7568).++ * HTML reader:++ + Handle empty tbody element in table (#7589).++ * Ipynb reader (Kolen Cheung):++ + Get cell output mime from `raw_mimetype` in addition to `format`.+ (`format` is what the spec calls for, but `raw_mimetype` is+ often used in practice; see jupyter/nbformat#229).+ + Add more formats that can be handled as "raw" cells.+ + Fix mime type for `rst`.+ + Support `text/markdown`, which is now a supported mime type for raw+ output (#7561).++ * RTF reader:++ + Support `\binN` for binary image data.+ + If doc begins with {\rtf1 ... } only parse its contents.+ Some documents seem to have non-RTF (e.g. XML) material after the+ `{\rtf1 ... }` group.+ + Ignore `\pgdsc` group. Otherwise we get style names treated as test.+ + Better handling of `\*` and bookmarks. We now ensure that groups+ starting with `\*` never cause text to be added to the document.+ In addition, bookmarks now create a span between the start+ and end of the bookmark, rather than an empty span.++ * Docx reader:++ + Avoid blockquote when parent style has more indent (Milan Bracke).+ When a paragraph has an indentation different from the parent (named)+ style, it used to be considered a blockquote. But this only makes sense+ when the paragraph has more indentation. So this commit adds a check+ for the indentation of the parent style.+ + Fix handling of empty fields (Milan Bracke). Some fields only+ have an `instrText` and no content, Pandoc didn't understand these,+ causing other fields to be misunderstood because it seemed like+ a field was still open when it wasn't.+ + Implement PAGEREF fields (Milan Bracke). These fields, often used+ in tables of contents, can be a hyperlink.+ + Fix handling of nested fields (Milan Bracke). Fields delimited by+ `fldChar` elements can contain other fields. Before, the nested+ fields would be ignored, except for the end, which would be+ considered the end of the parent field.+ + Add placeholder for word diagram instead of just omitting it (Ezwal).++ * Org reader:++ + Don't parse a list as first item in a list item (#7557).+ + Allow an initial `:PROPERTIES:` drawer to add to metadata (#7520).++ * Docx writer:++ + Make id used in `native_numbering` predictable (#7551).+ If the image has the id IMAGEID, then we use the id ref_IMAGEID+ for the figure number. This allows one to create a filter that+ adds a figure number with figure name, e.g.+ `<w:fldSimple w:instr=" REF ref_superfig "><w:r><w:t>Figure X</w:t>+ </w:r></w:fldSimple>`.+ If an image lack an id, an id of the form `ref_fig1` is used.+ + Ensure we have unique ids for `wp:docPr` and `pic:cNvPr` elements+ (#7527, #7503).+ + Handle SVG images (#4058). This change has several parts:+ - In Text.Pandoc.App, if the writer is docx, we fill the media+ bag and attempt to convert any SVG images to PNG, adding these+ to the media bag. The PNG backups have the same filenames as+ the SVG images, but with an added .png extension. If the conversion+ cannot be done (e.g. because rsvg-convert is not present),+ a warning is omitted.+ - In Text.Pandoc.Writers.Docx, we now use Word 2016's syntax for+ including SVG images. If a PNG fallback is present in the media bag,+ we include a link to that too.++ * Powerpoint writer (Emily Bourke):++ + Add support for more layouts (#5097). Up til now, four layouts+ were supported: "Title Slide" (used for the automatically generated+ metadata slide), "Section Header" (used for headings above slide+ level), "Two Column" (used when there's a columns div), "Title and+ Content" (used for all other slides). We now support three+ additional layouts: "Comparison", "Content with Caption", and+ "Blank". The manual describes the logic that determines which+ layout is used for a slide. Layouts may be customized in the+ reference doc.+ + Support specifying slide background images using a `background-image`+ attribute on the slide's heading. Only the "stretch" mode is supported,+ and the background image is centred around the slide in the image's+ larger axis, matching the observed default behaviour of PowerPoint.+ + Add support for incremental lists (through same methods as in+ other slide writers) (#5689).+ + Copy embedded fonts from reference doc.+ + Include all themes in output archive.+ + Fix list level numbering (#4828, #4663). In PowerPoint,+ the content of a top-level list is at the same level as the content+ of a top-level paragraph: the only difference is that a list style+ has been applied. Previously, the writer incremented the paragrap+ h level on each list, turning what should be top-level lists into+ second-level lists.+ + Line up list continuation paragraphs. This commit+ changes the `marL` and `indent` values used for plain paragraphs+ and numbered lists, and changes the spacing defined in the+ reference doc master for bulleted lists. For paragraphs, there is+ now a left-indent taken from the `otherStyle` in the master.+ For numbered lists, the number is positioned where the text would be+ if this were a plain paragraph, and the text is indented to the next+ level. This means that continuation paragraphs line up nicely with+ numbered lists. Existing reference docs may need to be modified so+ that `otherStyle` and `bodyStyle` indent levels match, for this+ feature to work with them.+ + Consolidate text runs when possible (jgm). This slims down the output+ files by avoiding unnecessary text run elements.+ + Support footers in the reference doc.+ There is one behaviour which may not be immediately obvious: if the+ reference doc specifies a fixed date (i.e. not automatically updating),+ and there’s a date specified in the metadata for the document, the+ footer date is replaced by the metadata date.+ + Fix presentation rel numbering. Before now, the numbering of `rId`s+ was inconsistent when making the presentation XML and when making+ the presentation relationships XML.+ + Don’t add relationships unnecessarily. Before now, for any layouts+ added to the output from the default reference doc, the relationships+ were unconditionally added to the output. However, if there was already+ a layout in slideMaster1 at the same index then that results in+ duplicate relationships.+ + If slide level is 0, don't insert a slide break between a heading+ and a following table, "columns" div, or paragraph starting+ with an image.+ + Fix capitalisation of `notesMasterId`.+ + Restructure tests.++ * Asciidoc writer:++ + Translate numberLines attribute to `linesnum` switch (Samuel Tardieu).+ + Improve escaping for `--` in URLs (#7529).++ * LaTeX writer:++ + Make babel use more idiomatic (#7604, hseg). Use babel's+ bidi implementation. Import babel languages individually instead+ of as package options. Move `header-includes` to after+ `babel` setup so it can be modified.+ + Use babel, not polyglossia, with xelatex. Previously polyglossia+ worked better with xelatex, but that is no longer the case, so+ we simplify the code so that babel is used with all latex+ engines. This involves a change to the default LaTeX template.++ * Markdown writer:++ + Avoid bad wraps at the Doc Text level. Previously we tried to+ do this at the Inline list level, but it makes more sense to+ intervene on breaking spaces at the Doc Text level.+ + Use `underline` class rather than `ul` for underline.+ This only affects output with `bracketed_spans` enabled.+ The markdown reader parses spans with either `.ul` or `.underline` as+ Underline elements, but we're moving towards preferring the latter.++ * RST writer:++ + Properly handle anchors to ids with spaces or leading underscore+ (#7593). In this cases we need the quoted form, e.g.+ ```+ .. _`foo bar`:++ .. _`_foo`:+ ```+ Side note: rST will "normalize" these identifiers anyway,+ ignoring the underscore.++ * HTML writer:++ + Render `\ref` and `\eqref` as inline math, not display (see #7589).+ + Pass through `\ref` and `\eqref` if MathJax is used (#7587).+ + Pass through inline math environments with KaTeX.+ + Support `--reference-location` for HTML output (#7461,+ Francesco Mazzoli).+ + Set "hash" to True by default (for reveal.js) (#7574). See #6968+ where the motivation for setting "hash" to True is explained.++ * Native writer: Use pretty-show to format native output (#7580).+ Previously we used our own homespun formatting. But this produces+ over-long lines that aren't ideal for diffs in tests.+ Performance is slower by about a factor of 10, but this isn't+ really a problem because native isn't suitable as a serialization+ format. (For serialization you should use json, because the reader+ is so much faster than native.)++ * Org writer:++ + Don't indent contents of code blocks. We previously indented them+ by two spaces, following a common convention. Since the convention+ is fading, and the indentation is inconvenient for copy/paste, we are+ discontinuing this practice.+ + Update list of supported source languages in org writer (#5440).++ * Ipynb writer (Kolen Cheung):++ + Improve round trip identity for raw cell output.+ See jupyter/nbformat#229. The Jupyter ecosystem, including nbconvert,+ lab and notebook, deviated from their own spec in nbformat, where+ they used the key `raw_mimetype` instead of `format`. Moreover,+ the mime-type of rst used in Jupyter deviated from that suggested by+ https://docutils.sourceforge.io/FAQ.html and is defined as+ `text/restructuredtext` when chosen from "Raw NBConvert Format" in+ Jupyter. The new behavior should matche the real world usage better,+ hence improving the round-trip "identity" in raw-cell.+ + Add more formats that can be handled as "raw" cells.++ * EPUB writer:++ + Add EPUB3 subject metadata (authority/term) (nuew).+ This adds the ability to specify EPUB 3 `authority` and `term` specific+ refinements to the `subject` tag. Specifying a plain `subject` tag in+ metadata will function as before.+ + Treat epub:type "frontispiece" as front matter (#7600).++ * reveal.js template: Fix line numbers in source code (#7634).+ We need `overflow: visible` for these to work, and reveal's+ default css disables this. So we re-enable it in the default template.++ * Text.Pandoc.Writers.Shared:++ + Export `splitSentences` as a Doc Text transform [API change].+ Use this in man/ms. We used to attempt automatic sentence+ splitting in man and ms output, since sentence-ending+ periods need to be followed by two spaces or a newline in+ these formats. But it's difficult to do this reliably at+ the level of `[Inline]`.++ * Text.Pandoc.Translations: small revisions for compatibility+ with aeson 2.++ * Don't prepend `file://` to `--syntax-definition` on Windows (#6374).+ This was a fix for a problem in skylighting, but this+ problem doesn't exist now that we've moved from HXT to xml-conduit.++ * Text.Pandoc.Extensions:++ + Add `Ext_footnotes` to default `gfm` etxensions. Now `gfm`+ supports footnotes.+ + Alphabetize Extension constructors (also affects `--list-extensions`).++ * Text.Pandoc.Citeproc.Util: Better implementation of `splitStrWhen`.+ Previously the citeproc code had two less efficient+ implementations.++ * Update documentation for definition_list extension (#7594).+ In 2015, we relaxed indentation requirements for the first+ line of a definition (see commit d3544dc and issue #2087), but+ the documnentation wasn't updated to reflect the change.++ * Text.Pandoc.Citeproc.BibTeX: Fix expansion of special strings in series+ e.g. `newseries` or `library` (#7591). Expansion should not happen+ when these strings are protected in braces, or when they're+ capitalized.++ * Text.Pandoc.Logging: add `NotUTF8Encoded` constructor to `LogMessage`+ [API change].++ * Text.Pandoc.App.FormatHeuristics: remove `.tei.xml` extension for TEI+ (#7630). This never worked, because `takeExtension`+ only returns `.xml`. So it won't be missed if we remove it.++ * Text.Pandoc.Image:++ + Generalize `svgToPng` to MonadIO.+ + `svgToPng`, change first parameter from WriterOptions to Int.++ * Text.Pandoc.Class:++ + Add `readStdinStrict` method to PandocMonad [API change].+ + Generalize type of `extractMedia` [API change].+ It was uselessly restricted to PandocIO, instead of any+ instance of PandocMonad and MonadIO.++ * Text.Pandoc.Class.PandocIO: derive MonadCatch, MonadThrow, MonadMask.+ This allows us to use `withTempDir` [API change].++ * Add module Text.Pandoc.Class.Sandbox, defining+ `sandbox`. Exported via Text.Pandoc.Class. [API change]++ * Text.Pandoc.Filter: Generalize type of `applyFilters`+ from PandocIO to any instance of MonadIO and PandocMonad [API change].++ * Text.Pandoc.PDF: generalize type of `makePDF`:+ instead of PandocIO, it can be used in any instance of+ PandocMonad, MonadIO, and MonadMask [API change].++ * Lua subsystem and custom writers: generalize types from PandocIO+ to any instance of PandocMonad and MonadIO [API change].+ The type of `runLua` is now++ (PandocMonad m, MonadIO m) =>+ LuaE PandocError a -> m (Either PandocError a)++ The change from `Lua` to `LuaE PandocError` is due to the switch to+ hslua-2.0; see next item.++ * Lua modules (Albert Krewinkel):++ + Switch to hslua-2.0. The new HsLua version takes a somewhat different+ approach to marshalling and unmarshalling, relying less on typeclasses+ and more on specialized types. This allows for better performance and+ improved error messages. Furthermore, new abstractions allow to+ document the code and exposed functions.+ + Marshal Version values, Inline elements, Attr elements,+ and Pandoc elements as userdata.+ + Remove deprecated inline constructors `DoubleQuoted`,+ `SingleQuoted`, `DisplayMath`, and `InlineMath`.+ + Attr values are no longer normalized when assigned to an Inline+ element property.+ + It's no longer possible to access parts of Inline elements via+ numerical indexes. E.g., `pandoc.Span('test')[2]` used to give+ `pandoc.Str 'test'`, but yields `nil` now. This was undocumented+ behavior not intended to be used in user scripts. Use named properties+ instead.+ + Accessing `.c` to get a JSON-like tuple of all components no longer+ works. This was undocumented behavior.+ + Only known properties can be set on an element value. Trying to set a+ different property will now raise an error.+ + Adds a new `pandoc.AttributeList()` constructor, which creates the+ associative attribute list that is used as the third component of+ `Attr` values. Values of this type can often be passed to constructors+ instead of `Attr` values.+ + Convert IOErrors to PandocErrors in `pandoc.pipe` function (#7523).++ * Text.Pandoc.PDF: Previously we had to run `runIOorExplode` inside+ `withTempDir`. Now that PandocIO is an instance of MonadMask, this is+ no longer necessary.++ * Text.Pandoc.App:++ + Reorganize to make it easier to limit IO in main loop.+ Previously we used liftIO fairly liberally. The code has+ been restructured to avoid this.+ + Move output-file writing out of PandocMonad action.++ * Text.Pandoc.App.OutputSettings: Generalize some types+ so we can run this with any instance of PandocMonad and MonadIO,+ not just PandocIO.++ * Use `simpleFigure` builder in readers and `SimpleFigure`+ pattern synonym in writers (Aner Lucero).++ * Allow time 1.12.++ * Use skylighting-0.12, skylighting-core-0.12.+ This fixes highlighting issues with typescript, scala, and other+ syntaxes that include keyword lists from different syntaxes.++ * Use citeproc 0.6, commonmark 0.2.2.1, commonmark-extensions 0.2.2,+ texmath 0.12.3.2, ipynb 0.1.0.2. (These changes also allow+ building with aeson >= 2.)++ * Require doclayout >= 0.3.1.1. This fixes recognition of "real widths"+ of emoji characters, which is important for tabular layout.++ * Cut out over 100K of fat in epub test golden files.++ * Make `test/epub/wasteland.epub` valid.++ * Add missing `%` on some command tests.+ This prevented `--accept` from working properly.++ * Command tests: raise error if command doesn't begin with `%`.++ * OOXML tests: use pretty-printed form to display diffs.+ Otherwise everything is on one line and the diff is uninformative.++ * Fix compareXML helper in Tests.Writers.OOXML.+ Given how it is used, we were getting "mine" and "good"+ flipped in the test results.++ * MANUAL.txt:++ + Clarify `attributes` extension support (William Lupton).+ + Document formats affected by `--reference-location`.+ + Document error code 25+ + Add some more info regarding `--slide-level=0` (Salim B).+ + Add more to security section of manual.+ + Mention support of `title-toc` (#7171, Christophe Dervieux).++ * doc/lua-filters.md:++ + Add missing type for Image title (Quinn).+ + Improve order of Image fields (Quinn).+ + Rephrase pandoc.path docs (#7548, Quinn).+ + Do not leak working directory in TikZ filter (Jeroen de Haas).++## pandoc 2.14.2 (2021-08-21)++ * Allow `--slide-level=0` (#7476). When the slide level is set+ to 0, headings won't be used at all in splitting the document+ into slides. Horizontal rules must be used to separate slides.++ * Add RTF reader (#3982). `rtf` is now supported as an input+ format as well as an output format. New module+ Text.Pandoc.Readers.RTF (exporting `readRTF`). [API change]++ * HTML reader: treat comments as blank when parsing (#7482).++ * Markdown reader:++ + Fix raw LaTeX injection issue (#7497). Using a code block+ containing `\end{verbatim}`, one could inject raw TeX into a+ LaTeX document even when `raw_tex` is disabled. Thanks to+ Augustin Laville for noticing the bug.+ + Multimarkdown sub- and superscripts (#5512, OCzarnecki).+ Added an extension `short_subsuperscripts` which modifies+ the behavior of `subscript` and `superscript`, allowing+ subscripts or superscripts containing only alphanumerics+ to end with a space character (eg. `x^2 = 4` or `H~2 is+ combustible`). This improves support for multimarkdown.++ * RST reader: Fix `:literal:` includes (#7513). These should create+ code blocks, not insert raw RST.++ * LaTeX reader:++ + Proper implicit grouping around environment macros.+ + Support `\global` before `\def`, `\let`, etc. (#7494).+ + Fix scope for LaTeX macros (#7494). They should by default+ scope over the group in which they are defined (except `\gdef`+ and `\xdef`, which are global). In addition, environments must+ be treated as groups.+ + Improve handling of plain TeX macro primitives (#7474).+ Fixed semantics for `\let`.+ + Implement `\edef`, `\gdef`, and `\xdef`.++ * Docx reader: Improve docx reader's robustness in extracting+ images (#7511). The docx reader made some assumptions about+ how docx containers were laid out that were not always true, with+ the result that some images in documents did not get+ extracted.++ * LaTeX writer: Increase table column width precision (#7466,+ Peter Fabinski). In some cases, the rounding performed by the+ LaTeX table writer would introduce visible overrun outside+ the text area. This adds two more decimal places to the width+ values.++ * Powerpoint writer:++ + Include image title in description (#7352, Emily Bourke). The+ image title (i.e. ``) was previously+ ignored when writing to pptx. This commit includes it in+ PowerPoint's description of the image, along with the link.+ + Select layouts from reference doc by name (Emily Bourke). Until+ now, users had to make sure that their reference doc contains+ layouts in a specific order: the first four layouts in the file+ had to have a specific structure. Now the layout selection uses+ the layout names rather than order: users must make sure their+ reference doc contains four layouts with specific names, and if+ a layout with the right name isn’t found pandoc will emit+ a warning and use the corresponding layout from the default+ reference doc as a fallback.++ * Docx writer: be sensitive to the `native_numbering` extension+ (#7499). Figure and table numbers are now only included if+ `native_numbering` is enabled. (By default it is disabled.)+ This is a behavior change with respect to 2.14.1, but the+ default behavior is now that of previous versions. The+ change was necessary to avoid incompatibilities between+ pandoc's native numbering and third-party cross reference+ filters like pandoc-crossref.++ * RTF writer:++ + Omit `\bin` in `\pict`. According to the spec, this is not+ needed or wanted when the data is in hexadecimal format, as+ here.+ + Emit `\outlinelevel`` for section headings.++ * RTF template: specify font family for fixed-width font f1.+ According to the spec, this is mandatory.++ * LaTeX writer: Use ulem for underline (#7351). ulem is+ conditionally included already when the `strikeout` variable+ is set, so we set this when there is underlined text, and use+ `\uline` instead of `\underline`. This fixes wrapping for+ underlined text.++ * Text.Pandoc.Citeproc:++ + Revise citeproc code to fit new citeproc 0.5 API (thanks to+ Benjamin Bray). Linkification of URLs in the bibliography+ is now done in the citeproc library, depending on the+ setting of an option. We set that option depending on the+ value of the metadata field `link-bibliography` (defaulting+ to true, for consistency with earlier behavior). If a DOI,+ PMID, PMCID, or URL field is present but not explicitly+ rendered, the title (or if no title, the whole entry) is+ hyperlinked. These changes implement the recommendations+ from the draft CSL v1.0.2 spec (Appendix VI):+ <https://github.com/citation-style-language/documentation/blob/master/specification.rst#appendix-vi-links>+ + Avoid odd handling of quotes. Recent citeproc changes+ allow us to ignore Quoted elements; citeproc now uses its own+ method for represented quoted things, and only localizes and+ flipflops quotes it adds itself. Convert Quoted in bib+ entries to special Spans before passing them off to+ citeproc. This ensures that we get proper localization and+ flipflopping if, e.g., quotes are used in titles+ (jgm/citeproc#87).+ + Removed quote localization from citeproc processing.+ This is now done in citeproc itself.++ * Text.Pandoc.Logging: Add PowerpointTemplateWarning log message+ type [API change] (Emily Bourke).++ * Text.Pandoc.Extension: Add `Ext_short_subsuperscripts`+ constructor to `Extension` [API change] (OCzarnecki).++ * Various sample.lua editorial fixes (#7493, #7487, William+ Lupton).++ * Bump base-compat version so we get compatibility with base 4.12.++ * Use Prelude from base-compat for ghc 8.4 too.++ * Add haskell-language-server to shell.nix (#7496, Emily Bourke).++ * Tests.Helpers: export testGolden and use it in RTF reader.+ This gives a diff output on failure.++ * Remove obsolete and incorrect sentence in `--slide-level` docs.++ * Add internal module Text.Pandoc.Network.HTTP, exporting+ `urlEncode`.++ * Text.Pandoc.Parsing: `parseFromString`: preserve at least+ the source directory (#7464). Previously we just set the+ source name to "chunk" when parsing from strings, to avoid+ misleading source positions. This had the side effect that+ `rebase_relative_paths` would break inside sections that+ were parsed as strings. So, now we use+ "ORIGINAL_SOURCE_PATH_chunk" instead of just "chunk".++ * Text.Pandoc.MIME: use image/x-xcf instead of application/x-xcf+ (#7454).++ * Don’t compare `cdLine` in OOXML golden tests (Emily Bourke).+ The `cdLine` field gives the line of the file some CData was+ found on, which reflects irrelevant formatting differences.++ * Provide more detailed XML diff in tests (Emily Bourke).++ * OOXML tests: silence warnings. These can make the test output+ confusing, making people think tests are failing when they're+ passing.++ * INSTALL.md: Add GitLab CI/CD example (#7448, Veratyr).++ * MANUAL.txt++ - Clarifications (William Lupton).+ - Add a note on security risks of include directives.++ * Document use of the 'underline' class (#7492, #7484, William+ Lupton).++ * Add a FAQ about the "Cannot allocate memory" error on M1 macs.++ * Use texmath 0.12.3.1.++ * Use released citeproc 0.5.++ * Remove dependency on HTTP package (#7456, mt_caret).++## pandoc 2.14.1 (2021-07-18)++ * Text.Pandoc.ImageSize: Add Tiff constructor for ImageType (#7405)+ [Minor API change]. This allows pandoc to get size information from+ tiff images.++ * Markdown reader: don't try to read contents in self-closing HTML tag.+ Previously we had problems parsing raw HTML with self-closing+ tags like `<col/>`. The problem was that pandoc would look+ for a closing tag to close the markdown contents, but the+ closing tag had, in effect, already been parsed by `htmlTag`.++ * LaTeX reader:++ + Avoid trailing hyphen in translating languages (#7447).+ Previously `\foreignlanguage{english}` turned into `<span lang="en-">`.+ The same issue affected Arabic.+ + Support `\cline` in LaTeX tables (#7442).+ + Improved parsing of raw LaTeX from Text streams (`rawLaTeXParser`,+ used to read LaTeX in Markdown files, #7434). We now use source+ positions from the token stream to tell us how much of the text stream+ to consume. Getting this to work required a few other changes to+ make token source positions accurate.++ * DocBook reader:++ + Handle images with imageobjectco elements (#7440).+ + Add support for citerefentry (#7437, Jan Tojnar).++ * RST reader: fix regression with code includes (#7436).+ With the recent changes to include infrastructure,+ included code blocks were getting an extra newline.++ * HTML reader:++ + Recognize data-external when reading HTML img tags (#7429,+ Michael Hoffmann). Preserve all attributes in img tags. If attributes+ have a `data-` prefix, it will be stripped. In particular, this+ preserves a `data-external` attribute as an `external` attribute in+ the pandoc AST.+ + Add col, colgroup to 'closes' definitions++ * HTML writer:++ + Remove duplicated alt text in HTML output (Aner Lucero).+ + Remove `aria-hidden` when explicit alt text is provided (Aner Lucero).+ + Set boolean values for reveal.js variables.++ * Docx writer:++ + Add table numbering for captioned tables.+ The numbers are added using fields, so that Word can+ create a list of tables that will update automatically.+ + Support figure numbers. These are set up in such a way that they+ will work with Word's automatic table of figures (#7392).++ * Markdown writer: put space between Plain and following fenced Div+ (#4465).++ * EPUB writer: Don't incorporate externally linked images in EPUB documents+ (#7430, Michael Hoffmann). Just as it is possible to avoid incorporating+ an image in EPUB by passing `data-external="1"` to a raw HTML snippet,+ this makes the same possible for native Images, by looking for an+ associated `external` attribute.++ * Text.Pandoc.PDF:++ + Fix `svgIn` path error (#7431). We were duplicating+ the temp directory; this didn't cause problems on macOS or linux+ because there we use absolute paths for the temp directory.+ But on Windows it caused errors converting SVG files.+ + `convertImage`: normalize paths (#7431). This will avoid paths+ on Windows with mixed path separators.++ * Text.Pandoc.Class: Always use / when adding directory to image destination+ with `extractMedia`, even on Windows.++ * Text.Pandoc.Citeproc:++ + Allow `$` characters in bibtex keys (#7409).+ + Set proper initial source name in parsing BibTeX (for better error+ messages.)+ + Revamp note citation handling (#7394). Use latest+ citeproc, which uses a Span with a class rather than a Note for notes.+ This helps us distinguish between user notes and citation notes. Don't+ put citations at the beginning of a note in parentheses. Fix small bug+ in handling of citations in notes, which led to commas at the end of+ sentences in some cases.+ + Cleanup and efficiency improvement in `deNote`.+ + Improve punctuation moving with `--citeproc`. Previously, using+ `--citeproc` could cause punctuation to move in quotes even when+ there aer no citations. This has been changed; punctuation moving+ is now limited to citations. In addition, we only move footnotes+ around punctuation if the style is a note style, even if+ `notes-after-punctuation` is `true`.++ * Use citeproc 0.10. This helps improve note citations (see above)+ and eliminates double hyperlinks in author-in-text citations.+ Author-only citations are no longer hyperlinked. See jgm/citeproc#77.+ It also fixes moving of punctuation inside quotes to conform to+ the CSL spec: only comma and period are moved, not question+ mark or exclamation point.++ * Text.Pandoc.Error: fix line calculations in reporting parsec errors.+ Also remove a spurious initial newline in the error report.++ * Use doctemplates 0.4.1, which gives us better support for boolean+ variable values. Previously `$if(foo)$` would evaluate to true+ for variables with boolean `false` values, because it cared only+ about the string rendering (#7402).++ * Require commonmark-pandoc >= 0.2.2.1.+ This fixes task lists with multiple paragraphs.++ * Use skylighting 0.11.++ * CSS in HTML template: reset overflow-wrap on code blocks+ (Mauro Bieg, #7423).++ * LaTeX template: Revert change in PR #7295: "move title, author, date up+ to top of preamble." The change caused problem for people who used+ LaTeX commands defined defined later in the preamble in the title+ or author fields (#7422).++ * Add `doc/faqs.md`. This is imported from the website; in the future the+ website version will be drawn from here.+ Added a FAQ on the use of `\AtEndPreamble` for cases when the contents of+ `header-includes` need to refer to definitions that come later in the+ preamble. See #7422.++ * Upgrade Debian 10 AMI for build-arm.sh.++ * CircleCI: change to using xcode 11.1.0 (macOS 10.14.4).+ We previously built on 10.13, but 10.13 no longer gets+ security updates and CirclCI is deprecating.++## pandoc 2.14.0.3 (2021-06-22)++ * Text.Pandoc.MediaBag `insertMediaBag`: ensure we get a sane mediaPath+ for URLs (#7391). In earlier 2.14.x versions, we'd get+ incorrect paths for resources downloaded from URLs when the+ media are extracted (including in PDF production).+ * Text.Pandoc.Parsing: improve `emailAddress` (#7398).+ Previously the parser would accept characters in domains+ that are illegal in domains, and this sometimes caused it+ to gobble bits of the following text.+ * txt2tags reader: modify the email address parser so+ it still includes form parameters, even after the change to+ `emailAddress` in Text.Pandoc.Parsing.+ * Text.Pandoc.Readers.Metadata: Fix regression with comment-only YAML+ metadata blocks (#7400).+ * reveal.js writer and template: better handling of options. Previously+ it was impossible to specify false values for options that default to+ true (e.g. `center`); setting the option to false just caused the portion+ of the template setting the option to be omitted. Now we prepopulate+ all the variables with their default values, including them all+ unconditionally and allowing them to be overridden.+ * Markdown writer: Fix regression in code blocks with attributes (#7397).+ Code blocks with a single class but nonempty attributes+ were having attributes drop as a result of #7242.+ * LaTeX writer:+ + Add strut at end of minipage if it contains line breaks.+ Without them, the last line is not as tall as it should be in+ some cases.+ + Always use a minipage for cells with line breaks, when+ width information is available (#7393). Otherwise the way we treat them+ can lead to content that overflows a cell.+ + Use `\strut` instead of `~` before `\\` in empty line.+ * Use lts-18.0 stack resolver.+ * Require skylighting 0.10.5.2 (adding support for Swift).+ * Require commonmark 0.2.1.+ * Rephrase section on unsafe HTML in manual.+ * Create SECURITY.md++## pandoc 2.14.0.2 (2021-06-13)++ * Fix MediaBag regressions (#7345). iIn the 2.14 release `--extract-media`+ stopped working as before; there could be mismatches between the+ paths in the rendered document and the extracted media.+ This patch makes several changes that restore the earlier behavior+ (while keeping the same API). The `mediaPath` in 2.14 was always+ constructed from the SHA1 hash of the media contents. Now, we+ preserve the original path unless it's an absolute path or contains+ `..` segments (in that case we use a path based on the SHA1 hash of+ the contents).++ In Text.Pandoc.MediaBag, `mediaDirectory` and `mediaItems` now use the+ `mediaPath`, rather than the mediabag key, for the first component of the+ tuple. This makes more sense, I think, and fits with the documentation of+ these functions; eventually, though, we should rework the API so that+ `mediaItems` returns both the keys and the MediaItems.++ In Text.Pandoc.Class.IO, rewriting of source paths in `extractMedia` has+ been fixed.++ In Text.Pandoc.Class.PandocMonad, `fillMediaBag` has been modified so that+ it doesn't modify image paths (that was part of the problem in #7345).++ We now do path normalization (e.g. `\` separators on Windows) in+ writing the media.++ * Text.Pandoc.PDF:++ + Text.Pandoc.PDF: Fix regression in 2.14 for generation of PDFs with+ SVGs (#7344).+ + Only print relevant part of environment on `--verbose`. Since+ `--verbose` output might be put in an issue, we want to avoid+ spilling out secrets in environment variables.++ * Markdown reader: fix pipe table regression in 2.11.4 (#7343).+ Previously pipe tables with empty headers (that is, a header+ line with all empty cells) would be rendered as headerless+ tables. This broke in 2.11.4. The fix here is to produce an+ AST with an empty table head when a pipe table has all empty+ header cells.++ * LaTeX reader: don't allow optional `*` on symbol control sequences+ (#7340). Generally we allow optional starred variants of LaTeX commands+ (since many allow them, and if we don't accept these explicitly,+ ignoring the star usually gives acceptable results). But we+ don't want to do this for `\(*\)` and similar cases.++ * Docx reader: handle absolute URIs in Relationship Target (#7374).++ * Docx writer: fix handling of empty table headers (Albert Krewinkel,+ #7369). A table header which does not contain any cells is now treated as+ an empty header.++ * LaTeX writer: Fix regression in table header position (#7347).+ In recent versions the table headers were no longer bottom-aligned+ (if more than one line). This patch fixes that by using minipages+ for table headers in non-simple tables.++ * CommonMark writer:++ + Do not use simple class for fenced-divs (Jan Tojnar, amends #7242.)+ + Do not throw away attributes when `Ext_attributes` is enabled.+ `Ext_attributes` covers at least the following:+ `Ext_fenced_code_attributes`, `Ext_header_attributes`,+ `Ext_inline_code_attributes`, `Ext_link_attributes`.++ * Markdown writer:++ + Allow `pipe_tables` to be disabled for commonmark formats+ (`commonmark_x`, `gfm`) (#7375).+ + Re-use functions from Text.Pandoc.Markdown.Inline (Jan Tojnar).++ * DocBook writer: Remove non-existent admonitions (Jan Tojnar).+ `attention`, `error` and `hint` are reStructuredText specific.++ * HTML writer: Don't omit width attribute on div (#7342).++ * Text.Pandoc.MIME, `extensionFromMimeType`: add a few special cases.+ When we do a reverse lookup in the MIME table, we just get the+ last match, so when the same mime type is associated with several+ different extensions, we sometimes got weird results, e.g. `.vs`+ for `text/plain`. These special cases help us get the most standard+ extensions for mime types like `text/plain`.++ * Lua utils: fix handling of table headers in `from_simple_table` (Albert+ Krewinkel, #7369). Passing an empty list of header cells now results+ in an empty table header.++ * Text.Pandoc.Citeproc:++ + Avoid duplicate classes and attributes on references div.+ + Fix regression in citeproc processing (#7376). If inline+ references are used (in the metadata `references` field), we+ should still only include in the bibliography items that are+ actually cited (unless `nocite` is used).++ * Require citeproc 0.4.0.1. This fixes a bug which led to doubled+ "et al." in some (rare) circumstances.++ * MANUAL.txt:++ + Mention GladTeX for EPUB export (Sebastian Humenda).+ This updates the manual and the web site about the GladTeX usage.+ + More details and a useful link for YAML syntax.++ * CONTRIBUTING.md: update modules overview (Albert Krewinkel).++ * using-the-pandoc-api.md: switch from String to Text (Albert Krewinkel).+++## pandoc 2.14.0.1 (2021-06-01)++ * Commonmark reader: Fix regression in 2.14 with YAML metdata block parsing,+ which could cause the document body to be omitted after metadata (#7339).++ * HTML reader: fix column width regression in 2.14 (#7334).+ Column widths specified with a style attribute were off by a factor of 100.++ * Markdown reader: in `rebasePaths`, check for both Windows and Posix+ absolute paths. Previously Windows pandoc was treating+ `/foo/bar.jpg` as non-absolute.++ * Text.Pandoc.Logging: In rendering `LoadedResource`, use relative paths.++ * Docx writer: fix regression on captions (#7328). The "Table Caption"+ style was no longer getting applied. (It was overwritten by "Compact.")++ * Use commonmark-extensions 0.2.1.2++## pandoc 2.14 (2021-05-28)++ * Change reader types, allowing better tracking of source positions+ [API change]. Previously, when multiple file arguments were provided,+ pandoc simply concatenated them and passed the contents to the readers,+ which took a Text argument. As a result, the readers had no way of knowing+ which file was the source of any particular bit of text. This meant that+ we couldn't report accurate source positions on errors or include accurate+ source positions as attributes in the AST. More seriously, it meant that+ we couldn't resolve resource paths relative to the files containing them+ (see e.g. #5501, #6632, #6384, #3752).++ * Add `rebase_relative_paths` extension (#3752). When enabled, this+ extension rewrites relative image and link paths by prepending+ the (relative) directory of the containing file. This+ behavior is useful when your input sources are split+ into multiple files, across several directories, with files+ referring to images stored in the same directory. The+ extension can be enabled for all markdown and commonmark-based formats.++ * Add Text.Pandoc.Sources (exported module), with a `Sources` type and a+ `ToSources` class. A `Sources` wraps a list of `(SourcePos, Text)` pairs+ [API change]. A parsec `Stream` instance is provided for `Sources`. The+ module also exports versions of parsec's `satisfy` and other Char parsers+ that track source positions accurately from a `Sources` stream (or any+ instance of the new `UpdateSourcePos` class).++ * Text.Pandoc.Parsing++ + Export the modified Char parsers defined in Text.Pandoc.Sources+ instead of the ones parsec provides. Modified parsers to use a+ `Sources` as stream [API change].+ + Improve include file functions [API change]. Remove old+ `insertIncludedFileF`. Give `insertIncludedFile` a more general type,+ allowing it to be used where `insertIncludedFileF` was.+ + Add parameter to the `citeKey` parser from+ Text.Pandoc.Parsing, which controls whether the `@{..}`+ syntax is allowed [API change].++ * Text.Pandoc.Error: Modified the constructor `PandocParsecError` to take a+ `Sources` rather than a `Text` as first argument, so parse error locations+ can be accurately reported.++ * Fix source position reporting for YAML bibliographies (#7273).++ * Issue error message when reader or writer format is malformed+ (#7231). Previously we exited with an error status but (due to a bug)+ no message.++ * Smarter smart quotes (#7216, #2103). Treat a leading `"` with no+ closing `"` as a left curly quote. This supports the practice, in+ fiction, of continuing paragraphs quoting the same speaker without an+ end quote. It also helps with quotes that break over lines in line blocks.++ * Markdown reader:++ + Use MetaInlines not MetaBlocks for multimarkdown metadata fields.+ This gives better results in converting to e.g. pandoc markdown.+ + Implement curly-brace syntax for Markdown citation keys (#6026).+ The change provides a way to use citation keys that contain+ special characters not usable with the standard citation key syntax.+ Example: `@{foo_bar{x}'}` for the key `foo_bar{x}`. It also allows+ separating citation keys from immediately following text, e.g. `@{foo}A`.++ * RST reader:++ + Seek include files in the directory of the file+ containing the include directive, as RST requires (#6632).+ + Use `insertIncludedFile` from Text.Pandoc.Parsing+ instead of reproducing much of its code.++ * Org reader: Resolve org includes relative to the directory containing the+ file containing the INCLUDE directive (#5501).++ * ODT reader: Treat tabs as spaces (#7185, niszet).++ * Docx reader:++ + Add handling of vml image objects (#7257, mbrackeantidot).+ + Support new table features (Emily Bourke, #6316): column+ spans, row spans, multiple header rows, table description+ (parsed as a simple caption), captions, column widths.++ * LaTeX reader:++ + Improved siunitx support (#6658, #6620).+ + Better support for `\xspace` (#7299).+ + Improve parsing of `\def` macros. We previously set "verbatim mode"+ even for parsing the initial `\def`; this caused problems+ for `\def` nested inside another `\def`.+ + Implement `\newif`.++ * ConTeXt writer: improve ordered lists (#5016, Denis Maier).+ Change ordered list from itemize to enumerate. Add new+ itemgroup for ordered lists. Remove manual insertion of+ width attributes. Use tabular figures in ordered list+ enumerators.++ * HTML reader:++ + Don't fail on unmatched closing "script" tag (Albert Krenkel, #7282).+ + Keep h1 tags as normal headers (#2293, Albert Krewinkel).+ The tags `<title>` and `<h1 class="title">` often contain the same+ information, so the latter was dropped from the document. However, as+ this can lead to loss of information, the heading is now always+ retained. Use `--shift-heading-level-by=-1` to turn the `<h1>`+ into the document title, or a filter to restore the previous behavior.+ + Handle relative lengths (e.g. `2*`) in HTML column widths (#4063).+ See <https://www.w3.org/TR/html4/types.html#h-6.6>.++ * DocBook/JATS readers:++ + Fix mathml regression caused by the switch in XML libraries (#7173).+ + Fix "phrase" in DocBook: take classes from "role" not "class" (#7195).++ * DocBook reader: ensure that first and last names are separated (#6541).++ * Jira reader (Albert Krewinkel, #7218):++ + Support "smart" links: `[alias|https://example.com|smart-card]` syntax.+ + Allow spaces and most unicode characters in attachment links.+ + No longer require a newline character after `{noformat}`.+ + Only allow URI path segment characters in bare links.+ + The `file:` schema is no longer allowed in bare links; these+ rarely make sense.++ * Plain writer: handle superscript unicode minus (#7276).++ * LaTeX writer:++ + Better handling of line breaks in simple tables (#7272).+ Now we also handle the case where they're embedded in other elements,+ e.g. spans.+ + For beamer output, support `exampleblock` and `alertblock` (#7278).+ A block will be rendered as an `exampleblock` if the heading+ has class `example` and an `alertblock` if it has class `alert`.+ + Separate successive quote chars with thin space (#6958,+ Albert Krewinkel). Successive quote characters are separated with+ a thin space to improve readability and to prevent unwanted ligatures.+ Detection of these quotes sometimes had failed if the second quote+ was nested in a span element.+ + Separate successive quote chars with thin space (#6958, Albert+ Krewinkel).++ * EPUB Writer: Fix belongs-to-collection XML id choice (#7267, nuew).+ The epub writer previously used the same XML id for both the book+ identifier and the epub collection. This causes an error on epubcheck.++ * BibTeX/BibLaTeX writer: Handle `annote` field (#7266).++ * ZimWiki writer: allow links and emphasis in headers (#6605,+ Albert Krewinkel).++ * ConTeXt writer:++ + Support blank lines in line blocks (#6564, Albert Krewinkel,+ thanks to @denismaier).+ + Use span identifiers as reference anchors (#7246, Albert Krewinkel).++ * HTML writer:++ + Keep attributes from code nested below `pre` tag (#7221,+ Albert Krewinkel). If a code block is defined with `<pre><code+ class="language-x">…</code></pre>`, where the `<pre>` element has no+ attributes, then the attributes from the `<code>` element are used+ instead. Any leading `language-` prefix is dropped in the code's+ `class` attribute are dropped to improve syntax highlighting.+ + Ensure headings only have valid attribs in HTML4 (#5944, Albert+ Krewinkel).+ + Parse `<header>` as a Div (Albert Krewinkel).++ * Org writer:++ + Inline latex envs need newlines (#7252, tecosaur).+ As specified in https://orgmode.org/manual/LaTeX-fragments.html, an+ inline \begin{}...\end{} LaTeX block must start on a new line.+ + Use LaTeX style maths deliminators (#7196, tecosaur).++ * JATS writer (Albert Krewinkel):++ + Use either styled-content or named-content for spans (#7211).+ If the element has a content-type attribute, or at least one class,+ then that value is used as `content-type` and the span is put inside+ a `<named-content>` element. Otherwise a `<styled-content>` element+ is used instead.+ + Reduce unnecessary use of `<p>` elements for wrapping (#7227).+ The `<p>` element is used for wrapping in cases were the contents+ would otherwise not be allowed in a certain context. Unnecessary+ wrapping is avoided, especially around quotes (`<disp-quote>` elements).+ + Convert spans to `<named-content>` elements (#7211). Spans with+ attributes are converted to `<named-content>` elements instead of+ being wrapped with `<milestone-start/>` and `<milestone-end>`+ elements. Milestone elements are not allowed in documents using the+ articleauthoring tag set, so this change ensures the creation of valid+ documents.+ + Add footnote number as label in backmatter (#7210). Footnotes in the+ backmatter are given the footnote's number as a label. The+ articleauthoring output is unaffected from this change, as footnotes+ are placed inline there.+ + Escape disallows chars in identifiers. XML identifiers must start+ with an underscore or letter, and can contain only a limited set+ of punctuation characters. Any IDs not adhering to these rules are+ rewritten by writing the offending characters as `Uxxxx`,+ where `xxxx` is the character's hex code.++ * Jira writer: use `{color}` when span has a color attribute+ (Albert Krewinkel, tarleb/jira-wiki-markup#10).++ * Docx writer:++ + Autoset table width if no column has an explicit width (Albert+ Krewinkel).+ + Extract Table handling into separate module (Albert Krewinkel).+ + Support colspans and rowspans in tables (Albert Krewinkel, #6315).+ + Support multirow table headers (Albert Krewinkel).+ + Improve integration of settings from reference.docx (#1209).+ This change allows users to create a reference.docx that+ sets `w:proofState` for spelling or grammar to `dirty`,+ so that spell/grammar checking will be triggered on the+ generated docx.+ + Copy over more settings from reference.docx (#7240). From settings.xml+ in the reference-doc, we now include: `zoom`, `embedSystemFonts`,+ `doNotTrackMoves`, `defaultTabStop`, `drawingGridHorizontalSpacing`,+ `drawingGridVerticalSpacing`, `displayHorizontalDrawingGridEvery`,+ `displayVerticalDrawingGridEvery`, `characterSpacingControl`,+ `savePreviewPicture`, `mathPr`, `themeFontLang`, `decimalSymbol`,+ `listSeparator`, `autoHyphenation`, `compat`.+ + Set zoom to 100% by default in settings.xml.+ + Align math options more with current Word defaults (e.g. Cambria Math+ font).+ + Remove `rsid`s from default settings.xml. Word will add these+ when revisions are made.++ * Ms writer: Handle tables with multiple paragraphs (#7288).+ Previously they overflowed the table cell width. We now set line lengths+ per-cell and restore them after the table has been written.++ * Markdown writer:++ + Use cleaner braceless syntax for code blocks with a+ single class (#7242, Jan Tojnar).+ + Add quotes properly in markdown YAML metadata fields (#7245).+ This fixes a bug, which caused the writer to look at the *last*+ rather than the *first* character in determining whether quotes+ were needed. So we got spurious quotes in some cases and+ didn't get necessary quotes in others.+ + Use `@{..}` syntax for citations when needed.+ + Use fewer unneeded escapes for `#` (see #6259).+ + Improve escaping of `@`. We need to escape literal `@` before+ `{` because of the new citation syntax.++ * Commonmark writer: Use backslash escapes for `<` and `|`...+ instead of entities (#7208).++ * Powerpoint writer: allow `monofont` to be specified in metadata+ (#7187).++ * LaTeX template:++ + Use non-starred names for xcolor color names (#6109).+ This should make svgnames and x11names work properly.+ + Fix bad vertical spacing after bibliography (#7234, badumont).+ + List of figures before list of tables (#7235, Julien Dutant).+ + Move CSL macro definitions before header-includes so they can be+ overridden (#7286).+ + Improve treatment of CSL `entry-spacing` (#7296).+ Previously with the default template settings (`indent` variable+ not set), we would get interparagraph spaces separating bib+ entries even with `entry-spacing="0"`. On the other hand,+ setting `entry-spacing="2"` gave ridiculously large spacing.+ This change makes the spacing caused by `entry-spacing` a multiple+ of `\parskip` by default, which gives aesthetically reasonable+ output. Those who want a larger or smaller unit (e.g. because+ they use `indent` which sets `\parskip` to 0) may+ `\setlength{\cslentryspacingunit}{10pt}` in header-includes+ to override the defaults.+ + Move title, author, date up to top of preamble (#7295).+ This allows header-includes to use them, and puts them+ in a position where you can see them immediately.+ + Define commands for zero width non-joiner character+ (#6639, Albert Krewinkel). The zero-width non-joiner character+ is used to avoid ligatures (e.g. in German).++ * ConTeXt template:++ + Define `enumerate` itemgroup (#5016, Denis Maier).+ + List of figures before list of tables (#7235, Julien Dutant).++ * reveal.js template:++ + Support `toc-title` (#7171, Florian Kohrt).+ + Use `hash: true` by default rather than `history: true` (#6968).++ * HTML-based slide shows: add support for `institute` (#7289, Thomas+ Hodgson).++ * Text.Pandoc.Extensions: Add constructor `Ext_rebase_relative_paths` to+ `Extensions` [API change].++ * Text.Pandoc.XML.Light: add Eq, Ord instances for Content,+ Element, Attr, CDataKind [API change].++ * Text.Pandoc.MediaBag:++ + Change type to use a `Text` key instead of `[FilePath]`.+ We normalize the path and use `/` separators for consistency.+ + Export `MediaItem` type [API change].+ + Change `MediaBag` type to a map from Text to MediaItem [API change].+ + `lookupMedia` now returns a `MediaItem` [API change].+ + Change `insertMedia` so it sets the `mediaPath` to a filename based on+ the SHA1 hash of the contents. This will be used when contents+ are extracted.++ * Text.Pandoc.Class.PandocMonad:++ + Remove `fetchMediaResource` [API change]. Use `fetchItem` to get+ resources in `fillMediaBag`.+ + Add informational message in `downloadOrRead` indicating what path+ local resources have been loaded from.++ * Text.Pandoc.Logging:++ + Remove single quotes around paths in messages.+ + Add LoadedResource constructor to LogMessage [API change].+ This is for INFO-level messages telling where image data has been+ loaded from. (This can vary because of the resource path.)++ * Text.Pandoc.Asciify: simplify code and export `toAsciiText` [API change].+ Instead of encoding a giant (and incomplete) map, we now+ just use unicode-transforms to normalize the text to+ a canonical decomposition, and manipulate the result.++ * App: allow tabs expansion even if file-scope is used (Albert Krewinkel,+ #6709). Tabs in plain-text inputs are now handled correctly, even if+ the `--file-scope` flag is used.++ * Add new internal module Text.Pandoc.Writers.GridTable (Albert Krewinkel).++ * Text.Pandoc.Highlighting: Change type of `languagesByExtension`, adding+ a parameter for a `SyntaxMap` [API change] (Jan Tojnar, #7241).+ Languages defined using `--syntax-definition` were not recognized by+ `languagesByExtension`. This patch corrects that, allowing the writers+ to see all custom definitions. The LaTeX writer still uses the default+ syntax map, but that's okay in that context, since+ `--syntax-definition` won't create new listings styles.++ * Text.Pandoc.Citeproc:++ + Ensure that CSL-related attributes are passed on to a Div with id+ 'refs'. Otherwise things like `entry-spacing` won't work when+ such Divs are used.+ + Use metadata's `lang` for the lang parameter of citeproc, overriding+ `localeLanguage`.+ + Recognize locators spelled with a capital letter (#7323).+ + Add a comma and a space in front of the suffix if it doesn't start+ with space or punctuation (#7324).+ + Don't detect math elements as locators (#7321).++ * Remove Text.Pandoc.BCP47 module [API change]. Use types and functions+ from UnicodeCollation.Lang instead. This is a richer implementation+ of BCP 47.++ * Text.Pandoc.Shared:++ + Fix regression in grid tables for wide characters (#7214).+ In the translation from String to Text, a char-width-sensitive+ `splitAt'` was dropped. This commit reinstates it and uses it to make+ `splitTextByInstances` char-width sensitive.+ + Add `getLang` (formerly in the now-removed BCP47) [API change].++ * Text.Pandoc.SelfContained: use `application/octet-stream`+ for unknown mime types instead of halting with an error (#7202).++ * Lua filters: respect Inlines/Blocks filter functions in `pandoc.walk_*`+ (Albert Krewinkel).++ * Add text as build-depend for trypandoc (#7193, Roman Beránek).++ * Bump upper-bounds for network-uri, time, attoparsec.++ * Use citeproc 0.4.++ * Use texmath 0.12.3.++ * Use jira-wiki-markup 1.3.5 (Albert Krewinkel).++ * Require latest skylighting (fixes a bug in XML syntax highlighting).++ * Use latest xml-conduit.++ * Use latest commonmark, commonmark-extensions, commonmark-pandoc.++ * Use haddock-library-1.10.0 (Albert Krewinkel).++ * Allow compilation with base 4.15 (Albert Krewinkel).++ * MANUAL:++ + Add information about `lang` and bibliography sorting.+ + Add info about YAML escape sequences, link to spec (#7152,+ Albert Krewinkel).+ + Note that `institute` variable works for HTML-based slides.+ + Update documentation on citation syntax.+ + Add citation example for locators and suffixes (Tristan Stenner)++ * Updated and fixed typos in documentation (Charanjit Singh,+ Anti-Distinctlyminty, Tatiana Porras, obcat).++ * Add instructions for installing pandoc-types before compiling filter.++ * INSTALL: add note that parallel installations should be avoided+ (#6865).++ * Remove `biblatex-nussbaum.md` test. It is basically the same+ as `biblaetx-quotes.md`.++ * Command tests: fail if a file contains no tests---and fix a+ test that failed in that way!++ * Use smaller images in tests, reducing the size of the source tarball by 8 MB.+++## pandoc 2.13 (2021-03-21)++ * Support `yaml_metadata_block` extension for `commonmark`, `gfm` (#6537).+ This supported is a bit more limited than with pandoc's+ `markdown`. The YAML block must be the first thing in the input,+ and the leaf notes are parsed in isolation from the rest of+ the document. So, for example, you can't use reference+ links if the references are defined later in the document.++ * Fix fallback to default partials when custom templates are used.+ If the directory containing a template does not contain the partial,+ it should be sought in the default templates, but this was not+ working properly (#7164).++ * Handle `nocite` better with `--biblatex` and `--natbib` (#4585).+ Previously the nocite metadata field was ignored with these formats.+ Now it populates a `nocite-ids` template variable and causes a+ `\nocite` command to be issued.++ * Text.Pandoc.Citeproc: apply `fixLinks` correctly (#7130). This is code+ that incorporates a prefix like `https://doi.org/` into a following link+ when appropriate.++ * Text.Pandoc.Shared:++ + Remove `backslashEscapes`, `escapeStringUsing` [API change]. Replace+ these inefficient association list lookups with more efficient escaping+ functions in the writers that used them (for a 10-25% performance boost+ in org, haddock, rtf, texinfo writers).+ + Remove `ToString`, `ToText` typeclasses [API change]. These were needed+ for the transition from String to Text, but they are no longer used and+ may clash with other things.+ + Simplify `compactDL`.++ * Text.Pandoc.Parsing:++ + Change type of `readWithM` so that it is no longer polymorphic+ [API change]. The `ToText` class has been removed, and now that we've+ completed the transition to Text we no longer need this to operate+ on Strings.+ + Remove `F` type synonym [API change]. Muse and Org were defining their+ own `F` anyway.++ * Text.Pandoc.Readers.Metadata:++ + Export `yamlMetaBlock` [API change].+ + Make `yamlBsToMeta`, `yamlBsToRefs` polymorphic on the parser state+ [API change].++ * Markdown reader: Fix regression with `tex_math_backslash` (#7155).++ * MediaWiki reader: Allow block-level content in notes (ref) (#7145).++ * Jira reader (Albert Krewinkel):++ + Fixed parsing of autolinks (i.e., of bare URLs in the text).+ Previously an autolink would take up the rest of a line, as spaces+ were allowed characters in these items.+ + Emoji character sequences no longer cause parsing failures. This was+ due to missing backtracking when emoji parsing fails.+ + Mark divs created from panels with class "panel".++ * RST reader: fix logic for ending comments (#7134). Previously comments+ sometimes got extended too far.++ * DocBook writer: include Header attributes as XML attributes on+ section (Erik Rask). Attributes with key names that are not allowed+ as XML attributes are dropped, as are attributes with invalid values+ and `xml:id` (DocBook 5) and `id` (DocBook 4).++ * Docx writer:++ + Make `nsid` in `abstractNum` deterministic. Previously we assigned+ a random number, but we don't need random values, so now we just+ assign a value based on the list marker.+ + Use integral values for `w:tblW` (#7141).++ * Jira writer (Albert Krewinkel):++ + Block quotes are only rendered as `bq.` if they do not contain a+ linebreak.+ + Jira writer: improve div/panel handling. Include div attributes in+ panels, always render divs with class `panel` as panels, and+ avoid nesting of panels.++ * HTML writer: Add warnings on duplicate attribute values.+ This prevents emitting invalid HTML. Ultimately it would be good to+ prevent this in the types themselves, but this is better for now.++ * Org writer: Prevent unintended creation of ordered list items (#7132,+ Albert Krewinkel). Adjust line wrapping if default wrapping would cause+ a line to be read as an ordered list item.++ * JATS templates: support 'equal-contrib' attrib for authors (Albert+ Krewinkel). Authors who contributed equally to a paper may be marked+ with `equal-contrib`.++ * reveal.js template: replace JS comment with HTML (#7154, Florian Kohrt).++ * Text.Pandoc.Logging: Add `DuplicateAttribute` constructor to `LogMessage`.+ [API change]++ * Use `-j4` for linux release build. This speeds up the build dramatically+ on arm.++ * cabal.project: remove ghcoptions. Move flags to top level, so they can+ be set differently on the command line.++ * Require latest texmath, skylighting, citeproc, jira-wiki-markup.+ (The latest skylighting fixes a bad bug with Haskell syntax highlighting.)+ Narrow version bounds for texmath, skylighting, and citeproc, since+ the test output depend on them.++ * Use doclayout 0.3.0.2. This significantly reduces the time and memory+ needed to compile pandoc.++ * Use `foldl'` instead of `foldl` everywhere.++ * Update bounds for random (#7156, Alexey Kuleshevich).++ * Remove uses of some partial functions.++ * Don't bake in a larger stack size for the executable.++ * Test improvements:++ + Use `getExecutablePath` from base, avoiding the dependency on+ `executable-path`.+ + Factor out `setupEnvironment` in Helpers, to avoid code duplication.+ + Fix finding of data files by setting teh `pandoc_datadir` environment+ variable when we shell out to pandoc. This avoids the need to use+ `--data-dir` for the tests, which caused problems finding `pandoc.lua`+ when compiling without the `embed_data_files` flag (#7163).++ * Benchmark improvements:++ + Build `+RTS -A8m -RTS` into default ghc-options for benchmark.+ This is necessary to get accurate benchmark results; otherwise we+ are largely measuring garbage collecting, some not related to the+ current benchmark.+ + Allow specifying BASELINE file in 'make bench' for comparison+ (otherwise the latest benchmark is chosen by default).+ + Force `readFile` in benchmarks early (Bodigrim).++ * CONTRIBUTING: suggest using a `cabal.project.local` file (#7153,+ Albert Krewinkel).++ * Add ghcid-test to Makefile. This loads the test suite in ghcid.+++## pandoc 2.12 (2021-03-08)++ * `--resource-path` now accumulates if specified multiple+ times (#6152). Resource paths specified later on the command line are+ prepended to those specified earlier. Thus,+ `--resource-path foo --resource-path bar:baz` is equivalent to+ `--resource-path bar:bas:foo`. (The previous behavior was+ for the last `--resource-path` to replace all the rest.)+ `resource-path` in defaults files behaves the same way: it+ will be prepended to the resource path set by earlier+ command line options or defaults files. This change+ facilitates the use of multiple defaults files: each can+ specify a directory containing resources it refers to+ without clobbering the resource paths set by the others.++ * Allow defaults files to refer to the home directory, the+ user data directory, and the directory containing the defaults file+ itself (#5871, #5982, #5977). In fields that expect file paths+ (and only in these fields),++ + `${VARIABLE}` will expand to the value of the environment variable+ `VARIABLE` (and in particular `${HOME}` will expand to the path+ of the home directory). A warning will be raised for undefined+ variables.+ + `${USERDATA}` will expand to the path of the user data+ directory in force when the defaults file is being processed.+ + `${.}` will expand to the directory containing the defaults file.+ (This allows default files to be placed in a directory containing+ resources they make use of.)++ * When downloading content from URL arguments, be sensitive to+ the character encoding (#5600). We can properly handle UTF-8 and latin1+ (ISO-8859-1); for others we raise an error. Fall back to latin1 if+ no charset is given in the mime type and UTF-8 decoding fails.++ * Allow abbreviations that don't end in a period to be+ specified using `--abbreviations` (#7124).++ * Add new unexported module Text.Pandoc.XML.Light, as well+ as Text.Pandoc.XML.Light.Types, Text.Pantoc.XML.Light.Proc,+ Text.Pandoc.XML.Light.Output. (Closes #6001, #6565, #7091).++ This module exports definitions of `Element` and `Content`+ that are isomorphic to xml-light's, but with Text+ instead of String. This allows us to keep most of the code in existing+ readers that use xml-light, but avoid lots of unnecessary allocation.++ We also add versions of the functions from xml-light's+ Text.XML.Light.Output and Text.XML.Light.Proc that operate on our+ modified XML types, and functions that convert xml-light types to our+ types (since some of our dependencies, like texmath, use xml-light).++ We export functions that use xml-conduit's parser to produce an+ `Element` or `[Content]`. This allows existing pandoc code to use+ a better parser without much modification.++ The new parser is used in all places where xml-light's parser was+ previously used. Benchmarks show a significant performance improvement+ in parsing XML-based formats (with docbook, opml, jats, and docx+ almost twice as fast, odt and fb2 more than twice as fast).++ In addition, the new parser gives us better error reporting than+ xml-light. We report XML errors, when possible, using the new+ `PandocXMLError` constructor in `PandocError`.++ These changes revealed the need for some changes in the tests. The+ docbook-reader.docbook test lacked definitions for the entities it used;+ these have been added. And the docx golden tests have been updated,+ because the new parser does not preserve the order of attributes.++ * DocBook reader:++ + Avoid expensive tree normalization step, as it is not necessary+ with the new XML parser.+ + Support `informalfigure` (#7079) (Nils Carlson).++ * Docx reader:++ + Use Map instead of list for Namespaces. This gives a speedup of+ about 5-10%. With this and the XML parsing changes, the docx reader+ is now about twice as fast as in the previous release.++ * HTML reader:++ + Small performance tweaks.+ + Also, remove exported class `NamedTag(..)` [API change]. This was just+ intended to smooth over the transition from String to Text and is no+ longer needed.+ + As a result, the functions `isInlineTag` and `isBlockTag`+ are no longer polymorphic; they apply to a `Tag Text` [API change].+ + Do a lookahead to find the right parser to use. This takes+ benchmarks from 34ms to 23ms, with less allocation.+ + Fix bad handling of empty `src` attribute in `iframe` (#7099).+ If `src` is empty, we simply skip the `iframe`.+ If `src` is invalid or cannot be fetched, we issue a warning+ nd skip instead of failing with an error.++ * JATS reader:++ + Avoid tree normalization, which is no longer necessary given the+ new XML parser.++ * LaTeX reader:++ + Don't export `tokenize`, `untokenize` [API change]. These are internal+ implementation details, which were only exported for testing.+ They don't belong in the public API.+ + Improved efficiency of the parser. With these changes the reader+ is almost twice as fast as in the last release in our benchmarks.+ + Code cleanup, removing some unnecessary things.+ + Rewrite `withRaw` so it doesn't rely on fragile assumptions+ about token positions (which break when macros are expanded)+ (#7092). This requires the addition of `sEnableWithRaw` and+ `sRawTokens` in `LaTeXState`, and a new combinator `disablingWithRaw`+ to disable collecting of raw tokens in certain contexts.+ Add `parseFromToks` to Text.Pandoc.Readers.LaTeX.Parsing.+ Fix parsing of single character tokens so it doesn't mess+ up the new raw token collecting. These changes slightly increase+ allocations and have a small performance impact.+ + Handle some bibtex/biblatex-specific commands that used to be+ dealt with in pandoc-citeproc (#7049).+ + Optimize `satisfyTok`, avoiding unnecessary macro expansion steps.+ Benchmarks after this change show 2/3 of the run time and 2/3 of the+ allocation of the Feb. 10 benchmarks.+ + Removed `sExpanded` in state. This isn't actually needed and checking+ it doesn't change anything.+ + Improve `braced'`. Remove the parameter, have it parse the+ opening brace, and make it more efficient.+ + Factor out pieces of the LaTeX reader to make the module smaller.+ This reduces memory demands when compiling. Created+ Text.Pandoc.Readers.{LaTeX,Math,Citation,Table,Macro,Inline}.+ Changed Text.Pandoc.Readers.LaTeX.SIunitx to export a command map+ instead of individual commands.+ + Handle table cells containing `&` in `\verb` (#7129).++ * Make Text.Pandoc.Readers.LaTeX.Types an unexported module [API change].++ * Markdown reader:++ + Improved handling of mmd link attributes in references (#7080).+ Previously they only worked for links that had titles.+ + Improved efficiency of the parser (benchmarks show a 15% speedup).++ * OPML reader:++ + Avoid tree normalization, which is no longer necessary with the+ new XML parser.++ * ODT reader:++ + Finer-grained errors on parse failure (#7091).+ + Give more information if the zip container can't be unpacked.++ * Org reader:++ + Support `task_lists` extension (Albert Krewinkel, #6336).+ + Fix bug in org-ref citation parsing (Albert Krewinkel, #7101).+ The org-ref syntax allows to list multiple citations separated by+ comma. Previously commas were accepted as part of the citation id,+ so all citation lists were parsed as one single citation.++ * RST reader:++ + Use `getTimestamp` instead of `getCurrentTime` to fetch timestamp.+ Setting `SOURCE_DATE_EPOCH` will allow reproducible builds.+ + RST reader: fix handling of header in CSV tables (#7064).+ The interpretation of this line is not affected by the delim option.++ * Jira reader:++ + Modified the Doc parser to skip leading blank lines. This fixes+ parsing of documents which start with multiple blank lines (Albert+ Krewinkel, #7095).+ + Prevent URLs within link aliases to be treated as autolinks (Albert+ Krewinkel, #6944).++ * Text.Pandoc.Shared++ + Remove formerly exported functions that are no longer used in the+ code base: `splitByIndices`, `splitStringByIndicies`, `substitute`,+ and `underlineSpan` (which had been deprecated in April 2020)+ [API change].+ + Export `handleTaskListItem` (Albert Krewinkel) [API change].+ + Change `defaultUserDataDirs` to `defaultUserDataDir` [API+ change]. We determine what is the default user data directory+ by seeing whether the XDG directory and/or legacy+ directory exist.++ * BibTeX writer:++ + BibTeX writer: use doclayout and doctemplate. This change allows+ bibtex/biblatex output to wrap as other formats do,+ depending on the settings of `--wrap` and `--columns` (#7068).++ * CSL JSON writer:++ + Output `[]` if no references in input, instead of raising a+ PandocAppError as before.++ * Docx writer:++ + Use `getTimestamp` instead of `getCurrentTime` for timestamp.+ Setting `SOURCE_DATE_EPOCH` will allow reproducible builds.++ * EPUB writer:++ + Use `getTimestamp` instead of `getCurrentTime` for timestamp.+ Setting `SOURCE_DATE_EPOCH` will allow reproducible builds (#7093).+ This does not suffice to fully enable reproducible in EPUB, since+ a unique id is still being generated for each build.+ + Support `belongs-to-collection` metadata (#7063) (Nick Berendsen).++ * JATS writer:++ + Escape special chars in reference elements (Albert Krewinkel).+ Prevents the generation of invalid markup if a citation element+ contains an ampersand or another character with a special meaning+ in XML.++ * Jira writer:++ + Use Span identifiers as anchors (Albert Krewinkel).+ + Use `{noformat}` instead of `{code}` for unknown languages (Albert+ Krewinkel). Code blocks which are not marked as a language supported+ by Jira are rendered as preformatted text via `{noformat}` blocks.++ * LaTeX writer:++ + Adjust hypertargets to beginnings of paragraphs (#7078).+ Use `\vadjust pre` so that the hypertarget takes you to the beginning+ of the paragraph rather than one line down.+ This makes a particular difference for links to citations using+ `--citeproc` and `link-citations: true`.+ + Change BCP47 lang tag from `jp` to `ja` (Mauro Bieg, #7047).+ + Use function instead of map for accent lookup (should be+ more efficient).+ + Split the module to make it easier to compile on low-memory+ systems: added Text.Pandoc.Writers.LaTeX.{Util,Citation,Lang}.++ * Markdown writer:++ + Handle math right before digit. We insert an HTML comment to+ avoid a `$` right before a digit, which pandoc will not recognize+ as a math delimiter.+ + Split the module to make it easier to compile on low-memory+ systems: added Text.Pandoc.Writers.Markdown.{Types,Inline}.++ * ODT writer:++ + Use `getTimestamp` instead of `getCurrentTime` for timestamp.+ Setting `SOURCE_DATE_EPOCH` will allow reproducible builds.+ + Update default ODT style (Lorenzo). Previously, the "First paragraph"+ style inherited from "Standard" but not from "Text body." Now+ it is adjusted to inherit from "Text body", to avoid some ugly+ spacing issues. It may be necessary to update a custom `reference.odt`+ in light of this change.++ * Org writer:++ + Support `task_lists` extension (Albert Krewinkel, #6336).++ * Pptx writer:++ + Use `getTimestamp` instead of `getCurrentTime` for timestamp.+ Setting `SOURCE_DATE_EPOCH` will allow reproducible builds.++ * JATS templates: tag `author.name` as `string-name` (Albert Krewinkel).+ The partitioning the components of a name into surname, given names,+ etc. is not always possible or not available. Using `author.name`+ allows to give the full name as a fallback to be used when+ `author.surname` is not available.++ * Add default templates for bibtex and biblatex, so that+ the variables `header-include`, `include-before`, `include-after`+ (or alternatively the command line options+ `--include-in-header`, `--include-before-body`, `--include-after-body`)+ may be used.++ * LaTeX template:++ + Update to iftex package (#7073) (Andrew Dunning)+ + Wrap url colours in braces (#7121) (Loïc Grobol).++ * revealjs template: Add 'center' option for vertical slide centering.+ (maurerle, #7104).++ * Text.Pandoc.XML: Improve efficiency of `fromEntities`.++ * Text.Pandoc.MIME++ + Add exported function `getCharset` [API change].++ * Text.Pandoc.UTF8: change IO functions to return Text, not String+ [API change]. This affects `readFile`, `getContents`, `writeFileWith`,+ `writeFile`, `putStrWith`, `putStr`, `putStrLnWith`, `putStrLn`.+ `hPutStrWith`, `hPutStr`, `hPutStrLnWith`, `hPutStrLn`, `hGetContents`.+ This avoids the need to uselessly create a linked list of characters+ when emiting output.++ * Text.Pandoc.App++ + Add `parseOptionsFromArgs` [API change, new exported function].+ + Add fields for CSL options to `Opt` [API change]:+ `optCSL`, `optbibliography`, `optCitationAbbreviations`.++ * Text.Pandoc.Citeproc.BibTeX++ + `Text.Pandoc.Citeproc.writeBibTeXString` now returns+ `Doc Text` instead of `Text` (#7068).+ + Correctly handle `pages` (= `page` in CSL) (#7067).+ + Correctly handle BibLaTeX `langid` (= `language` in CSL, #7067).+ + In BibTeX output, protect foreign titles since there's no language+ field (#7067).+ + Clean up BibTeX parsing (#7049). Previously there was a messy code+ path that gave strange results in some cases, not passing through raw+ tex but trying to extract a string content. This was an artefact of+ trying to handle some special bibtex-specific commands in the BibTeX+ reader. Now we just handle these in the LaTeX reader and simplify+ parsing in the BibTeX reader. This does mean that more raw tex will+ be passed through (and currently this is not sensitive to the+ `raw_tex` extension; this should be fixed).++ * Text.Pandoc.Citeproc.MetaValue++ + Correctly parse "raw" date value in markdown references metadata.+ (See jgm/citeproc#53.)++ * Text.Pandoc.Citeproc++ + Use https URLs for links (Salim B, #7122).++ * Text.Pandoc.Class++ + Add `getTimestamp` [API change]. This attempts to read the+ `SOURCE_DATE_EPOCH` environment variable and parse a UTC time+ from it (treating it as a unix date stamp, see+ https://reproducible-builds.org/specs/source-date-epoch/). If the+ variable is not set or can't be parsed as a unix date stamp, then the+ function returns the current date.++ * Text.Pandoc.Error++ + Add `PandocUnsupportedCharsetError` constructor for+ `PandocError` [API change].+ + Export `renderError` [API change].+ + Refactor `handleError` to use `renderError`. This allows us render+ error messages without exiting.++ * Text.Pandoc.Extensions++ + `Ext_task_lists` is now supported by org (and turned+ on by default) (Albert Krewinkel, #6336).+ + Remove `Ext_fenced_code_attributes` from allowed commonmark attributes+ (#7097). This attribute was listed as allowed, but it didn't actually+ do anything. Use `attributes` for code attributes and more.++ * Lua subsystem:++ + Always load built-in Lua scripts from default data-dir (Albert+ Krewinkel). The Lua modules `pandoc` and `pandoc.List` are now always+ loaded from the system's default data directory. Loading from a+ different directory by overriding the default path, e.g. via+ `--data-dir`, is no longer supported to avoid unexpected behavior+ and to address security concerns.+ + Add module "pandoc.path" (Albert Krewinkel, #6001, #6565).+ The module allows to work with file paths in a convenient and+ platform-independent manner.+ + Use strict evaluation when retrieving AST value from the stack+ (Albert Krewinkel, #6674).++ * Text.Pandoc.PDF++ + Disable `smart` extension when building PDF via LaTeX.+ This is to prevent accidental creation of ligatures like+ `` ?` `` and `` !` `` (especially in languages with quotations like+ German), and similar ligature issues. (See jgm/citeproc#54.)++ * Text.Pandoc.CSV:++ + Fix parsing of unquoted values (#7112). Previously we didn't allow+ unescaped quotes in unquoted values, but they are allowed+ in CSV.++ * Test suite:++ + Use a more robust method for testing the executable. Many+ of our tests require running the pandoc executable. This+ is problematic for a few different reasons. First,+ cabal-install will sometimes run the test suite after+ building the library but before building the executable,+ which means the executable isn't in place for the tests.+ One can work around that by first building, then building+ and running the tests, but that's fragile. Second, we+ have to find the executable. So far, we've done that using+ a function `findPandoc` that attempts to locate it+ relative to the test executable (which can be located+ using findExecutablePath). But the logic here is delicate+ and work with every combination of options. To solve both+ problems, we add an `--emulate` option to the+ `test-pandoc` executable. When `--emulate` occurs as the+ first argument passed to `test-pandoc`, the program simply+ emulates the regular pandoc executable, using the rest of+ the arguments (after `--emulate`). Thus, `test-pandoc+ --emulate -f markdown -t latex` is just like `pandoc -f+ markdown -t latex`. Since all the work is done by library+ functions, implementing this emulation just takes a couple+ lines of code and should be entirely reliable. With this+ change, we can test the pandoc executable by running the+ test program itself (locatable using `findExecutablePath`)+ with the `--emulate` option. This removes the need for the+ fragile `findPandoc` step, and it means we can run our+ integration tests even when we're just building the+ library, not the executable. [Note: part of this change+ involved simplifying some complex handling to set+ environment variables for dynamic library paths. I have+ tested a build with `--enable-dynamic-executable`, and it+ works, but further testing may be needed.]+ + Print accurate location if a test fails (Albert+ Krewinkel). Ensures that tasty-hunit reports the location+ of the failing test instead of the location of the helper+ `test` function.++ * Documentation: Update URLs and use `https` where possible (#7122,+ Salim B).++ * Add `doc/libraries.md`, a description of libraries that support pandoc.++ * MANUAL.txt++ + MANUAL: block-level formatting is not allowed in line blocks (#7107).+ + Clarify `tex_math_dollars` extension. Note that no blank lines+ are allowed between the delimiters in display math.+ + Add MANUAL section on reproducible builds.+ + Document no template fallback for absolute path (#7077, Nixon+ Enraght-Moony.)+ + Improve docs for cite-method.+ + Update README and man page.++ * Makefile: in `make bench`, create CSV files for comparison and compare+ against previous benchmark run. Add timestamp to CSV filenames.++ * cabal.project: don't explicitly set -trypandoc.+ If we do, this can't be overridden on the cabal command line.++ * doc/lua-filters.md: improve documentation for+ `pandoc.mediabag.insert`, `pandoc.mediabag.fetch`,+ `directory`, `normalize` (Albert Krewinkel).++ * Allow base64-bytestring-1.2.* (Dmitrii Kovanikov)++ * Require jira-wiki-markup 1.3.3 (Albert Krewinkel)++ * Require citeproc 0.3.0.8, which correctly titlecases when titles+ contain non-ASCII characters.++ * Use skylighting 0.10.4. This version of skylighting uses xml-conduit+ rather than hxt. This speeds up parsing of XML syntax definitions+ fourfold, and removes four packages from pandoc's dependency graph:+ hxt-charproperties, hxt-unicode, hxt-regex-xmlschema, hxt.++ * Add script `tools/parseTimings.pl` to help pin down which+ modules take the most time and memory to compile.++ * Avoid unnecessary use of NoImplicitPrelude pragma (#7089) (Albert+ Krewinkel)++ * Benchmarks++ + Use the lighter-weight tasty-bench instead of criterion.+ + Run writer benchmarks for binary formats too.+ + Alphabetize benchmarks.+ + Don't run benchmarks for bibliography formats+ (yet; we need a special input for them).+ + Show allocation data+ + Clean up benchmark code.+ + Allow specifying patterns using `-p blah'.++ * trypandoc: add 2 second timeout.++ * Use `-split-sections` in creating linux release binary.+ This reduces executable size significantly (by about 30%).++ * Remove `weigh-pandoc`. It's not really useful any more, now that our+ regular benchmarks include data on allocation.++ * Improve linux package build process and add script to+ automate building an arm64 binary package.+++## pandoc 2.11.4 (2021-01-22)++ * Add `biblatex`, `bibtex` as output formats (closes #7040).++ * Recognize more extensions as markdown by default (#7034):+ `mkdn`, `mkd`, `mdwn`, `mdown`, `Rmd`.++ * Implement defaults file inheritance (#6924, David Martschenko).+ Allow defaults files to inherit options from other defaults files by+ specifying them with the following syntax:+ `defaults: [list of defaults files or single defaults file]`.++ * Fix infinite HTTP requests when writing epubs from URL source (#7013).+ Due to a bug in code added to avoid overwriting the cover image+ if it had the form `fileX.YYY`, pandoc made an endless sequence+ of HTTP requests when writing epub with input from a URL.++ * Org reader:++ + Allow multiple pipe chars in todo sequences (Albert Krewinkel, #7014).+ Additional pipe chars, used to separate "action" state from "no further+ action" states, are ignored. E.g., for the following sequence, both+ `DONE` and `FINISHED` are states with no further action required:+ `#+TODO: UNFINISHED | DONE | FINISHED`.+ + Restructure output of captioned code blocks (Albert Krewinkel, #6977).+ The Div wrapper of code blocks with captions now has the class+ "captioned-content". The caption itself is added as a Plain block+ inside a Div of class "caption". This makes it easier to write filters+ which match on captioned code blocks. Existing filters will need to be+ updated.+ + Mark verbatim code with class `verbatim` (Dimitri Sabadie, #6998).++ * LaTeX reader:++ + Handle `filecontents` environment (#7003).+ + Put contents of unknown environments in a Div when `raw_tex` is not+ enabled (#6997). (When `raw_tex` is enabled, the whole environment is+ parsed as a raw block.) The class name is the name of the environment.+ Previously, we just included the contents without the surrounding Div,+ but having a record of the environment's boundaries and name can be+ useful.++ * Mediawiki reader:++ + Allow space around storng/emph delimiters (#6993).++ * New module Text.Pandoc.Writers.BibTeX, exporting+ writeBibTeX and writeBibLaTeX. [API change]++ * LaTeX writer:++ + Revert table line height increase in 2.11.3 (#6996).+ In 2.11.3 we started adding `\addlinespace`, which produced less dense+ tables. This wasn't an intentional change; I misunderstood a comment in+ the discussion leading up to the change. This commit restores the earlier+ default table appearance. Note that if you want a less dense table, you+ can use something like `\def\arraystretch{1.5}` in your header.++ * EPUB writer:++ + Adjust internal links to identifiers defined in raw HTML sections+ after splitting into chapters (#7000).+ + Recognize `Format "html4"`, `Format "html5"` as raw HTML.+ + Adjust internal links to images, links, and tables after splitting into+ chapters. Previously we only did this for Div and Span and Header+ elements (see #7000).++ * Ms writer:++ + Don't justify text inside table cells.++ * JATS writer:++ + Use `<element-citation>` if `element_citations`+ extension is enabled (Albert Krewinkel).+ + Fix citations (Albert Krewinkel, #7018). By default+ we use formatted citations.+ + Ensure that `<disp-quote>` is always wrapped in `<p>` (#7041).++ * Markdown writer:++ + Cleaned up raw formats. We now react appropriately+ to `gfm`, `commonmark`, and `commonmark_x` as raw formats.++ * RST writer:++ + Fix bug with dropped content from inside spans with a class in+ some cases (#7039).++ * Docx writer:++ + Handle table header using styles (#7008). Instead of hard-coding+ the border and header cell vertical alignment, we now let this+ be determined by the Table style, making use of Word's+ "conditional formatting" for the table's first row. For+ headerless tables, we use the tblLook element to tell Word+ not to apply conditional first-row formatting.++ * Commonmark writer:++ + Implement start number on ordered lists (#7009). Previously they always+ started at 1, but according to the spec the start number is respected.++ * HTML writer:++ + Fix implicit_figure at end of footnotes (#7006).++ * ConTeXt template: Remove `\setupthinrules` from default template.+ The width parameter this used is not actually supported,+ and the command didn't do anything.++ * Text.Pandoc.Extensions:++ + Add `Ext_element_citations` constructor (Albert Krewinkel).++ * Text.Pandoc.Citeproc.BibTeX: New unexported function+ `writeBibtexString`.++ * Text.Pandoc.Citeproc:++ + Use finer grained imports (Albert Krewinkel).+ + Factor out and export `getStyle` [API change].+ + Export `getReferences` [API change, #7106].+ + Factor out getLang.++ * Text.Pandoc.Parsing: modify `gridTableWith'` for headerless tables.+ If the table lacks a header, the header row should be an empty+ list. Previously we got a list of empty cells, which caused+ an empty header to be emitted instead of no header. In LaTeX/PDF+ output that meant we got a double top line with space between.++ * ImageSize: use `viewBox` for SVG if no length, width attributes (#7045).+ This change allows pandoc to extract size information from more SVGs.++ * Add simple default.nix.++ * Use commonmark 0.1.1.3.++ * Use citeproc 0.3.0.5.++ * Update default CSL to use latest chicago-author-date.csl.++ * CONTRIBUTING.md: add note on GNU xargs.++ * MANUAL.txt:++ + Update description of `-L`/`--lua-filter`.+ + Document use of citations in note styles (#6828).++## pandoc 2.11.3.2 (2020-12-29)++ * HTML reader: use renderTags' from Text.Pandoc.Shared (Albert Krewinkel).+ A side effect of this change is that empty `<col>` elements are written+ as self-closing tags in raw HTML blocks.++ * Asciidoc writer: Add support for writing nested tables (#6972, timo-a).+ Asciidoc supports one level of nesting. If deeper tables are to be+ written, they are omitted and a warning is issued.++ * Docx writer: fix nested tables with captions (#6983).+ Previously we got unreadable content, because docx seems+ to want a `<w:p>` element (even an empty one) at the end of+ every table cell.++ * Powerpoint writer: allow arbitrary OOXML in raw inline elements+ (Albert Krewinkel). The raw text is now included verbatim in the+ output. Previously is was parsed into XML elements, which prevented+ the inclusion of partial XML snippets.++ * LaTeX writer: support colspans and rowspans in tables (#6950,+ Albert Krewinkel). Note that the multirow package is needed for+ rowspans. It is included in the latex template under a variable,+ so that it won't be used unless needed for a table.++ * HTML writer: don't include p tags in CSL bibliography entries+ (#6966). Fixes a regression in 2.11.3.++ * Add `meta-description` variable to HTML templates (#6982). This+ is populated by the writer by stringifying the `description`+ field of metadata (Jerry Sky). The `description` meta tag will+ make the generated HTML documents more complete and SEO-friendly.++ * Citeproc: fix handling of empty URL variables (`DOI`, etc.).+ The `linkifyVariables` function was changing these to links+ which then got treated as non-empty by citeproc, leading+ to wrong results (e.g. ignoring nonempty URL when empty DOI is present).+ See jgm/citeproc#41.++ * Use citeproc 0.3.0.3. Fixes an issue in author-only citations when+ both an author and translator are present, and an issue with+ citation group delimiters.++ * Require texmath 0.12.1. This improves siunitx support in math,+ fixes bugs with `\*mod` family operators and arrays, and avoids+ italicizing symbols and operator names in docx output.++ * Ensure that the perl interpreter used for filters with `.pl`+ extension (wuffi).++ * MANUAL: note that textarea content is never parsed as Markdown+ (Albert Krewinkel).+++## pandoc 2.11.3.1 (2020-12-18)++ * Added some missing files to extra-source-files and data+ files, so they are included in the sdist tarball. Closes #6961.+ Cleaned up some extraneous data and test files, and added+ a CI check to ensure that the test and data files included+ in the sdist match what is in the git repository.++ * Use citeproc 0.3.0.1, which avoids removing nonbreaking+ space at the end of the `initialize-with` attribute. (Some+ journals require nonbreaking space after initials, and this+ makes that possible.)++## pandoc 2.11.3 (2020-12-17)++ * With `--bibliography` (or `bibliography` in metadata), a+ URL may now be provided, and pandoc will fetch the resource.+ In addition, if a file path is provided and it is not+ found relative to the working directory, the resource+ path will be searched (#6940).++ * Add `sourcepos` extension for `commonmark`, `gfm`, `commonmark_x`+ (#4565). With the `sourcepos` extension set set, `data-pos`+ attributes are added to the AST by the commonmark reader. No other+ readers are affected. The `data-pos` attributes are put on elements+ that accept attributes; for other elements, an enlosing Div or Span+ is added to hold the attributes.++ * Change extensions for `commonmark_x`: replace `auto_identifiers`+ with `gfm_auto_identifiers` (#6863). `commonmark_x` never actually+ supported `auto_identifiers` (it didn't do anything), because the+ underlying library implements gfm-style identifiers only. Attempts+ to add the `auto_identifiers` extension to `commonmark` will now+ fail with an error.++ * HTML reader:++ + Split module into several submodules (Albert Krewinkel). Reducing+ module size should reduce memory use during compilation.+ + Support advanced table features (Albert Krewinkel):+ block level content in captions, row and colspans,+ body headers, row head columns, footers, attributes.+ + Disable round-trip testing for tables. Information for cell+ alignment in a column is not preserved during round-trips (Albert+ Krewinkel).+ + Allow finer grained options for tag omission (Albert Krewinkel).+ + Simplify list attribute handling (Albert Krewinkel).+ + Pay attention to `lang` attributes on body element (#6938).+ These (as well as `lang` attributes on the html element) should update+ lang in metadata.+ + Retain attribute prefixes and avoid duplicates (#6938).+ Previously we stripped attribute prefixes, reading `xml:lang` as+ `lang` for example. This resulted in two duplicate `lang`+ attributes when `xml:lang` and `lang` were both used. This commit+ causes the prefixes to be retained, and also avoids invald+ duplicate attributes.++ * Commonmark reader:++ + Refactor `specFor`.+ + Set input name to `""` to avoid clutter in sourcepos output.++ * Org reader:++ + Parse `#+LANGUAGE` into `lang` metadata field (#6845, Albert+ Krewinkel).+ + Preserve targets of spurious links (#6916, Albert+ Krewinkel). Links with (internal) targets that the reader doesn't+ know about are converted into emphasized text. Information on the+ link target is now preserved by wrapping the text in a Span of class+ `spurious-link`, with an attribute `target` set to the link's+ original target. This allows to recover and fix broken or unknown+ links with filters.++ * DocBook reader:++ + Table text width support (#6791, Nils Carlson).+ Table width in relation to text width is not natively supported+ by docbook but is by the docbook `fo` stylesheets through an XML+ processing instruction, `<?dbfo table-width="50%"?>`.++ * LaTeX reader:++ + Improve parsing of command options (#6869, #6873).+ In cases where we run into trouble parsing inlines til the+ closing `]`, e.g. quotes, we return a plain string with the+ option contents. Previously we mistakenly included the brackets+ in this string.+ + Preserve center environment (#6852, Igor Pashev).+ The contents of the `center` environment are put in a `Div`+ with class `center`.+ + Don't parse `\rule` with width 0 as horizontal rule. These are+ sometimes used as spacers in LaTeX.+ + Don't apply theorem default styling to a figure inside (#6925).+ If we put an image in italics, then when rendering to Markdown+ we no longer get an implicit figure.++ * Dokuwiki reader:++ + Handle unknown interwiki links better (#6932).+ DokuWiki lets the user define his own Interwiki links. Previously+ pandoc reacted to these by emitting a google search link, which is+ not helpful. Instead, we now just emit the full URL including the+ wikilink prefix, e.g. `faquk>FAQ-mathml`. This at least gives users+ the ability to modify the links using filters.++ * Markdown writer:++ + Properly handle boolean values in writing YAML metadata (#6388).+ + Ensure that a new csl-block begins on a new line (#6921).+ This just looks better and doesn't affect the semantics.++ * RST writer:++ + Better image handling (#6948). An image alone in its paragraph+ (but not a figure) is now rendered as an independent image, with an+ `alt` attribute if a description is supplied. An inline image that+ is not alone in its paragraph will be rendered, as before, using a+ substitution. Such an image cannot have a "center", "left", or+ "right" alignment, so the classes `align-center`, `align-left`, or+ `align-right` are ignored. However, `align-top`, `align-middle`,+ `align-bottom` will generate a corresponding `align` attribute.++ * Docx writer:++ + Keep raw openxml strings verbatim (#6933, Albert Krewinkel).+ + Use Content instead of Element. This allows us to inject+ raw OpenXML into the document without reparsing it into an+ Element, which is necessary if you want to inject an open+ tag or close tag.+ + Fix bullets/lists indentation, so that the first level is slightly+ indented to the right instead of right on the margin (cholonam).+ + Support bold and italic in "complex script" (#6911).+ Previously bold and italics didn't work properly in LTR+ text. This commit causes the w:bCs and w:iCs attributes+ to be used, in addition to w:b and w:i, for bold and+ italics respectively.++ * ICML writer:++ + Fix image bounding box for custom widths/heighta (Mauro Bieg, #6936).++ * LaTeX writer:++ + Improve table spacing (#6842, #6860).+ Remove the `\strut` that was added at the end of minipage+ environments in cells. Replace `\tabularnewline` with+ `\\ \addlinespace`.+ + Improve calculation of column spacing (#6883).+ + Extract table handling into separate module (Albert Krewinkel).+ + Fix bug with nested `csl-` display Spans (#6921).+ + Improve longtable output (#6883). Don't create minipages for+ regular paragraphs. Put width and alignment information in the+ longtable column descriptors.++ * OpenDocument writer:++ + Support for table width as a percentage of text width+ (#6792, Nils Carson).+ + Implement Div and Span ident support (#6755, Nils Carson).+ Spans and Divs containing an ident in the Attr will become bookmarks+ or sections with idents in OpenDocument format.+ + Add two extensions, `xrefs_name` and `xrefs_number` (#6774, Nils+ Carlson). Links to headings, figures and tables inside the+ document are substituted with cross-references that will use the+ name or caption of the referenced item for `xrefs_name` or the+ number for `xrefs_number`. For the `xrefs_number` to be useful+ heading numbers must be enabled in the generated document and+ table and figure captions must be enabled using for example the+ `native_numbering` extension. In order for numbers and reference+ text to be updated the generated document must be refreshed.++ * JATS writer:++ + Support advanced table features (Albert Krewinkel).+ + Support author affiliations (#6687, Albert Krewinkel).++ * Docbook writer:++ + Use correct id attribute consistently (Jan Tojnar).+ DocBook5 should always use `xml:id` instead of `id`.+ + Handle admonition titles better (Jan Tojnar).+ Docbook reader produces a `Div` with `title` class for `<title>`+ element within an “admonition” element. Markdown writer then turns+ this into a fenced div with `title` class attribute. Since fenced+ divs are block elements, their content is recognized as a+ paragraph by the Markdown reader. This is an issue for Docbook+ writer because it would produce an invalid DocBook document from+ such AST – the `<title>` element can only contain “inline”+ elements. Handle this special case separately by unwrapping+ the paragraph before creating the `<title>` element.+ + Add XML namespaces to top-level elements (#6923, Jan Tojnar).+ Previously, we only added `xmlns` attributes to chapter+ elements, even when running with `--top-level-division=section`.+ These namespaces are now added to part and section elements too,+ when they are the selected top-level divisions.+ We do not need to add namespaces to documents produced with+ `--standalone` flag, since those will already have xmlns attribute on+ the root element in the template.++ * HTML writer:++ + Fix handling of nested `csl-` display spans (#6921).+ Previously inner Spans used to represent CSL display attributes were+ not rendered as div tags as intended.++ * EPUB writer:++ + Include title page in landmarks (#6919).+ Note that the toc is also included if `--toc` is specified.+ + Add frontmatter type on body element for nav.xhtml (#6918).++ * EPUB templates: use preserveAspectRatio="xMidYMid" for cover image (#6895,+ Shin Sang-jae). This change affects both the epub2 and the epub3+ templates. It avoids distortion of the cover image by requiring that the+ aspect ratio be preserved.++ * LaTeX template:++ + Include `csquotes` package if `csquotes` variable set.+ + Put back `amssymb`. We need it for checkboxes in todo lists,+ and maybe for other things. In this location it seems compatible+ with the cases that prompted #6469 and PR #6762.+ + Disable language-specific shorthands in babel (#6817, #6887).+ Babel defines "shorthands" for some languages, and these can+ produce unexpected results. For example, in Spanish, `1.22`+ gets rendered as `122`, and `et~al.` as `etal`.+ One would think that babel's `shorthands=off` option (which+ we were using) would disable these, but it doesn't. So we+ remove `shorthands=off` and add some code that redefines+ the shorthands macro. Eventually this will be fixed in babel,+ I hope, and we can revert to something simpler.++ * JATS template: allow array of persistent institute ids in `pid`+ (Albert Krewinkel).++ * Text.Pandoc.Parsing: minor code and efficiency improvements.++ * Text.Pandoc.Extension:++ + Add `Ext_sourcepos` constructor for `Extension` [API change].+ + Add `Ext_xrefs_name` and `Ext_xrefs_number` constructors for+ `Extension` (Nils Carson) [API change].++ * Text.Pandoc.Citeproc:++ + Fix truncation of `[Citation]` list in `Cite` inside footnotes (#6890).+ This affected author-in-text citations in footnotes. It didn't cause+ problems for the printed output, but for filters that expected the+ citation id and other information.+ + Allow the use of both inline and external references (#6951),+ as with pandoc-citeproc. References defined in the document's+ metadata take priority over references with the same id defined in+ an external bibliography.+ + Use `fetchItem` to get external bibliography (#6940).+ + Ensure that BCP47 lang codes can be used. We ignore the variants+ and just use the base lang code and country code when passing off+ to citeproc.+ + Citeproc BibTeX parser: revert change in `getRawField`+ which was made (for reasons forgotten) when transferring+ this code from pandoc-citeproc. The change led to `--` in+ URLs being interpreted as en-dashes, which is unwanted (#6874).++ * Text.Pandoc.ImageSize:++ + Default to DPI 72 if the format specifies DPI of 0 (#6880).+ This shouldn't happen, in general, but it can happen with+ JPEGs that don't conform to the spec. Having a DPI of 0+ will blow up size calculations (division by 0).+ + ImageSize: use JuicyPixels to determine size for png, jpeg, and+ gif, instead of doing our own binary parsing (#6936). This+ gives more reliable results.++ * Text.Pandoc.CSS:++ + Remove `foldOrElse` (internal module) (Albert Krewinkel).++ * Use skylighting 0.10.2 (#6625).++ * Use citeproc 0.3. This fixes issues with references with+ duplicate ids (jgm/citeproc#36).++ * Use doctemplates 0.9. This fixes issues with boolean+ metadata values in the Markdown writer (#6388)+ and in `meta-json` (#6650). It also fixes+ issues with nested for loops in templates.++ * Add translations zh-Hans.yaml and zh-Hant.yaml (#6904, #6909,+ Kolen Cheung, taotieren).++ * Add tests: True to cabal.project.+ This fixes some CI failures for cabal.++ * Normalize test/tables/*.native (#6888, Kolen Cheung).++ * Move executable to `app` directory to avoid problems with cabal repl.++ * CONTRIBUTING: add section "How can I help?" (#6892, Albert Krewinkel).+ Also adds a paragraph aimed at highlighting the importance of feature+ maintenance.++ * MANUAL: Document that --number-sections works in `ms` (#6935).+++## pandoc 2.11.2 (2020-11-19)++ * Default to using ATX (`##`-style) headings for Markdown output+ (#6662, Aner Lucero). Previously we used Setext (underlined) headings+ by default for levels 1--2.++ * Add option `--markdown-headings=atx|setext`, and deprecate+ `--atx-headers` (#6662, Aner Lucero).++ * Support `markdown-headings` in defaults files.++ * Fix corner case in YAML metadata parsing (#6823). Previously YAML+ metadata would sometimes not get recognized if a field ended with a+ newline followed by spaces.++ * `--self-contained`: increase coverage (#6854).+ Previously we only self-contained attributes for certain tag names+ (`img`, `embed`, `video`, `input`, `audio`, `source`, `track`,+ `section`). Now we self-contain any occurrence of `src`,+ `data-src`, `poster`, or `data-background-image`, on any tag; and+ also `href` on `link` tags.++ * Markdown reader:++ + Fix detection of locators following in-text citations.+ Prevously, if we had `@foo [p. 33; @bar]`, the `p. 33` would be+ incorrectly parsed as a prefix of `@bar` rather than a suffix of+ `@foo`.+ + Improve period suppression algorithm for citations in notes+ in note citation styles (#6835).+ + Don't increment `stateNoteNumber` for example list references.+ This helps with #6836 (a bug in which example list references+ disturb calculation of citation note number and affect when+ `ibid` is triggered).++ * LaTeX reader:++ + Move `getNextNumber` from Readers.LaTeX to Readers.LaTeX.Parsing.+ + Fix negative numbers in siunitx commands. A change in pandoc 2.11+ broke negative numbers, e.g. `\SI{-33}{\celcius}` or `\num{-3}`.+ This fixes the regression.++ * DocBook reader: drop period in formalpara title+ and put it in a div with class `formalpara-title`, so that+ people can reformat with filters (#6562).++ * Man reader: improve handling of `.IP` (#6858). We now better handle+ `.IP` when it is used with non-bullet, non-numbered lists, creating a+ definition list. We also skip blank lines like groff itself.++ * Bibtex reader: fall back on `en-US` if locale for LANG not found.+ This reproduces earlier pandoc-citeproc behavior (jgm/citeproc#26).++ * JATS writer:++ + Wrap all tables (Albert Krewinkel).+ All `<table>` elements are put inside `<table-wrap>` elements, as the+ former are not valid as immediate child elements of `<body>`.+ + Move Table handling to separate module (Albert Krewinkel).+ Adds two new unexported modules:+ Text.Pandoc.Writers.JATS.Types, Text.Pandoc.Writers.JATS.Table.++ * Org writer:++ + Replace org #+KEYWORDS with #+keywords (TEC).+ As of ~2 years ago, lower case keywords became the standard (though+ they are handled case insensitive, as always).+ + Update org supported languages and identifiers according to the+ current list contained in+ <https://orgmode.org/worg/org-contrib/babel/languages/index.html>+ (TEC).++ * Only use `filterIpynbOutput` if input format is ipynb (#6841).+ Before this change content could go missing from divs with class+ `output`, even when non-ipynb was being converted.++ * When checking reader/writer name, check base name now that we permit+ extensions on formats other than markdown.++ * Text.Pandoc.PDF: Fix `changePathSeparators` for Windows (#6173).+ Previously a path beginning with a drive, like `C:\foo\bar`, was+ translated to `C:\/foo/bar`, which caused problems.+ With this fix, the backslashes are removed.++ * Text.Pandoc.Logging:++ + Add constructor `ATXHeadingInLHS` to `LogMessage` [API change].+ + Add constructor `EnvironmentVariableUndefined` to+ `LogMessage` [API change].++ * Fix error that is given when people specify `doc` output (#6834,+ gison93).++ * LaTeX template: add a `\break` after parbox in `CSLRightInline`.+ This should fix spacing problems between entries with numeric styles.+ Also fix number of params on `CSLReferences`.++ * reveal.js template: Put quotes around `controlsLayout`,+ `controlsBackArrows`, and `display`, since these require strings.+ Add `showSlideNumber`, `hashOneBasedIndex`, `pause`.++ * Use citeproc 0.2. This fixes a bug with title case around parentheses.++ * pandoc.cabal: remove 'static' flag.+ This isn't really necessary and can be misleading (e.g. on macOS,+ where a fully static build isn't possible). cabal's new option+ `--enable-executable-static` does the same. On stack you can add+ something like this to the options for your executable in package.yaml:++ ld-options: -static -pthread++ * Remove obsolete bibutils flag setting in `linux/make_artifacts.sh`.++ * Manual:++ + Correct `link-citation` -> `link-citations`.+ + Add a sentence about `pagetitle` for HTML (#6843, Alex Toldaiev).++ * INSTALL.md: Remove references to `pandoc-citeproc` (#6857).++ * CONTRIBUTING: describe hlint and how it's used (#6840, Albert+ Krewinkel).++## pandoc 2.11.1.1 (2020-11-07)++ * Citeproc: improve punctuation in in-text note citations (#6813).+ Previously in-text note citations inside a footnote would sometimes have+ the final period stripped, even if it was needed (e.g. on the end of+ 'ibid').++ * Use citeproc 0.1.1.1. This improves the decision about when+ to use `ibid` in cases where citations are used inside+ a footnote (#6813).++ * Support `nocase` spans for `csljson` output.++ * Require latest commonmark, commonmark-extensions.+ This fixes a bug with `autolink_bare_uris` and commonmark.++ * LaTeX reader: better handling of `\\` inside math in table cells (#6811).++ * DokuWiki writer: translate language names for code elements+ and improve whitespace (#6807).++ * MediaWiki writer: use `syntaxhighlight` tag instead of deprecated+ `source` for highlighted code (#6810). Also support `startFrom`+ attribute and `numberLines`.++ * Lint code in PRs and when committing to master (#6790,+ Albert Krewinkel).++ * doc/filters.md: describe technical details of filter invocations (#6815,+ Albert Krewinkel).+++## pandoc 2.11.1 (2020-11-03)++ * DocBook Reader: fix duplicate bibliography bug (#6773, Nils Carlson).++ * HTML reader:++ + Parse contents of iframes (#6770).+ + Parse inline svg as image unless `raw_html` is set in the reader (in+ which case the svg is passed through as raw HTML) (#6770).++ * LaTeX reader:++ + Fix bug parsing macro arguments (#6796). If `\cL` is+ defined as `\mathcal{L}`, and `\til` as `\tilde{#1}`, then+ `\til\cL` should expand to `\tilde{\mathcal{L}}`, but+ pandoc was expanding it to `\tilde\mathcal{L}`. This is+ fixed by parsing the arguments in "verbatim mode" when the+ macro expands arguments at the point of use.+ + Properly support optional (cite) argument for+ `\blockquote` from `csquotes` (#6802).++ * LaTeX writer: Improved calculation of table column widths.+ We now have LaTeX do the calculation, using `\tabcolsep`.+ So we should now have accurate relative column widths no+ matter what the text width. The default template has been modified to load+ the calc package if tables are used.++ * HTML writer: Fix duplicate "class" attribute for table+ rows (Andy Morris).++ * Text.Pandoc.Filter: allow shorter YAML representation of Citeproc+ (Albert Krewinkel). The map-based YAML representation of filters expects+ `type` and `path` fields. The path field had to be present for all filter+ types, but is not used for citeproc filters. The field can now be omitted+ when type is "citeproc", as described in the MANUAL.++ * Text.Pandoc.Error: Add `PandocBibliographyError` constructor+ for `PandocError` [API change]. This ensures that bibliography parsing+ errors generate messages that include the bibliography file name --+ otherwise it can be quite mysterious where it is coming from.++ * Citeproc: properly handle `csl` field with `data:` URI (#6783).+ This is used with the JATS writer, so this fixes a regression+ in pandoc 2.11 with JATS output and citeproc.++ * Allow `citation-abbreviations` in defaults file.++ * JATS templates: ensure `jats_publishing` output is valid+ (Albert Krewinkel).++ * LaTeX template: Fix `CSLRightInline`, so that it does not+ run over the right margin.++ * HTML template: default CSS tweaks (Mauro Bieg and John+ MacFarlane).++ - Fix margin before codeblock+ - Add `monobackgroundcolor` variable, making the background color+ and padding of code optional.+ - Ensure that backgrounds from highlighting styles take precedence over+ monobackgroundcolor+ - Remove list markers from TOC+ - Add margin-bottom where needed+ - Remove italics from blockquote styling+ - Change borders and spacing in tables to be more consistent with other+ output formats+ - Style h5, h6+ - Set font-size for print media to 12pt.+ - Reduce interline space.+ - Reduce interparagraph space.+ - Reduce line width.+ - Remove the special `line-height: 1` for table cells.+ - Remove the special line-height for pre.+ - Ensure that there is a bit more space before a heading+ than after.+ - Slightly reduced space after title header.+ - Add CSS example to MANUAL++ * man template: Change comment that triggers `tbl` from+ `.\"t` to `'\" t`, as specified in groff_man(7) (#6803).++ * Use latest commonmark, commonmark-extensions.+ This fixes a bug with nested blocks in footnotes with the+ `footnote` extension to `commonmark`. See jgm/commonmark-hs#63.++ * Citeproc: use comma for in-text citations inside footnotes.+ When an author-in-text citation like `@foo` occurs in a footnote,+ we now render it with: `AUTHOR NAME + COMMA + SPACE + REST`.+ Previously we rendered: `AUTHOR NAME + SPACE + "(" + REST + ")"`.+ This gives better results. Note that normal citations are still+ rendered in parentheses.++ * Use latest citeproc:++ + citeproc no longer capitalizes notes, so we do it+ in pandoc when appropriate.+ + Closes #6783.++ * Clarify manual on `--track-changes` (#6801).++ * Add `doc/jats.md` to document pandoc's handling of JATS+ (#6794, Albert Krewinkel).++ * Fix code example in lua-filters.md (#6795).++## pandoc 2.11.0.4 (2020-10-21)++ * Commonmark writer: fix regression with fenced divs (#6768).+ Starting with 2.10.1, fenced divs no longer render with+ HTML div tags in commonmark output. This is a regression+ due to our transition from cmark-gfm. This commit fixes it.++ * Use released version of citeproc. (This fixes a mis-step+ in the 2.11.0.3 release, which is now deprecated.)++ * Use latest sylighting, with support for `groovy`.++ * Document that --html-q-tags requires the smart extension on the reader+ (#6766).++## pandoc 2.11.0.3 (2020-10-20)++ * Use latest citeproc (closes #6765). This fixes a problem with+ author-in-text citations for references including both an author+ and an editor. Previously, both were included in the text, but only+ the author should be.++ * With `--citeproc`, ensure that the final period is removed when+ citations that occur in notes in note-based styles get put in+ parentheses. See jgm/citeproc#20.++ * Normalize rewritten image paths with `--extract-media` (#6761).+ This change will avoid mixed paths like this one when+ `--extract-media` is used with a Word file:+ ``. Instead we'll get+ ``.++ * Modify `--version` output. Use space more efficiently and report the+ citeproc and ipynb versions, along with skylighting, texmath, and+ pandoc-types. Drop the word "default" before "user data directory."++ * DocBook reader: bibliomisc and anchor support (#6754, Nils Carlson).+ Also ensure that bibliodiv without a title no longer results in+ an empty Header.++ * ConTeXt template: adds `\setupinterlinespace` to fonts larger+ than normal (#6763, Denis Maier).++ * LaTeX template: Do not load amssymb if not needed (#6469, Angelo Peronio).+ See <https://tex.stackexchange.com/a/549938>.++ * Relax upper bound on hslua, allow hslua-1.3.* (Albert Krewinkel).++ * MANUAL:++ + Improve explanation of "indent" variable (#6767, Cyrus Yip).+ + Remove org from list of input formats supporting raw_tex (#6753,+ Nick Fleisher).+++## pandoc 2.11.0.2 (2020-10-15)++ * Fix handling of `xdata` in bibtex/biblatex bibliographies (#6752).++ * Fix some small typos in the API documentation (#6751, Michael Hoffmann).++ * Require citeproc 0.1.0.2. This fixes a regression from pandoc-citeproc+ involving spacing between components of a reference in certain styles+ (e.g. `cell.csl`).++ * Fix typos in comments, doc strings, error messages, and tests+ (Albert Krewinkel, #6738).++## pandoc 2.11.0.1 (2020-10-13)++ * LaTeX reader: support more acronym commands (#6746):+ `\acl`, `\aclp`, and capitalized versions of already+ supported commands.++ * Commonmark reader: add `pipe_table` extension *after* defaults (#6739).+ Otherwise we get bad results for non-table, non-paragraph+ lines containing pipe characters.++ * Markdown writer: Fix autolinks rendering for gfm (#6740).+ Previously, autolinks rendered as raw HTML, due to the+ `class="uri"` added by pandoc's markdown reader.++ * LaTeX writer:++ + Escape option values in lstlistings environment (#6742).+ + Fix handling of `lang` `pt-BR` (#2953). For polyglossia we now+ use `\setmainlanguage[variant=brazilian]{portuguese}` and for babel+ `\usepackage[shorthands=off,main=brazilian]{babel}`.++ * Depend on latest citeproc (0.1.0.1).++ + This fixes the citation number issue with ieee.csl and other+ styles that do not explicitly sort bibliographies (#6741). (Pandoc+ was numbering them by their order in the bibliography file,+ rather than the order cited, as required by the CSL spec.)+ + Fixes groupin/collapsing with citation items with prefixes.++ * default.latex: fix `CSLReference` macro definition.++ * Fix MANUAL.txt CSL JSON conversion examples.++ * Fix spelling errors in changelog, MANUAL.txt, `doc/org.md` (#6738).+++## pandoc 2.11 (2020-10-11)++ * Add `--citeproc` (`-C`) option to trigger built-in citation processing.+ It is no longer necessary to use the external `pandoc-citeproc`+ filter. `--citeproc` behaves like a filter and can be positioned+ relative to other filters as they appear on the command line.++ The new built-in citation processing uses the citeproc library,+ a reimplementation of CSL citation processing that fixes many+ of the shortcomings of pandoc-citeproc. In general, citation+ processing should work much the same as it did with pandoc-citeproc,+ but with greater fidelity to CSL styles and better performance.+ (The tests from the pandoc-citeproc package have been carried+ over to pandoc.) The following differences should be noted:++ - At this point, only some of the writers (HTML, ms, LaTeX) properly+ interpret CSL display styles. You should get decent output in+ all formats (at least as good as with pandoc-citeproc), but+ indentation and block-alignment may not be right.++ - pandoc-citeproc searches the `~/.csl` directory for `.csl`+ styles. Pandoc instead searches the `csl` subdirectory of+ the pandoc user data directory (e.g., `~/.pandoc/csl` or+ `~/.local/share/pandoc/csl`). Users who already keep+ CSL styles in `~/.csl` may find it convenient to add a+ symlink.++ - Some of the bibliography formats supported by pandoc-citeproc (via+ hs-bibutils) are no longer supported: Copac, EndNote,+ ISI, MEDLINE, MODS, and RIS. If you use one of these formats,+ you may use the `bibutils` utility to convert to BibLaTeX.+ We now support only BibTeX, BibLaTeX, CSL JSON,+ and pandoc's YAML/Markdown analogue of CSL JSON.++ - pandoc-citeproc would always retrieve the independent parent+ of a dependent style by doing an HTTP request. pandoc will+ now first seek the independent parent locally (in the resource+ path or in the `csl` subdirectory of the pandoc user data+ directory) before resorting to HTTP. In addition, you may+ omit the `.csl` extension, e.g. `--csl zoology`.++ - Using the `--bibliography` option (or including+ `bibliography` in YAML metadata) no longer triggers+ citation processing implicitly: one must always use the+ `--citeproc` option if citation processing is wanted.++ * Add `csljson` as and input and output format. This allows pandoc+ to convert between `csljson` and other bibliography formats+ (e.g. `-f csljson -t markdown -s` or `-f bibtex -t csljson`),+ and to generate formatted versions of CSL JSON bibliographies+ (e.g., `pandoc -f csljson --citeproc pl.json -o pl.pdf`).++ * Added `bibtex`, `biblatex` as input formats. This allows pandoc+ to convert between BibLaTeX and BibTeX and other bibliography formats,+ and to generated formatted versions of BibTeX/BibLaTeX bibliographies+ (e.g., `pandoc -f biblatex --citeproc pl.bib -o pl.pdf`).++ * Raise informative errors when YAML metadata parsing fails (#6730).+ Previously the command would succeed, returning empty metadata,+ with no errors or warnings.++ * Sort languages in `--list-highlight-languages` output (#6718,+ Albert Krewinkel). Languages were previously sorted by their+ long name, which leads to unexpected results).++ * Add CSS to default HTML template (#6601, Mauro Bieg). This+ greatly improves the default typography in pandoc's HTML+ output. The CSS is sensitive to a number of variables+ (e.g. `mainfont`, `fontsize`, `linestretch`): see the manual for+ details. To restore the earlier, more spartan output, you can+ disable this with `-M document-css=false`.++ * Support `--toc-depth` option for ODT writer (#6696, niszet).++ * Fix issues with Windows UNC paths with some options (#5127).++ * Remove `fenced_code_blocks` and `backtick_code_blocks` from allowed+ `commonmark` and `gfm` extensions. These shouldn't really be counted+ as extensions, because they can't be disabled in commonmark.+ Adjust markdown writer to check for the commonmark variant in addition+ to extensions.++ * Add these extensions to `gfm` and `commonmark`:+ `fenced_code_blocks`, `backtick_code_blocks`, `fenced_code_attributes`.+ These can't really be disabled in the reader, but they need to be enabled+ in the writer or we just get indented code.++ * Make sure proper set of extensions is recognized for `commonmark_x`.++ * Allow `gfm_auto_identifiers`, `ascii_identifiers` extensions for `docx`.++ * Markdown reader:++ + Add `Maybe FilePath` parameter to `yamlToMeta` [API change].+ + Export `yamlToRefs` [API change], a version of `yamlToMeta`+ specialized to references.+ + Set `citationNoteNum` accurately in citations.+ + Revise abbreviation support. Don't insert a nonbreaking space after a+ potential abbreviation if it comes right before a note or citation.+ This causes problems for citeproc's moving of note citations.++ * LaTeX reader:++ + Support missing siunitx commands (#6658).+ + Support `squared`, `cubed`, `tothe` in siunitx (#6657).+ + Improved uncertainty handling in slunitx.+ + Factored out siunitx stuff into separate unexposed module.+ + Fix improper empty cell filtering (#6689, Christian Despres).+ + Fix parsing of "show name" in `\newtheorem` (#6734).+ Previously we were just treating it as a string and+ ignoring accents and formatting.+ + Prevent wrong nesting of `\multirow` and `\multicolumn` table+ cells (#6603, Laurent P. René de Cotret).+ + Table cell parser not consuming spaces correctly (#6596,+ Laurent P. René de Cotret).+ + Change `SIRange` to `SIrange` (#6617, Emerson Harkin).+ + Allow blank lines inside `\author` (#6324).++ * DocBook reader:++ + Don't squelch space at end of emphasis and other inline elements;+ instead, move it outside the element (#6719).+ + Implement table cell alignment (#6698, Nils Carlson).+ + Implement column span support for tables (#6492, Nils Carlson).+ + Update list of block level tags (#6610).+++ * JATS reader:++ + Don't squelch space at end of emphasis and other inline elements;+ instead, move it outside the element (#6719).++ * RST reader:++ + Apply `.. class::` directly to following Header rather than creating+ a surrounding Div (#6699).++ * Docx reader:++ + Allow empty dates in comments and tracked changes (#6726, Diego+ Balseiro).++ * Markdown writer:++ + Be less aggressive about using quotes for YAML values,+ allowing e.g. a quotation mark or bracket as long as it's not at the+ beginning of the line.+ + Use double quotes for YAML metadata (#6727).+ + Sort YAML metadata keys in Markdown output case-insensitive.+++ * Asciidoc writer:++ + Support asciidoctor's block figures (#6538, argent0).++ * LaTeX writer:++ + Fix spacing issue with list in definition list.+ When a list occurs at the beginning of a definition list definition,+ it can start on the same line as the label, which looks bad.+ Fix that by starting such lists with an `\item[]`.++ * HTML writer:++ + Support intermediate table headers (#5314, Albert Krewinkel).+ + Support attributes on all table elements (Albert Krewinkel).+ + Render table footers if present (#6314, Albert Krewinkel).+ + Fix addition of `doc-biblioentry` role.+ + Support colspans and rowspans in HTML tables (#6312, Albert Krewinkel).++ * ICML writer:++ + Support internal document links (#5541, Leonard Rosenthol).+ + Changed default link state to invisible (#6676, Leonard Rosenthol).++ * Docx writer:++ + Better handle list items whose contents are lists (#5948, Michael+ Hoffmann). If the first element of a bulleted or ordered list is+ another list, then that first item would previously disappear if the+ target format is docx.+ + Separate adjacent tables (#4315). Word combines adjacent tables,+ so to prevent this we insert an empty paragraph between two+ adjacent tables.++ * Org writer:++ + Don't force blank line after headings (#6554).++ * OpenDocument writer:++ + Implement table cell alignment (#6700 Nils Carson, Mauro Bieg).+ + New table cell support with row and column spans (#6682, Nils Carson).+ + Syntax highlighting for inline code (#6711, niszet).++ * Add Text.Pandoc.Citeproc module, exporting `processCitations`+ [API change]. This depends on several other, unexported+ modules under Text.Pandoc.Citeproc.++ * Add module Text.Pandoc.Writers.CslJson, exporting `writeCslJson`.+ [API change]++ * Add module Text.Pandoc.Readers.CslJson, exporting `readCslJson`.+ [API change]++ * Add module Text.Pandoc.Readers.BibTeX, exporting `readBibTeX` and+ `readBibLaTeX`. [API change]++ * Text.Pandoc.Filter: Add `CiteprocFilter` constructor to Filter.+ [API change] This runs the processCitations transformation.+ We need to treat it like a filter so it can be placed+ in the sequence of filter runs (after some, before others).+ In FromYAML, this is parsed from `citeproc` or `{type: citeproc}`,+ so this special filter may be specified either way in a defaults file+ (or by `citeproc: true`, though this gives no control of positioning+ relative to other filters).++ * Add new exported module Text.Pandoc.Writers.AnnotatedTable [API change]+ (#6655, Christian Despres). This module (which should generally+ be imported qualified to avoid name conflicts) provides a+ `Table` type that mirrors the structure of a pandoc `Table`,+ but with added inferred information so that the writers do not have to+ lay out tables themselves. The `toTable` and `fromTable` functions convert+ between an annotated `Table` and a regular pandoc `Table`. In addition to+ producing a `Table` with coherent and well-formed annotations, the+ `toTable` function also normalizes its input table like the table+ builder does. Tests ensure that `toTable` normalizes tables exactly+ like the table builder, and that its annotations are coherent.++ * Text.Pandoc.Logging:++ + Remove unused `CouldNotParseYamlMetadata` constructor for `LogMessage`+ [API change].+ + Add `CiteprocWarning` constructor to `LogMessage` [API change].++ * Text.Pandoc.Readers.Metadata: export `yamlBsToRefs` [API change].+ These allow specifying an id filter so we parse only references+ that are used in the document.++ * Text.Pandoc.Parsing:++ + Export ParseError [API change].+ + Add `stateInNote` and `stateNoteNumber` to `ParserState`+ [API change]. These are used to populate note numbers for citation+ processing.++ * Fix apparent typos in sample.lua (#6729, William Lupton).+ Also make the writer less aggressive in escaping quotes.++ * Text.Pandoc.Options:++ + `defaultMathJaxURL`: use `tex-chtml-full` instead of `tex-mml-chtml`+ (#6599, Kolen Cheung). This drops the MathML support (which we+ don't need for HTML math rendering) and includes the full JavaScript,+ which makes it possible to use `--self-contained` (though there may+ still be issues if the required math fonts aren't available). This+ change should also reduce latency in pages with lots of formulas.+ + Add `/tex-chtml-full.js` to `defaultMathJaxURL` (#6593) Previously we+ added this in processing command line options, but not in processing+ defaults files, which was inconsistent.++ * epub.css: Fix cover page selectors and add note explaining their use+ (#6649, a-vrma).++ * Add data files needed for Text.Pandoc.Citeproc: these include+ `default.csl` in the data directory and a `citeproc` directory that+ is only used at compile-time for biblatex localizations. Note that we've+ added `file-embed` as a mandatory rather than a conditional+ dependency, because of the biblatex localization files.++ * Lua filters:++ + Add SimpleTable for backwards compatibility (#6575, Albert Krewinkel).+ A new type `SimpleTable` is made available to Lua filters. It is+ similar to the `Table` type in pandoc versions before 2.10;+ conversion functions from and to the new Table type are provided.+ Old filters using tables now require minimal changes and can use, e.g.,++ if PANDOC_VERSION > {2,10,1} then+ pandoc.Table = pandoc.SimpleTable+ end++ and++ function Table (tbl)+ tbl = pandoc.utils.to_simple_table(tbl)+ …+ return pandoc.utils.from_simple_table(tbl)+ end++ to work with the current pandoc version.++ + Make `attr` argument optional in `Table` constructor (Albert Krewinkel).+ This changes the Lua API. It is highly unlikely for this change to affect+ existing filters, since the documentation for the new Table constructor+ (and type) was incomplete and partly wrong before. The Lua API is now+ more consistent, as all constructors for elements with attributes now+ take attributes as the last parameter.++ * MANUAL.txt:++ * Add a dedicated Citations section which consolidates the information+ the manual used to contain about citation processing, and incorporates+ some information formerly found in the pandoc-citeproc man page.+ + Add note about lualatex using `selnolig`.+ + Remove duplicate `seriespage` (#6568, Blake Eryx).+ + Remove lists of support extensions for markdown variants (#6604).+ Instead, offer the advice to use `--list-extensions=FORMAT`.+ + Fix position of attributes in header (Albert Krewinkel).+ + Delete obsolete section on compact and loose lists (#6684).+++ * doc/lua-filters.md:++ + Add info on how to debug Lua filters (#6732, Ian Max Andolina).+ + Document Underline type and constructor (Albert Krewinkel).+ + Document `body` field (Albert Krewinkel).+ + Add missing header attribute+ + Add missing Link.title field (Albert Krewinkel).+ + Make the setting-the-date example conditional (the-solipsist).+ This makes the example a bit more realistic.+ + Remove outdated link table example.++ * doc/org.md:++ + Add section on tables (Albert Krewinkel).+ + Add section on handling of unknown directives (Albert Krewinkel).++ * CONTRIBUTING.md: fix typo (#6584, Dmitry Volodin).++ * Use golden test framework for command tests. This means that+ `--accept` can be used to update expected output.++ * Use the `smart` extension when generating pandoc's man page (#6613).++ * Release-candidate: don't build windows i386.+ So far we haven't been able to figure out how to get+ stack to use a 32-bit ghc.++ * Use `null` instead of deprecated `Builder.isNull`.++ * Makefile:++ + Fix macospkg target to fetch target from S3 artifacts.+ + Fix pandoc-templates target to include all partials.++ * Remove duplicated dependency in pandoc.cabal (#6591, Felix Yan).++ * Sort build depends in pandoc.cabal alphabetically (#6691,+ Albert Krewinkel).++ * Add .travis.yml for macos release candidate build (#6622).+ We need to build the release candidate on Travis rather+ than GitHub actions, because GH has macos 10.15, and+ binaries compiled on that OS will not work with 10.13.+ This build is only triggered on `rc/*` branches.++ * Remove instructions for building pandoc-citeproc from CI and+ release binary build instructions. We will no longer distribute+ pandoc-citeproc.++ * Fix math rendering in trypandoc (this broke after+ commit d8ad766d17603784b86fc5c2e1b22864125d04d1).++ * Use latest versions of skylighting, commonmark (#6589),+ comonmark-extensions, commonmark-pandoc, texmath.++ * Relax version bounds for hslua, hslua-module-text, bytestring.++ * Use released pandoc-types 1.22. This changes the JSON+ encoding slightly for the new table types introduced+ in 1.21, so they're more consistent with the rest.+ Developers of libraries for pandoc filters will want+ to take note.++ * Fix hlint suggestions, update hlint.yaml (#6680, Christian Despres).++ * Code cleanup (#6678, Joseph C. Sible).++ * Add haddocks to functions in Text.Pandoc.Writers.Shared (Albert+ Krewinkel).++ * Remove duplicate `tshow` definition.++ * Linux release candidate build: use ghc-musl container. This simplifies+ our build process (over using a customized alpine container).+++## pandoc 2.10.1 (2020-07-23)++ * Add `commonmark_x` output format. This is `commonmark` with a number+ of useful pandoc extensions enabled.++ * Many more extensions now work with `commonmark` and `gfm`.++ * Add generic `attributes` extension. This allows attributes to+ be added to any block or inline element in a uniform way. Since+ the Pandoc AST doesn't include attributes on each element type,+ the attributes will sometimes be added by creating a surrounding+ Div or Span container. Currently this extension is only+ compatible with the `commonmark` and `gfm` readers.++ To add an attribute to a block-level element, e.g. a paragraph,+ put it before the block:+ ```+ {#mypara}+ This is a paragraph.+ ```+ Multiple attributes may be used and will be combined:+ ```+ {#mypara}+ {.blue .warning key="val"}+ This is a paragraph.+ ```+ To add an attribute to an inline-level element, put it+ immediately after the element:+ ```+ *emphasized text*{.special}+ ```++ * Support `--number-sections` for docx output (#1413).++ * LaTeX reader:++ + Support `\SIRange` reader (#6418, Emerson Harkin).+ + Support table col-span and row-span (#6311, Laurent P. René de Cotret).+ Supports `\multirow` and `\multicolumn`.+ + Support amsthm: `\newtheorem`, `\theoremstyle`, and theorem and+ proof environments, including labels and references. The only thing+ that is unsupported is the second optional argument, which causes+ numbering to be reset after the specified series is incremented.+ + Moved some code to T.P.LaTeX.Parsing. We need to reduce the size+ of the LaTeX reader to ease compilation on resource-limited systems.++ * RST reader:++ + Fix csv tables with multiline cells (#6549).+ + Fix spurious newlines in some attributes from directives.+ + Avoid extra newline in included code blocks.++ * Commonmark reader:++ + Switch from cmark-gfm to commonmark-hs for commonmark and gfm+ parsing. This avoids depending on a C library+ and allows us to support more pandoc extensions for+ `commonmark` and `gfm`.++ * DocBook reader:++ + Parse releaseinfo as metadata (#6542).++ * Docx reader:++ + Only use `bCs/iCs` on runs with `rtl` or `cs` property (#6514, Nikolay+ Yakimov).+ + Code cleanup/refactoring (Nikolay Yakimov).++ * Org reader (Albert Krewinkel):++ + Respect export setting which disables entities+ MathML-like entities, e.g., `\alpha`, can be disabled with the+ `#+OPTION: e:nil` export setting (Albert Krewinkel).+ + Respect export setting disabling footnotes. Footnotes can be removed+ from the final document with the `#+OPTION: f:nil` export setting.+ + Respect tables-excluding export setting. Tables can be removed from+ the final document with the `#+OPTION: |:nil` export setting.++ * Markdown writer:++ + Move `asciify` out of `escapeString`. Otherwise `unsmartify`+ doesn't catch quotes that have already been turned to entities.+ + Add `writeCommonmark` (new exported function, API change).+ + Use unicode super/subscript characters when possible if the+ `superscript` or `subscript` extension or `raw_html` aren't available.+ + Render caption as following paragraph when `table_caption` extension+ is not enabled.+ + Use numerical labels for reference links that are longer+ than 999 characters or contain square brackets, for conformity+ with commonmark (#6560).++ * Commonmark writer:++ + Instead of using cmark-gfm, use `writeCommonmark` from the+ Markdown writer. This function calls the markdown writer+ with appropriate extensions and a few small modifications+ (e.g. not requiring backslashes before spaces inside+ super/subscripts). With this change `comonmark` and+ `gfm` output can be used with a wider selection of+ extensions.++ * Jira writer: keep image caption as alt attribute (#6529, Albert+ Krewinkel).++ * HTML writer:++ + Improve alt-text/caption handling for HTML5 (#6491, Albert Krewinkel).+ Screen readers read an image's `alt` attribute and the figure caption,+ both of which come from the same source in pandoc. The figure caption is+ hidden from screen readers with the `aria-hidden` attribute. This+ improves accessibility. For HTML4, where `aria-hidden` is not allowed,+ pandoc still uses an empty `alt` attribute to avoid duplicate contents.++ * Ms writer:++ + Fix code highlighting with blank lines. Previously blank lines+ were simply omitted from highlighted code.+ + Escape starting periods in ms writer code blocks (#6505, Michael+ Hoffmann). If a line of ms code block output starts with a period (.),+ it should be prepended by `\&` so that it is not interpreted as a roff+ command.++ * Text.Pandoc.Extensions:++ + Add `raw_markdown` extension (which only affects `ipynb`+ input).+ + Trim down `githubMarkdownExtensions`.+ Previously it included all of the following, which make+ sense for the legacy `markdown_github` but not for `gfm`,+ since they are part of base commonmark and thus+ can't be turned off in `gfm`:++ - `Ext_all_symbols_escapable`+ - `Ext_backtick_code_blocks`+ - `Ext_fenced_code_blocks`+ - `Ext_space_in_atx_header`+ - `Ext_intraword_underscores`+ - `Ext_lists_without_preceding_blankline`+ - `Ext_shortcut_reference_links`++ These have been removed from `githubMarkdownExtensions`, though+ they're still turned on for legacy `markdown_github`.+ + Add `Ext_attributes` constructor for `Extension` [API change].++ * LaTeX template: use selnolig to selectively suppress ligatures with+ lualatex (#6534).++ * Benchmark bytestring readers (Nikolay Yakimov).++ * Documentation:++ + Update using-the-pandoc-api.md (favonia).+ + Fix Typos in lua-filters.md (tajmone).+ + Rewrite Raw HTML/TeX section in MANUAL.txt to avoid duplicate+ headings for the extensions.+ + Fix typo in MANUAL.txt (Benjamin Wuethrich).+ + Remove duplicate 'titlepage' in MANUAL.txt (Blake Eryx).+ + CONTRIBUTING.md: Advertise the official nightlies in GitHub actions.+ Replaces #6500, thanks to @ickc.++++## pandoc 2.10 (2020-06-29)++ * Use pandoc-types 1.21. This adds two things:++ + A native Underline constructor for Inline (#6277, Vaibhav Sagar).+ + More expressive types for tables (#1024, Christian Despres).+ Tables can now take attributes; and rowspans and colspans,+ column headers, multiple row headers, table head and foot+ can all be represented. (Note, however, that reader and+ writer support for these features is still lacking, so+ most users won't see any differences in table conversion+ yet. These changes just lay the foundation for further+ improvements.)++ * Support new Underline element in readers and writers (#6277,+ Vaibhav Sagar).++ * Support new Table type (Christian Despres).+ The Builder.simpleTable now only adds a row to the TableHead+ when the given header row is not null. This uncovered an+ inconsistency in the readers: some would unconditionally+ emit a header filled with empty cells, even if the header+ was not present. Now every reader has the conditional+ behaviour. Only the XWiki writer depended on the header row+ being always present; it now pads its head as necessary.++ * Add an option to disable certificate validation (#6156, Cédric Couralet,+ Cécile Chemin, Juliette Fourcot). This commit adds the option+ `--no-check-certificate`, which disables certificate checking when+ resources are fetched by HTTP.++ * Unify defaults and markdown metadata parsers (#6328, Nikolay+ Yakimov). Clean up code in Text.Pandoc.Readers.Metadata and+ properly handle errors in `yamlToMeta`. This fixes parsing+ of Boolean fields in metadata withinin defaults files and reduces+ code duplication.++ * Docbook reader:++ + Implement `<procedure>` (#6442, Mathieu Boespflug).+ + Implement `<phrase>` (#6438, Mathieu Boespflug).+ + Treat envar and systemitem like code (#6435, Mathieu Boespflug).+ + Implement `<replaceable>` (#6437, Mathieu Boespflug)+ + Map `<simplesect>` to unnumbered section (#6436, Mathieu Boespflug).++ * JATS reader:++ + Handle "label" element in section title (#6288).+ + Parse abstract element into metadata field of same name+ (#6480, Albert Krewinkel).++ * Jira reader (Albert Krewinkel):++ + Resolve multiple parsing problems, including issues with empty+ table cells, faulty recognition of closing emphasis characters, and+ parsing of image attributes (#6212, #6219, #6220).+ + Two consecutive markup chars are now parsed verbatim (#6343);+ styled text must not be empty.+ + Newlines are no longer allowed within styled text (#6325).+ + Links to anchors are now parsed as links (#6407).+ + Retain image attributes (#6234). Jira images attributes as in+ `!image.jpg|align=right!` are retained as key-value pairs. Thumbnail+ images, such as `!example.gif|thumbnail!`, are marked by a+ `thumbnail` class in their attributes.+ + Use Underline for inserted text (#6237). Previously, the span was+ marked with the non-standard class `inserted`.+ + Improve icon conversion for `(/)`, `(x)`, `(!)`, `(?)`+ `(+)`, `(-)`, `(off)`, `(*)`. (#6236, #6264).+ + Support citations, attachment links, and user links (#6231, #6238,+ #6239).+ + Resolve parsing issues of blockquote, color (#6233, #6235).++ * HTML reader:++ + Parse attributes into table attributes.+ + Support `<bdo>` (#5794, Tristan de Cacqueray).+ + Add `summary` to list of block-level HTML tags (#6385).+ This improves support for summary/details inside Markdown.+ NOTE: you need to include a blank line before the closing+ `</details>`, if you want the last part of the content to+ be parsed as a paragraph.+ + Fix parsing unclosed th elements in a table (#6247).++ * Commonmark reader: Implement `implicit_figures` extension (#6350).++ * Markdown Reader:++ + Fix inline code in lists (#6284, Nikolay Yakimov).+ Previously inline code containing list markers was sometimes+ parsed incorrectly.+ + Don't require blank line after grid table (#6481).+ This allows grid tables to be enclosed in fenced divs with no+ intervening blank lines.++ * LaTeX reader:++ + Don't parse beyond `\end{document}` (#6380).+ This required some internal changes to `\subfile` handling.+ + Better handling of `\lettrine`. SmallCaps instead of Span+ for the part after the initial capital. Ensure that both+ arguments are parsed, so that in Markdown both+ are treated as raw LateX. (Closes #6258.)++ * Org reader (Albert Krewinkel):++ + Recognize images with uppercase extensions (#6472).+ + Keep unknown keyword lines as raw org. The lines of unknown+ keywords, like `#+SOMEWORD: value` are no longer read as metadata,+ but kept as raw `org` blocks. This ensures that more information+ is retained when round-tripping org-mode files; additionally,+ this change makes it possible to support non-standard org+ extensions via filters.+ + Unify keyword handling. Handling of export settings and other+ keywords (like `#+LINK`) has been combined and unified.+ + Support `LATEX_HEADER_EXTRA` and `HTML_HEAD_EXTRA`+ settings. These export settings are treated like their non-extra+ counterparts, i.e., the values are added to the `header-includes`+ metadata list.+ + Allow multiple `#+SUBTITLE` export settings. The values of all+ lines are read as inlines and collected in the `subtitle`+ metadata field.+ + Read `#+INSTITUTE` values as text with markup. The value is+ stored in the `institute` metadata field and used in the+ default beamer presentation template.+ + The behavior of the `#+AUTHOR` and `#+KEYWORD` export+ settings has changed: Org now allows multiple such lines+ and adds a space between the contents of each line. Pandoc+ now always parses these settings as meta inlines; setting+ values are no longer treated as comma-separated lists.+ Note that a Lua filter can be used to restore the previous+ behavior.+ + Read description lines as inlines (#6485). `#+DESCRIPTION` lines+ are now treated as text with markup. If multiple such+ lines are given, then all lines are read and separated by soft+ linebreaks.+ + Honor tex export option (#4070). The `tex` export option can be set+ with `#+OPTION: tex:nil` and allows three settings:+ `t` (the default) causes LaTeX fragments to be parsed as TeX or added+ as raw TeX. `nil` removes all LaTeX fragments from the document.+ `verbatim` treats LaTeX as text.+++ * RST reader:++ + Pass arbitrary attributes through in code blocks (#6465).+ Exceptions: name (which becomes the id), class (which becomes the+ classes), and number-lines (which is treated specially to fit+ with pandoc highlighting).+ + Handle `date::` directive (#6276).++ * Textile reader: support `pre.` for code blocks (#6454).++ * Ipynb reader:++ + Implement `raw_markdown` extension (#5408). Specifying+ `-f ipynb+raw_markdown` will cause Markdown cells+ to be represented as raw Markdown blocks, instead of being+ parsed. This is not what you want when going from `ipynb`+ to other formats, but it may be useful when going from `ipynb`+ to Markdown or to `ipynb`, to avoid semantically insignificant+ changes in the contents of the Markdown cells that might+ otherwise be introduced.+ + Handle application/pdf output as image (#6430).+ + Properly handle image/svg+xml as an image (#6430).++ * Docx reader:++ + Distinguish between docx parsing and docx container unpacking errors.++ * MediaWiki reader:++ + Fix `gfm_auto_identifiers` so that `-` is not replaced by `_` (#6335).++ * Vimwiki reader:++ + Add nested syntax highlighting (#6256, Vlad Hanciuta).+ Nested syntaxes are specified like this:+ ```+ {{{sql+ SELECT * FROM table+ }}}+ ```+ The preformatted code block parser has been extended to check if the+ first attribute of the block is not a `key=value` pair, and in that+ case it will be considered as a class.+++ * Jira writer (Albert Krewinkel):++ + Always escape braces (#6478). Braces are now always escaped, even+ within words or when surrounded by whitespace. Jira and+ Confluence treat braces specially.+ + Convert Underline to inserted text (`+inserted+`).+ + Add image attributes (#6234). Image attributes are added+ to the output as image parameters. If the image has a+ class "thumbnail", then a thumbnail image is generated;+ all other attributes are discarded in this case.++ * LaTeX writer:++ + Ensure that `-M csquotes` works even in fragment mode (#6265).+ + Escape `^` specially for listings (#6460).+ + Create hypertarget for links with identifier (#6360).+ + Distinguish between single and double quotes when using enquote+ package (#6457, dbecher-ito).+ + Add support for customizable alignment of columns in beamer (#6331,+ andrebauer).+ + Add support for customizable alignment of columns in beamer+ (#4805, #4150, andrebauer).++ * HTML writer:++ + Use CSS in favor of `<br>` for display math (#6372)+ Some CSS to ensure that display math is+ displayed centered and on a new line is now included+ in the default HTML-based templates; this may be+ overridden if the user wants a different behavior.++ * Org writer:++ + Clean-up Div handling (Albert Krewinkel).++ * Docx writer:++ + Enable column and row bands for tables (#6371).+ This change will not have any effect with the default style.+ However, it enables users to use a style (via a reference.docx)+ that turns on row and/or column bands.++ * OpenDocument (and ODT) writer:++ + Add custom-style "Abstract" in metadata abstract.+ This ensures that the abstract is rendered with style Abstract.+ + Enable custom-style attribute on a Div.+ This allows you to apply a custom style to contained paragraphs.++ * DocBook writer:++ + Add id of figure to enclosed image.+ + Add personname element to docbook author (#6244).++ * FB2 writer:++ + Properly handle cover-image containing spaces (#6391).++ * Markdown writer:++ + Ensure consistent padding for pipe tables (#6240).+ + Avoid unnecessary escapes before intraword `_` when+ `intraword_underscores` extension is enabled (#6296).++ * RST writer:++ + Properly handle images with same alt text (#6194).+ Previously we created duplicate references for these in rendering RST.++ * AsciiDoc writer:++ + Add blank line after Div (#6308).++ * Haddock Writer:++ + Support Haddock tables (Joe Hermaszewski).+ See this PR on Haddock for details on the table format:+ <https://github.com/haskell/haddock/pull/718>.++ * PowerPoint writer (Jesse Rosenthal):++ + Write math input verbatim in speaker notes (#6301).+ OMML in speaker notes would lead to corrupt PowerPoint output. We now+ output the OMML verbatim as LaTeX in the speaker notes.++ * LaTeX template: Make polyglossia package options list-aware+ (#6444, Frederik Elwert).++ * Reveal.js template:++ + Update template for reveal.js 4.0.0 (#6390, Salim B).+ + Update template with newly available options (#6347, Jake Zimmerman).+ + Use CDN version of revealjs v4 by default (#6408).++ * opendocument template: Add abstract and subtitle to opendocument+ template (#6369).++ * reference.odt: clean up styles. Add Abstract.+ Change Author, Date to centered paragraphs with no character+ styling.++ * epub.css: wrap overlong lines in highlighted code blocks (#6242).+ This fixes a problem in iBooks v2.4 with our earlier+ horizontally scrolling code blocks. The problem seems to+ be a bug in iBooks, not pandoc, but since iBooks is a major+ target we're changing pandoc's default behavior so that+ pandoc-produced epubs work on that platform.++ * Text.Pandoc.PDF:++ + Use `--enable-local-file-access` in invoking `wkhtmltopdf` (#6474).+ `wkhtmltopdf` changed in recent versions to require this for+ access to local files. This fixes PDF via HTML5 with `--css`.+ + Send verbose output to stderr, not stdout (#6483).++ * Text.Pandoc.MIME: Fix MIME type for TrueType fonts in EPUBs+ (#6464, Michael Reed).++ * Text.Pandoc.Shared:++ + `makeSections`: omit number attribute when unnumbered class+ is present (#6339). Previously the attribute was included but given+ an empty value, and this caused the table of contents creation+ functions in Text.Pandoc.Writers.Shared to think these items had+ numbers, which meant that they were included in the TOC even if the+ `unlisted` class was used.+ + Deprecate `underlineSpan` in Shared in favor of+ `Text.Pandoc.Builder.underline` (Vaibhav Sagar).+ + `renderTags'`: use self-closing tag for col element (#6295).++ * Text.Pandoc.UUID: Fix `getRandomUUID`, which previously would+ return the same value twice in a row. Make `getRandomUUID`+ polymorphic in PandocMonad. Remove `getUUID` (#6228, Joseph C. Sible).++ * Text.Pandoc.Class: Generalize `PandocIO` functions to `MonadIO`.++ * Fixed Katex standalone script (#6399, Lucas Escot).+ Global macros are now persistent when using the HTML Writer with the+ `--katex` option.++ * Lua subsystem (Albert Krewinkel):++ + Use new type PandocLua for all pandoc Lua operations (API change).+ The new type `PandocLua` is an instance of the `PandocMonad` typeclass+ and can thus be used in a way similar to `PandocIO`.+ + Use PandocError for exceptions in Lua subsystem (API change).+ The PandocError type is used throughout the Lua subsystem. All Lua+ functions throw an exception of this type if an error occurs. The+ `LuaException` type is removed and no longer exported from+ `Text.Pandoc.Lua`. In its place, a new constructor `PandocLuaError`+ is added to PandocError.++ * Lua filters: improve error messages for failing filters (#6332,+ Albert Krewinkel). Print the Lua error properly instead of+ displaying their `show` string.++ * Use latest skylighting. This fixes a bug with lua multiline+ comments (and may improve handling of other syntaxes as well).+ IT also adds `aria-hidden="true"` to the empty a elements, which+ helps people who use screen readers.++ * Use latest texmath.++ * Require latest doctemplates 0.8.2.+ This adds support for template pipes `first`, `rest`,+ `last`, `allbutlast`.++ * Revert 0e48a02 and dependency on base-noprelude, which hasn't+ been updated for ghc 8.10 (see #6187).++ * Dependency adjustments:++ + Allow haddock-library 1.9.x.+ + Allow hslua 1.1 (#6243, Felix Yan).+ + Allow base64-bytestring 1.1.+ + Use latest jira-wiki-markup.+ + Allow http-client 0.7.+ + Allow tasty 1.3.x.+ + Allow aeson 1.5 (#6400, Felix Yan).+ + Remove unused dependency `vector` (#6462, Laurent P. René de Cotret).+ + Bump QuickCheck upper bound.++ * Significant code cleanup and simplification (Joseph C. Sible, #6223,+ #6209, #6225, #6229, #6226, #6340).++ * Remove unnecessary hlint ignores (#6341, Joseph C. Sible).++ * Remove obsolete RelaxedPolyRec extension (#6487, Nikolay Yakimov).++ * trypandoc improvements (Mike Tzou):++ + Add standalone option to the command text (#6210).+ + Update third party libraries.++ * MANUAL.txt:++ + Clarify template partial naming (#6476, Mauro Bieg).+ + Describe `jira` as "Jira/Confluence wiki markup" (#6351, Albert+ Krewinkel). In the past, Jira's wiki markup was also used by -- and+ could be imported into -- Atlassian Confluence.+ + Add link to print-css.rocks (#6272, Mauro Bieg).+ + Clarify pipe table column width adjustment (#6254).+ + Fix ATX header syntax.+ + Fix misleading note about image size conversions (#6353).+ + Update links to reveal.js documentation (#6386, Salim B).+ + Separate adjacent verbatim code blocks (#6307, tom-audm).++ * org.md:++ + Document behavior of `smart` extension (#4387, Albert Krewinkel).+ + Describe all supported export options in detail.++ * lua-filters.md:++ + Fix description of BulletList Lua type (Levi Gruspe).+ + Use pandoc.system module in TikZ example (Albert+ Krewinkel). Showcase temporary directory handling with+ `with_temporary_directory` and `with_working_directory`.++ * INSTALL.md: fix FreeBSD port link (#6422, Mo).+ The FreeBSD port was renamed from pandoc to hs-pandoc in 2010.+ The old pandoc port is still at version 1.5.1.1++ * Propagate `(DY)LD_LIBRARY_PATH` in tests (#6376, Lila).++ * Bump `cabal-version` to 2.2 (#6377).++ * Make it possible to compile using Stack on NixOS (#6439, Mathieu+ Boespflug).++ * CI action to check for commit message length (Nikolay Yakimov, #6398).+++## pandoc 2.9.2.1 (2020-03-23)++ * Markdown reader: Fix table alignment when heading begins with t (#6153).+ Due to a typo (`t` instead of `\t`) we were center aligning column+ headings that begin with a lowercase `t`!++ * Text.Pandoc.Readers.Roff:++ + Fix parsing of `\.` in man/ms readers (#6175).+ Previously due to a typo it was being parsed as `` ` ``.+ + Fix parsing of `\'` in man/ms readers (#6175). It was being parsed+ as a backtick.++ * Jira reader (Albert Krewinkel):++ + Fix parsing of tables without preceding blankline (#6198).+ A bug was fixed which caused faulty parsing if a table was not+ preceded by a newline and the first table cell had no space+ after the initial `|` characters.+ + Fix parsing of strikeout, emphasis (#6196). A bug was fixed which+ caused non-emphasized text containing digits and/or non-special+ symbols (like dots) to sometimes be parsed incorrectly.+ + Support colored inline text, indented lists (#6183, #6184).++ * Ms writer:++ + Fix definition lists so indent even when paragraph indent is+ set to 0 (as is the default). Also ensure indent for display math+ that falls back to TeX.+ + Use `.QS/.QE` instead of `.RS/.RE` for block quotes.++ * EPUB writer: fix regression on detection of front/back/bodymatter+ (#6170). This bug caused sections with epub:type `dedication` to be+ misplaced in bodymatter instead of frontmatter as specified+ in the manual. The same problem would affect other epub:types.+ The pattern matching needed to be changed with the use of+ `makeSection`.++ * AsciiDoc writer: remove redundant `otherwise` guard in+ `inlineToAsciiDoc` (#6146, Ryan Scott).++ * Text.Pandoc.Class:++ + Fix missing import when data files are not embedded (Albert Krewinkel).+ + Subdivide Text.Pandoc.Class into small unexported modules+ and ensure that all functions have Haddock documentation (#6106,+ Albert Krewinkel).+ + Finer grained imports of Text.Pandoc.Class submodules (#6203, Albert+ Krewinkel).++ * Text.Pandoc.XML: Add to list of HTML5 attributes:+ `allow`, `autocapitalize`, `decoding`, `enterkeyhint`,+ `imagesizes`, `imagesrcset`, `loading`.++ * Use implicit Prelude (#6187, Albert Krewinkel).+ The previous behavior was introduced as a fix for #4464. It seems that+ this change alone did not fix the issue, and `stack ghci` and `cabal+ repl` only work with GHC 8.4.1 or newer, as no custom Prelude is loaded+ for these versions. Given this, it seems cleaner to revert to the+ implicit Prelude.++ * Always use custom prelude (#6187, Albert Krewinkel).+ Previously, the custom prelude was used only with older GHC versions, as+ a workaround for problems with ghci. The ghci problems are resolved by+ replacing package `base` with `base-noprelude`, allowing for consistent+ use of the custom prelude across all GHC versions.++ * Remove outdated checks for no longer supported base versions+ (Albert Krewinkel).++ * PDF via wkhtmltopdf: put user-specified options last (#6171).+ Certain options (e.g. `cover`) need to come after flags on+ the command line.++ * Text.Pandoc.App: set resource path at the beginning so it can affect+ things like include-in-header (#5982).++ * Change macOS release candidate CI process so that notarized+ packages can be produced (#6169).++ * Make MANUAL more explicit about nonbreaking space handling by+ `all_symbols_escapable` (#6154, Fabien Schurter).++ * trypandoc (Mike Tzou):++ + Add checkbox for standalone option (#6189).+ + Use strict mode for JavaScript code (#6188).+ + Fetch resources over https (#6188).+ + Remove unnecessary attributes on style, script elements (#6188).++ * Use details tag to make GitHub releases changelog collapsible.++ * Update filter code in doc/filters.md so it works with latest pandoc+ (#6185).++ * linux/Dockerfile: upgrade to alpine 3.11 (#6180, Albert Krewinkel).+ This is used to build the static linux binaries.+++## pandoc 2.9.2 (2020-02-15)++ * Add `csv` as an input format (#6100). The CSV table is converted into a+ pandoc simple table. A new module Text.Pandoc.Readers.CSV+ exports `readCSV` [API change].++ * Introduce new format variants for JATS writer (#6014, Albert Krewinkel):++ - `jats_archiving` for the "Archiving and Interchange Tag Set",+ - `jats_publishing` for the "Journal Publishing Tag Set", and+ - `jats_articleauthoring` for the "Article Authoring Tag Set."++ The `jats` output format is now an alias for `jats_archiving`.+ The module Text.Pandoc.Writers.JATS now exports+ `writeJatsArchiving`, `writeJatsPublishing`, and+ `writeJatsArticleAuthoring`, as well as the legacy+ `writeJATS` [API change].++ * `--defaults`: Support `bibliography` and `csl` fields.+ Move `addMeta` from Text.Pandoc.App.CommandLineOptions to+ Text.Pandoc.App.Opt (internal change).++ * Add timing info for filters in `--verbose` mode (#6112).+ When verbose mode is specified (verbosity == INFO), print a+ notice when running a filter and when a filter completes (including+ timing).++ * LaTeX reader:++ + Allow `&` in LaTeX citation keys (#6110).+ + Improve caption and label parsing.+ + Don't emit empty Span elements for labels.+ + Put tables with labels in a surrounding Div.+ + Resolve `\ref` to table numbers (#6137).+ + Skip comments in more places where this is needed (#6114).+ + Allow beamer overlays for all commands in all raw tex (#6043).+ This affects parsing of raw tex in LaTeX and in Markdown and+ other formats.+ + Improve parsing of raw environments (#6034). If parsing fails+ in a raw environment (e.g. due to special characters like unescaped+ `_`), try again as a verbatim environment, which is less sensitive to+ special characters. This allows us to capture special environments+ that change catcodes as raw tex when `-f latex+raw_tex` is used.++ * RST reader:++ + Add highlight directive (#6140, Lucas Escot).++ * MediaWiki writer:++ + Prevent triple `[[[` which confuses MediaWiki (#6119).++ * HTML reader:++ + Don't parse `data-id` as `id` attribute. And similarly don't+ parse any `data-X` as `X` when `X` is a valid HTML attribute.++ * Org reader:++ + Simplify parsing of sub- and superscripts (#6127, Albert Krewinkel).+ Speeds up parsing of single-word, markup-less sub- and superscripts.++ * LaTeX writer:++ + Group biblatex citations even with prefix and suffix (#5849, Ethan+ Riley). Previously biblatex citations were only grouped if there+ was no prefix. This patch allows them to be grouped in subgroups split+ by prefixes and suffixes, which allows better citation sorting.+ + Fix regression in handling of columns in beamer slides (#6033).+ Columns in title slides were causing problems with+ slide division.+ + Fix duplicate frame classes in LaTeX/Beamer output (#6107).++ * HTML writer:++ + Fix duplicate attributes on headings (#6062), regression from 2.7.x.+ + Fix `--number-offset` with HTML TOC. Eventually it would be worth+ adding a parameter to `makeSections` so this could be done at that+ level; then it would also affect other writers that construct+ TOC manually.+ + reveal.js: restore old behavior for 2D nesting (#6032).+ The fix to #6030 actually changed behavior, so that the+ 2D nesting occurred at slide level N-1 and N, instead of+ at the top-level section. This commit restores the v2.7.3 behavior.+ If there are more than 2 levels, the top level is horizontal+ and the rest are collapsed to vertical.+ + reveal.js: ensure that pauses work even in title slides (#5819).++ * Markdown writer:++ + Fix regression: spurious dots in markdown_mmd metadata output (#6133).++ * Docx writer:++ + Fix regression with Compact style on tight lists (#6072).+ Starting in 2.8, the docx writer no longer distinguishes between tight+ and loose lists, since the Compact style is omitted. This is a+ side-effect of the fix to #5670, as explained in the changelog. This+ patch fixes the problem by extending the exception currently offered to+ Plain blocks inside tables to Plain blocks inside list items.++ * Jira writer:++ + Fix output of table headers (Albert Krewinkel, #6035).++ * Add Text.Pandoc.Image with unexported svgToPng.++ * Text.Pandoc.XML: Export `html5Attributes`, `html4Attributes`,+ `rdfaAttributes` (formerly unexported in Text.Pandoc.Writers.HTML).+ [API change]++ * Text.Pandoc.Shared: Export a new function `findM` (#6125,+ Joseph C. Sible).++ * Text.Pandoc.Logging: Add `RunningFilter`, `FilterCompleted`+ constructors to LogMessage [API change].++ * Text.Pandoc.CSV: fix bug in CSV parser; previously an extra blank record+ would sometimes be inserted at the end.++ * LaTeX template: add space option to xeCJK with PassOptionsToPackage+ (#6002). Otherwise we can get a clash with documentclasses that+ already load the package.++ * Lua filters:++ + Allow filtering of element lists (#6038, Albert Krewinkel). Lists of+ Inline and Block elements can now be filtered via `Inlines` and+ `Blocks` functions, respectively. This is helpful if a filter+ conversion depends on the order of elements rather than a single+ element. For example, the following filter can be used to remove all+ spaces before a citation:++ function isSpaceBeforeCite (spc, cite)+ return spc and spc.t == 'Space'+ and cite and cite.t == 'Cite'+ end++ function Inlines (inlines)+ for i = #inlines-1,1,-1 do+ if isSpaceBeforeCite(inlines[i], inlines[i+1]) then+ inlines:remove(i)+ end+ end+ return inlines+ end++ + Add methods `insert`, `remove`, and `sort` to pandoc.List+ (Albert Krewinkel). Example of use:++ local numbers = pandoc.List {2, 3, 1}+ numbers:sort() -- numbers is now {1, 2, 3}+ + Make `pandoc.List` a callable constructor (Albert Krewinkel).+ It is now possible to construct a new List via+ `pandoc.List()` instead of `pandoc.List:new()`.+ + Add tests for pandoc.List module (Albert Krewinkel).++ * Text.Pandoc.App.CommandLineOptions: Change `setVariable` to use `Text`+ instead of `String`. This avoids some unnecessary unpacking.++ * Use versioned directory for windows release zipfile.+ Also remove old `make-windows-installer.bat`, superseded by GitHub+ actions workflow, and modify `pandoc.wxs` for new paths.++ * Extensive code cleanup (#6141, #6128, #6129, #6130, #6123,+ #6105, 6102, #6117, #6124, #6115, #6116, #6111, Joseph C. Sible).++ * Fix hlint warnings (Albert Krewinkel).++ * Use latest doclayout, doctemplates (#6031). The new version of+ doclayout fixes a memory leak that affected `--include-in-header` with+ large files (and possibly other cases involving extremely long lines).++ * Use latest texmath.++ * Use latest skylighting and fix test suite (#6086).++ * sample.lua: Fix typo in descriptive comments (#6136, Caleb Maclennan).+ Fix typo in error message (#6135).++ * Add Docker and GH Actions instructions/links to INSTALL.md.++ * Update filter documentation (#6065). Improve cabal v2 instructions.+ Remove example using pandoc API directly (we have other+ docs for that and it was outdated).++ * Lua filter docs:++ + Cross-link constructors and types (Albert Krewinkel).+ Thanks to @bpj for the idea.+ + Sort pandoc.List methods alphabetically (Albert Krewinkel).+ + Unify, fix anchors and internal links (#6061, Albert Krewinkel).+ Links and anchors now follow consistent conventions, like+ lowercase-only anchor names. This breaks some links to specific+ sections in the document, but will make it much easier to link+ documentation in the future.+ + Clarify filter function execution order (#6059, Albert Krewinkel).++ * In docs, update URLs and use `https:` wherever possible (#6090,+ Salim B).++## pandoc 2.9.1.1 (2020-01-05)++ * Markdown reader:++ + Fix parsing bug affected indented code after raw HTML (#6009, #5360).++ * LaTeX writer:++ + Fix regression in beamer slide structure with certain slide levels+ (#6030).+ + Allow framebreaks for beamer's TOC (Heiko Schlittermann, #6012)+ + Properly handle unnumbered headings level 4+ (#6018).+ Previously the `\paragraph` command was used instead of+ `\paragraph*` for unnumbered level 4 headings.++ * HTML writer:++ + Fix revealjs slide structure regression with certain slide levels+ (#6030).+ + Add newlines to make slide show output more readable.++ * Org writer:++ + Remove extra spaces from table cells (Albert Krewinkel, #6024).++ * JATS template: Update JATS dtd (Arfon Smith, #6020). Use the archiving+ and interchange DTD rather than the more restrictive journal publishing+ DTD (which doesn't permit ext-link as a valid child).++ * Text.Pandoc.PDF: Fix `runTeXProgram` so that the input source is always+ overwritten (#6027). Previously it wasn't overridden if the file already+ existed, which led to bad results on subsequent runs when+ `pdf-engine-opt=-output-directory=` was used to specify an explicit temp+ dir.++ * Text.Pandoc.BCP47: Change `getLang` to handle block-level contents+ (#6008). Some readers (e.g. RST) will populate the `lang` metadata field+ with block-level content. `getLang` has been modified to handle this.+ Previously in these cases the LaTeX writer would not properly set the+ "main language" of the document.++ * Fix `test/tables.org` (Albert Krewinkel).++ * Use HTTPS in copyright message (Felix Yan, #6010)+++## pandoc 2.9.1 (2019-12-23)++ * Add Jira reader (Albert Krewinkel, #5556).++ * Jira writer: use jira-wiki-markup renderer (Albert Krewinkel,+ #5926). The following improvements are included in this change:++ + non-jira raw blocks are fully discarded instead of showing+ as blank lines;+ + table cells can contain multiple blocks;+ + unnecessary blank lines are removed from the output;+ + markup chars within words are properly surrounded by+ braces;+ + preserving soft linebreaks via `--wrap=preserve` is+ supported.++ Note that backslashes are rendered as HTML entities, as there+ appears no alternative to produce a plain backslash if it is+ followed by markup. This may cause problems when used with+ confluence, where rendering seems to fail in this case.++ * Fix regression with `--number-sections`. Starting with 2.8,+ `--number-sections` also had the effect of `--section-divs`,+ even if `--section-divs` was not specified.++ * Improved table of contents generation in markdown, RTF,+ commonmark, better handling cases where section headings are+ enclosed in divs.++ * Ensure that later default file values for `variable` replace+ earlier ones (5988).++ * HTML reader: Add `nav` to list of block-level tags.++ * Org reader (Albert Krewinkel):++ + Wrap named table in Div, using name as id (#5984).+ Tables which are given a name via `#+NAME:` or `#+LABEL:`+ are wrapped in an additional Div, with the name set as the+ Div's ID.+ + Report parsing errors properly.+ + Fix parsing problem for colons in headline (#5993).++ * Text.Pandoc.PDF: Ensure UTF8 when printing source in+ `--verbose` mode, avoiding an error on platforms that+ default to something other than UTF-8 (#5997).++ * Text.Pandoc.Templates: Strip directory before trying to find+ partial in data files (#5987).++ * Text.Pandoc.Shared: Improve `makeSections` so we don't get+ doubled "number" attributes in EPUB output (or anywhere+ else) (#5986).++ * Added tests for `--toc` and `--section-divs`.++ * Text.Pandoc.MIME: Added glsl MIME type for WebGL maps (#6000,+ Jared Lander).++ * MANUAL: A bit clearer explanation for `--base-header-level`.+ We now say exactly how to translate between the deprecated+ `--base-header-level` and `--shift-heading-level-by`.++ * lua-filters.md:++ + Remove spurious dot in title (#5996, Mauro Bieg).+ + Replace metadata example with image centering (#6004,+ Albert Krewinkel). Thanks to @efx for proposing this filter.+++## pandoc 2.9 (2019-12-11)++ * Text.Pandoc.Templates [API change]++ + Add Monad wrappers `WithDefaultPartials` and `WithPartials`.+ Wrapping these around an instance of `PandocMonad` gives+ us different instances of `TemplateMonad`, with different+ search behavior in retrieving partials.+ To compile a template and limit partial search to pandoc's+ data files, use `runWithDefaultPartials (compileTemplate ...)`.+ To compile a template and allow partials to be found locally+ (either on the file system or via HTTP, in the event that+ the main template has an absolute URL), ue+ `runWithPartials (compileTemplate ...)`.+ + Export `getTemplate`, which seeks a template locally,+ or via HTTP if the template has an absolute URL, falling+ back to the data files if not found.+ + Export `compileDefaultTemplate` -- does `getDefaultTemplate`+ and compiles the result, raising an error on failure.++ * Text.Pandoc.Class [API change]++ + Remove `TemplateMonad` instances for `PandocIO` and `PandocPure`.+ These were too limiting and caused a bug whereby a local+ partial could be used even when the default template was requested.+ We now rely on instances provided in the Templates module.++ * Text.Pandoc.App.OutputSettings: Simplify template retrieval code.++ * ConTeXt template: Adjust to title formatting (#5949, Denis Maier).+ Add `\setupinterlinespace` to `title`, `subtitle`, `date` and `author`+ elements: otherwise longer titles that run over multiple lines will look+ squashed as `\tfd` etc. won't adapt the line spacing to the font size.++ * reveal.js template: Add title-slide-attributes variable (#5981,+ Frederik Elwert).++ * More informative JSON parse error (#5973).++ * Use external emojis package (forked from pandoc). Removed emoji data+ in Text.Pandoc.Emoji.++ * Fix regression in `makeSections` (#5965).+ Previously `hierarchicalize` (the ancestor of `makeSections`) would put+ header attributes on the containing Div. In 2.8 this behavior changed,+ which broke some tools depending on pandoc. Here we roll back this change,+ so that attributes again migrate from the header to the containing Div when+ `makeSections` is run. Note that attributes are retained on the header as+ well (unlike before) -- with the exception of the `id` attribute, which of+ course cannot be duplicated.++ * Fix `--toc-depth` regression in 2.8 (#5967).++ * Use doctemplates 0.8. Rename template 'filters' as 'pipes'+ to avoid confusion with the other notion of filter used by pandoc.++ * Fix README.md so that relative links from manual become absolute.+ Previously they'd be broken links when viewed on GitHub or Hackage.+ So we add the base URL for the pandoc manual.++ * Document display math syntax in manual.++## pandoc 2.8.1 (2019-12-05)++ * Add `ascii_identifiers` as a supported extension for `markdown`.+ This fixes a regression in 2.8.++ * Fix regression with behavior of `--variable` (#5962).+ Previously `-Vfoo=1 -Vfoo=2` would produce a list value for foo;+ with 2.8 it produced just `2`. This commit restores the earlier+ behavior.++ * Roll back part of of `--shift-heading-level-by` change (#5957).+ With positive heading shifts, starting in 2.8 this option+ caused metadata titles to be removed and changed to regular+ headings. This behavior is incompatible with the old+ behavior of `--base-header-level` and breaks old workflows,+ so we have rolled back the change. Note that there is now an+ asymmetry in positive and negative heading level shifts:+ With positive shifts, the metadata title stays the same and+ does not get changed to a heading in the body, while with+ negative shifts, a heading can be converted into the+ metadata title.++ * Text.Pandoc.Shared: Fix `makeSections` so it doesn't turn+ column Divs into sections.++ * HTML writer: add task-list class to ul if all elements are+ task list items. This will allow styling unordered task+ lists in a way that omits the bullet.++ * HTML-based templates: Add CSS to suppress bullet on unordered task lists.++ * ConTeXt template: Fix `\startcslreferences` and use ConTeXt syntax+ conventions (#5945, Denis Maier). The old version had a too large+ a skip at the beginning of the reference list.++ * LaTeX template: keep the `\author{}` command even if author is not+ specified (#5961, Yihui Xie). Avoids a LaTeX warning.++ * Generate Emoji module with TH.++ + Add Text.Pandoc.Emoji.TH.+ + Replace long literal list in Text.Pandoc.Emoji with one-liner+ generating it from `emoji.json` using TH.+ + Add Makefile target to download `emoji.json`.+ + Remove `tools/emoji.hs`.++ * Increase GC allocation space for compilation in cabal.project.++ * Clean up manual on PDF generation backend options (#5940).++ * Update release checklist to include code signing step and update+ Windows release-candidate builds (#5950).+++## pandoc 2.8.0.1 (2019-11-26)++ * List `pdf` in `--list-output-formats`.+ * EPUB writer: Fix regression with `--css` (#5937). In 2.8 `--css`+ would not have an effect on EPUB output.+ * RST writer: Use grid tables for one-column tables, since+ simple tables clash with heading syntax in this case (#5936).+ * Add unexported module Text.Pandoc.Readers.Metadata (see #5914).+ * Use doctemplates 0.7.2, which adds the `nowrap` filter to+ templates.+ * Update default man template using `nowrap` for .TH heading (#5929).+ * HTML templates: Add support for `toc-title` variable (#5930,+ Alexandre Franke).+ * Remove `grffile` (LaTeX package) requirement in MANUAL.txt+ (#5927, Ian Max Andolina).+ * Use skylighting 0.8.3.++## pandoc 2.8 (2019-11-22)++ * Improvements in templates system (from doctemplates):++ + Pandoc templates now support a number of new features that+ have been added in doctemplates: notably, `elseif`, `it`,+ partials, filters, and syntax to control nesting and reflowing of+ text. These changes make pandoc more suitable out of the+ box for generating plain-text documents from data in YAML+ metadata. It can create enumerated lists and even tabular+ structures.+ + We now used templates parameterized on doclayout Doc types.+ The main impact of this change is better reflowing of+ content interpolated into templates. Previously,+ interpolated variables were rendered independently and+ interpolated as strings, which could lead to overly long+ lines. Now the templates interpolated as Doc values which+ may include breaking spaces, and reflowing occurs after+ template interpolation rather than before.+ + Remove code from the LaTeX, Docbook, and JATS writers that+ looked in the template for strings to determine whether it+ is a book or an article, or whether csquotes is used. This+ was always kludgy and unreliable.+ + Change template code to use new API for doctemplates.++ * Add `--defaults`/`-d` option. This adds the ability to specify+ a collection of default values for options in a YAML file. For+ example, one might define a set of defaults for letters,+ and then do `pandoc -d letter myletter.md -o myletter.pdf`.+ See the documentation of this feature in MANUAL.txt.++ * Raise error on unsupported extensions (#4338).++ * The `--list-extensions[=FORMAT]` option now lists only+ extensions that affect the given FORMAT.++ * Add `-L` option as shortcut for `--lua-filter`.++ * Add `--shift-heading-level-by` option and deprecate+ `--base-heading-level` (#5615). The new option does+ everything the old one does, but also allows negative shifts.+ It also promotes the document metadata (if not null) to a+ level-1 heading with a +1 shift, and demotes an initial+ level-1 heading to document metadata with a -1 shift. This+ supports converting documents that use an initial level-1+ heading for the document title.++ * Allow `--metadata-file` to be used repeatedly to include+ multiple metadata files (Owen McGrath, #5702). Values in+ files specified first will be overridden by those in later+ files.++ * `--ascii` now uses numerical hex character references (#5718).++ * Allow PDF output to stdout (#5751). PDF output now behaves like other+ binary formats: it will not be output to the terminal, but can be+ sent to stdout using either `-o -` or a pipe. The intermediate format+ will be determined based on the setting of `--pdf-engine`.++ * Make some writers sensitive to 'unlisted' class on headings (#1762).+ If this is present on a heading with the 'unnumbered' class,+ the heading won't appear in the TOC. This class has no+ effect if 'unnumbered' is not also specified. This affects HTML-based+ writers (including slide shows and EPUB), LateX (including beamer), RTF,+ and PowerPoint. Other writers do not yet support `unlisted`.++ * Fix `gfm_auto_identifiers` behavior with emojis (#5813). Note that+ we also now use emoji names for emojis when `ascii_identifiers`+ is enabled.++ * When `--ipynb-output` is used with the default "best" format, strip+ ANSI escape codes for non-ipynb output (#5633). These cause problems+ in many formats, including LaTeX.++ * Don't look for template files remotely for remote input (#5579).+ Previously pandoc would look for the template at a remote URL when a+ URL was used for the input file, instead of taking it from the+ data directory.++ * Allow combining `-Vheader-includes` and `--include-in-header` (#5904).+ Previously `header-includes` set as a variable would be+ clobbered by material included using `--include-in-header`.++ * Change merge behavior for metadata. Previously, if a document+ contained two YAML metadata blocks that set the same field, the+ conflict would be resolved in favor of the first. Now it is resolved+ in favor of the second (due to a change in pandoc-types).+ This makes the behavior more uniform with other things in pandoc+ (such as reference links and `--metadata-file`).++ * Don't add a newline to fragment output if there's already one.++ * Change exit codes and document in MANUAL.txt:++ + `PandocAppError` was 1, is now 4+ + `PandocOptionError` was 2, is now 6+ + `PandocMakePDFError` was 65, is now 66++ * Switch to new pandoc-types and use Text instead of String [API change].+ (Christian Despres, #5884).++ * HTML reader:++ + Better handling of `<q>` with cite attribute (#5798, Ole Martin Ruud).+ If a `<q>` tag has a `cite` attribute, we interpret it as a Quoted+ element with an inner Span.+ + Add support for HTML `<samp>` element (#5792, Amogh Rathore).+ The `<samp>` element is parsed as Code with class `sample`.+ + Add support for HTML `<var>` element (#5799, Amogh Rathore).+ The `<var>` element is parsed as Code with class `variable`.+ + Add support for `<mark>` elements (Florian B, #5797). Parse+ `<mark>` elements from HTML as Spans with class `mark`.+ + Add support for `<kbd>` elements, parsing them as Span with class+ `kbd` (Daniele D'Orazio, #5796).+ + Add support for `<dfn>`, parsing this as a Span with class `dfn`+ (#5882, Florian Beeres).++ * Markdown reader:++ + Headers: don't parse content over newline boundary (#5714).+ + Handle inline code more eagerly within lists (Brian Leung, #5627).+ + Removed some needless lookaheads.+ + Don't parse footnote body unless extension enabled.+ + Fix small super/subscript issue (#5878). Superscripts and subscripts+ cannot contain spaces, but newlines were previously allowed+ (unintentionally). This led to bad interactions in some cases+ with footnotes. With this change newlines are also not allowed inside+ super/subscripts.+ + Use `take1WhileP` for `str`, table row. This yields a small but+ measurable performance improvement.+++ * LaTeX reader:++ + Fix parsing of optional arguments that contain braced text (#5740).+ + Don't try to parse includes if `raw_tex` is set (#5673).+ When the `raw_tex` extension is set, we just carry through+ `\usepackage`, `\input`, etc. verbatim as raw LaTeX.+ + Properly handle optional arguments for macros (#5682).+ + Fix `\\` in `\parbox` inside a table cell (#5711).+ + Improve `withRaw` so it can handle cases where the token string is+ modified by a parser (e.g. accent when it only takes part of a Word+ token) (#5686). This fixes a bug that caused the ends of+ certain documents to be dropped.+ + Handle `\passthrough` macro used by latex writer (#5659).+ + Support tex `\tt` command (#5654).+ + Search for image with list of extensions like latex does, if an+ extension is not provided (#4933).+ + Handle `\looseness` command values better (#4439).+ + Add `mbox` and `hbox` handling (Vasily Alferov, #5586).+ When `+raw_tex` is enabled, these are passed through literally.+ Otherwise, they are handled in a way that emulates LaTeX's behavior.+ + Properly handle `\providecommand` and `\provideenvironment` (#5635).+ They are now ignored if the corresponding command or environment+ is already defined.+ + Support epigraph command in LaTeX Reader (oquechy, #3523).+ + Ensure that expanded macros in raw LaTeX end with a space+ if the original did (#4442).+ + Treat `ly` environment from lilypond as verbatim (Urs Liska, #5671).+ + Add `tikzcd` to list of special environments (Eigil Rischel).+ This allows it to be processed by filters, in the same way that+ one can do for `tikzpicture`.++ * Roff reader:++ + Better support for `while`.+ + More improvements in parsing conditionals.+ + Fix problem parsing comments before macro.+ + Improve handling of groups.+ + Better parsing of groups (#5410). We now allow groups+ where the closing `\\}` isn't at the beginning of a line.++ * RST reader:++ + Keep `name` property in `imgAttr` (Brian Leung, #5619).+ + Fixed parsing of indented blocks (#5753). We were requiring+ consistent indentation, but this isn't required by RST.+ + Use title, not admonition-title, for admonition title.+ This puts RST reader into alignment with docbook reader.+ + Don't strip final underscore from absolute URI (#5763).+ + Avoid spurious warning when resolving links to internal anchors+ ending with `_` (#5763).++ * Org reader:++ + Accept `ATTR_LATEX` in block attributes (Albert Krewinkel, #5648).+ Attributes for LaTeX output are accepted as valid block attributes;+ however, their values are ignored.+ + Modify handling of example blocks (Brian Leung, #5717).+ + Allow the `-i` switch to ignore leading spaces (Brian Leung).+ + Handle awkwardly-aligned code blocks within lists (Brian Leung).+ Code blocks in Org lists must have their `#+BEGIN_` aligned in a+ reasonable way, but their other components can be+ positioned otherwise.+ + Fix parsing of empty comment lines (#5856, Albert Krewinkel).+ Comment lines in Org-mode can be completely empty.++ * Muse reader (Alexander Krotov):++ + Add RTL support (#5551).+ + Do not allow closing asterisks to be followed by `*`.+ + Do not split series of asterisks into symbols and emphasis (#5821).+ + Do not terminate emphasis on `*` not followed by space.++ * DokuWiki reader:++ + Parse markup inside monospace ('') (#5916, Alexander Krotov).++ * Docx reader:++ + Move style-parsing-specific code to a new unexported module,+ Text.Pandoc.Readers.Docx.Parse.Styles (Nikolay Yakimov).+ + Move StyleMap to docx writer (Nikolay Yakimov).+ + Only use LTR when it is overriding BiDi setting (#5723, Jesse+ Rosenthal). The left-to-right direction setting in docx is used+ in the spec only for overriding an explicit right-to-left setting.+ We only process it when it happens in a paragraph set with BiDi.+ This is especially important for docs exported from Google Docs,+ which explicitly (and unnecessarily) set `rtl=0` for every paragraph.+ + Fix list number resumption for sublists (#4324).+ The first list item of a sublist should not resume numbering+ from the number of the last sublist item of the same level,+ if that sublist was a sublist of a different list item.++ * Docbook reader:++ + Richer parse for admonitions (Michael Peyton Jones, #1234).+ Instead of parsing admonitions as blockquotes, we now parse+ them as Divs with an appropriate class. We also handle titles+ for admonitions as a nested Div with the "title" class.+ + Fix nesting of chapters and sections (#5864, Florian Klink,+ Félix Baylac-Jacqué).+ + Fix bug with entities in mathphrase element (#5885).++ * MediaWiki reader:++ + Skip optional `{{table}}` template (#5757).++ * LaTeX reader:++ + Fix dollar-math parsing to ensure that space is left between a+ control sequence and a following letter (#5836).+ + In `untokenize`, ensure space between control sequence+ and following letter (#5836).+ + Don't omit macro definitions defined in the preamble.+ These were formerly omitted (though they still affected macro+ resolution if `latex_macros` was set). Now they are included in+ the document body.+ + Parse macro definitions as raw LaTeX when `latex_macros` is+ disabled. (When `latex_macros` is enabled, we omit them, since+ pandoc is applying the macros itself.)+ + Fix a hang/memory leak in certain circumstances (#5845).+ + Text.Pandoc.Readers.LaTeX.Parsing: add `[Tok]` parameter to+ `rawLaTeXParser`. This allows us to repeat retokenizing+ unnecessarily in e.g. `rawLaTeXBlock`.+ + Add KOMA-Script metadata commands (#5910, Andrew Dunning).+ Add all titling commands to existing definition for `\dedication`.+ + Parse `\micro` siunitx unit command (#5921, Jose Luis Duran).++ * Markdown writer:++ + Ensure proper nesting when we have long ordered list markers (#5705).+ + Make `plain` output plainer (#5741). Previously we used the following+ Project Gutenberg conventions for plain output: extra space before and+ after level 1 and 2 headings, all-caps for strong emphasis,+ underscores surrounding regular emphasis. Now these+ conventions are used only when the `gutenberg` extension is+ enabled. By default, Strong and Emph are rendered without+ special formatting, and headings are rendered without+ special formatting, and with only one blank line following.+ To restore the former behavior, use `-t plain+gutenberg`.+ + Prefer using raw_attribute when enabled (#4311).+ The `raw_attribute` will be used to mark raw bits, even HTML+ and LaTeX, and even when `raw_html` and `raw_tex` are+ enabled, as they are by default. To get the old behavior,+ disable `raw_attribute` in the writer.+ + Prefer `pipe_tables` to raw HTML even when we must+ lose width information (#2608, #4497).+ + Improve escaping in list items (#5918).++ * AsciiDoc writer:++ + Don't include `+` in code blocks for regular asciidoc.+ This is asciidoctor-specific.+ + Handle admonitions (#5690).++ * LaTeX writer:++ + Add thin space when needed in LaTeX quote ligatures (#5684).+ + Use `\hspace{0pt}` for 0-width space U+200B (#5756).+ + Use `cslreferences` environment for csl bibliographies.+ This allows bibliographies to receive special formatting.+ The template now contains definition of this environment (enabled+ only when CSL is used). It also defines a `\cslhangindent` length.+ This is set to 2em by default when the bibliography style specifies+ a hanging indent. To override the length, you can use e.g.+ `\setlength{\cslhangindent}{7em}` in header-includes.+ See jgm/pandoc-citeproc#410.+ + Strip off `{}` around locator for biblatex/natbib output (#5722).+ + Fix line breaks at start of paragraph (#3324).+ Previously we just omitted these. Now we render them+ using `\hfill\break` instead of `\\`. This is a revision+ of a PR by @sabine (#5591) who should be credited with the idea.+ + We no longer look in the template or header-includes to see if a+ book or article documentclass is used, or to see whether the+ `csquotes` package is used. To use `csquotes` for LaTeX, set+ `csquotes` in your variables or metadata. To specify a book+ style, use the `documentclass` variable or+ `--top-level-division`.+ + Fix horizontal rule (#5801). We change to use 0.5pt rather than+ `\linethickness`, which apparently only ever worked "by accident"+ and no longer works with recent updates to texlive.++ * ConTeXt writer:++ + Add option to include source files in ConTeXt PDFs (Tristan+ Stenner, #5578). The metadata field or variable+ (`includesource`) can be set to attach the source documents+ to the resulting PDF.+ + Customizable type of PDF/A for the ConTeXt writer (Karl+ Pettersson, #5608). The `pdfa` variable may now be set in metadata.+ Also updated color profile settings in accordance with ConTeXt wiki,+ and made ICC profile and output intent for PDF/A customizable+ using `pdfaiccprofile` and `pdfaintent`.+ + Unit tests: adjust code property to avoid an irrelevant+ failure involving inline code with two consecutive newlines.+ + Set `csl-hanging-indent` variable if needed.+ + Use special environment for CSL references.+ + Use braces, not start/stop, for inline language tags.+ This prevents unwanted gobbling of spaces.++ * HTML writer:++ + Use numeric character references with `--ascii` (#5718).+ Previously we used named character references with html5 output.+ But these aren't valid XML, and we aim to produce html5 that is+ also valid XHTML (polyglot markup). (This is also needed for epub3.)+ + Ensure that line numbers in code blocks get id-prefix (#5650).+ + Ensure TeX formulas are rendered correctly (Philip Pesca,+ #5658). The web service passed in to `--webtex` may render+ formulas using inline or display style by default.+ Prefixing formulas with the appropriate command ensures+ they are rendered correctly.+ + Render inline formulas correctly with `--webtex` (Philip+ Pesca, #5655). We add `\textstyle` to the beginning of the+ formula to ensure it will be rendered in inline style.+ + Pass through `aria-` attributes to HTML5 (#5642).+ + Render a Quoted element with an inner Span with+ `cite` attribute using a `<q>` tag (#5798, Ole Martin Ruud).+ + Render a Span with class `mark` using the `<mark>` element+ (Florian Beeres, #5797).+ + Render Span with class `dfn` using `<dfn>` element+ (Florian Beeres, #5882).+ + Render Span with class `kbd` using `<kbd>` element (Daniele+ D'Orazio, #5796).+ + Render Code with class `variable` using `<var>` element+ (Amogh Rathore, #5799).+ + Render Code with class `sample` using `<samp>` element+ (Amogh Rathore, #5799).++ * EPUB writer:++ + Improve splitting into chapters (#5761), using `makeSection`.+ + Avoid issuing warning multiple times when title not set (see #5760).+ + Use svg tag wrapper for cover image (#5638). In addition, the+ code generating the image has been moved to the template, to make it+ more customizable. NOTE: Those who use custom EPUB+ templates will need to adjust their templates, adding the+ code to generate the cover image. (Previously this was just+ inserted into 'body'.)+ + Improve toChapters, making it work better if there are Divs+ around sections.+ + Add support for EPUB2 covers (blmage, #3992).+ + Do not override existing "fileN" medias when writing to EPUB format+ (blmage, #4206).+ + Ensure that `lang` variable is set on all chapters (so that it+ will add an `xml:lang` attribute on the `html` element).++ * RST writer:++ + Removed remnants of `admonition-title`.+ + Fix handling of `:align:` on figures and images (#4420).+ When the image has the `align-right` (etc.) class, we now use+ an `:align:` attribute.+ + Improve spacing for tables with no width information (#5899).+ If a simple table would be too wide, we use a grid table.+ + Fix backslash escaping after strings (Albert Krewinkel, #5906).+ The check whether a complex inline element following a string must+ be escaped, now depends on the last character of the string instead+ of the first.+ + Ensure there's a blank line before tables (#5898).++ * Dokuwiki writer:++ + Handle mixed lists without HTML fallback (#5107).++ * XWiki writer:++ + Fix multiline table (Zihang Chen, #5683).++ * Muse writer:++ + Add RTL support (Alexander Krotov, #5551).++ * Man writer:++ + Suppress non-absolute link URLs (#5770). Absolute URLs are+ still printed in parentheses following the link text, but relative+ URLs are suppressed (just as internal links starting with '#'+ always have been).+ + Improved definition list term output. Now we boldface code but+ not other things. This matches the most common style in man pages+ (particularly option lists).++ * Ms writer:++ + Use `.LP` instead of `.PP` for line block (#5588).+ + Use boldface for definition terms in DefinitionLists.++ * JATS writer:++ + Do not emit empty `<fn-group>` (Mauro Bieg, #5595).+ + Update template to v1.1dtd (#5632, Arfon Smith).+ + Update `data/jats.csl` to avoid commas between editor+ name-part elements. (#5629)+ + Add `abstract` to template (Mauro Bieg).++ * TEI writer:++ + Don't strip hash from internal links (#5922).++ * Jira writer:++ + Remove escapeStringForJira for code blocks (Jan-Otto Kröpke).+ + Remove extraneous newline after single-line block quotes+ (#5858, Albert Krewinkel).+ + Improve escaping of special characters, using backslash escapes+ instead of HTML entities (#5858, Albert Krewinkel).++ * OpenDocument writer:++ + Avoid duplicate attributes (#4634). We use the innermost+ attribute in nested cases.+ + If `native_numbering` extension is set, use native OpenDocument+ enumeration for figures and tables (Nils Carlson).+ + Place caption before table (#5681, Dmitry Pogodin).++ * ODT writer:++ + Add a test for MathML formulas in ODT documents (blmage).+ + Improve the parsing of frames in ODT documents (blmage).++ * Docx writer:++ + Make handling of styles more robust in localized versions+ of Word (Nikolay Yakimov, #5523, #5052, #5074). We now use+ style names, not ids, for assigning semantic meaning, since+ the ids can change depending on the locale. Style name+ comparisons are case-insensitive, since those are+ case-insensitive in Word. Since docx style names can have+ spaces in them, and pandoc-markdown classes can't, anywhere+ when style name is used as a class name, spaces are+ replaced with ASCII dashes `-`. Code styles, i.e. "Source+ Code" and "Verbatim Char" now honor style inheritance. Docx+ Reader now honours "Compact" style (used in+ Pandoc-generated docx). The side-effect is that "Compact"+ style no longer shows up in docx+styles output. Styles+ inherited from "Compact" will still show up.+ + Re-use Readers.Docx.Parse for StyleMap (#5766, Nikolay Yakimov).+ + Internal improvements and code simplification (Nikolay Yakimov).+ + Preserve built-in styles in DOCX with custom style (Ben Steinberg,+ #5670). This change prevents custom styles on divs and spans+ from overriding styles on certain elements inside them, like+ headings, blockquotes, and links. On those elements, the+ "native" style is required for the element to display correctly.+ This change also allows nesting of custom styles; in order to do so,+ it removes the default "Compact" style applied to Plain blocks,+ except when inside a table.+ + Add `proofState` to list of elements carried over from+ settings.xml in the reference.docx (Krystof Beuermann, #5703).+ + Change order of `ilvl` and `numId` in `document.xml` (Agustín+ Martín Barbero, #5645). Also, make list para properties go first.+ This reordering of properties shouldn't be necessary but+ it seems Word Online does not understand the docx correctly otherwise.++ * PowerPoint writer:++ + Code formatting is now context dependent (Jeroen de Haas, #5573).+ This commit alters the way in which the Powerpoint writer treats+ inline code and code blocks. Inline code is now formatted at+ the same size as the surrounding text. Code blocks are now given+ a margin and font size according to their level.+ Furthermore this commit allows changing the font with which code is+ formatted via the `monofont` option.+ + Start numbering at appropriate numbers (Jesse Rosenthal, #5709).+ Starting numbers for ordered lists were previously ignored. Now+ we specify the number if it is something other than 1.++ * Text.Pandoc.Parsing:++ + Add `manyChar`, `many1Char`, `manyTillChar`, `many1TillChar`,+ `many1Till`, `manyUntil`, `mantyUntilChar`: these are like their+ unsuffixed counterparts but pack some or all of their output+ (Christian Despres, #5884).+ + Add `stateAllowLineBreaks` to `ParserState` [API change].+ + Fix inline parsing in grid table cells (#5708).+ + Change type of `setLastStrPos` so it takes a `Maybe SourcePos`+ rather than a `SourcePos` [API change].+ + Make `parseFromString'` and `gridTableWith` and+ `gridTableWith'` polymorphic in the parser state,+ constraining it with `HasLastStrPosition` [API change].+ + `parseFromString'`: reset `stateLastStrPos` to `Nothing` before parse.+ + Rename takeWhileP -> take1WhileP and clean it up.+ (It doesn't match the empty sequence.)++ * Text.Pandoc.PDF:++ + For PDFs via HTML, ensure temp file is deleted even if the pdf+ program is not found (#5720).+ + Better detection of a Cygwin environment (#5451).+ + Don't assume tex log file is UTF8-encoded (#5872).+ Fall back to latin1 if it can't be read as UTF-8.++ * Text.Pandoc.Extensions:++ + Export new function `getAllExtensions`, which returns the+ extensions that affect a given format (whether enabled by default+ or not) [API change].+ + Change type of `parseFormatSpec` from+ `Either ParseError (String, Extensions -> Extensions)`+ to `Either ParseError (String, [Extension], [Extension])`+ [API change].+ + Add `Ext_gutenberg` constructor to `Extension` [API change].+ + Add `Ext_native_numbering` constructor to `Extension` [API change]+ (Nils Carlson).++ * Text.Pandoc.Readers, Text.Pandoc.Writers:++ + Change type of `getReader` and `getWriter` so they return+ a value in the PandocMonad instance rather than an Either+ [API change]. Exceptions for unknown formats and unsupported+ extensions are now raised by these functions.++ * Text.Pandoc.App++ + Change `optMetadataFile` type from `Maybe FilePath` to `[FilePath]`+ (Owen McGrath, #5702) [API change].++ * Text.Pandoc.Logging:++ + Add `CouldNotDeduceFormat` constructor to `LogMessage` [API change].+ Issue this warning when we're falling back to markdown or+ html because we don't recognize the extension of the input or+ output files.+ + Clarify warning for missing title (#5760).+ + Add `UnusualConversion` constructor to `LogMessage` [API change]+ (Mauro Bieg, #5736). Emit warning on `-f latex -o out.pdf`.++ * Lua filters:++ + Improve function documentation (Albert Krewkinkel).+ + Traverse nested blocks and inlines in correct order (Albert+ Krewinkel, #5667). Traversal methods are updated to use the new+ Walk module so that sequences with nested Inline (or Block) elements+ are traversed in the order in which they appear in the linearized+ document.+ + New unexported module `Text.Pandoc.Lua.Walk` (Albert Krewinkel).+ Lua filters must be able to traverse sequences of AST+ elements and to replace elements by splicing sequences back+ in their place. Special `Walkable` instances can be used for+ this; those are provided in a new module+ `Text.Pandoc.Lua.Walk`.+ + `Attr` values can now be given as normal Lua tables (Albert+ Krewinkel, #5744). This can be used as a convenient alternative+ to constructing `Attr` values with `pandoc.Attr`. Identifiers+ are taken from the `id` field, classes must be given as+ space separated words in the `class` field. All remaining fields+ are included as attributes. With this change, the following lines+ now create equal elements:+ ```+ pandoc.Span('test', {id = 'test', class = 'a b', check = 1})+ pandoc.Span('test', pandoc.Attr('test', {'a','b'}, {check = 1}))+ ```+ This also works when using the *attr* setter:+ ```+ local span = pandoc.Span 'text'+ span.attr = {id = 'test', class = 'a b', check = 1}+ ```+ Furthermore, the *attributes* field of AST elements can now be a+ plain key-value table even when using the `attributes` accessor:+ ```+ local span = pandoc.Span 'test'+ span.attributes = {check = 1} -- works as expected now+ ```+ + Export `make_sections`, remove `hierarchicalize`. Lua filters that+ use `hierarchicalize` will need to be rewritten to use+ `make_sections`.+ + Add a `clone()` method to all AST elements (Albert Krewinkel, #5568).+ + Fix Lua function names in pandoc.system (niszet). Change+ `get_current_directory` to `get_working_directory` and+ `with_temp_directory` to `with_temporary_directory`, to+ conform to the manual.++ * Text.Pandoc.Error:++ + Add constructors `PandocUnknownReaderError`,+ `PandocUnknownWriterError`, `PandocUnsupportedExtensionError`.+ [API change].+ + Better message for `PandocShouldNeverHappenError`.+ + Better message for `PandocTemplateError`.++ * Text.Pandoc.Emoji:++ + Update emoji list (#5666). Done using new `tools/emojis.hs`,+ which uses the list from the gem GitHub uses. Future updates+ can be done with this tool.++ * Text.Pandoc.PDF:++ + Pass value of `--dpi` to `rsvg-convert` when converting SVG to PDF+ in the process of creating a PDF (#5721).++ * Text.Pandoc.Shared:++ + Replace `Element` and `makeHierarchical` with `makeSections`.+ Now that we have Divs, we can use them to represent the+ structure of sections, and we don't need a special Element type.+ `makeSections` reorganizes a block list, adding Divs with class+ `section` around sections, and adding numbering if needed.+ This change also fixes some longstanding issues recognizing section+ structure when the document contains Divs (#3057, see also #997).+ + Remove `Element` type [API change]+ + Remove `makeHierarchicalize` [API change]+ + Add `makeSections` [API change]+ + Export `deLink` [API change]+ + Make `filterIpynbOutput` strip ANSI escapes from code in output+ for non-ipynb formats, when the default "best" option is used with+ `--ipynb-output` (#5633).+ + Fix `camelCaseToHyphenated` so it handles `ABCDef` better.+ + Improve `isTight` (#5857). If a list has an empty item,+ this should not count against its being a tight list.+ + Export `htmlSpanLikeElements` [API change] (Daniele D'Orazio, #5796).+ This is a mapping of HTML span-like elements that are internally+ represented as a Span with a single class.+ + Change the implementation of `htmlSpanLikeElements` to retain+ classes and attributes (#5882, Florian Beeres).++ * Text.Pandoc.Slides: recognize content in Divs when determining+ slide level.++ * Text.Pandoc.SelfContained:++ + Omit content-type on type attribute for `<style>` (#5725).+ It doesn't seem to be valid for HTML5, and as a result Chrome+ ignores the style element.++ * Text.Pandoc.Pretty has been removed [API change].+ We now use the new external doclayout module instead.++ * Text.Pandoc.Writers.Shared:++ + Remove `metaToJSON`, `metaToJSON'` [API change].+ + Modify `addVariablesToContext`, `defField`, `setField`, `getField`,+ `resetField` to work with Context rather than JSON values. [API change]+ + Export new function `endsWithPlain` [API change].+ + Change `gridTables` so it does better at keeping the widths of+ columns (#4320) and does better at figuring out column widths+ when no widths are given (#5899).++ * Text.Pandoc.Options++ + Change type of `writerTemplate` to `Maybe Template` instead+ of `Maybe String`.+ + Change To/FromJSON instances for `HTMLMathMethod`, `CiteMethod`,+ `ObfuscationMethod`, `TrackChanges`, `WrapOption`,+ `TopLevelDivision`, `ReferenceLocation`, `HTMLSlideVariant` (#5790).+ In each case we use lowercase (or hyphenated lowercase) for+ constructors to line up more closely with command-line option+ values. This is a breaking change for those who manually decode or+ encode JSON for these data types (e.g. for `ReaderOptions` or+ `WriterOptions`).++ * Text.Pandoc.Filters:++ + Add `FromYAML` instance for `Filter`.+ + `applyFilters`: Add and apply filters in order (not reversed)+ This changes `applyFilters` from Text.Pandoc.Filter so+ that it does a left fold rather than a right fold, applying+ the filters in the order listed.++ * Text.Pandoc.XML:++ + Change `toEntities` to emit numerical hex character references+ (#5718).++ * Text.Pandoc.Highlighting:++ + Add additional listings languages (Wandmalfarbe).++ * Text.Pandoc.MediaBag:++ + Some of the types using Strings were switched to use FilePath instead+ (Christian Despres, #5884).++ * Text.Pandoc.Templates:++ + Don't import/export `varListToJSON` [API change]. It is removed in+ doctemplates >= 0.3.+ + Change type of `renderTemplate'` [API change]. Return value is+ now Text rather than being polymorphic. This makes room for+ upcoming removal of the `TemplateTarget` class from doctemplates.++ * Text.Pandoc.App.Opt [API changes]:++ + More convenient To/FromJSON instances. Make the field names+ like `strip-empty-paragraphs` rather than `optStripEmptyParagraphs`.+ Anyone who is using JSON serialization of Opt will need to adjust+ things accordingly.+ + Change `optHighlightStyle` to a `Maybe String` instead of+ `Maybe Style`. Do the parsing/loading of themes later, after+ option parsing.+ + Remove `optBaseHeaderLevel` from `Opt`. We now just use+ `optShiftHeadingLevelBy`, to avoid redundancy.+ + Change `optShiftHeadingLevel` to `optShiftHeadingLevelBy` to+ match the option.+ + Custom FromJSON instance for `LineEnding`, so either `CRLF`+ or `crlf` will work.+ + Change `optVariables` from `[(String, String)]` to `Context Text`.+ + Change `optMetadata` to `Meta`, to allow structured values.+ The current behavior of the `--metadata` option stays the same.+ + Rename `optReader`, `optWriter` as `optFrom`, `optTo`.+ + Add `FromYAML` instances to `Opt` and to all subsidiary types.+ + Rename `optMetadataFile` to `optMetadataFiles`.+ + Rename `optPDFEngineArgs` to `optPDFEngineOpts`.+ + Rename `optWrapText` to `optWrap`.+ + Add `IpynbOutput` enumerated type: use this instead of+ a string for `optIpynbOutput`.+ + Change optInputFiles to a `Maybe [FilePath]` (#5888) [API change].+ `Nothing` means: nothing specified.+ `Just []` means: an empty list specified (e.g. in defaults).+ + List fields in Opt so they aren't reversed (#5881) [API change].+ Previously `optIncludeInHeader`, etc. were in reverse order.+ + The `sourcefile` variable is now always a list. It used to be+ sometimes a string, sometimes a list (when there was more than one).++ * Template changes:++ + default.latex: added code for `cslreferences` environment,+ to be used for pandoc-citeproc references. A `csl-hanging-indent`+ variable (set automatically if there is a `hanging-ident`+ class on the references Div) controls whether contents of this+ environment receive a hanging indent.+ + default.latex: Add `space` as default option for xeCJK, so that+ spaces between words are preserved (#5855, jeongminkim-islab).+ This is necessary for Korean.+ + default.latex: Remove include of `grffile` (#5848).+ This package used to be needed for proper handling of image filenames+ containing periods (in addition to the period before the extension).+ It no longer works with the latest LaTeX kernel and graphicx,+ so we have removed it. Future versions of graphicx will handle+ these filenames without the need for `grffile`.+ + default.context: add a saner default for page numbers.+ Previously they appeared centered at the top of the page;+ now we put them centered at the bottom, unless the `pagenumbering`+ variable is set.+ + default.context: define a start-stop-pair `cslreferences` to+ allow for hanging indents in the bibliography (#5875, Denis Maier).+ + default.ms: update defaults. Use Palatino font, use slightly+ wider interparagraph space, don't indent paragraphs,+ and put page numbers on the bottom. This brings ms output+ closer to default LaTeX output.+ + default.revealjs: add navigationMode (Mauro Bieg, #5657).+ + default.muse: handle multiple authors better.+ + docbook4, docbook5 templates: add indentation to body.+ + HTML-based templates: use `styles.html` partial to avoid+ code duplication.+ + HTML-based templates: change indentation of styles in template.++ * reference.docx (#5820):++ + Change Block Text (block quote) style so that the same font+ is used as in the body text, and the block text is indented+ left and right.+ + All headings now have a uniform color.+ + Level-1 headings no longer set `w:themeShade="B5"`.+ + Level-2 headings are now 14 point rather than 16 point.+ + Level-3 headings are now 12 point rather than 14 point.+ + Level-4 headings are italic rather than bold.++ * epub.css: Add CSS for hanging-indent div to support pandoc-citeproc's+ new hanging indents.++ * pandoc.cabal:++ + Repeat ghc-options in all stanzas.+ + Remove conditionals for ghc < 8 (Albert Krewinkel, #5693).+ + Compile with `-Wcpp-undef` and `-fhide-source-paths` when possible+ (Albert Krewinkel).+ + Add cabal.project to extra-source-files (Albert Krewinkel).+ + Add dependency on skylighting-core (#5729). Even though it shouldn't+ be needed, some tools require it.+ + Require latest pandoc-types, texmath, skylighting, haddock-library.+ + Ensure TemplateHaskell is added to other-extensions when it is+ used (Vanessa McHale, #5728).+ + Remove `derive_json_via_th` flag; always use TH. This cuts down+ on code duplication and reduces the chance for errors. See #4083.++ * Makefile:++ + Add ghci target.+ + Add ghcid target.+ + Remove references to obsolete flag (#5694).++ * Benchmarks: fix failure on ipynb.++ * Use MathJax 3 (zorkow).++ * KaTeX math: respect `classoption=fleqn` variable,+ bump KaTeX version to 0.11.1 (#5815, Mauro Bieg).++ * Fix redundant constraint compiler warnings (Pete Ryland, #5625).++ * Use throwError instead of fail when appropriate.++ * Use Prelude.fail to avoid ambiguity with fail from GHC.Base.++ * Add `diff-zip.sh` to tools (John MacFarlane, Agustín Martín Barbero).+ This is intended to make it easier to test differences in zip+ containers, like epub, docx, or odt.++ * Add `.gitattributes` (#5747). This ensures that the golden files+ in `test/fb2/reader/` don't have newlines converted. This should fix+ a test failure on GitHub CI with Windows.++ * Reorder options in `--help`.++ * Revise code for HsYAML-0.2.0.0 (@vijayphoenix, #5704).++ * Remove blank line in code example in Haddocks (Leif Metcalf, #5679).++ * Fix trypandoc with `getReader`/`getWriter` changes.++ * Allow building pandoc with GHC 8.8.++ * linux tarball: add architecture `-amd64` to filename.+ Now it will be: `pandoc-VERSION-linux-ARCH.tar.gz`.++ * MANUAL.txt:++ + Add section for exit codes.+ + Document some pptx limitations in slide show section:+ No incremental display (#5689). No pause with `. . .` (#5701).+ + reveal.js flags (Mauro Bieg, #5653).+ + Document addition of `data-` prefix to unknown attributes in HTML5.+ + Link to YAML spec (Mauro Bieg, #5687).+ + Fix capitalization of "Linux" (#5859, Marcus Stollsteimer).+ + Use a table for exit codes.+ + Put all template variable docs into one section.+ + Use ATX headers consistently.+ + Add fuller documentation of templates (#5779), including+ new template syntax, partials, etc.+ + Add documentation for the variable `hyperrefoptions` (Wandmalfarbe).+ + Clarify when macro definitions are passed as raw latex.+ In Markdown input, they are always passed through. In LaTeX, only if+ `latex_macros` is disabled.+ + Clarify that `--dpi` provides a default and doesn't override+ dpi values specified in the images themselves (#5721).+ + Document how to use custom writers with `--standalone` (#5866).+ + Clarify `--preserve-tabs` default.++ * INSTALL.md:++ + Fix instructions for libicu.+ + Add Void Linux instructions (Volodymyr Kozachnyskyi).++ * CONTRIBUTING.md:++ + Add information on tests (Agustín Martín Barbero, #5652).+ + Add information about command test naming to CONTRIBUTING (Florian B).++ * Fix typos in changelog and comments (#5896, Brian Wignall).++ * doc/lua-filters.md:++ + Fix mistakes in mediabag module docs (#5851, Albert Krewinkel).+ + Improve metadata replacement example in lua-filters doc (#5851).+ + Mention which Lua version is shipped with pandoc (Albert Krewinkel,+ #5892).++## pandoc 2.7.3 (2019-06-11)++ * Add `jira` (Atlassian's Jira wiki markup) as output format (#2497,+ Albert Krewinkel).++ * Add `tex_math_dollars` to `multimarkdownExtensions` (#5512).+ This form is now supported in multimarkdown,+ in addition to `tex_math_double_backslash`.++ * Fix `--self-contained` so it works when output format has extensions.+ Previously if you used `--self-contained` with `html-smart` or+ `html+smart`, it wouldn't work.++ * Add template variable `curdir` with working directory+ from which pandoc is run (#5464).++ * Markdown reader: don't create implicit reference for empty header+ (#5549).++ * Muse reader: allow images inside link descriptions (Alexander Krotov).++ * HTML reader: epub related fixes.++ + With epub extensions, check for `epub:type` in addition to `type`.+ + Fix problem with noteref parsing which caused block-level+ content to be eaten with the noteref.+ + Rename `pAnyTag` to `pAny`.+ + Refactor note resolution.+ + Trim definition list terms (Alexander Krotov).++ * LaTeX reader:++ + Add braces when resolving `\DeclareMathOperator`+ (#5441). These seem to be needed for xelatex but not pdflatex.+ + Allow newlines in `\mintinline`.+ + Pass through unknown listings language as class (#5540).+ Previously if the language was not in the list of languages supported+ by listings, it would not be added as a class, so highlighting+ would not be triggered.+ + `rawLaTeXInline`: Include trailing `{}`s in raw latex commands (#5439).+ This change affects the markdown reader and other readers that allow raw+ LaTeX. Previously, trailing `{}` would be included for unknown+ commands, but not for known commands. However, they are sometimes used+ to avoid a trailing space after the command. The chances that a `{}`+ after a LaTeX command is not part of the command are very small.++ * MediaWiki reader: handle multiple attributes in table row (#5471,+ chinapedia).++ * Docx reader: Add support for `w:rtl` (#5545). Elements with this+ property are put into Span inlines with `dir="rtl"`.++ * DocBook reader: Issue `IgnoredElement` warnings.++ * Org reader (Albert Krewinkel):++ + Fix planning elements in headers level 3 and higher+ (#5494). Planning info is now always placed before+ the subtree contents. Previously, the planning info was placed after+ the content if the header's subtree was converted to a list, which+ happens with headers of level 3 and higher per default.+ + Omit, but warn about unknown export options. Unknown export+ options are properly ignored and omitted from the output.+ + Prefer plain symbols over math symbols (#5483).+ Symbols like `\alpha` are output plain and unemphasized, not as math.+ + Recognize emphasis after TODO/DONE keyword (#5484).++ * FB2 reader:++ + Skip unknown elements rather than throwing errors (#5560).+ Sometimes custom elements are used (e.g. `id` element+ inside `author`); previously the reader would halt with an error.+ Now it skips the element and issues an `IgnoredElement` warning.+ + Parse notes (#5493, Alexander Krotov).+ + Internal improvements (Alexander Krotov).++ * OpenDocument writer: Roll back automatic figure/table numbering+ (#5474). This was added in pandoc 2.7.2, but it makes it impossible+ to use pandoc-crossref. So this has been rolled back for now,+ until we find a good solution to make this behavior optional+ (or a creative way to let pandoc-crossref and this feature+ to coexist).++ * New module Text.Pandoc.Writers.Jira, exporting `writeJira` [API+ change] (Albert Krewinkel).++ * EPUB writer:++ + Don't include 'landmarks' if there aren't any.+ Previously we could get an empty ol element, which caused+ validation errors with epubcheck.+ + Ensure unique ids for styleesheets in content.opf (#5463).+ + Make stylesheet link compatible with kindlegen (#5466,+ Eric Schrijver). Pandoc omitted `type="text/css"` from both+ `<style>` and `<rel="stylesheet">` elements in all templates, which+ is valid according to the spec. However, Amazon’s kindlegen software+ relies on this attribute on `<link>` elements when detecting+ stylesheets to include.++ * HTML writer:++ + Output video and audio elements depending on file+ extension of the image path (Mauro Bieg).+ + Emit empty alt tag in figures (#5518, Mauro Bieg).+ The same text is already in the <figcaption> and+ screen-readers would read it twice, see #4737.+ + Don't add variation selector if it's already there.+ This fixes round-trip failures.+ + Prevent gratuitous emojification on iOS (#5469).+ iOS chooses to render a number of Unicode entities, including '↩', as+ big colorful emoji. This can be defeated by appending Unicode+ VARIATION SELECTOR-15'/'VARIATION SELECTOR-16'. So we now append this+ character when escaping strings, for both '↩' and '↔'. If other+ characters prove problematic, they can simply be added to+ `needsVariationSelector`. + Add `class="heading"` to level 7+ Headers+ rendered as `<p>` elements (#5457).++ * RST writer: treat Span with no attributes as transparent (#5446).+ Previously an Emph inside a Span was being treated as+ nested markup and ignored. With this patch, the Span+ is just ignored.++ * LaTeX writer:++ + Include inline code attributes with `--listings` (#5420).+ + Don't produce columns environment unless beamer (#5485).+ + Fix footnote in image caption. Regression: the fix for #4683 broke+ this case.+ + Don't highlight code in headings (#5574). This causes+ compilation errors.+ + Use `\mbox` to get proper behavior inside `\sout` (#5529).++ * EPUB writer: Fix document section assignments (#5546).+ For example, introduction should go in bodymatter, not frontmatter, and+ epigraph, conclusion, and afterward should go in bodymatter, not+ backmatter. For the full list of assignments, see the manual.++ * Markdown writer:++ + Add backslashes to avoid unwanted interpretation of+ definition list terms as other kinds of block (#554).+ + Ensure the code fence is long enough (#5519).+ Previously too few backticks were used when the code block+ contained an indented line of backticks. (Ditto tildes.)+ + Handle labels with integer names (Jesse Rosenthal, #5495).+ Previously if labels had integer names, it could produce a conflict+ with auto-labeled reference links. Now we test for a conflict and+ find the next available integer. This involves adding a new state+ variable `stPrevRefs` to keep track of refs used in other document+ parts when using `--reference-location=block|section`++ * Textile writer: fix closing tag for math output (Albert Krewinkel).+ Opening and closing tag for math output match now.++ * Org writer: always indent src blocks content by 2 spaces (#5440, Albert+ Krewinkel). Emacs always uses two spaces when indenting the content of+ src blocks, e.g., when exiting a `C-c '` edit-buffer. Pandoc used to+ indent contents by the space-equivalent of one tab, but now always uses+ two spaces, too.++ * Asciidoc writer:++ + Use `` `+...+` `` form for inline code.+ The old `` `a__b__c` `` yields emphasis inside code in asciidoc.+ To get a pure literal code span, use `` `+a__b__c+` ``.+ + Use proper smart quotes with asciidoctor (#5487).+ Asciidoctor has a different format for smart quotes.+ + Use doubled ## when necessary for spans (#5566).+ + Ensure correct nesting of strong/emph (#5565): strong+ must be the outer element.++ * JATS writer:++ + Wrap elements with p when needed (#5570). The JATS spec restricts+ what elements can go inside `fn` and `list-item`. So we wrap other+ elements inside `<p specific-use="wrapper">` when needed.+ + Properly handle footnotes (#5511) according to "best practice."+ (Group them at the end in `<fn-group>` and use `<xref>` elements+ to link them.)+ + Fix citations with PMID so they validate (#5481). This includes+ an update to data/jats.csl.+ + Ensure validity of `<pub-date>` by parsing the date and+ extracting year, month, and day, as expected. Also add an+ iso-8601-date attribute automatically.+ + Don't use `<break>` element for LineBreak. It is only+ allowed in a few special contexts, and not in `<p>` elements.+ + Don't make `<string-name>` a child of `<string>`, which is illegal.++ * FB2 writer:++ + Do not wrap note references into `<sup>` and brackets+ (Alexander Krotov). Existing FB2 readers, such as FBReader, already+ display links with type="note" as a superscript.+ + Use genre metadata field (#5478).++ * Muse writer: do not escape empty line after `<br>` (Alexander Krotov).++ * Add unicode code point in "Missing character" warning (#5538).+ If the character isn't in the console font, the message is pretty useless,+ so we show the code point for anything non-ASCII.++ * Lua: add Version type to simplify comparisons (Albert Krewinkel).+ Version specifiers like `PANDOC_VERSION` and `PANDOC_API_VERSION` are+ turned into `Version` objects. The objects simplify version-appropriate+ comparisons while maintaining backward-compatibility.+ A function `pandoc.types.Version` is added as part of the newly+ introduced module `pandoc.types`, allowing users to create version+ objects in scripts.++ * pandoc lua module (Albert Krewinkel):++ - Fix deletion of nonexistent attributes (#5569).+ - Better tests for Attr and AttributeList.++ * pandoc.mediabag lua module (Albert Krewinkel):++ + Add function `delete` for deleting a single item.+ + Add function `empty` for removing all entries.+ + Add function `items` for iterating over mediabag.++ * Text.Pandoc.Class: Fix handling of `file:` URL scheme in+ `downloadOrRead` (#5517, Mauro Bieg). Previously `file:/`+ URLs were handled wrongly and pandoc attempted to make HTTP+ requests, which failed.++ * Text.Pandoc.MIME: add `mediaCategory` [API change] (Mauro Bieg).++ * Text.Pandoc.Shared:++ + Add `onlySimpleTableCells` [API change]+ (Mauro Bieg) and use this to consolidate simple-table detection+ (#5524). This fixes an inconsistency in the HTML reader, which did not+ treat tables with `<p>` inside cells as simple.+ + `metaToJSON`: treat digits starting with 0 as a string, not a number+ (#5479). This fixes a regression in YAML metadata in pandoc 2.7.2.++ * Text.Pandoc.Logging: Add `IgnoredElement` constructor for+ `LogMessage`. `SkippedConetnt` doesn't work for some XML-based+ readers which don't have access to parsec source positions.++ * Text.Pandoc.Asciify: Add Turkish undotted-i (#5433, Mauro Bieg).++ * Improve output of Lua tests (#5499, Albert Krewinkel).+ This makes use of tasty-lua, a package to write tests in Lua+ and integrate the results into Tasty output. Test output becomes+ more informative: individual tests and test groups become visible+ in test output. Failures are reported with helpful error messages.++ * Lua: add `pandoc.system` module (#5468, Albert Krewinkel).+ The `system` Lua module provides utility functions to interact with the+ operating- and file system. E.g.+ `print(pandoc.system.get_current_directory())`+ or+ ```lua+ pandoc.system.with_temporary_directory('tikz', function (dir)+ -- write and compile a TikZ file with pdflatex+ end)+ ```++ * LaTeX template: Add pdflang to hypersetup if lang is set (#5443).++ * beamer template: Fix using Beamer with geometry (#5505, Daniel Maslowski).+ Beamer already loads geometry, so we need to use the `\geometry`+ command to set geometry options.++ * EPUB2/3 templates: Move inline styles to default epub.css (#5466).+ NOTE: Those who use a custom CSS stylesheet with EPUB should+ add these lines:++ code{ white-space: pre-wrap; }+ span.smallcaps{ font-variant: small-caps; }+ span.underline{ text-decoration: underline; }+ q { quotes: "“" "”" "‘" "’"; }+ div.column{ display: inline-block; vertical-align: top; width: 50%; }++ * reveal.js template:++ + Updates for revealjs 3.8.0 (#5435, ebiim).+ + Remove reference to head.min.js (#5448, Winnie Hellmann).+ NOTE: users will need to update reveal.js to at least 3.8.0+ for their presentations generated with this version of pandoc+ to work correctly.++ * Text.Pandoc.PDF:++ + Replace `</>` with literal `/` (#5451).+ We use forward-slash for a directory separator in tmpDir,+ even on Windows (because that's what tex likes). So we+ should not put a backslash between the tmpDir and the+ filename on Windows. This is harmless enough in normal+ Windows setups, but it breaks on Cygwin.+ Thanks to @cc2x for noticing and diagnosing the problem.+ + Allow use of `-output-directory` in `--pdf-engine-opt` (#5462).+ This is currently possible with `mklatex` and `-outdir`, but+ was not yet possible with xelatex and `-output-directory`.+ + For PDF via ms/pdfroff, make TOC appear at beginning and in+ PDF bookmarks (#5553). Previously the TOC appeared at the end+ of the document, and was not bookmarked. To keep it at the end,+ add `--pdf-engine-opt=--no-toc-relocation` to your command line.++ * Fix broken links in documents (#5473, Shim Myeongseob).+ Also, use absolute links to pandoc.org when possible, so that+ the links can be followed by people viewing these documents+ on GitHub.++ * Improved sample lua tikz filter in lua-filters docs (#5445,+ Matthew Doty). There are three changes:++ + It only processes elements which begin with `\begin{tikzpicture}`+ + It uses pdf2svg instead of imagemagick to preserve fidelity+ + The images produced have transparent backgrounds++ * MANUAL.txt:++ + Add note about `title-meta`, `author-meta`, `date-meta` (#5486).+ + Fix typo (#5489, Christian Krause).++ * add test/tables.xwiki to git and pandoc.cabal (#5498, Mauro Bieg).++ * Disable missing-home-modules warning in `stack.yaml`.+ Otherwise `stack ghci` fails.+++## pandoc 2.7.2 (2019-04-05)++ * Add XWiki writer (#1800, Derek Chen-Becker).+ Add `Text.Pandoc.Writers.XWiki`, exporting `writeXWiki` [API change].++ * Dokuwiki Reader: parse single curly brace (#5416, Mauro Bieg).++ * Vimwiki reader: improve handling of internal links (#5414).+ We no longer append `.html` to link targets, and we add a title+ `wikilink`. This mirrors behavior of other wiki readers. Generally+ the `.html` extension is not wanted. It may be important for output+ to HTML in certain circumstances, but it can always be added using a+ filter that matches on links with title `wikilink`.++ If your workflow requires the current behavior, here is a lua filter+ that will add the `.html` extension:++ ```lua+ function Link(el)+ if el.title == 'wikilink' then+ el.target = el.target .. ".html"+ end+ return el+ end+ ```+ * ipynb reader:++ + Use format `ipynb` for raw cell where no format given.+ + Avoid introducing spurious `.0` on integers in metadata.++ * Markdown reader: fenced div takes priority over setext header.++ * HTML reader: read `data-foo` attribute into `foo` (#5392).+ The HTML writer adds the `data-` prefix for HTML5 for nonstandard+ attributes. But the attributes are represented in the AST without+ the `data-` prefix, so we should strip this when reading HTML.++ * LaTeX reader: Improve autolink detection (#5340).++ * PowerPoint writer (Jesse Rosenthal):++ + Expand builtin reference doc to model all layouts.+ The previous built-in reference doc had only title and content+ layouts. Add in a section-header slide and a two-content slide, so+ users can more easily modify it to build their own templates.+ + Always open up in slide view. When editing a+ template/reference-doc, the user might be in Master view, but when+ producing a slide show, it is assumed that slide view will be+ desired.+ + Remove `handoutsMasterList` from template presentation.xml+ + Fix numerous errors in templating (#5402). Previously, some templates+ produced by Office 365 (MacOS) would not render with `--reference-doc`+ correctly. We now apply correct shapes for content, and build+ shape trees correctly.+ + Make default placeholder type for template lookup.+ + Apply speaker notes to metadata slide if applicable.+ + Test for speaker notes after breaking header.+ + Correctly handle notes after section-title header.+ Previously, if notes came after a section-title header (ie, a level-1+ header in a slide-level=2 presentation), they would go on the next+ slide. This keeps them on the slide with the header.+ + Internal improvements.++ * ipynb writer:++ + Use format `ipynb` for raw cell where no format given.+ According to nbformat docs, this is supposed to render in every+ format. We don't do that, but we at least preserve it as a raw+ block in markdown, so you can round-trip.+ + Consolidate adjacent raw blocks. Sometimes pandoc creates two+ HTML blocks, e.g. one for the open tag and one for a close tag.+ If these aren't consolidated, only one will show up in output cell.+ + Fixed carry-over of nbformat from metadata.+ + Preserve `nbformat_minor` if it's given. This helps with round-tripping.++ * LaTeX writer:++ + Avoid inadvertently creating ?` or !` ligatures (#5407).+ These are upside down ? and !, resp.+ + Fix footnotes in table caption and cells (#5367). This fixes a+ bug wherein footnotes appeared in the wrong order, and with+ duplicate numbers, when in table captions and cells.+ We now use regular `\footnote` commands, even in the table+ caption and the minipages containing cells. Apparently+ longtable knows how to handle this.++ * HTML writer: Don't add data- prefix to RDFa attributes (#5403).++ * JATS writer: Ensure that plain strings go inside `<pub-id>` tag (#5397).++ * Markdown writer:++ + Better rendering of numbers (#5398). If the number is integral,+ we render it as an integral not a float.+ + Proper rendering of empty map in YAML metadata (#5398). Should+ be `{}`, not empty string.+ + Properly escape attributes in Markdown writer (#5369).+ + Be sure implicit figures work in list contexts (#5368).+ Previously they would sometimes not work: e.g., when they+ occurred in final paragraphs in lists that were originally+ parsed as Plain and converted later using PlainToPara.++ * Docx writer: Use `w:br` without attributes for line breaks (#5377).+ We previously added the attribute `type="textWrapping"`, but+ this causes problems on Word Online.++ * LaTeX template (Andrew Dunning):++ + Ensure correct heading/table order (#5365). Improve workaround+ (#1658) for tables following headings. The new solution works whether+ or not the `indent` variable is enabled.+ + Remove `subparagraph` variable. The default is now to use run-in+ style for level 4 and 5 headings (`\paragraph` and `\subparagraph`).+ To get the previous default behavior (where these were formatted as+ blocks, like `\subsubsection`), set the `block-headings` variable.+ + Add pandoc to PDF metadata (#5388).+ + Group graphics-related code (#5389).+ + Move `\setstretch` after front matter (#5179). Ensures that+ `\maketitle`, `\tableofcontents`, and so forth are not affected by+ changes to line spacing.++ * Update data/jats.csl to avoid commas between name-part elements+ (#5397).++ * Add support for golang (`go`) with `--listings` (#5427).++ * Text.Pandoc.Shared - improve `metaToJSON` behavior with numbers.+ We now do a better job marshalling numbers from MetaString+ or MetaInlines into JSON Number.++ * Text.Pandoc.Writers.Shared: `metaValueToJSON`: use Number Values for+ integers. Pandoc's MetaValue doesn't have a distinguished number type,+ so numbers are put in MetaStrings. If the MetaString consists+ entirely of digits, we convert it to a Number. We should probably+ consider adding a MetaNumber constructor to MetaValue, for better+ round-tripping with JSON etc. This change aids round-tripping in+ ipynb metadata fields, like `toc_depth`.++ * Text.Pandoc.Class: `fetchItem`: don't treat UNC paths as+ protocol-relative URLs (#5127). These are paths beginning `//?/UNC/...`.++ * Text.Pandoc.ImageSize: Improve `pdfSize` so it handles+ a wider range of PDFs (#4322, with help from Richard Davis).++ * Text.Pandoc.Pretty: avoid stack overflow by using strict sum (#5401).++ * Fix harmless error in file-scope code (#5422).++ * MANUAL.txt:++ + Improve 'header' and 'heading' usage (#5423, Andrew+ Dunning). The term 'header' was being used where 'heading'+ is more appropriate.+ + Add paragraph on options affecting markdown in ipynb.++ * stack.yaml - remove -Wmissing-home-modules+ This seems to cause problems with stack ghci. Remove RTS options.++ * Add ghc-options to cabal.project.++ * appveyor.yml - use ghc 8.6.4. Fixes segfault issues on Windows (#5037).++ * linux build process: Remove clone of pandoc-citeproc (#5366).+ It wasn't being used; cabal.project specifies the version to use.++## pandoc 2.7.1 (2019-03-14)++ * Add tectonic as an option for --pdf-engine (#5345, Cormac Relf).+ Runs tectonic on STDIN instead of a temporary .tex file, so that it+ looks in the working directory for `\include` and `\input` like the rest+ of the engines. Allows overriding the output directory+ args with `--pdf-engine-opt=--outdir --pdf-engine-opt="$DIR"`.++ * Allow `-o/--output` to be used with `--print-default-data-file`,+ `--print-highlighting-style`, `--print-default-template`.+ Note that `-o` must occur BEFORE the `--print*` command on the command+ line (this is documented, #5357).++ * LaTeX reader:++ + Support `\underline`, `\ul`, `\uline` (#5359, Paul+ Tilley). These are parsed as a Span with class `underline`, as+ with other readers.+ + Ensure that `\Footcite` and `\Footcites` get put in a note.++ * ipynb reader:++ + Remove sensitivity to `raw_html`, `raw_tex` extensions.+ We now include every output format. Pruning is handled by+ `--ipynb-output`.+ + Better handling of cell metadata. We now include even complex cell+ metadata in the Div's attributes (as JSON, in complex cases, or+ as plain strings in simple cases).++ * ipynb writer:++ + Recurse into native divs for output cell data (#5354).+ + Render cell metadata fields from div attributes.++ * Docx writer: avoid extra copy of abstractNum and num elements+ in numbering.xml. This caused pandoc-produced docx files to+ be uneditable using Word Online (#5358).++ * Markdown writer: improve handling of raw blocks/inline.+ We now emit raw content using `raw_attribute` when no more+ direct method is available. Use of `raw_attribute` can be+ forced by disabling `raw_html` and `raw_tex`.++ * LaTeX writer: Add classes for frontmatter support (#5353, Andrew Dunning)+ and remove frontmatter from `scrreprt`.++ * LaTeX template:++ + Improve readability (#5363, Andrew Dunning).+ + Robust section numbering removal (#5351, Andrew Dunning).+ Ensures that section numbering does not reappear with custom+ section levels. See <https://tex.stackexchange.com/questions/473653/>.+ + Better handling of front/main/backmatter (#5348).+ In pandoc 2.7 we assumed that every class with chapters would accept+ `\frontmatter`, `\mainmatter`, and `\backmatter`. This is not so (e.g.+ report does not). So pandoc 2.7 breaks on report class by including an+ unsupported command. Instead of the `book-class` variable, we use two+ variables, `has-chapters` and `has-frontmatter`, and set these+ intelligently in the writer.++ * Text.Pandoc.Shared: Improve `filterIpynbOutput`. Ensure that+ images are prioritized over text. `best` should include everything+ for ipynb.++ * Tests.Old: specify `--data-dir=../data` to ensure tests can find+ data files even if they haven't been installed. Remove old+ `pandoc_datadir` environment variable, which hasn't done anything for a+ long time.++ * MANUAL.txt: Add recommendation to use `raw_attribute` with ipynb (#5354).++ * Use cmark-gfm-hs 0.1.8 (note that 0.1.7 is buggy).++ * Use latest pandoc-citeproc, texmath.+++## pandoc 2.7 (2019-03-03)++ * Use XDG data directory for user data directory (#3582). Instead of+ `$HOME/.pandoc`, the default user data directory is now+ `$XDG_DATA_HOME/pandoc`, where `XDG_DATA_HOME` defaults to+ `$HOME/.local/share` but can be overridden by setting the+ environment variable. If this directory is missing, then+ `$HOME/.pandoc` is searched instead, for backwards compatibility.+ However, we recommend moving local pandoc data files from+ `$HOME/.pandoc` to `$HOME/.local/share/pandoc`. On Windows the+ default user data directory remains the same.++ * Slide show formats behavior change: content under headers+ less than slide level is no longer ignored, but included in+ the title slide (for HTML slide shows) or in a slide after+ the title slide (for beamer). This change makes possible+ 2D reveal.js slideshows with content in the top slide on+ each stack (#4317, #5237).++ * Add command line option `--ipynb-output=all|none|best` (#5339).+ Output cells in ipynb notebooks often contain several different+ versions of an output, with different MIME types, e.g. an HTML+ table and a plain-text fallback. Specifying `--ipynb-output=best`+ (the default) ensures that the best version for the output format+ is used. `all` includes all versions, and `none` suppresses them+ all, leaving output cells empty.++ * `asciidoctor` is now an output format separate from `asciidoc`,+ to accommodate some minor implementation-specific differences+ (currently just in the treatment of display math).++ * Add `latexmk` as an option for `--pdf-engine` (#3195).+ Note that you can use `--pdf-engine-opt=-outdir=bar` to specify+ a persistent temp directory.++ * Markdown reader:++ + Improve tight/loose list handling (#5285). Previously the+ algorithm allowed list items with a mix of Para and Plain, which+ is never wanted.+ + Add newline when parsing blocks in YAML (#5271). Otherwise last+ block gets parsed as a Plain rather than a Para. This is a+ regression in pandoc 2.x. This patch restores pandoc 1.19+ behavior.+ + Make `yamlToMeta` respect extensions (#5272, Mauro Bieg).+ This adds a `ReaderOptions` parameter to `yamlToMeta` [API change].+ + Fix bug parsing fenced code blocks (#5304). Previously parsing+ would break if the code block contained a string of backticks of+ sufficient length followed by something other than end of line.++ * LaTeX reader: don't let `\egroup` match `{`. `braced` now actually+ requires nested braces. Otherwise some legitimate command and+ environment definitions can break.++ * Docx reader (Jesse Rosenthal):++ + Rename `getDocumentPath` as `getDocumentXmlPath`.+ + Use field notation for setting `ReaderEnv`.+ + Figure out `document.xml` path once at the beginning of parsing, and+ add it to the environment, so we can avoid repeated lookups.+ + Dynamically determine main document xml path (#5277).+ The desktop Word program places the main document file in+ `word/document.xml`, but the online word places it in+ `word/document2.xml`. This file path is actually stated in the root+ `_rels/.rels` file, in the `Relationship` element with an+ `http://../officedocument` type.+ + Fix paths in archive to prevent Windows failure (#5277).+ Some paths in archives are absolute (have an opening slash) which, for+ reasons unknown, produces a failure in the test suite on MS+ Windows. This fixes that by removing the leading slash if it exists.+ + Add comments to aid code readability.+ + Trim space inside the last inline (#5273).+ + Unwrap sdt elements in footnotes and comments (#5302).++ * Muse reader (Alexander Krotov):++ + Test that block level markup does not break `<verbatim>`.+ + Add secondary note support.++ * ipynb reader: handle images referring to attachments. Previously+ we didn't strip off the attachment: prefix, so even though the+ attachment was available in the mediabag, pandoc couldn't find it.++ * JATS reader:++ + Fix parsing of figures (#5321). This ensures that a figure+ containing a single image is parsed as a pandoc "implicit+ figure" (i.e., a Para with a single Image whose title attribute+ begins with `fig:`). More complex figures will still be parsed+ as divs.+ + Support `fig-group` block element (#5317).+ + Handle citations with multiple references (#5310). The `rid`+ attribute can have a space-separated list of ids.++ * AsciiDoc Writer: Add `writeAsciiDoctor` [API change, Tarik Graba].+ Handle display math appropriately for Asciidoctor.++ * JATS writer: wrap figure caption in `<p>` to fix validation (#5290,+ Mauro Bieg).++ * HTML writer:++ + Implement WAI-ARIA roles for (end)notes, citations, and+ bibliography (#4213). Note that doc-biblioref is only used when+ link-citations produces links, since it belongs on links.+ + Include content (including speaker notes) in title slides+ (#4317, #5237).++ * ipynb writer:++ + Ensure final newline.+ + Only include metadata under `jupyter` field.+ + Don't create attachments for images with absolute URIs,+ including data: URIs (#5303).+ + Keep plain text fallbacks in output even if a richer format is+ included (#5293). We don't know what output format will be needed.+ See the `--ipynb-output` command line option for a way to control+ what formats are included in the output.++ * Markdown writer: use `markdown="1"` when appropriate for Divs:+ when `native_divs` and `markdown_in_html_blocks` are disabled+ but `raw_html` and `markdown_attribute` are enabled.++ * LaTeX writer:++ + Use right fold for `escapeString`. This is more elegant than+ the explicit recursive code we were using.+ + Avoid `{}` after control sequences when escaping.+ `\ldots{}.` doesn't behave as well as `\ldots.` with the latex+ ellipsis package. This patch causes pandoc to avoid emitting+ the `{}` when it is not necessary. Now `\ldots` and other+ control sequences used in escaping will be followed by either+ a `{}`, a space, or nothing, depending on context.+ + For beamer, include contents under headers superordinate to+ slidelevel (#4317). Currently we keep the fancy title slide, and+ add a new slide with the same title and whatever content was+ under the header.++ * Powerpoint writer (Jesse Rosenthal): support underlines.+ Use span with single class "underline" as in docx writer.++ * Muse writer: escape secondary notes (Alexander Krotov).++ * FB2 writer: add section identifiers support (#5229, John KetzerX).++ * Make `--fail-if-warnings` work for PDF output (#5343).++ * Lua filters (Albert Krewinkel):++ + Load module `pandoc` before calling `init.lua` (#5287). The file+ `init.lua` in pandoc's data directory is run as part of pandoc's+ Lua initialization process. Previously, the `pandoc` module was+ loaded in `init.lua`, and the structure for marshaling was+ set up after. This allowed simple patching of element+ marshaling, but made using `init.lua` more difficult. Now, all+ required modules are now loaded before calling `init.lua`. The+ file can be used entirely for user customization. Patching+ marshaling functions, while discouraged, is still possible via+ the `debug` module.+ + All Lua modules bundled with pandoc, i.e., `pandoc.List`,+ `pandoc.mediabag`, `pandoc.utils`, and `text` are re-exported from the+ `pandoc` module. They are assigned to the fields `List`, `mediabag`,+ `utils`, and `text`, respectively.++ * Text.Pandoc.Lua (Albert Krewinkel):++ + Split `StackInstances` into smaller Marshaling modules.+ + Get `CommonState` from Lua global. This allows more control over+ the common state from within Lua scripts.++ * LaTeX template:++ + Support the `subject` metadata variable (#5289, Pascal Wagler).+ + Add `\frontmatter`, `\mainmatter`, `\backmatter`+ for book classes (#5306).++ * epub3 template: Add titlepage class to section (#5269).++ * HTML5 template: Add ARIA role `doc-toc` for table of contents (#4213).++ * Make `--metadata-file` use selected extensions (#5279, #5272, Mauro Bieg).++ * Text.Pandoc.Shared:++ + Remove `withTempDir` [API change].+ + Add new exported function `defaultUserDataDirs` [API change].+ + Add `filterIpynbOutput` [API change].+ + `compactify`: Avoid lists with a mix of Plain and Para elements+ (#5285).++ * Text.Pandoc.Translations: reorder alphabetically and remove `Author`+ (#5334, Mauro Bieg).++ * Text.Pandoc.Extensions:++ + More carefully groom ipynb default extensions.+ + Add `all_symbols_escapable` to `githubMarkdownExtensions`.++ * Text.Pandoc.PDF:++ + Use system temp directory when possible (#1192). Previously we+ created temp dirs in the working directory, partly (a) because+ there were problems using the system temp directory on Windows,+ when their pathnames included tildes, and partly (b) because+ programs like `epstopdf.pl` would not be allowed to write to+ directories outside the working directory in restricted mode. We+ now (a) use the system temp dir except when the path includes+ tildes, and (b) set `TEXMFOUTPUT` when creating the PDF, so that+ subsidiary programs can use the system temp directory. This+ addresses problems that occurred when pandoc was used in a+ synced directory (such as Dropbox).+ + Change types of subsidiary functions to PandocIO, to allow+ warnings to be threaded through (#5343).++ * Text.Pandoc.MIME: add WebP (#5267, Mauro Bieg).++ * Tests: avoid calling `findPandoc` multiple times.++ * Old tests: remove need for temp files by using `pipeProcess`.++ * Added simple ipynb reader/writer tests (#5274).++ * Rearrange `--help` output in a more rational way, with common+ options at the beginning and options grouped by function (#5336).++ * trypandoc: Add JATS and other missing formats (Arfon Smith, #5291).++ * Add missing copyright notices and remove license boilerplate (#4592,+ Albert Krewinkel).++ * Use latest basement/foundation on 32bit windows.++ * Use latest skylighting (#5328). Custom syntax definitions no+ longer try to load `language.dtd`.++ * Require texmath 0.11.2.1++ * Use latest pandoc-citeproc (0.16.1.1).++ * MANUAL.txt:++ + Clarify variable substitution indentation in templates (#5338,+ Agustín Martín Barbero).+ + Reorder custom-styles section (#5324, Mauro Bieg).++## pandoc 2.6 (2019-01-30)++ * Support ipynb (Jupyter notebook) as input and output format.++ + Add `ipynb` as input and output format (extension `.ipynb`).+ + Added Text.Pandoc.Readers.Ipynb [API change].+ + Added Text.Pandoc.Writers.Ipynb [API change].+ + Add `PandocIpynbDecodingError` constructor to Text.Pandoc.Error.Error+ [API change].+ + Depend on ipynb library.+ + Note: there is no template for ipynb.++ * Add DokuWiki reader (#1792, Alexander Krotov). This adds+ Text.Pandoc.Readers.DokuWiki [API change], and adds `dokuwiki`+ as an input format.++ * Implement task lists (#3051, Mauro Bieg). Added `task_lists`+ extension. Task lists are supported from markdown and gfm input.+ They should work, to some degree, in all output formats, though in+ most formats you'll get a bullet list with a unicode character for+ the box. In HTML, you get checkboxes and in LaTeX/PDF output, a+ box is used as the list marker. API changes:++ + Added constructor `Ext_task_lists` to `Extension`.+ + Added `taskListItemFromAscii` and `taskListItemToAscii` to+ Text.Pandoc.Shared.++ * Allow some command line options to take URL in addition to FILE.+ `--include-in-header`, `--include-before-body`, `--include-after-body`.++ * HTML reader:++ + Handle empty `start` attribute (see #5162).+ + Treat `textarea` as a verbatim environment (#5241) and preserve+ spacing.++ * RST reader:++ + Change treatment of `number-lines` directive (Brian Leung,+ #5207). Directives of this type without numeric inputs should+ not have a `startFrom` attribute; with a blank value, the+ writers can produce extra whitespace.+ + Removed superfluous `sourceCode` class on code blocks (#5047).+ + Handle `sourcecode` directive as synonym for `code` (#5204). * Markdown reader:
@@ -34,7 +34,7 @@ return 0 ;; --pdf-engine)- COMPREPLY=( $(compgen -W "pdflatex lualatex xelatex latexmk tectonic wkhtmltopdf weasyprint prince context pdfroff" -- ${cur}) )+ COMPREPLY=( $(compgen -W "pdflatex lualatex xelatex latexmk tectonic wkhtmltopdf weasyprint prince context pdfroff groff" -- ${cur}) ) return 0 ;; --print-default-data-file)
@@ -1,682 +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>- <!-- PUNCTUATION -->- <term name="open-quote">"</term>- <term name="close-quote">"</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" 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>
@@ -15,9 +15,7 @@ <w:pStyle w:val="Title" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Title-</w:t>+ <w:t xml:space="preserve">Title</w:t> </w:r> </w:p> <w:p>@@ -25,9 +23,7 @@ <w:pStyle w:val="Subtitle" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Subtitle-</w:t>+ <w:t xml:space="preserve">Subtitle</w:t> </w:r> </w:p> <w:p>@@ -35,9 +31,7 @@ <w:pStyle w:val="Author" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Author-</w:t>+ <w:t xml:space="preserve">Author</w:t> </w:r> </w:p> <w:p>@@ -45,20 +39,15 @@ <w:pStyle w:val="Date" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Date-</w:t>+ <w:t xml:space="preserve">Date</w:t> </w:r> </w:p> <w:p> <w:pPr>- <w:pStyle w:val="Compact" /> <w:pStyle w:val="Abstract" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Abstract-</w:t>+ <w:t xml:space="preserve">Abstract</w:t> </w:r> </w:p> <w:p>@@ -67,9 +56,7 @@ </w:pPr> <w:bookmarkStart w:id="21" w:name="heading-1" /> <w:r>- <w:t xml:space="preserve">-Heading 1-</w:t>+ <w:t xml:space="preserve">Heading 1</w:t> </w:r> <w:bookmarkEnd w:id="21" /> </w:p>@@ -79,9 +66,7 @@ </w:pPr> <w:bookmarkStart w:id="22" w:name="heading-2" /> <w:r>- <w:t xml:space="preserve">-Heading 2-</w:t>+ <w:t xml:space="preserve">Heading 2</w:t> </w:r> <w:bookmarkEnd w:id="22" /> </w:p>@@ -91,9 +76,7 @@ </w:pPr> <w:bookmarkStart w:id="23" w:name="heading-3" /> <w:r>- <w:t xml:space="preserve">-Heading 3-</w:t>+ <w:t xml:space="preserve">Heading 3</w:t> </w:r> <w:bookmarkEnd w:id="23" /> </w:p>@@ -103,9 +86,7 @@ </w:pPr> <w:bookmarkStart w:id="24" w:name="heading-4" /> <w:r>- <w:t xml:space="preserve">-Heading 4-</w:t>+ <w:t xml:space="preserve">Heading 4</w:t> </w:r> <w:bookmarkEnd w:id="24" /> </w:p>@@ -115,9 +96,7 @@ </w:pPr> <w:bookmarkStart w:id="25" w:name="heading-5" /> <w:r>- <w:t xml:space="preserve">-Heading 5-</w:t>+ <w:t xml:space="preserve">Heading 5</w:t> </w:r> <w:bookmarkEnd w:id="25" /> </w:p>@@ -127,9 +106,7 @@ </w:pPr> <w:bookmarkStart w:id="26" w:name="heading-6" /> <w:r>- <w:t xml:space="preserve">-Heading 6-</w:t>+ <w:t xml:space="preserve">Heading 6</w:t> </w:r> <w:bookmarkEnd w:id="26" /> </w:p>@@ -139,9 +116,7 @@ </w:pPr> <w:bookmarkStart w:id="27" w:name="heading-7" /> <w:r>- <w:t xml:space="preserve">-Heading 7-</w:t>+ <w:t xml:space="preserve">Heading 7</w:t> </w:r> <w:bookmarkEnd w:id="27" /> </w:p>@@ -151,9 +126,7 @@ </w:pPr> <w:bookmarkStart w:id="28" w:name="heading-8" /> <w:r>- <w:t xml:space="preserve">-Heading 8-</w:t>+ <w:t xml:space="preserve">Heading 8</w:t> </w:r> <w:bookmarkEnd w:id="28" /> </w:p>@@ -163,9 +136,7 @@ </w:pPr> <w:bookmarkStart w:id="29" w:name="heading-9" /> <w:r>- <w:t xml:space="preserve">-Heading 9-</w:t>+ <w:t xml:space="preserve">Heading 9</w:t> </w:r> <w:bookmarkEnd w:id="29" /> </w:p>@@ -174,9 +145,7 @@ <w:pStyle w:val="FirstParagraph" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-First Paragraph.-</w:t>+ <w:t xml:space="preserve">First Paragraph.</w:t> </w:r> </w:p> <w:p>@@ -184,57 +153,39 @@ <w:pStyle w:val="BodyText" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Body Text. Body Text Char.-</w:t>+ <w:t xml:space="preserve">Body Text. Body Text Char.</w:t> </w:r> <w:r>- <w:t xml:space="preserve">- -</w:t>+ <w:t xml:space="preserve"> </w:t> </w:r> <w:r> <w:rPr> <w:rStyle w:val="VerbatimChar" /> </w:rPr>- <w:t xml:space="preserve">-Verbatim Char-</w:t>+ <w:t xml:space="preserve">Verbatim Char</w:t> </w:r> <w:r>- <w:t xml:space="preserve">-.-</w:t>+ <w:t xml:space="preserve">.</w:t> </w:r> <w:r>- <w:t xml:space="preserve">- -</w:t>+ <w:t xml:space="preserve"> </w:t> </w:r> <w:hyperlink r:id="rId30"> <w:r> <w:rPr> <w:rStyle w:val="Hyperlink" /> </w:rPr>- <w:t xml:space="preserve">-Hyperlink-</w:t>+ <w:t xml:space="preserve">Hyperlink</w:t> </w:r> </w:hyperlink> <w:r>- <w:t xml:space="preserve">-.-</w:t>+ <w:t xml:space="preserve">.</w:t> </w:r> <w:r>- <w:t xml:space="preserve">- -</w:t>+ <w:t xml:space="preserve"> </w:t> </w:r> <w:r>- <w:t xml:space="preserve">-Footnote.-</w:t>+ <w:t xml:space="preserve">Footnote.</w:t> </w:r> <w:r> <w:rPr>@@ -248,9 +199,7 @@ <w:pStyle w:val="BlockText" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Block Text.-</w:t>+ <w:t xml:space="preserve">Block Text.</w:t> </w:r> </w:p> <w:p>@@ -258,22 +207,19 @@ <w:pStyle w:val="TableCaption" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Table caption.-</w:t>+ <w:t xml:space="preserve">Table caption.</w:t> </w:r> </w:p> <w:tbl> <w:tblPr> <w:tblStyle w:val="Table" />- <w:tblW w:type="pct" w:w="0.0" /> <w:tblLook w:firstRow="1" /> <w:tblCaption w:val="Table caption." /> </w:tblPr> <w:tblGrid /> <w:tr> <w:trPr>- <w:cnfStyle w:firstRow="1" />+ <w:cnfStyle w:firstRow="1" w:val="100000000000" /> </w:trPr> <w:tc> <w:tcPr>@@ -288,9 +234,7 @@ <w:jc w:val="left" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Table-</w:t>+ <w:t xml:space="preserve">Table</w:t> </w:r> </w:p> </w:tc>@@ -307,9 +251,7 @@ <w:jc w:val="left" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Table-</w:t>+ <w:t xml:space="preserve">Table</w:t> </w:r> </w:p> </w:tc>@@ -322,9 +264,7 @@ <w:jc w:val="left" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-1-</w:t>+ <w:t xml:space="preserve">1</w:t> </w:r> </w:p> </w:tc>@@ -335,9 +275,7 @@ <w:jc w:val="left" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-2-</w:t>+ <w:t xml:space="preserve">2</w:t> </w:r> </w:p> </w:tc>@@ -348,9 +286,7 @@ <w:pStyle w:val="ImageCaption" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Image Caption-</w:t>+ <w:t xml:space="preserve">Image Caption</w:t> </w:r> </w:p> <w:p>@@ -358,9 +294,7 @@ <w:pStyle w:val="DefinitionTerm" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-DefinitionTerm-</w:t>+ <w:t xml:space="preserve">DefinitionTerm</w:t> </w:r> </w:p> <w:p>@@ -368,9 +302,7 @@ <w:pStyle w:val="Definition" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Definition-</w:t>+ <w:t xml:space="preserve">Definition</w:t> </w:r> </w:p> <w:p>@@ -378,9 +310,7 @@ <w:pStyle w:val="DefinitionTerm" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-DefinitionTerm-</w:t>+ <w:t xml:space="preserve">DefinitionTerm</w:t> </w:r> </w:p> <w:p>@@ -388,11 +318,13 @@ <w:pStyle w:val="Definition" /> </w:pPr> <w:r>- <w:t xml:space="preserve">-Definition-</w:t>+ <w:t xml:space="preserve">Definition</w:t> </w:r> </w:p>- <w:sectPr />+ <w:sectPr>+ <w:footnotePr>+ <w:numRestart w:val="eachSect" />+ </w:footnotePr>+ </w:sectPr> </w:body> </w:document>
@@ -1,52 +1,52 @@-<?xml version="1.0" encoding="UTF-8"?>+<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <w:fonts xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">-	<w:font w:name="Symbol">-		<w:panose1 w:val="02000500000000000000" />-		<w:charset w:val="02" />-		<w:family w:val="auto" />-		<w:pitch w:val="variable" />-		<w:sig w:usb0="00000000" w:usb1="00000000" w:usb2="00010000" w:usb3="00000000" w:csb0="80000000" w:csb1="00000000" />-	</w:font>-	<w:font w:name="Times New Roman">-		<w:panose1 w:val="02020603050405020304" />-		<w:charset w:val="00" />-		<w:family w:val="auto" />-		<w:pitch w:val="variable" />-		<w:sig w:usb0="00000003" w:usb1="00000000" w:usb2="00000000" w:usb3="00000000" w:csb0="00000001" w:csb1="00000000" />-	</w:font>-	<w:font w:name="Courier New">-		<w:panose1 w:val="02070309020205020404" />-		<w:charset w:val="00" />-		<w:family w:val="auto" />-		<w:pitch w:val="variable" />-		<w:sig w:usb0="00000003" w:usb1="00000000" w:usb2="00000000" w:usb3="00000000" w:csb0="00000001" w:csb1="00000000" />-	</w:font>-	<w:font w:name="Wingdings">-		<w:panose1 w:val="05020102010804080708" />-		<w:charset w:val="02" />-		<w:family w:val="auto" />-		<w:pitch w:val="variable" />-		<w:sig w:usb0="00000000" w:usb1="00000000" w:usb2="00010000" w:usb3="00000000" w:csb0="80000000" w:csb1="00000000" />-	</w:font>-	<w:font w:name="Cambria">-		<w:panose1 w:val="02040503050406030204" />-		<w:charset w:val="00" />-		<w:family w:val="auto" />-		<w:pitch w:val="variable" />-		<w:sig w:usb0="00000003" w:usb1="00000000" w:usb2="00000000" w:usb3="00000000" w:csb0="00000001" w:csb1="00000000" />-	</w:font>-	<w:font w:name="Calibri">-		<w:panose1 w:val="020F0502020204030204" />-		<w:charset w:val="00" />-		<w:family w:val="auto" />-		<w:pitch w:val="variable" />-		<w:sig w:usb0="00000003" w:usb1="00000000" w:usb2="00000000" w:usb3="00000000" w:csb0="00000001" w:csb1="00000000" />-	</w:font>-	<w:font w:name="Arial">-		<w:panose1 w:val="020B0604020202020204" />-		<w:charset w:val="00" />-		<w:family w:val="auto" />-		<w:pitch w:val="variable" />-		<w:sig w:usb0="00000003" w:usb1="00000000" w:usb2="00000000" w:usb3="00000000" w:csb0="00000001" w:csb1="00000000" />-	</w:font>+ <w:font w:name="Aptos">+ <w:panose1 w:val="020B0004020202020204"/>+ <w:charset w:val="00"/>+ <w:family w:val="swiss"/>+ <w:pitch w:val="variable"/>+ <w:sig w:usb0="20000287" w:usb1="00000003" w:usb2="00000000" w:usb3="00000000" w:csb0="0000019F" w:csb1="00000000"/>+ </w:font>+ <w:font w:name="Times New Roman">+ <w:panose1 w:val="02020603050405020304"/>+ <w:charset w:val="00"/>+ <w:family w:val="roman"/>+ <w:pitch w:val="variable"/>+ <w:sig w:usb0="E0002EFF" w:usb1="C000785B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>+ </w:font>+ <w:font w:name="Aptos Display">+ <w:panose1 w:val="020B0004020202020204"/>+ <w:charset w:val="00"/>+ <w:family w:val="swiss"/>+ <w:pitch w:val="variable"/>+ <w:sig w:usb0="20000287" w:usb1="00000003" w:usb2="00000000" w:usb3="00000000" w:csb0="0000019F" w:csb1="00000000"/>+ </w:font>+ <w:font w:name="Cambria Math">+ <w:panose1 w:val="02040503050406030204"/>+ <w:charset w:val="00"/>+ <w:family w:val="roman"/>+ <w:pitch w:val="variable"/>+ <w:sig w:usb0="E00002FF" w:usb1="420024FF" w:usb2="00000000" w:usb3="00000000" w:csb0="0000019F" w:csb1="00000000"/>+ </w:font>+ <w:font w:name="Courier New">+ <w:panose1 w:val="02070309020205020404"/>+ <w:charset w:val="00"/>+ <w:family w:val="modern"/>+ <w:pitch w:val="fixed"/>+ <w:sig w:usb0="E0002AFF" w:usb1="C0007843" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>+ </w:font>+ <w:font w:name="Cambria">+ <w:panose1 w:val="02040503050406030204"/>+ <w:charset w:val="00"/>+ <w:family w:val="roman"/>+ <w:pitch w:val="variable"/>+ <w:sig w:usb0="E00002FF" w:usb1="400004FF" w:usb2="00000000" w:usb3="00000000" w:csb0="0000019F" w:csb1="00000000"/>+ </w:font>+ <w:font w:name="Calibri">+ <w:panose1 w:val="020F0502020204030204"/>+ <w:charset w:val="00"/>+ <w:family w:val="swiss"/>+ <w:pitch w:val="variable"/>+ <w:sig w:usb0="E0002AFF" w:usb1="C000247B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>+ </w:font> </w:fonts>
@@ -1,7 +1,21 @@ <?xml version="1.0" encoding="UTF-8"?>-<w:footnotes xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"><w:footnote w:type="continuationSeparator" w:id="0"><w:p><w:r><w:continuationSeparator /></w:r></w:p></w:footnote><w:footnote w:type="separator" w:id="-1"><w:p><w:r><w:separator /></w:r></w:p></w:footnote><w:footnote w:id="31"><w:p><w:pPr><w:pStyle w:val="FootnoteText" /></w:pPr><w:r>- <w:rPr>- <w:rStyle w:val="FootnoteReference" />- </w:rPr>- <w:footnoteRef />-</w:r><w:r><w:t xml:space="preserve"> </w:t></w:r><w:r><w:t xml:space="preserve">Footnote Text.</w:t></w:r></w:p></w:footnote></w:footnotes>+<w:footnotes xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">+ <w:footnote w:type="continuationSeparator" w:id="0"><w:p><w:r><w:continuationSeparator /></w:r></w:p></w:footnote>+ <w:footnote w:type="separator" w:id="-1"><w:p><w:r><w:separator /></w:r></w:p></w:footnote>+ <w:footnote w:id="31">+ <w:p>+ <w:pPr><w:pStyle w:val="FootnoteText" /></w:pPr>+ <w:r>+ <w:rPr>+ <w:rStyle w:val="FootnoteReference" />+ </w:rPr>+ <w:footnoteRef />+ </w:r>+ <w:r><w:t>Footnote Text.</w:t></w:r>+ </w:p>+ <w:p>+ <w:pPr><w:pStyle w:val="FootnoteBlockText"/></w:pPr>+ <w:r><w:t>Footnote Block Text</w:t></w:r>+ </w:p>+ </w:footnote>+</w:footnotes>
@@ -4,10 +4,6 @@ <w:embedSystemFonts /> <w:proofState w:spelling="clean" w:grammar="clean" /> <w:stylePaneFormatFilter w:val="0004" />- <w:footnotePr>- <w:footnote w:id="-1" />- <w:footnote w:id="0" />- </w:footnotePr> <w:doNotTrackMoves /> <w:defaultTabStop w:val="720" /> <w:drawingGridHorizontalSpacing w:val="360" />@@ -16,6 +12,10 @@ <w:displayVerticalDrawingGridEvery w:val="0" /> <w:characterSpacingControl w:val="doNotCompress" /> <w:savePreviewPicture />+ <w:footnotePr>+ <w:footnote w:id="-1" />+ <w:footnote w:id="0" />+ </w:footnotePr> <w:rsids> </w:rsids> <m:mathPr>
@@ -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>@@ -20,14 +20,14 @@ <w:name w:val="Normal" /> <w:qFormat /> </w:style>- <w:style w:type="paragraph" w:styleId="BodyText">+ <w:style w:type="paragraph" w:styleId="BodyText"> <w:name w:val="Body Text" /> <w:basedOn w:val="Normal" /> <w:link w:val="BodyTextChar" />+ <w:qFormat /> <w:pPr> <w:spacing w:before="180" w:after="180" /> </w:pPr>- <w:qFormat /> </w:style> <w:style w:type="paragraph" w:customStyle="1" w:styleId="FirstParagraph"> <w:name w:val="First Paragraph" />@@ -47,57 +47,120 @@ <w:name w:val="Title" /> <w:basedOn w:val="Normal" /> <w:next w:val="BodyText" />+ <w:link w:val="TitleChar" />+ <w:uiPriority w:val="10" /> <w:qFormat />+ <w:rsid w:val="00A10FD9" /> <w:pPr>- <w:keepNext />- <w:keepLines />- <w:spacing w:before="480" w:after="240" />+ <w:spacing w:after="80" w:line="240" w:lineRule="auto" />+ <w:contextualSpacing /> <w:jc w:val="center" /> </w:pPr> <w:rPr>- <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />- <w:b />- <w:bCs />- <w:color w:val="345A8A" w:themeColor="accent1" w:themeShade="B5" />- <w:sz w:val="36" />- <w:szCs w:val="36" />+ <w:rFonts w:asciiTheme="majorHAnsi"+ w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+ w:cstheme="majorBidi" />+ <w:sz w:val="56" />+ <w:szCs w:val="56" /> </w:rPr> </w:style>- <w:style w:type="paragraph" w:styleId="Subtitle">+ <w:style w:type="character" w:customStyle="1"+ w:styleId="TitleChar">+ <w:name w:val="Title Char" />+ <w:basedOn w:val="DefaultParagraphFont" />+ <w:link w:val="Title" />+ <w:uiPriority w:val="10" />+ <w:rsid w:val="00A10FD9" />+ <w:rPr>+ <w:rFonts w:asciiTheme="majorHAnsi"+ w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+ w:cstheme="majorBidi" />+ <w:sz w:val="56" />+ <w:szCs w:val="56" />+ </w:rPr>+ </w:style>+ <w:style w:type="paragraph" w:styleId="Subtitle"> <w:name w:val="Subtitle" /> <w:basedOn w:val="Title" /> <w:next w:val="BodyText" />+ <w:link w:val="SubtitleChar" />+ <w:uiPriority w:val="11" /> <w:qFormat />+ <w:rsid w:val="00A10FD9" /> <w:pPr>- <w:keepNext />- <w:keepLines />- <w:spacing w:before="240" w:after="240" />- <w:jc w:val="center" />+ <w:numPr>+ <w:ilvl w:val="1" />+ </w:numPr> </w:pPr> <w:rPr>- <w:sz w:val="30" />- <w:szCs w:val="30" />+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:spacing w:val="15" />+ <w:sz w:val="28" />+ <w:szCs w:val="28" /> </w:rPr>- </w:style>+ </w:style>+ <w:style w:type="character" w:customStyle="1"+ w:styleId="SubtitleChar">+ <w:name w:val="Subtitle Char" />+ <w:basedOn w:val="DefaultParagraphFont" />+ <w:link w:val="Subtitle" />+ <w:uiPriority w:val="11" />+ <w:rsid w:val="00A10FD9" />+ <w:rPr>+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:color w:val="595959" w:themeColor="text1"+ w:themeTint="A6" />+ <w:spacing w:val="15" />+ <w:sz w:val="28" />+ <w:szCs w:val="28" />+ </w:rPr>+ </w:style> <w:style w:type="paragraph" w:customStyle="1" w:styleId="Author"> <w:name w:val="Author" />+ <w:basedOn w:val="Title" /> <w:next w:val="BodyText" /> <w:qFormat /> <w:pPr> <w:keepNext /> <w:keepLines />- <w:jc w:val="center" /> </w:pPr>+ <w:rPr>+ <w:sz w:val="24" />+ <w:szCs w:val="24" />+ </w:rPr> </w:style> <w:style w:type="paragraph" w:styleId="Date"> <w:name w:val="Date" />+ <w:basedOn w:val="Title" /> <w:next w:val="BodyText" /> <w:qFormat /> <w:pPr> <w:keepNext /> <w:keepLines />+ </w:pPr>+ <w:rPr>+ <w:sz w:val="24" />+ <w:szCs w:val="24" />+ </w:rPr>+ </w:style>+ <w:style w:type="paragraph" w:customStyle="1" w:styleId="AbstractTitle">+ <w:name w:val="Abstract Title" />+ <w:basedOn w:val="Normal" />+ <w:next w:val="Abstract" />+ <w:qFormat />+ <w:pPr>+ <w:keepNext />+ <w:keepLines />+ <w:spacing w:before="300" w:after="0" /> <w:jc w:val="center" /> </w:pPr>+ <w:rPr>+ <w:b />+ <w:sz w:val="20" />+ <w:szCs w:val="20" />+ </w:rPr> </w:style> <w:style w:type="paragraph" w:customStyle="1" w:styleId="Abstract"> <w:name w:val="Abstract" />@@ -107,7 +170,7 @@ <w:pPr> <w:keepNext /> <w:keepLines />- <w:spacing w:before="300" w:after="300" />+ <w:spacing w:before="100" w:after="300" /> </w:pPr> <w:rPr> <w:sz w:val="20" />@@ -123,193 +186,371 @@ <w:rPr /> </w:style> <w:style w:type="paragraph" w:styleId="Heading1">- <w:name w:val="Heading 1" />+ <w:name w:val="heading 1" /> <w:basedOn w:val="Normal" /> <w:next w:val="BodyText" />+ <w:link w:val="Heading1Char" /> <w:uiPriority w:val="9" /> <w:qFormat />+ <w:rsid w:val="00A10FD9" /> <w:pPr> <w:keepNext /> <w:keepLines />- <w:spacing w:before="480" w:after="0" />+ <w:spacing w:before="360" w:after="80" /> <w:outlineLvl w:val="0" /> </w:pPr> <w:rPr>- <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />- <w:b />- <w:bCs />- <w:color w:val="4F81BD" w:themeColor="accent1" />- <w:sz w:val="32" />- <w:szCs w:val="32" />+ <w:rFonts w:asciiTheme="majorHAnsi"+ w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+ w:cstheme="majorBidi" />+ <w:color w:val="0F4761" w:themeColor="accent1"+ w:themeShade="BF" />+ <w:sz w:val="40" />+ <w:szCs w:val="40" /> </w:rPr> </w:style> <w:style w:type="paragraph" w:styleId="Heading2">- <w:name w:val="Heading 2" />+ <w:name w:val="heading 2" /> <w:basedOn w:val="Normal" /> <w:next w:val="BodyText" />+ <w:link w:val="Heading2Char" /> <w:uiPriority w:val="9" />+ <w:semiHidden /> <w:unhideWhenUsed /> <w:qFormat />+ <w:rsid w:val="00A10FD9" /> <w:pPr> <w:keepNext /> <w:keepLines />- <w:spacing w:before="200" w:after="0" />+ <w:spacing w:before="160" w:after="80" /> <w:outlineLvl w:val="1" /> </w:pPr> <w:rPr>- <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />- <w:b />- <w:bCs />- <w:color w:val="4F81BD" w:themeColor="accent1" />- <w:sz w:val="28" />- <w:szCs w:val="28" />+ <w:rFonts w:asciiTheme="majorHAnsi"+ w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+ w:cstheme="majorBidi" />+ <w:color w:val="0F4761" w:themeColor="accent1"+ w:themeShade="BF" />+ <w:sz w:val="32" />+ <w:szCs w:val="32" /> </w:rPr> </w:style> <w:style w:type="paragraph" w:styleId="Heading3">- <w:name w:val="Heading 3" />+ <w:name w:val="heading 3" /> <w:basedOn w:val="Normal" /> <w:next w:val="BodyText" />+ <w:link w:val="Heading3Char" /> <w:uiPriority w:val="9" />+ <w:semiHidden /> <w:unhideWhenUsed /> <w:qFormat />+ <w:rsid w:val="00A10FD9" /> <w:pPr> <w:keepNext /> <w:keepLines />- <w:spacing w:before="200" w:after="0" />+ <w:spacing w:before="160" w:after="80" /> <w:outlineLvl w:val="2" /> </w:pPr> <w:rPr>- <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />- <w:b />- <w:bCs />- <w:color w:val="4F81BD" w:themeColor="accent1" />- <w:sz w:val="24" />- <w:szCs w:val="24" />+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:color w:val="0F4761" w:themeColor="accent1"+ w:themeShade="BF" />+ <w:sz w:val="28" />+ <w:szCs w:val="28" /> </w:rPr> </w:style> <w:style w:type="paragraph" w:styleId="Heading4">- <w:name w:val="Heading 4" />+ <w:name w:val="heading 4" /> <w:basedOn w:val="Normal" /> <w:next w:val="BodyText" />+ <w:link w:val="Heading4Char" /> <w:uiPriority w:val="9" />+ <w:semiHidden /> <w:unhideWhenUsed /> <w:qFormat />+ <w:rsid w:val="00A10FD9" /> <w:pPr> <w:keepNext /> <w:keepLines />- <w:spacing w:before="200" w:after="0" />+ <w:spacing w:before="80" w:after="40" /> <w:outlineLvl w:val="3" /> </w:pPr> <w:rPr>- <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" /> <w:i />- <w:bCs />- <w:color w:val="4F81BD" w:themeColor="accent1" />- <w:sz w:val="24" />- <w:szCs w:val="24" />+ <w:iCs />+ <w:color w:val="0F4761" w:themeColor="accent1"+ w:themeShade="BF" /> </w:rPr> </w:style> <w:style w:type="paragraph" w:styleId="Heading5">- <w:name w:val="Heading 5" />+ <w:name w:val="heading 5" /> <w:basedOn w:val="Normal" /> <w:next w:val="BodyText" />+ <w:link w:val="Heading5Char" /> <w:uiPriority w:val="9" />+ <w:semiHidden /> <w:unhideWhenUsed /> <w:qFormat />+ <w:rsid w:val="00A10FD9" /> <w:pPr> <w:keepNext /> <w:keepLines />- <w:spacing w:before="200" w:after="0" />+ <w:spacing w:before="80" w:after="40" /> <w:outlineLvl w:val="4" /> </w:pPr> <w:rPr>- <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />- <w:iCs />- <w:color w:val="4F81BD" w:themeColor="accent1" />- <w:sz w:val="24" />- <w:szCs w:val="24" />+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:color w:val="0F4761" w:themeColor="accent1"+ w:themeShade="BF" /> </w:rPr> </w:style> <w:style w:type="paragraph" w:styleId="Heading6">- <w:name w:val="Heading 6" />+ <w:name w:val="heading 6" /> <w:basedOn w:val="Normal" /> <w:next w:val="BodyText" />+ <w:link w:val="Heading6Char" /> <w:uiPriority w:val="9" />+ <w:semiHidden /> <w:unhideWhenUsed /> <w:qFormat />+ <w:rsid w:val="00A10FD9" /> <w:pPr> <w:keepNext /> <w:keepLines />- <w:spacing w:before="200" w:after="0" />+ <w:spacing w:before="40" w:after="0" /> <w:outlineLvl w:val="5" /> </w:pPr> <w:rPr>- <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />- <w:color w:val="4F81BD" w:themeColor="accent1" />- <w:sz w:val="24" />- <w:szCs w:val="24" />+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:i />+ <w:iCs />+ <w:color w:val="595959" w:themeColor="text1"+ w:themeTint="A6" /> </w:rPr> </w:style> <w:style w:type="paragraph" w:styleId="Heading7">- <w:name w:val="Heading 7" />+ <w:name w:val="heading 7" /> <w:basedOn w:val="Normal" /> <w:next w:val="BodyText" />+ <w:link w:val="Heading7Char" /> <w:uiPriority w:val="9" />+ <w:semiHidden /> <w:unhideWhenUsed /> <w:qFormat />+ <w:rsid w:val="00A10FD9" /> <w:pPr> <w:keepNext /> <w:keepLines />- <w:spacing w:before="200" w:after="0" />+ <w:spacing w:before="40" w:after="0" /> <w:outlineLvl w:val="6" /> </w:pPr> <w:rPr>- <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />- <w:color w:val="4F81BD" w:themeColor="accent1" />- <w:sz w:val="24" />- <w:szCs w:val="24" />+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:color w:val="595959" w:themeColor="text1"+ w:themeTint="A6" /> </w:rPr> </w:style> <w:style w:type="paragraph" w:styleId="Heading8">- <w:name w:val="Heading 8" />+ <w:name w:val="heading 8" /> <w:basedOn w:val="Normal" /> <w:next w:val="BodyText" />+ <w:link w:val="Heading8Char" /> <w:uiPriority w:val="9" />+ <w:semiHidden /> <w:unhideWhenUsed /> <w:qFormat />+ <w:rsid w:val="00A10FD9" /> <w:pPr> <w:keepNext /> <w:keepLines />- <w:spacing w:before="200" w:after="0" />+ <w:spacing w:after="0" /> <w:outlineLvl w:val="7" /> </w:pPr> <w:rPr>- <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />- <w:color w:val="4F81BD" w:themeColor="accent1" />- <w:sz w:val="24" />- <w:szCs w:val="24" />+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:i />+ <w:iCs />+ <w:color w:val="272727" w:themeColor="text1"+ w:themeTint="D8" /> </w:rPr> </w:style> <w:style w:type="paragraph" w:styleId="Heading9">- <w:name w:val="Heading 9" />+ <w:name w:val="heading 9" /> <w:basedOn w:val="Normal" /> <w:next w:val="BodyText" />+ <w:link w:val="Heading9Char" /> <w:uiPriority w:val="9" />+ <w:semiHidden /> <w:unhideWhenUsed /> <w:qFormat />+ <w:rsid w:val="00A10FD9" /> <w:pPr> <w:keepNext /> <w:keepLines />- <w:spacing w:before="200" w:after="0" />+ <w:spacing w:after="0" /> <w:outlineLvl w:val="8" /> </w:pPr> <w:rPr>- <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />- <w:color w:val="4F81BD" w:themeColor="accent1" />- <w:sz w:val="24" />- <w:szCs w:val="24" />+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:color w:val="272727" w:themeColor="text1"+ w:themeTint="D8" /> </w:rPr> </w:style>+ <w:style w:type="character" w:customStyle="1" w:styleId="Heading1Char">+ <w:name w:val="Heading 1 Char" />+ <w:basedOn w:val="DefaultParagraphFont" />+ <w:link w:val="Heading1" />+ <w:uiPriority w:val="9" />+ <w:rsid w:val="00A10FD9" />+ <w:rPr>+ <w:rFonts w:asciiTheme="majorHAnsi"+ w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+ w:cstheme="majorBidi" />+ <w:color w:val="0F4761" w:themeColor="accent1"+ w:themeShade="BF" />+ <w:sz w:val="40" />+ <w:szCs w:val="40" />+ </w:rPr>+ </w:style>+ <w:style w:type="character" w:customStyle="1"+ w:styleId="Heading2Char">+ <w:name w:val="Heading 2 Char" />+ <w:basedOn w:val="DefaultParagraphFont" />+ <w:link w:val="Heading2" />+ <w:uiPriority w:val="9" />+ <w:semiHidden />+ <w:rsid w:val="00A10FD9" />+ <w:rPr>+ <w:rFonts w:asciiTheme="majorHAnsi"+ w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi"+ w:cstheme="majorBidi" />+ <w:color w:val="0F4761" w:themeColor="accent1"+ w:themeShade="BF" />+ <w:sz w:val="32" />+ <w:szCs w:val="32" />+ </w:rPr>+ </w:style>+ <w:style w:type="character" w:customStyle="1"+ w:styleId="Heading3Char">+ <w:name w:val="Heading 3 Char" />+ <w:basedOn w:val="DefaultParagraphFont" />+ <w:link w:val="Heading3" />+ <w:uiPriority w:val="9" />+ <w:semiHidden />+ <w:rsid w:val="00A10FD9" />+ <w:rPr>+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:color w:val="0F4761" w:themeColor="accent1"+ w:themeShade="BF" />+ <w:sz w:val="28" />+ <w:szCs w:val="28" />+ </w:rPr>+ </w:style>+ <w:style w:type="character" w:customStyle="1"+ w:styleId="Heading4Char">+ <w:name w:val="Heading 4 Char" />+ <w:basedOn w:val="DefaultParagraphFont" />+ <w:link w:val="Heading4" />+ <w:uiPriority w:val="9" />+ <w:semiHidden />+ <w:rsid w:val="00A10FD9" />+ <w:rPr>+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:i />+ <w:iCs />+ <w:color w:val="0F4761" w:themeColor="accent1"+ w:themeShade="BF" />+ </w:rPr>+ </w:style>+ <w:style w:type="character" w:customStyle="1"+ w:styleId="Heading5Char">+ <w:name w:val="Heading 5 Char" />+ <w:basedOn w:val="DefaultParagraphFont" />+ <w:link w:val="Heading5" />+ <w:uiPriority w:val="9" />+ <w:semiHidden />+ <w:rsid w:val="00A10FD9" />+ <w:rPr>+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:color w:val="0F4761" w:themeColor="accent1"+ w:themeShade="BF" />+ </w:rPr>+ </w:style>+ <w:style w:type="character" w:customStyle="1"+ w:styleId="Heading6Char">+ <w:name w:val="Heading 6 Char" />+ <w:basedOn w:val="DefaultParagraphFont" />+ <w:link w:val="Heading6" />+ <w:uiPriority w:val="9" />+ <w:semiHidden />+ <w:rsid w:val="00A10FD9" />+ <w:rPr>+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:i />+ <w:iCs />+ <w:color w:val="595959" w:themeColor="text1"+ w:themeTint="A6" />+ </w:rPr>+ </w:style>+ <w:style w:type="character" w:customStyle="1"+ w:styleId="Heading7Char">+ <w:name w:val="Heading 7 Char" />+ <w:basedOn w:val="DefaultParagraphFont" />+ <w:link w:val="Heading7" />+ <w:uiPriority w:val="9" />+ <w:semiHidden />+ <w:rsid w:val="00A10FD9" />+ <w:rPr>+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:color w:val="595959" w:themeColor="text1"+ w:themeTint="A6" />+ </w:rPr>+ </w:style>+ <w:style w:type="character" w:customStyle="1"+ w:styleId="Heading8Char">+ <w:name w:val="Heading 8 Char" />+ <w:basedOn w:val="DefaultParagraphFont" />+ <w:link w:val="Heading8" />+ <w:uiPriority w:val="9" />+ <w:semiHidden />+ <w:rsid w:val="00A10FD9" />+ <w:rPr>+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:i />+ <w:iCs />+ <w:color w:val="272727" w:themeColor="text1"+ w:themeTint="D8" />+ </w:rPr>+ </w:style>+ <w:style w:type="character" w:customStyle="1"+ w:styleId="Heading9Char">+ <w:name w:val="Heading 9 Char" />+ <w:basedOn w:val="DefaultParagraphFont" />+ <w:link w:val="Heading9" />+ <w:uiPriority w:val="9" />+ <w:semiHidden />+ <w:rsid w:val="00A10FD9" />+ <w:rPr>+ <w:rFonts w:eastAsiaTheme="majorEastAsia"+ w:cstheme="majorBidi" />+ <w:color w:val="272727" w:themeColor="text1"+ w:themeTint="D8" />+ </w:rPr>+ </w:style> <w:style w:type="paragraph" w:styleId="BlockText"> <w:name w:val="Block Text" /> <w:basedOn w:val="BodyText" />@@ -330,6 +571,18 @@ <w:unhideWhenUsed /> <w:qFormat /> </w:style>+ <w:style w:type="paragraph" w:styleId="FootnoteBlockText">+ <w:name w:val="Footnote Block Text" />+ <w:basedOn w:val="FootnoteText" />+ <w:next w:val="FootnoteText" />+ <w:uiPriority w:val="9" />+ <w:unhideWhenUsed />+ <w:qFormat />+ <w:pPr>+ <w:spacing w:before="100" w:after="100" />+ <w:ind w:firstLine="0" w:left="480" w:right="480" />+ </w:pPr>+ </w:style> <w:style w:type="character" w:default="1" w:styleId="DefaultParagraphFont"> <w:name w:val="Default Paragraph Font" /> <w:semiHidden />@@ -351,18 +604,11 @@ </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:vAlign w:val="bottom"/> <w:tcBorders> <w:bottom w:val="single"/> </w:tcBorders>+ <w:vAlign w:val="bottom"/> </w:tcPr> </w:tblStylePr> </w:style>
@@ -1,2 +1,293 @@-<?xml version="1.0" encoding="UTF-8"?>-<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme"><a:themeElements><a:clrScheme name="Office"><a:dk1><a:sysClr val="windowText" lastClr="000000" /></a:dk1><a:lt1><a:sysClr val="window" lastClr="FFFFFF" /></a:lt1><a:dk2><a:srgbClr val="1F497D" /></a:dk2><a:lt2><a:srgbClr val="EEECE1" /></a:lt2><a:accent1><a:srgbClr val="4F81BD" /></a:accent1><a:accent2><a:srgbClr val="C0504D" /></a:accent2><a:accent3><a:srgbClr val="9BBB59" /></a:accent3><a:accent4><a:srgbClr val="8064A2" /></a:accent4><a:accent5><a:srgbClr val="4BACC6" /></a:accent5><a:accent6><a:srgbClr val="F79646" /></a:accent6><a:hlink><a:srgbClr val="0000FF" /></a:hlink><a:folHlink><a:srgbClr val="800080" /></a:folHlink></a:clrScheme><a:fontScheme name="Office"><a:majorFont><a:latin typeface="Calibri" /><a:ea typeface="" /><a:cs typeface="" /><a:font script="Jpan" typeface="MS ゴシック" /><a:font script="Hang" typeface="맑은 고딕" /><a:font script="Hans" typeface="宋体" /><a:font script="Hant" typeface="新細明體" /><a:font script="Arab" typeface="Times New Roman" /><a:font script="Hebr" typeface="Times New Roman" /><a:font script="Thai" typeface="Angsana New" /><a:font script="Ethi" typeface="Nyala" /><a:font script="Beng" typeface="Vrinda" /><a:font script="Gujr" typeface="Shruti" /><a:font script="Khmr" typeface="MoolBoran" /><a:font script="Knda" typeface="Tunga" /><a:font script="Guru" typeface="Raavi" /><a:font script="Cans" typeface="Euphemia" /><a:font script="Cher" typeface="Plantagenet Cherokee" /><a:font script="Yiii" typeface="Microsoft Yi Baiti" /><a:font script="Tibt" typeface="Microsoft Himalaya" /><a:font script="Thaa" typeface="MV Boli" /><a:font script="Deva" typeface="Mangal" /><a:font script="Telu" typeface="Gautami" /><a:font script="Taml" typeface="Latha" /><a:font script="Syrc" typeface="Estrangelo Edessa" /><a:font script="Orya" typeface="Kalinga" /><a:font script="Mlym" typeface="Kartika" /><a:font script="Laoo" typeface="DokChampa" /><a:font script="Sinh" typeface="Iskoola Pota" /><a:font script="Mong" typeface="Mongolian Baiti" /><a:font script="Viet" typeface="Times New Roman" /><a:font script="Uigh" typeface="Microsoft Uighur" /></a:majorFont><a:minorFont><a:latin typeface="Cambria" /><a:ea typeface="" /><a:cs typeface="" /><a:font script="Jpan" typeface="MS 明朝" /><a:font script="Hang" typeface="맑은 고딕" /><a:font script="Hans" typeface="宋体" /><a:font script="Hant" typeface="新細明體" /><a:font script="Arab" typeface="Arial" /><a:font script="Hebr" typeface="Arial" /><a:font script="Thai" typeface="Cordia New" /><a:font script="Ethi" typeface="Nyala" /><a:font script="Beng" typeface="Vrinda" /><a:font script="Gujr" typeface="Shruti" /><a:font script="Khmr" typeface="DaunPenh" /><a:font script="Knda" typeface="Tunga" /><a:font script="Guru" typeface="Raavi" /><a:font script="Cans" typeface="Euphemia" /><a:font script="Cher" typeface="Plantagenet Cherokee" /><a:font script="Yiii" typeface="Microsoft Yi Baiti" /><a:font script="Tibt" typeface="Microsoft Himalaya" /><a:font script="Thaa" typeface="MV Boli" /><a:font script="Deva" typeface="Mangal" /><a:font script="Telu" typeface="Gautami" /><a:font script="Taml" typeface="Latha" /><a:font script="Syrc" typeface="Estrangelo Edessa" /><a:font script="Orya" typeface="Kalinga" /><a:font script="Mlym" typeface="Kartika" /><a:font script="Laoo" typeface="DokChampa" /><a:font script="Sinh" typeface="Iskoola Pota" /><a:font script="Mong" typeface="Mongolian Baiti" /><a:font script="Viet" typeface="Arial" /><a:font script="Uigh" typeface="Microsoft Uighur" /></a:minorFont></a:fontScheme><a:fmtScheme name="Office"><a:fillStyleLst><a:solidFill><a:schemeClr val="phClr" /></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="50000" /><a:satMod val="300000" /></a:schemeClr></a:gs><a:gs pos="35000"><a:schemeClr val="phClr"><a:tint val="37000" /><a:satMod val="300000" /></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="15000" /><a:satMod val="350000" /></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="1" /></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="100000" /><a:shade val="100000" /><a:satMod val="130000" /></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="50000" /><a:shade val="100000" /><a:satMod val="350000" /></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="0" /></a:gradFill></a:fillStyleLst><a:lnStyleLst><a:ln w="9525" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"><a:shade val="95000" /><a:satMod val="105000" /></a:schemeClr></a:solidFill><a:prstDash val="solid" /></a:ln><a:ln w="25400" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr" /></a:solidFill><a:prstDash val="solid" /></a:ln><a:ln w="38100" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr" /></a:solidFill><a:prstDash val="solid" /></a:ln></a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="20000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="38000" /></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000" /></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000" /></a:srgbClr></a:outerShdw></a:effectLst><a:scene3d><a:camera prst="orthographicFront"><a:rot lat="0" lon="0" rev="0" /></a:camera><a:lightRig rig="threePt" dir="t"><a:rot lat="0" lon="0" rev="1200000" /></a:lightRig></a:scene3d><a:sp3d><a:bevelT w="63500" h="25400" /></a:sp3d></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst><a:solidFill><a:schemeClr val="phClr" /></a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="40000" /><a:satMod val="350000" /></a:schemeClr></a:gs><a:gs pos="40000"><a:schemeClr val="phClr"><a:tint val="45000" /><a:shade val="99000" /><a:satMod val="350000" /></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="20000" /><a:satMod val="255000" /></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" t="-80000" r="50000" b="180000" /></a:path></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="80000" /><a:satMod val="300000" /></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="30000" /><a:satMod val="200000" /></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" t="50000" r="50000" b="50000" /></a:path></a:gradFill></a:bgFillStyleLst></a:fmtScheme></a:themeElements><a:objectDefaults><a:spDef><a:spPr /><a:bodyPr /><a:lstStyle /><a:style><a:lnRef idx="1"><a:schemeClr val="accent1" /></a:lnRef><a:fillRef idx="3"><a:schemeClr val="accent1" /></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent1" /></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="lt1" /></a:fontRef></a:style></a:spDef><a:lnDef><a:spPr /><a:bodyPr /><a:lstStyle /><a:style><a:lnRef idx="2"><a:schemeClr val="accent1" /></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1" /></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1" /></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1" /></a:fontRef></a:style></a:lnDef></a:objectDefaults><a:extraClrSchemeLst /></a:theme>+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>+<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">+ <a:themeElements>+ <a:clrScheme name="Office">+ <a:dk1>+ <a:sysClr val="windowText" lastClr="000000"/>+ </a:dk1>+ <a:lt1>+ <a:sysClr val="window" lastClr="FFFFFF"/>+ </a:lt1>+ <a:dk2>+ <a:srgbClr val="0E2841"/>+ </a:dk2>+ <a:lt2>+ <a:srgbClr val="E8E8E8"/>+ </a:lt2>+ <a:accent1>+ <a:srgbClr val="156082"/>+ </a:accent1>+ <a:accent2>+ <a:srgbClr val="E97132"/>+ </a:accent2>+ <a:accent3>+ <a:srgbClr val="196B24"/>+ </a:accent3>+ <a:accent4>+ <a:srgbClr val="0F9ED5"/>+ </a:accent4>+ <a:accent5>+ <a:srgbClr val="A02B93"/>+ </a:accent5>+ <a:accent6>+ <a:srgbClr val="4EA72E"/>+ </a:accent6>+ <a:hlink>+ <a:srgbClr val="467886"/>+ </a:hlink>+ <a:folHlink>+ <a:srgbClr val="96607D"/>+ </a:folHlink>+ </a:clrScheme>+ <a:fontScheme name="Office">+ <a:majorFont>+ <a:latin typeface="Aptos Display" panose="02110004020202020204"/>+ <a:ea typeface=""/>+ <a:cs typeface=""/>+ <a:font script="Jpan" typeface="游ゴシック Light"/>+ <a:font script="Hang" typeface="맑은 고딕"/>+ <a:font script="Hans" typeface="等线 Light"/>+ <a:font script="Hant" typeface="新細明體"/>+ <a:font script="Arab" typeface="Times New Roman"/>+ <a:font script="Hebr" typeface="Times New Roman"/>+ <a:font script="Thai" typeface="Angsana New"/>+ <a:font script="Ethi" typeface="Nyala"/>+ <a:font script="Beng" typeface="Vrinda"/>+ <a:font script="Gujr" typeface="Shruti"/>+ <a:font script="Khmr" typeface="MoolBoran"/>+ <a:font script="Knda" typeface="Tunga"/>+ <a:font script="Guru" typeface="Raavi"/>+ <a:font script="Cans" typeface="Euphemia"/>+ <a:font script="Cher" typeface="Plantagenet Cherokee"/>+ <a:font script="Yiii" typeface="Microsoft Yi Baiti"/>+ <a:font script="Tibt" typeface="Microsoft Himalaya"/>+ <a:font script="Thaa" typeface="MV Boli"/>+ <a:font script="Deva" typeface="Mangal"/>+ <a:font script="Telu" typeface="Gautami"/>+ <a:font script="Taml" typeface="Latha"/>+ <a:font script="Syrc" typeface="Estrangelo Edessa"/>+ <a:font script="Orya" typeface="Kalinga"/>+ <a:font script="Mlym" typeface="Kartika"/>+ <a:font script="Laoo" typeface="DokChampa"/>+ <a:font script="Sinh" typeface="Iskoola Pota"/>+ <a:font script="Mong" typeface="Mongolian Baiti"/>+ <a:font script="Viet" typeface="Times New Roman"/>+ <a:font script="Uigh" typeface="Microsoft Uighur"/>+ <a:font script="Geor" typeface="Sylfaen"/>+ <a:font script="Armn" typeface="Arial"/>+ <a:font script="Bugi" typeface="Leelawadee UI"/>+ <a:font script="Bopo" typeface="Microsoft JhengHei"/>+ <a:font script="Java" typeface="Javanese Text"/>+ <a:font script="Lisu" typeface="Segoe UI"/>+ <a:font script="Mymr" typeface="Myanmar Text"/>+ <a:font script="Nkoo" typeface="Ebrima"/>+ <a:font script="Olck" typeface="Nirmala UI"/>+ <a:font script="Osma" typeface="Ebrima"/>+ <a:font script="Phag" typeface="Phagspa"/>+ <a:font script="Syrn" typeface="Estrangelo Edessa"/>+ <a:font script="Syrj" typeface="Estrangelo Edessa"/>+ <a:font script="Syre" typeface="Estrangelo Edessa"/>+ <a:font script="Sora" typeface="Nirmala UI"/>+ <a:font script="Tale" typeface="Microsoft Tai Le"/>+ <a:font script="Talu" typeface="Microsoft New Tai Lue"/>+ <a:font script="Tfng" typeface="Ebrima"/>+ </a:majorFont>+ <a:minorFont>+ <a:latin typeface="Aptos" panose="02110004020202020204"/>+ <a:ea typeface=""/>+ <a:cs typeface=""/>+ <a:font script="Jpan" typeface="游明朝"/>+ <a:font script="Hang" typeface="맑은 고딕"/>+ <a:font script="Hans" typeface="等线"/>+ <a:font script="Hant" typeface="新細明體"/>+ <a:font script="Arab" typeface="Arial"/>+ <a:font script="Hebr" typeface="Arial"/>+ <a:font script="Thai" typeface="Cordia New"/>+ <a:font script="Ethi" typeface="Nyala"/>+ <a:font script="Beng" typeface="Vrinda"/>+ <a:font script="Gujr" typeface="Shruti"/>+ <a:font script="Khmr" typeface="DaunPenh"/>+ <a:font script="Knda" typeface="Tunga"/>+ <a:font script="Guru" typeface="Raavi"/>+ <a:font script="Cans" typeface="Euphemia"/>+ <a:font script="Cher" typeface="Plantagenet Cherokee"/>+ <a:font script="Yiii" typeface="Microsoft Yi Baiti"/>+ <a:font script="Tibt" typeface="Microsoft Himalaya"/>+ <a:font script="Thaa" typeface="MV Boli"/>+ <a:font script="Deva" typeface="Mangal"/>+ <a:font script="Telu" typeface="Gautami"/>+ <a:font script="Taml" typeface="Latha"/>+ <a:font script="Syrc" typeface="Estrangelo Edessa"/>+ <a:font script="Orya" typeface="Kalinga"/>+ <a:font script="Mlym" typeface="Kartika"/>+ <a:font script="Laoo" typeface="DokChampa"/>+ <a:font script="Sinh" typeface="Iskoola Pota"/>+ <a:font script="Mong" typeface="Mongolian Baiti"/>+ <a:font script="Viet" typeface="Arial"/>+ <a:font script="Uigh" typeface="Microsoft Uighur"/>+ <a:font script="Geor" typeface="Sylfaen"/>+ <a:font script="Armn" typeface="Arial"/>+ <a:font script="Bugi" typeface="Leelawadee UI"/>+ <a:font script="Bopo" typeface="Microsoft JhengHei"/>+ <a:font script="Java" typeface="Javanese Text"/>+ <a:font script="Lisu" typeface="Segoe UI"/>+ <a:font script="Mymr" typeface="Myanmar Text"/>+ <a:font script="Nkoo" typeface="Ebrima"/>+ <a:font script="Olck" typeface="Nirmala UI"/>+ <a:font script="Osma" typeface="Ebrima"/>+ <a:font script="Phag" typeface="Phagspa"/>+ <a:font script="Syrn" typeface="Estrangelo Edessa"/>+ <a:font script="Syrj" typeface="Estrangelo Edessa"/>+ <a:font script="Syre" typeface="Estrangelo Edessa"/>+ <a:font script="Sora" typeface="Nirmala UI"/>+ <a:font script="Tale" typeface="Microsoft Tai Le"/>+ <a:font script="Talu" typeface="Microsoft New Tai Lue"/>+ <a:font script="Tfng" typeface="Ebrima"/>+ </a:minorFont>+ </a:fontScheme>+ <a:fmtScheme name="Office">+ <a:fillStyleLst>+ <a:solidFill>+ <a:schemeClr val="phClr"/>+ </a:solidFill>+ <a:gradFill rotWithShape="1">+ <a:gsLst>+ <a:gs pos="0">+ <a:schemeClr val="phClr">+ <a:lumMod val="110000"/>+ <a:satMod val="105000"/>+ <a:tint val="67000"/>+ </a:schemeClr>+ </a:gs>+ <a:gs pos="50000">+ <a:schemeClr val="phClr">+ <a:lumMod val="105000"/>+ <a:satMod val="103000"/>+ <a:tint val="73000"/>+ </a:schemeClr>+ </a:gs>+ <a:gs pos="100000">+ <a:schemeClr val="phClr">+ <a:lumMod val="105000"/>+ <a:satMod val="109000"/>+ <a:tint val="81000"/>+ </a:schemeClr>+ </a:gs>+ </a:gsLst>+ <a:lin ang="5400000" scaled="0"/>+ </a:gradFill>+ <a:gradFill rotWithShape="1">+ <a:gsLst>+ <a:gs pos="0">+ <a:schemeClr val="phClr">+ <a:satMod val="103000"/>+ <a:lumMod val="102000"/>+ <a:tint val="94000"/>+ </a:schemeClr>+ </a:gs>+ <a:gs pos="50000">+ <a:schemeClr val="phClr">+ <a:satMod val="110000"/>+ <a:lumMod val="100000"/>+ <a:shade val="100000"/>+ </a:schemeClr>+ </a:gs>+ <a:gs pos="100000">+ <a:schemeClr val="phClr">+ <a:lumMod val="99000"/>+ <a:satMod val="120000"/>+ <a:shade val="78000"/>+ </a:schemeClr>+ </a:gs>+ </a:gsLst>+ <a:lin ang="5400000" scaled="0"/>+ </a:gradFill>+ </a:fillStyleLst>+ <a:lnStyleLst>+ <a:ln w="6350" cap="flat" cmpd="sng" algn="ctr">+ <a:solidFill>+ <a:schemeClr val="phClr"/>+ </a:solidFill>+ <a:prstDash val="solid"/>+ <a:miter lim="800000"/>+ </a:ln>+ <a:ln w="12700" cap="flat" cmpd="sng" algn="ctr">+ <a:solidFill>+ <a:schemeClr val="phClr"/>+ </a:solidFill>+ <a:prstDash val="solid"/>+ <a:miter lim="800000"/>+ </a:ln>+ <a:ln w="19050" cap="flat" cmpd="sng" algn="ctr">+ <a:solidFill>+ <a:schemeClr val="phClr"/>+ </a:solidFill>+ <a:prstDash val="solid"/>+ <a:miter lim="800000"/>+ </a:ln>+ </a:lnStyleLst>+ <a:effectStyleLst>+ <a:effectStyle>+ <a:effectLst/>+ </a:effectStyle>+ <a:effectStyle>+ <a:effectLst/>+ </a:effectStyle>+ <a:effectStyle>+ <a:effectLst>+ <a:outerShdw blurRad="57150" dist="19050" dir="5400000" algn="ctr" rotWithShape="0">+ <a:srgbClr val="000000">+ <a:alpha val="63000"/>+ </a:srgbClr>+ </a:outerShdw>+ </a:effectLst>+ </a:effectStyle>+ </a:effectStyleLst>+ <a:bgFillStyleLst>+ <a:solidFill>+ <a:schemeClr val="phClr"/>+ </a:solidFill>+ <a:solidFill>+ <a:schemeClr val="phClr">+ <a:tint val="95000"/>+ <a:satMod val="170000"/>+ </a:schemeClr>+ </a:solidFill>+ <a:gradFill rotWithShape="1">+ <a:gsLst>+ <a:gs pos="0">+ <a:schemeClr val="phClr">+ <a:tint val="93000"/>+ <a:satMod val="150000"/>+ <a:shade val="98000"/>+ <a:lumMod val="102000"/>+ </a:schemeClr>+ </a:gs>+ <a:gs pos="50000">+ <a:schemeClr val="phClr">+ <a:tint val="98000"/>+ <a:satMod val="130000"/>+ <a:shade val="90000"/>+ <a:lumMod val="103000"/>+ </a:schemeClr>+ </a:gs>+ <a:gs pos="100000">+ <a:schemeClr val="phClr">+ <a:shade val="63000"/>+ <a:satMod val="120000"/>+ </a:schemeClr>+ </a:gs>+ </a:gsLst>+ <a:lin ang="5400000" scaled="0"/>+ </a:gradFill>+ </a:bgFillStyleLst>+ </a:fmtScheme>+ </a:themeElements>+ <a:objectDefaults/>+ <a:extraClrSchemeLst/>+ <a:extLst>+ <a:ext uri="{05A4C25C-085E-4340-85A3-A5531E510DB2}">+ <thm15:themeFamily xmlns:thm15="http://schemas.microsoft.com/office/thememl/2012/main" name="Office Theme" id="{2E142A2C-CD16-42D6-873A-C26D2A0506FA}" vid="{1BDDFF52-6CD6-40A5-AB3C-68EB2F1E4D0A}"/>+ </a:ext>+ </a:extLst>+</a:theme>
@@ -1,29 +1,214 @@ /* This defines styles and classes used in the book */-body { margin: 5%; text-align: justify; font-size: medium; }-code { font-family: monospace; }-h1 { text-align: left; }-h2 { text-align: left; }-h3 { text-align: left; }-h4 { text-align: left; }-h5 { text-align: left; }-h6 { text-align: left; }+@page {+ margin: 10px;+}+html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p,+blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img,+ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center,+fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td,+article, aside, canvas, details, embed, figure, figcaption, footer, header,+hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video, ol,+ul, li, dl, dt, dd {+ margin: 0;+ padding: 0;+ border: 0;+ font-size: 100%;+ vertical-align: baseline;+}+html {+ line-height: 1.2;+ font-family: Georgia, serif;+ color: #1a1a1a;+}+p {+ text-indent: 0;+ margin: 1em 0;+ widows: 2;+ orphans: 2;+}+img {+ max-width: 100%;+}+sup {+ vertical-align: super;+ font-size: smaller;+}+sub {+ vertical-align: sub;+ font-size: smaller;+}+h1 {+ margin: 3em 0 0 0;+ font-size: 2em;+ page-break-before: always;+ line-height: 150%;+}+h2 {+ margin: 1.5em 0 0 0;+ font-size: 1.5em;+ line-height: 135%;+}+h3 {+ margin: 1.3em 0 0 0;+ font-size: 1.3em;+}+h4 {+ margin: 1.2em 0 0 0;+ font-size: 1.2em;+}+h5 {+ margin: 1.1em 0 0 0;+ font-size: 1.1em;+}+h6 {+ font-size: 1em;+}+h1, h2, h3, h4, h5, h6 {+ text-indent: 0;+ text-align: left;+ font-weight: bold;+ page-break-after: avoid;+ page-break-inside: avoid;+}++ol, ul {+ margin: 1em 0 0 1.7em;+}+li > ol, li > ul {+ margin-top: 0;+}+blockquote {+ margin: 1em 0 1em 1.7em;+}+code {+ font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;+ font-size: 85%;+ margin: 0;+ hyphens: manual;+}+pre {+ margin: 1em 0;+ overflow: auto;+}+pre code {+ padding: 0;+ overflow: visible;+ overflow-wrap: normal;+}+.sourceCode {+ background-color: transparent;+ overflow: visible;+}+hr {+ background-color: #1a1a1a;+ border: none;+ height: 1px;+ margin: 1em 0;+}+table {+ margin: 1em 0;+ border-collapse: collapse;+ width: 100%;+ overflow-x: auto;+ display: block;+}+table caption {+ margin-bottom: 0.75em;+}+tbody {+ margin-top: 0.5em;+ border-top: 1px solid #1a1a1a;+ border-bottom: 1px solid #1a1a1a;+}+th, td {+ padding: 0.25em 0.5em 0.25em 0.5em;+}+th {+ border-top: 1px solid #1a1a1a;+}+header {+ margin-bottom: 4em;+ text-align: center;+}+#TOC li {+ list-style: none;+}+#TOC ul {+ padding-left: 1.3em;+}+#TOC > ul {+ padding-left: 0;+}+#TOC a:not(:hover) {+ text-decoration: none;+}+code {+ white-space: pre-wrap;+}+span.smallcaps {+ font-variant: small-caps;+}++/* This is the most compatible CSS, but it only allows two columns: */+div.column {+ display: inline-block;+ vertical-align: top;+ width: 50%;+}+/* If you can rely on CSS3 support, use this instead: */+/* div.columns {+ display: flex;+ gap: min(4vw, 1.5em);+}+div.column {+ flex: auto;+ overflow-x: auto;+} */++div.hanging-indent {+ margin-left: 1.5em;+ text-indent: -1.5em;+}+ul.task-list {+ list-style: none;+}+ul.task-list li input[type="checkbox"] {+ width: 0.8em;+ margin: 0 0.8em 0.2em -1.6em;+ vertical-align: middle;+}+.display.math {+ display: block;+ text-align: center;+ margin: 0.5rem auto;+}+ /* For title, author, and date on the cover page */ h1.title { } p.author { } p.date { }-nav#toc ol,-nav#landmarks ol { padding: 0; margin-left: 1em; }-nav#toc ol li,-nav#landmarks ol li { list-style-type: none; margin: 0; padding: 0; }-a.footnote-ref { vertical-align: super; }-em, em em em, em em em em em { font-style: italic;}-em em, em em em em { font-style: normal; }-code{ white-space: pre-wrap; }-span.smallcaps{ font-variant: small-caps; }-span.underline{ text-decoration: underline; }-q { quotes: "“" "”" "‘" "’"; }-div.column{ display: inline-block; vertical-align: top; width: 50%; }-div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}++nav#toc ol, nav#landmarks ol {+ padding: 0;+ margin-left: 1em;+}+nav#toc ol li, nav#landmarks ol li {+ list-style-type: none;+ margin: 0;+ padding: 0;+}+a.footnote-ref {+ vertical-align: super;+}+em, em em em, em em em em em {+ font-style: italic;+}+em em, em em em em {+ font-style: normal;+}+q {+ quotes: "“" "”" "‘" "’";+} @media screen { /* Workaround for iBooks issue; see #6242 */ .sourceCode { overflow: visible !important;
@@ -1,12 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?>-<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">- <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.text"/>+<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.3">+ <manifest:file-entry manifest:full-path="/" manifest:version="1.3" manifest:media-type="application/vnd.oasis.opendocument.text"/> <manifest:file-entry manifest:full-path="meta.xml" manifest:media-type="text/xml"/>- <manifest:file-entry manifest:full-path="settings.xml" manifest:media-type="text/xml"/> <manifest:file-entry manifest:full-path="content.xml" manifest:media-type="text/xml"/>- <manifest:file-entry manifest:full-path="Thumbnails/thumbnail.png" manifest:media-type="image/png"/> <manifest:file-entry manifest:full-path="manifest.rdf" manifest:media-type="application/rdf+xml"/>- <manifest:file-entry manifest:full-path="Configurations2/accelerator/current.xml" manifest:media-type=""/>- <manifest:file-entry manifest:full-path="Configurations2/" manifest:media-type="application/vnd.sun.xml.ui.configuration"/> <manifest:file-entry manifest:full-path="styles.xml" manifest:media-type="text/xml"/> </manifest:manifest>
binary file changed (785 → absent bytes)
@@ -1,2 +1,82 @@ <?xml version="1.0" encoding="UTF-8"?>-<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2"><office:scripts/><office:font-face-decls><style:font-face style:name="StarSymbol" svg:font-family="StarSymbol"/><style:font-face style:name="Tahoma1" svg:font-family="Tahoma"/><style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/><style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/><style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/><style:font-face style:name="Lucida Sans Unicode" svg:font-family="'Lucida Sans Unicode'" style:font-family-generic="system" style:font-pitch="variable"/><style:font-face style:name="Tahoma" svg:font-family="Tahoma" style:font-family-generic="system" style:font-pitch="variable"/></office:font-face-decls><office:automatic-styles><style:style style:name="P1" style:family="paragraph" style:parent-style-name="Footer"><style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/></style:style></office:automatic-styles><office:body><office:text><text:sequence-decls><text:sequence-decl text:display-outline-level="0" text:name="Illustration"/><text:sequence-decl text:display-outline-level="0" text:name="Table"/><text:sequence-decl text:display-outline-level="0" text:name="Text"/><text:sequence-decl text:display-outline-level="0" text:name="Drawing"/></text:sequence-decls><text:p text:style-name="Standard">Hello World!</text:p></office:text></office:body></office:document-content>+<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.3">+ <office:scripts/>+ <office:font-face-decls>+ <style:font-face style:name="StarSymbol" svg:font-family="StarSymbol"/>+ <style:font-face style:name="Tahoma1" svg:font-family="Tahoma"/>+ <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/>+ <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/>+ <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/>+ <style:font-face style:name="Lucida Sans Unicode" svg:font-family="'Lucida Sans Unicode'" style:font-family-generic="system" style:font-pitch="variable"/>+ <style:font-face style:name="Tahoma" svg:font-family="Tahoma" style:font-family-generic="system" style:font-pitch="variable"/>+ </office:font-face-decls>+ <office:automatic-styles>+ <style:style style:name="DemoTable" style:family="table">+ <style:table-properties style:width="6in" table:align="margins"/>+ </style:style>+ <style:style style:name="DemoTable.A" style:family="table-column">+ <style:table-column-properties style:column-width="3in"/>+ </style:style>+ </office:automatic-styles>+ <office:body>+ <office:text>+ <text:sequence-decls>+ <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>+ <text:sequence-decl text:display-outline-level="0" text:name="Table"/>+ <text:sequence-decl text:display-outline-level="0" text:name="Text"/>+ <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>+ </text:sequence-decls>+ <text:p text:style-name="Title">Title</text:p>+ <text:p text:style-name="Subtitle">Subtitle</text:p>+ <text:p text:style-name="Author">Author</text:p>+ <text:p text:style-name="Date">Date</text:p>+ <text:p text:style-name="Abstract">Abstract.</text:p>+ <text:h text:style-name="Heading_20_1" text:outline-level="1">Heading 1</text:h>+ <text:h text:style-name="Heading_20_2" text:outline-level="2">Heading 2</text:h>+ <text:h text:style-name="Heading_20_3" text:outline-level="3">Heading 3</text:h>+ <text:h text:style-name="Heading_20_4" text:outline-level="4">Heading 4</text:h>+ <text:h text:style-name="Heading_20_5" text:outline-level="5">Heading 5</text:h>+ <text:h text:style-name="Heading_20_6" text:outline-level="6">Heading 6</text:h>+ <text:p text:style-name="First_20_paragraph">First Paragraph.</text:p>+ <text:p text:style-name="Text_20_body">Body Text. <text:span text:style-name="Emphasis">Emphasis</text:span>. <text:span text:style-name="Strong_20_Emphasis">Strong Emphasis</text:span>. <text:span text:style-name="Strikeout">Strikeout</text:span>. <text:span text:style-name="Superscript">Superscript</text:span>. <text:span text:style-name="Subscript">Subscript</text:span>. <text:span text:style-name="Source_20_Text">Source Text</text:span>. <text:span text:style-name="Highlighted">Highlighted</text:span>. <text:a xlink:type="simple" xlink:href="https://pandoc.org"><text:span text:style-name="Definition">Hyperlink</text:span></text:a>. Footnote.<text:note text:id="ftn1" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote">Footnote text.</text:p></text:note-body></text:note></text:p>+ <text:p text:style-name="Quotations">Block quote.</text:p>+ <text:p text:style-name="Preformatted_20_Text">Preformatted Text.</text:p>+ <text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">Bullet list item.</text:p>+ </text:list-item>+ </text:list>+ <text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number">Numbered list item.</text:p>+ </text:list-item>+ </text:list>+ <text:p text:style-name="TableCaption">Table caption.</text:p>+ <table:table table:name="DemoTable" table:style-name="DemoTable">+ <table:table-column table:style-name="DemoTable.A"/>+ <table:table-column table:style-name="DemoTable.A"/>+ <table:table-header-rows>+ <table:table-row>+ <table:table-cell office:value-type="string">+ <text:p text:style-name="Table_20_Heading">Table Heading</text:p>+ </table:table-cell>+ <table:table-cell office:value-type="string">+ <text:p text:style-name="Table_20_Heading">Table Heading</text:p>+ </table:table-cell>+ </table:table-row>+ </table:table-header-rows>+ <table:table-row>+ <table:table-cell office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Table Contents</text:p>+ </table:table-cell>+ <table:table-cell office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Table Contents</text:p>+ </table:table-cell>+ </table:table-row>+ </table:table>+ <text:p text:style-name="FigureCaption">Image caption.</text:p>+ <text:p text:style-name="Definition_20_Term">Definition Term</text:p>+ <text:p text:style-name="Definition_20_Definition">Definition.</text:p>+ </office:text>+ </office:body>+</office:document-content>
@@ -6,7 +6,7 @@ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:grddl="http://www.w3.org/2003/g/data-view#"- office:version="1.2">+ office:version="1.3"> <office:meta> <meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0"
@@ -1,2 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<office:document-settings xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" office:version="1.2"><office:settings><config:config-item-set config:name="ooo:view-settings"><config:config-item config:name="ViewAreaTop" config:type="int">0</config:config-item><config:config-item config:name="ViewAreaLeft" config:type="int">0</config:config-item><config:config-item config:name="ViewAreaWidth" config:type="int">21747</config:config-item><config:config-item config:name="ViewAreaHeight" config:type="int">10874</config:config-item><config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item><config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item><config:config-item-map-indexed config:name="Views"><config:config-item-map-entry><config:config-item config:name="ViewId" config:type="string">view2</config:config-item><config:config-item config:name="ViewLeft" config:type="int">3041</config:config-item><config:config-item config:name="ViewTop" config:type="int">3041</config:config-item><config:config-item config:name="VisibleLeft" config:type="int">0</config:config-item><config:config-item config:name="VisibleTop" config:type="int">0</config:config-item><config:config-item config:name="VisibleRight" config:type="int">21745</config:config-item><config:config-item config:name="VisibleBottom" config:type="int">10873</config:config-item><config:config-item config:name="ZoomType" config:type="short">0</config:config-item><config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item><config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item><config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item><config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item></config:config-item-map-entry></config:config-item-map-indexed></config:config-item-set><config:config-item-set config:name="ooo:configuration-settings"><config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item><config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item><config:config-item config:name="MathBaselineAlignment" config:type="boolean">false</config:config-item><config:config-item config:name="Rsid" config:type="int">1473719</config:config-item><config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item><config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item><config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item><config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item><config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item><config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item><config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item><config:config-item config:name="CurrentDatabaseCommand" config:type="string"/><config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item><config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item><config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item><config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item><config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item><config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item><config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item><config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item><config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item><config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item><config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item><config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item><config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item><config:config-item config:name="PrintEmptyPages" config:type="boolean">false</config:config-item><config:config-item config:name="UnbreakableNumberings" config:type="boolean">false</config:config-item><config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item><config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">false</config:config-item><config:config-item config:name="TableRowKeep" config:type="boolean">false</config:config-item><config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item><config:config-item config:name="TabsRelativeToIndent" config:type="boolean">true</config:config-item><config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item><config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item><config:config-item config:name="AddFrameOffsets" config:type="boolean">false</config:config-item><config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item><config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item><config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item><config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item><config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item><config:config-item config:name="RsidRoot" config:type="int">1473719</config:config-item><config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item><config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item><config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item><config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item><config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/><config:config-item config:name="PrinterSetup" config:type="base64Binary"/><config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item><config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item><config:config-item config:name="PrinterName" config:type="string"/><config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item><config:config-item config:name="InvertBorderSpacing" config:type="boolean">false</config:config-item><config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item><config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item><config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item><config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item><config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item><config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item><config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item><config:config-item config:name="PrintFaxName" config:type="string"/><config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item><config:config-item config:name="AddParaTableSpacing" config:type="boolean">true</config:config-item><config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item><config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item><config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item><config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item><config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item><config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item><config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item><config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/><config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">false</config:config-item><config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item><config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item><config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item><config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item><config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item></config:config-item-set></office:settings></office:document-settings>
@@ -27,7 +27,7 @@ xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"-xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2">+xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.3"> <office:font-face-decls> <style:font-face style:name="StarSymbol" svg:font-family="StarSymbol" />@@ -73,6 +73,26 @@ style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none" /> </style:default-style>+ <style:style style:name="Title" style:family="paragraph"+ style:parent-style-name="Heading" style:next-style-name="Subtitle"+ style:class="chapter">+ <style:paragraph-properties fo:text-align="center"+ style:justify-single-word="false" fo:margin-top="0in"+ fo:margin-bottom="0.0835in" style:contextual-spacing="false" />+ <style:text-properties fo:font-size="28pt" fo:font-weight="bold"+ style:font-size-asian="28pt" style:font-weight-asian="bold"+ style:font-size-complex="28pt" style:font-weight-complex="bold" />+ </style:style>+ <style:style style:name="Subtitle" style:family="paragraph"+ style:parent-style-name="Heading" style:next-style-name="Text_20_body"+ style:class="chapter">+ <style:paragraph-properties fo:text-align="center"+ style:justify-single-word="false" fo:margin-top="0.0835in"+ fo:margin-bottom="0.0835in" style:contextual-spacing="false" />+ <style:text-properties fo:font-size="18pt" fo:font-style="italic"+ style:font-size-asian="18pt" style:font-style-asian="italic"+ style:font-size-complex="18pt" style:font-style-complex="italic" />+ </style:style> <style:style style:name="Author" style:family="paragraph" style:parent-style-name="Standard" style:class="html"> <style:paragraph-properties fo:text-align="center" />@@ -136,6 +156,24 @@ style:parent-style-name="Text_20_body" style:class="list"> <style:text-properties style:font-name-complex="Tahoma1" /> </style:style>+ <style:style style:name="List_20_Bullet"+ style:display-name="List Bullet" style:family="paragraph"+ style:parent-style-name="List" style:class="list" />+ <style:style style:name="List_20_Bullet_20_Tight"+ style:display-name="List Bullet Tight" style:family="paragraph"+ style:parent-style-name="List" style:class="list">+ <style:paragraph-properties fo:margin-top="0in"+ fo:margin-bottom="0in" style:contextual-spacing="false" />+ </style:style>+ <style:style style:name="List_20_Number"+ style:display-name="List Number" style:family="paragraph"+ style:parent-style-name="List" style:class="list" />+ <style:style style:name="List_20_Number_20_Tight"+ style:display-name="List Number Tight" style:family="paragraph"+ style:parent-style-name="List" style:class="list">+ <style:paragraph-properties fo:margin-top="0in"+ fo:margin-bottom="0in" style:contextual-spacing="false" />+ </style:style> <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> <style:paragraph-properties fo:margin-top="0.0835in"@@ -148,6 +186,9 @@ style:font-size-complex="12pt" style:font-style-complex="italic" /> </style:style>+ <style:style style:name="TableCaption" style:family="paragraph"+ style:parent-style-name="Caption" style:class="extra">+ </style:style> <style:style style:name="Table" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"> </style:style>@@ -247,17 +288,39 @@ <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" style:contextual-spacing="false" /> <style:text-properties style:font-name="Courier New"- fo:font-size="10pt" style:font-name-asian="Courier New"+ fo:font-family="'Courier New'"+ style:font-family-generic="modern"+ style:font-pitch="fixed"+ fo:font-size="10pt"+ style:font-name-asian="Courier New"+ style:font-family-asian="'Courier New'"+ style:font-family-generic-asian="modern"+ style:font-pitch-asian="fixed" style:font-size-asian="10pt" style:font-name-complex="Courier New"- style:font-size-complex="10pt" />+ style:font-family-complex="'Courier New'"+ style:font-family-generic-complex="modern"+ style:font-pitch-complex="fixed"+ style:font-size-complex="10pt"+ fo:language="zxx" /> </style:style>- <style:style style:name="Source_Text" style:family="text">+ <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text"> <style:text-properties style:font-name="Courier New"- fo:font-size="10pt" style:font-name-asian="Courier New"- style:font-size-asian="10pt"+ fo:font-family="'Courier New'"+ style:font-family-generic="modern"+ style:font-pitch="fixed"+ style:font-name-asian="Courier New"+ style:font-family-asian="'Courier New'"+ style:font-family-generic-asian="modern"+ style:font-pitch-asian="fixed" style:font-name-complex="Courier New"- style:font-size-complex="10pt" />+ style:font-family-complex="'Courier New'"+ style:font-family-generic-complex="modern"+ style:font-pitch-complex="fixed"+ fo:language="zxx" />+ </style:style>+ <style:style style:name="Highlighted" style:family="text">+ <style:text-properties fo:background-color="#ffff38" /> </style:style> <style:style style:name="Definition_20_Term" style:display-name="Definition Term" style:family="paragraph"
@@ -1,2 +1,2 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"><p:cSld><p:spTree><p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr><p:sp><p:nvSpPr><p:cNvPr id="2" name="Title 1"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="title"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:r><a:rPr lang="en-US" dirty="0"/><a:t>Section header</a:t></a:r></a:p></p:txBody></p:sp><p:sp><p:nvSpPr><p:cNvPr id="3" name="Text Placeholder 2"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="body" idx="1"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:r><a:rPr lang="en-US" dirty="0"/><a:t>Some explanatory text</a:t></a:r></a:p></p:txBody></p:sp></p:spTree><p:extLst><p:ext uri="{BB962C8B-B14F-4D97-AF65-F5344CB8AC3E}"><p14:creationId xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" val="3996781534"/></p:ext></p:extLst></p:cSld><p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr></p:sld>+<p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"><p:cSld><p:spTree><p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr><p:sp><p:nvSpPr><p:cNvPr id="2" name="Title 1"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="title"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:r><a:rPr lang="en-US" dirty="0"/><a:t>Section header</a:t></a:r></a:p></p:txBody></p:sp><p:sp><p:nvSpPr><p:cNvPr id="3" name="Text Placeholder 2"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="body" idx="1"/></p:nvPr></p:nvSpPr><p:spPr/></p:sp></p:spTree><p:extLst><p:ext uri="{BB962C8B-B14F-4D97-AF65-F5344CB8AC3E}"><p14:creationId xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" val="3996781534"/></p:ext></p:extLst></p:cSld><p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr></p:sld>
@@ -1,363 +0,0 @@--- This is a sample custom writer for pandoc. It produces output--- that is very similar to that of pandoc's HTML writer.--- There is one new feature: code blocks marked with class 'dot'--- are piped through graphviz and images are included in the HTML--- output using 'data:' URLs. The image format can be controlled--- via the `image_format` metadata field.------ Invoke with: pandoc -t sample.lua------ Note: you need not have lua installed on your system to use this--- custom writer. However, if you do have lua installed, you can--- use it to test changes to the script. 'lua sample.lua' will--- produce informative error messages if your code contains--- syntax errors.--local pipe = pandoc.pipe-local stringify = (require 'pandoc.utils').stringify---- The global variable PANDOC_DOCUMENT contains the full AST of--- the document which is going to be written. It can be used to--- configure the writer.-local meta = PANDOC_DOCUMENT.meta---- Choose the image format based on the value of the--- `image_format` meta value.-local image_format = meta.image_format- and stringify(meta.image_format)- or 'png'-local image_mime_type = ({- jpeg = 'image/jpeg',- jpg = 'image/jpeg',- gif = 'image/gif',- png = 'image/png',- svg = 'image/svg+xml',- })[image_format]- or error('unsupported image format `' .. image_format .. '`')---- Character escaping-local function escape(s, in_attribute)- return s:gsub('[<>&"\']',- function(x)- if x == '<' then- return '<'- elseif x == '>' then- return '>'- elseif x == '&' then- return '&'- elseif in_attribute and x == '"' then- return '"'- elseif in_attribute and x == "'" then- return '''- else- return x- end- end)-end---- Helper function to convert an attributes table into--- a string that can be put into HTML tags.-local function attributes(attr)- local attr_table = {}- for x,y in pairs(attr) do- if y and y ~= '' then- table.insert(attr_table, ' ' .. x .. '="' .. escape(y,true) .. '"')- end- end- return table.concat(attr_table)-end---- Table to store footnotes, so they can be included at the end.-local notes = {}---- Blocksep is used to separate block elements.-function Blocksep()- return '\n\n'-end---- This function is called once for the whole document. Parameters:--- body is a string, metadata is a table, variables is a table.--- This gives you a fragment. You could use the metadata table to--- fill variables in a custom lua template. Or, pass `--template=...`--- to pandoc, and pandoc will do the template processing as usual.-function Doc(body, metadata, variables)- local buffer = {}- local function add(s)- table.insert(buffer, s)- end- add(body)- if #notes > 0 then- add('<ol class="footnotes">')- for _,note in pairs(notes) do- add(note)- end- add('</ol>')- end- return table.concat(buffer,'\n') .. '\n'-end---- The functions that follow render corresponding pandoc elements.--- s is always a string, attr is always a table of attributes, and--- items is always an array of strings (the items in a list).--- Comments indicate the types of other variables.--function Str(s)- return escape(s)-end--function Space()- return ' '-end--function SoftBreak()- return '\n'-end--function LineBreak()- return '<br/>'-end--function Emph(s)- return '<em>' .. s .. '</em>'-end--function Strong(s)- return '<strong>' .. s .. '</strong>'-end--function Subscript(s)- return '<sub>' .. s .. '</sub>'-end--function Superscript(s)- return '<sup>' .. s .. '</sup>'-end--function SmallCaps(s)- return '<span style="font-variant: small-caps;">' .. s .. '</span>'-end--function Strikeout(s)- return '<del>' .. s .. '</del>'-end--function Link(s, tgt, tit, attr)- return '<a href="' .. escape(tgt,true) .. '" title="' ..- escape(tit,true) .. '"' .. attributes(attr) .. '>' .. s .. '</a>'-end--function Image(s, src, tit, attr)- return '<img src="' .. escape(src,true) .. '" title="' ..- escape(tit,true) .. '"/>'-end--function Code(s, attr)- return '<code' .. attributes(attr) .. '>' .. escape(s) .. '</code>'-end--function InlineMath(s)- return '\\(' .. escape(s) .. '\\)'-end--function DisplayMath(s)- return '\\[' .. escape(s) .. '\\]'-end--function SingleQuoted(s)- return '‘' .. s .. '’'-end--function DoubleQuoted(s)- return '“' .. s .. '”'-end--function Note(s)- local num = #notes + 1- -- insert the back reference right before the final closing tag.- s = string.gsub(s,- '(.*)</', '%1 <a href="#fnref' .. num .. '">↩</a></')- -- add a list item with the note to the note table.- table.insert(notes, '<li id="fn' .. num .. '">' .. s .. '</li>')- -- return the footnote reference, linked to the note.- return '<a id="fnref' .. num .. '" href="#fn' .. num ..- '"><sup>' .. num .. '</sup></a>'-end--function Span(s, attr)- return '<span' .. attributes(attr) .. '>' .. s .. '</span>'-end--function RawInline(format, str)- if format == 'html' then- return str- else- return ''- end-end--function Cite(s, cs)- local ids = {}- for _,cit in ipairs(cs) do- table.insert(ids, cit.citationId)- end- return '<span class="cite" data-citation-ids="' .. table.concat(ids, ',') ..- '">' .. s .. '</span>'-end--function Plain(s)- return s-end--function Para(s)- return '<p>' .. s .. '</p>'-end---- lev is an integer, the header level.-function Header(lev, s, attr)- return '<h' .. lev .. attributes(attr) .. '>' .. s .. '</h' .. lev .. '>'-end--function BlockQuote(s)- return '<blockquote>\n' .. s .. '\n</blockquote>'-end--function HorizontalRule()- return "<hr/>"-end--function LineBlock(ls)- return '<div style="white-space: pre-line;">' .. table.concat(ls, '\n') ..- '</div>'-end--function CodeBlock(s, attr)- -- If code block has class 'dot', pipe the contents through dot- -- and base64, and include the base64-encoded png as a data: URL.- if attr.class and string.match(' ' .. attr.class .. ' ',' dot ') then- local img = pipe('base64', {}, pipe('dot', {'-T' .. image_format}, s))- return '<img src="data:' .. image_mime_type .. ';base64,' .. img .. '"/>'- -- otherwise treat as code (one could pipe through a highlighter)- else- return '<pre><code' .. attributes(attr) .. '>' .. escape(s) ..- '</code></pre>'- end-end--function BulletList(items)- local buffer = {}- for _, item in pairs(items) do- table.insert(buffer, '<li>' .. item .. '</li>')- end- return '<ul>\n' .. table.concat(buffer, '\n') .. '\n</ul>'-end--function OrderedList(items)- local buffer = {}- for _, item in pairs(items) do- table.insert(buffer, '<li>' .. item .. '</li>')- end- return '<ol>\n' .. table.concat(buffer, '\n') .. '\n</ol>'-end--function DefinitionList(items)- local buffer = {}- for _,item in pairs(items) do- local k, v = next(item)- table.insert(buffer, '<dt>' .. k .. '</dt>\n<dd>' ..- table.concat(v, '</dd>\n<dd>') .. '</dd>')- end- return '<dl>\n' .. table.concat(buffer, '\n') .. '\n</dl>'-end---- Convert pandoc alignment to something HTML can use.--- align is AlignLeft, AlignRight, AlignCenter, or AlignDefault.-local function html_align(align)- if align == 'AlignLeft' then- return 'left'- elseif align == 'AlignRight' then- return 'right'- elseif align == 'AlignCenter' then- return 'center'- else- return 'left'- end-end--function CaptionedImage(src, tit, caption, attr)- if #caption == 0 then- return '<p><img src="' .. escape(src,true) .. '" id="' .. attr.id ..- '"/></p>'- else- local ecaption = escape(caption)- return '<figure>\n<img src="' .. escape(src,true) ..- '" id="' .. attr.id .. '" alt="' .. ecaption .. '"/>' ..- '<figcaption>' .. ecaption .. '</figcaption>\n</figure>'- end-end---- Caption is a string, aligns is an array of strings,--- widths is an array of floats, headers is an array of--- strings, rows is an array of arrays of strings.-function Table(caption, aligns, widths, headers, rows)- local buffer = {}- local function add(s)- table.insert(buffer, s)- end- add('<table>')- if caption ~= '' then- add('<caption>' .. escape(caption) .. '</caption>')- end- if widths and widths[1] ~= 0 then- for _, w in pairs(widths) do- add('<col width="' .. string.format('%.0f%%', w * 100) .. '" />')- end- end- local header_row = {}- local empty_header = true- for i, h in pairs(headers) do- local align = html_align(aligns[i])- table.insert(header_row,'<th align="' .. align .. '">' .. h .. '</th>')- empty_header = empty_header and h == ''- end- if not empty_header then- add('<tr class="header">')- for _,h in pairs(header_row) do- add(h)- end- add('</tr>')- end- local class = 'even'- for _, row in pairs(rows) do- class = (class == 'even' and 'odd') or 'even'- add('<tr class="' .. class .. '">')- for i,c in pairs(row) do- add('<td align="' .. html_align(aligns[i]) .. '">' .. c .. '</td>')- end- add('</tr>')- end- add('</table>')- return table.concat(buffer,'\n')-end--function RawBlock(format, str)- if format == 'html' then- return str- else- return ''- end-end--function Div(s, attr)- return '<div' .. attributes(attr) .. '>\n' .. s .. '</div>'-end---- The following code will produce runtime warnings when you haven't defined--- all of the functions you need for the custom writer, so it's useful--- to include when you're working on a writer.-local meta = {}-meta.__index =- function(_, key)- io.stderr:write(string.format("WARNING: Undefined function '%s'\n",key))- return function() return '' end- end-setmetatable(_G, meta)
@@ -0,0 +1,10 @@+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{$if(urlstyle)$$urlstyle$$else$same$endif$}+$if(links-as-notes)$+% Make links footnotes instead of hotlinks:+\DeclareRobustCommand{\href}[2]{#2\footnote{\url{#1}}}+$endif$+$if(verbatim-in-note)$+\VerbatimFootnotes % allow verbatim text in footnotes+$endif$
@@ -98,7 +98,7 @@ <surname>$if(author.non-dropping-particle)$${author.non-dropping-particle} $endif$$author.surname$</surname> <given-names>$author.given-names$$if(author.dropping-particle)$ ${author.dropping-particle}$endif$</given-names> $if(author.prefix)$-<prefix>${author.suffix}</prefix>+<prefix>${author.prefix}</prefix> $endif$ $if(author.suffix)$ <suffix>${author.suffix}</suffix>@@ -109,6 +109,17 @@ $else$ <string-name>$author$</string-name> $endif$+$for(author.roles)$+$if(it.credit)$+<role vocab="credit"$if(it.degree)$ degree-contribution="$it.degree$"$endif$+ vocab-identifier="https://credit.niso.org/"+ vocab-term-identifier="https://credit.niso.org/contributor-roles/$it.credit$/"+ vocab-term="$it.credit-name$"+>$if(it.name)$$it.name$$else$$it.credit-name$$endif$</role>+$elseif(it.name)$+<role>$it.name$</role>+$endif$+$endfor$ $if(author.email)$ <email>$author.email$</email> $endif$@@ -232,5 +243,10 @@ $back$ $endif$ </back>+$if(floats-group)$+<floats-group>+$floats-group$+</floats-group>+$endif$ </article>
@@ -0,0 +1,263 @@+$if(linestretch)$+\usepackage{setspace}+$endif$+$--+$-- paragraph formatting+$--+$if(indent)$+$else$+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+ \IfFileExists{parskip.sty}{%+ \usepackage{parskip}+ }{% else+ \setlength{\parindent}{0pt}+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+ \KOMAoptions{parskip=half}}+\makeatother+$endif$+$if(beamer)$+$else$+$if(block-headings)$+% Make \paragraph and \subparagraph free-standing+\makeatletter+\ifx\paragraph\undefined\else+ \let\oldparagraph\paragraph+ \renewcommand{\paragraph}{+ \@ifstar+ \xxxParagraphStar+ \xxxParagraphNoStar+ }+ \newcommand{\xxxParagraphStar}[1]{\oldparagraph*{#1}\mbox{}}+ \newcommand{\xxxParagraphNoStar}[1]{\oldparagraph{#1}\mbox{}}+\fi+\ifx\subparagraph\undefined\else+ \let\oldsubparagraph\subparagraph+ \renewcommand{\subparagraph}{+ \@ifstar+ \xxxSubParagraphStar+ \xxxSubParagraphNoStar+ }+ \newcommand{\xxxSubParagraphStar}[1]{\oldsubparagraph*{#1}\mbox{}}+ \newcommand{\xxxSubParagraphNoStar}[1]{\oldsubparagraph{#1}\mbox{}}+\fi+\makeatother+$endif$+$endif$+$--+$-- verbatim in notes+$--+$if(verbatim-in-note)$+\usepackage{fancyvrb}+$endif$+$-- highlighting+$if(listings)$+\usepackage{listings}+\newcommand{\passthrough}[1]{#1}+\lstset{defaultdialect=[5.3]Lua}+\lstset{defaultdialect=[x86masm]Assembler}+$endif$+$if(lhs)$+\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}+$endif$+$if(highlighting-macros)$+$highlighting-macros$+$endif$+$--+$-- tables+$--+$if(tables)$+\usepackage{longtable,booktabs,array}+\newcounter{none} % for unnumbered tables+$if(multirow)$+\usepackage{multirow}+$endif$+\usepackage{calc} % for calculating minipage widths+$if(beamer)$+\usepackage{caption}+% Make caption package work with longtable+\makeatletter+\def\fnum@table{\tablename~\thetable}+\makeatother+$else$+% Correct order of tables after \paragraph or \subparagraph+\usepackage{etoolbox}+\makeatletter+\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}+\makeatother+% Allow footnotes in longtable head/foot+\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}}+\makesavenoteenv{longtable}+$endif$+$endif$+$--+$-- graphics+$--+$if(graphics)$+\usepackage{graphicx}+\makeatletter+\newsavebox\pandoc@box+\newcommand*\pandocbounded[1]{% scales image to fit in text height/width+ \sbox\pandoc@box{#1}%+ \Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}%+ \Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}%+ \ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both+ \ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}%+ \else\usebox{\pandoc@box}%+ \fi%+}+% Set default figure placement to htbp+\def\fps@figure{htbp}+\makeatother+$endif$+$if(svg)$+\usepackage{svg}+$endif$+$--+$-- strikeout/underline+$--+$if(strikeout)$+\ifLuaTeX+ \usepackage{luacolor}+ \usepackage[soul]{lua-ul}+\else+ \usepackage{soul}+$if(beamer)$+ \makeatletter+ \let\HL\hl+ \renewcommand\hl{% fix for beamer highlighting+ \let\set@color\beamerorig@set@color+ \let\reset@color\beamerorig@reset@color+ \HL}+ \makeatother+$endif$+$if(CJKmainfont)$+ \ifXeTeX+ % soul's \st doesn't work for CJK:+ \usepackage{xeCJKfntef}+ \renewcommand{\st}[1]{\sout{#1}}+ \fi+$endif$+\fi+$endif$+$--+$-- CSL citations+$--+$if(csl-refs)$+% definitions for citeproc citations+\NewDocumentCommand\citeproctext{}{}+\NewDocumentCommand\citeproc{mm}{%+ \begingroup\def\citeproctext{#2}\cite{#1}\endgroup}+\makeatletter+ % allow citations to break across lines+ \let\@cite@ofmt\@firstofone+ % avoid brackets around text for \cite:+ \def\@biblabel#1{}+ \def\@cite#1#2{{#1\if@tempswa , #2\fi}}+\makeatother+\newlength{\cslhangindent}+\setlength{\cslhangindent}{1.5em}+\newlength{\csllabelwidth}+\setlength{\csllabelwidth}{3em}+\newenvironment{CSLReferences}[2] % #1 hanging-indent, #2 entry-spacing+ {\begin{list}{}{%+ \setlength{\itemindent}{0pt}+ \setlength{\leftmargin}{0pt}+ \setlength{\parsep}{0pt}+ % turn on hanging indent if param 1 is 1+ \ifodd #1+ \setlength{\leftmargin}{\cslhangindent}+ \setlength{\itemindent}{-1\cslhangindent}+ \fi+ % set entry spacing+ \setlength{\itemsep}{#2\baselineskip}}}+ {\end{list}}+\usepackage{calc}+\newcommand{\CSLBlock}[1]{\hfill\break\parbox[t]{\linewidth}{\strut\ignorespaces#1\strut}}+\newcommand{\CSLLeftMargin}[1]{\parbox[t]{\csllabelwidth}{\strut#1\strut}}+\newcommand{\CSLRightInline}[1]{\parbox[t]{\linewidth - \csllabelwidth}{\strut#1\strut}}+\newcommand{\CSLIndent}[1]{\hspace{\cslhangindent}#1}+$endif$+$--+$-- Babel language support+$--+$if(lang)$+\ifLuaTeX+\usepackage[bidi=basic$if(shorthands)$$else$,shorthands=off$endif$$for(babeloptions)$,$babeloptions$$endfor$]{babel}+\else+\usepackage[bidi=default$if(shorthands)$$else$,shorthands=off$endif$$for(babeloptions)$,$babeloptions$$endfor$]{babel}+\fi+$if(babel-lang)$+$if(mainfont)$+\ifPDFTeX+\else+\babelfont{rm}[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$$if(mainfontfallback)$,RawFeature={fallback=mainfontfallback}$endif$]{$mainfont$}+\fi+$endif$+$endif$+$for(babelfonts/pairs)$+\babelfont[$babelfonts.key$]{rm}{$babelfonts.value$}+$endfor$+\ifLuaTeX+ \usepackage{selnolig} % disable illegal ligatures+\fi+$endif$+$--+$-- pagestyle+$--+$if(pagestyle)$+\pagestyle{$pagestyle$}+$endif$+$--+$-- prevent overfull lines+$--+\setlength{\emergencystretch}{3em} % prevent overfull lines+$--+$-- tight lists+$--+\providecommand{\tightlist}{%+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+$--+$-- subfigure support+$--+$if(subfigure)$+\usepackage{subcaption}+$endif$+$--+$-- text direction support for pdftex+$--+$if(dir)$+\ifPDFTeX+ \TeXXeTstate=1+ \newcommand{\RL}[1]{\beginR #1\endR}+ \newcommand{\LR}[1]{\beginL #1\endL}+ \newenvironment{RTL}{\beginR}{\endR}+ \newenvironment{LTR}{\beginL}{\endL}+\fi+\ifluatex+ \newcommand{\RL}[1]{\bgroup\textdir TRT#1\egroup}+ \newcommand{\LR}[1]{\bgroup\textdir TLT#1\egroup}+ \newenvironment{RTL}{\textdir TRT\pardir TRT\bodydir TRT}{}+ \newenvironment{LTR}{\textdir TLT\pardir TLT\bodydir TLT}{}+\fi+$endif$+$--+$-- bibliography support support for natbib and biblatex+$--+$if(natbib)$+\usepackage[$natbiboptions$]{natbib}+\bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$}+$endif$+$if(biblatex)$+\usepackage[$if(biblio-style)$style=$biblio-style$,$endif$$for(biblatexoptions)$$biblatexoptions$$sep$,$endfor$]{biblatex}+$for(bibliography)$+\addbibresource{$bibliography$}+$endfor$+$endif$+$--+$-- csquotes+$--+$if(csquotes)$+\usepackage[$for(csquotesoptions)$$csquotesoptions$$sep$,$endfor$]{csquotes}+$endif$
@@ -0,0 +1,21 @@+$if(titleblock)$+$titleblock$++$endif$+$for(header-includes)$+$header-includes$++$endfor$+$for(include-before)$+$include-before$++$endfor$+$if(toc)$+$table-of-contents$++$endif$+$body$+$for(include-after)$++$include-after$+$endfor$
@@ -2,10 +2,12 @@ = $title$ $if(author)$ $for(author)$$author$$sep$; $endfor$-$endif$ $if(date)$ $date$ $endif$+$elseif(date)$+:revdate: $date$+$endif$ $if(keywords)$ :keywords: $for(keywords)$$keywords$$sep$, $endfor$ $endif$@@ -14,6 +16,9 @@ $endif$ $if(toc)$ :toc:+$endif$+$if(math)$+:stem: latexmath $endif$ $endif$
@@ -1,41 +0,0 @@-$if(titleblock)$-= $title$-$if(author)$-$for(author)$$author$$sep$; $endfor$-$endif$-$if(date)$-$date$-$endif$-$if(keywords)$-:keywords: $for(keywords)$$keywords$$sep$, $endfor$-$endif$-$if(lang)$-:lang: $lang$-$endif$-$if(toc)$-:toc:-$endif$-$if(math)$-:stem: latexmath-$endif$--$endif$-$if(abstract)$-[abstract]-== Abstract-$abstract$--$endif$-$for(header-includes)$-$header-includes$--$endfor$-$for(include-before)$-$include-before$--$endfor$-$body$-$for(include-after)$--$include-after$-$endfor$
@@ -0,0 +1,1 @@+$body$
@@ -0,0 +1,204 @@+$passoptions.latex()$+\documentclass[+$if(fontsize)$+ $fontsize$,+$endif$+ ignorenonframetext,+$if(handout)$+ handout,+$endif$+$if(aspectratio)$+ aspectratio=$aspectratio$,+$endif$+$if(babel-lang)$+ $babel-lang$,+$endif$+$for(classoption)$+ $classoption$$sep$,+$endfor$+]{$documentclass$}+$if(geometry)$+\geometry{$for(geometry)$$geometry$$sep$,$endfor$}+$endif$+\newif\ifbibliography+$if(background-image)$+\usebackgroundtemplate{%+ \includegraphics[width=\paperwidth]{$background-image$}%+}+% In beamer background-image does not work well when other images are used, so this is the workaround+\pgfdeclareimage[width=\paperwidth,height=\paperheight]{background}{$background-image$}+\usebackgroundtemplate{\pgfuseimage{background}}+$endif$+\usepackage{pgfpages}+\setbeamertemplate{caption}[numbered]+\setbeamertemplate{caption label separator}{: }+\setbeamercolor{caption name}{fg=normal text.fg}+\beamertemplatenavigationsymbols$if(navigation)$$navigation$$else$empty$endif$+$--+$-- section numbering+$--+$if(numbersections)$+$else$+% remove section numbering+\setbeamertemplate{part page}{+ \centering+ \begin{beamercolorbox}[sep=16pt,center]{part title}+ \usebeamerfont{part title}\insertpart\par+ \end{beamercolorbox}+}+\setbeamertemplate{section page}{+ \centering+ \begin{beamercolorbox}[sep=12pt,center]{section title}+ \usebeamerfont{section title}\insertsection\par+ \end{beamercolorbox}+}+\setbeamertemplate{subsection page}{+ \centering+ \begin{beamercolorbox}[sep=8pt,center]{subsection title}+ \usebeamerfont{subsection title}\insertsubsection\par+ \end{beamercolorbox}+}+$endif$+$for(beameroption)$+\setbeameroption{$beameroption$}+$endfor$+% Prevent slide breaks in the middle of a paragraph+\widowpenalties 1 10000+\raggedbottom+$if(section-titles)$+\AtBeginPart{+ \frame{\partpage}+}+\AtBeginSection{+ \ifbibliography+ \else+ \frame{\sectionpage}+ \fi+}+\AtBeginSubsection{+ \frame{\subsectionpage}+}+$endif$+$fonts.latex()$+$-- Set Beamer theme before user font settings so they can override theme+$if(theme)$+\usetheme[$for(themeoptions)$$themeoptions$$sep$,$endfor$]{$theme$}+$endif$+$if(colortheme)$+\usecolortheme[$for(colorthemeoptions)$$colorthemeoptions$$sep$,$endfor$]{$colortheme$}+$endif$+$if(fonttheme)$+\usefonttheme[$for(fontthemeoptions)$$fontthemeoptions$$sep$,$endfor$]{$fonttheme$}+$endif$+$if(mainfont)$+\usefonttheme{serif} % use mainfont rather than sansfont for slide text+$endif$+$if(innertheme)$+\useinnertheme[$for(innerthemeoptions)$$innerthemeoptions$$sep$,$endfor$]{$innertheme$}+$endif$+$if(outertheme)$+\useoutertheme[$for(outerthemeoptions)$$outerthemeoptions$$sep$,$endfor$]{$outertheme$}+$endif$+$font-settings.latex()$+$common.latex()$+$for(header-includes)$+$header-includes$+$endfor$+$after-header-includes.latex()$+$hypersetup.latex()$++$if(title)$+\title$if(shorttitle)$[$shorttitle$]$endif${\texorpdfstring{$title$}{$title-meta$}$if(thanks)$\thanks{$thanks$}$endif$}+$endif$+$if(subtitle)$+\subtitle$if(shortsubtitle)$[$shortsubtitle$]$endif${\texorpdfstring{$subtitle$}{$subtitle-meta$}}+$endif$+\author$if(shortauthor)$[$shortauthor$]$endif${\texorpdfstring{$for(author)$$author$$sep$ \and $endfor$}{$author-meta$}}+\date$if(shortdate)$[$shortdate$]$endif${$date$}+$if(institute)$+\institute$if(shortinstitute)$[$shortinstitute$]$endif${$for(institute)$$institute$$sep$ \and $endfor$}+$endif$+$if(titlegraphic)$+\titlegraphic{+$for(titlegraphic)$+ \includegraphics$if(titlegraphicoptions)$[$for(titlegraphicoptions)$$titlegraphicoptions$$sep$, $endfor$]$endif${$titlegraphic$}$sep$\enspace+$endfor$}+$endif$+$if(logo)$+\logo{\includegraphics$if(logooptions)$[$for(logooptions)$$logooptions$$sep$, $endfor$]$endif${$logo$}}+$endif$++\begin{document}+$if(title)$+\frame{\titlepage}+$if(abstract)$+\begin{abstract}+$abstract$+\end{abstract}+$endif$+$endif$++$for(include-before)$+$include-before$++$endfor$+$if(toc)$+$if(toc-title)$+\renewcommand*\contentsname{$toc-title$}+$endif$+\begin{frame}[allowframebreaks]+$if(toc-title)$+ \frametitle{$toc-title$}+$endif$+ \setcounter{tocdepth}{$toc-depth$}+ \tableofcontents+\end{frame}+\setcounter{tocdepth}{$toc-depth$}+\tableofcontents+}+$endif$+$if(lof)$+\listoffigures+$endif$+$if(lot)$+\listoftables+$endif$+$if(linestretch)$+\setstretch{$linestretch$}+$endif$+$body$++$if(natbib)$+$if(bibliography)$+$if(biblio-title)$+$if(has-chapters)$+\renewcommand\bibname{$biblio-title$}+$else$+\renewcommand\refname{$biblio-title$}+$endif$+$endif$+\begin{frame}[allowframebreaks]{$biblio-title$}+$if(nocite-ids)$+ \nocite{$for(nocite-ids)$$it$$sep$, $endfor$}+$endif$+ \bibliographytrue+ \bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$}+\end{frame}++$endif$+$endif$+$if(biblatex)$+\begin{frame}[allowframebreaks]{$biblio-title$}+$if(nocite-ids)$+ \nocite{$for(nocite-ids)$$it$$sep$, $endfor$}+$endif$+ \bibliographytrue+ \printbibliography[heading=none]+\end{frame}++$endif$+$for(include-after)$+$include-after$++$endfor$+\end{document}
@@ -0,0 +1,103 @@+<!DOCTYPE html>+<html xmlns="http://www.w3.org/1999/xhtml" lang="$lang$" xml:lang="$lang$"$if(dir)$ dir="$dir$"$endif$>+<head>+ <meta charset="utf-8" />+ <meta name="generator" content="pandoc" />+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />+$for(author-meta)$+ <meta name="author" content="$author-meta$" />+$endfor$+$if(date-meta)$+ <meta name="dcterms.date" content="$date-meta$" />+$endif$+$if(keywords)$+ <meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$" />+$endif$+$if(description-meta)$+ <meta name="description" content="$description-meta$" />+$endif$+ <title>$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$</title>+ <style>+ div.sitenav { display: flex; flex-direction: row; flex-wrap: wrap; }+ span.navlink { flex: 1; }+ span.navlink-label { display: inline-block; min-width: 4em; }+ $styles.html()$+ </style>+$for(css)$+ <link rel="stylesheet" href="$css$" />+$endfor$+$for(header-includes)$+ $header-includes$+$endfor$+$if(math)$+ $math$+$endif$+</head>+<body>+$for(include-before)$+$include-before$+$endfor$+<nav id="sitenav">+<div class="sitenav">+<span class="navlink">+$if(up.url)$+<span class="navlink-label">Up:</span> <a href="$up.url$" accesskey="u" rel="up">$up.title$</a>+$endif$+</span>+<span class="navlink">+$if(top)$+<span class="navlink-label">Top:</span> <a href="$top.url$" accesskey="t" rel="top">$top.title$</a>+$endif$+</span>+</div>+<div class="sitenav">+<span class="navlink">+$if(next.url)$+<span class="navlink-label">Next:</span> <a href="$next.url$" accesskey="n" rel="next">$next.title$</a>+$endif$+</span>+<span class="navlink">+$if(previous.url)$+<span class="navlink-label">Previous:</span> <a href="$previous.url$" accesskey="p" rel="previous">$previous.title$</a>+$endif$+</span>+</div>+</nav>+$if(top)$+$-- only print title block if this is NOT the top page+$else$+$if(title)$+<header id="title-block-header">+<h1 class="title">$title$</h1>+$if(subtitle)$+<p class="subtitle">$subtitle$</p>+$endif$+$for(author)$+<p class="author">$author$</p>+$endfor$+$if(date)$+<p class="date">$date$</p>+$endif$+$if(abstract)$+<div class="abstract">+<div class="abstract-title">$abstract-title$</div>+$abstract$+</div>+$endif$+$endif$+</header>+$endif$+$if(toc)$+<nav id="$idprefix$TOC" role="doc-toc">+$if(toc-title)$+<h2 id="$idprefix$toc-title">$toc-title$</h2>+$endif$+$table-of-contents$+</nav>+$endif$+$body$+$for(include-after)$+$include-after$+$endfor$+</body>+</html>
@@ -1,3 +1,8 @@+$if(tagging)$+\setupbackend[format=pdf/ua-2]+\enabledirectives[backend.usetags=mkiv]+\setuptagging[state=start]+$endif$ $if(context-lang)$ \mainlanguage[$context-lang$] $endif$@@ -23,6 +28,7 @@ style=$linkstyle$, color=$linkcolor$, contrastcolor=$linkcontrastcolor$]+\setupurl[style=$urlstyle$] % make chapter, section bookmarks visible when opening document \placebookmarks[chapter, section, subsection, subsubsection, subsubsubsection, subsubsubsubsection][chapter, section]@@ -46,7 +52,6 @@ profile={$if(pdfaiccprofile)$$for(pdfaiccprofile)$$pdfaiccprofile$$sep$,$endfor$$else$sRGB.icc$endif$}, intent=$if(pdfaintent)$$pdfaintent$$else$sRGB IEC61966-2.1$endif$] $endif$-\setupbackend[export=yes] \setupstructure[state=start,method=auto] % use microtypography@@ -58,11 +63,21 @@ \setupbodyfontenvironment[default][em=italic] % use italic as em, not slanted +$-- set up font fallbacks+$for(mainfontfallback)$+\definefallbackfamily[mainface][rm][$mainfontfallback/nowrap$][range=0x0000-0xFFFF, check=yes, force=no]+$endfor$+$for(sansfontfallback)$+\definefallbackfamily[mainface][ss][$sansfontfallback/nowrap$][range=0x0000-0xFFFF, check=yes, force=no]+$endfor$+$for(monofontfallback)$+\definefallbackfamily[mainface][tt][$monofontfallback/nowrap$][range=0x0000-0xFFFF, check=yes, force=no]+$endfor$ \definefallbackfamily[mainface][rm][CMU Serif][preset=range:greek, force=yes]-\definefontfamily[mainface][rm][$if(mainfont)$$mainfont$$else$Latin Modern Roman$endif$]-\definefontfamily[mainface][mm][$if(mathfont)$$mathfont$$else$Latin Modern Math$endif$]-\definefontfamily[mainface][ss][$if(sansfont)$$sansfont$$else$Latin Modern Sans$endif$]-\definefontfamily[mainface][tt][$if(monofont)$$monofont$$else$Latin Modern Typewriter$endif$][features=none]+\definefontfamily[mainface][rm][$if(mainfont)$$mainfont/nowrap$$else$Latin Modern Roman$endif$]+\definefontfamily[mainface][mm][$if(mathfont)$$mathfont/nowrap$$else$Latin Modern Math$endif$]+\definefontfamily[mainface][ss][$if(sansfont)$$sansfont/nowrap$$else$Latin Modern Sans$endif$]+\definefontfamily[mainface][tt][$if(monofont)$$monofont/nowrap$$else$Latin Modern Typewriter$endif$][features=none] \setupbodyfont[mainface$if(fontsize)$,$fontsize$$endif$] \setupwhitespace[$if(whitespace)$$whitespace$$else$medium$endif$]@@ -114,6 +129,12 @@ \setupxtable[foot][] \setupxtable[lastrow][bottomframe=on] +$if(emphasis-commands)$+$emphasis-commands$+$endif$+$if(highlighting-commands)$+$highlighting-commands$+$endif$ $if(csl-refs)$ \definemeasure[cslhangindent][1.5em] \definenarrower[hangingreferences][left=\measure{cslhangindent}]
@@ -0,0 +1,27 @@+$if(title)$+# $title$++$endif$+$if(author)$+$for(author)$+$author$+$endfor$++$endif$+$if(date)$+$date$++$endif$+$for(header-includes)$+$header-includes$++$endfor$+$for(include-before)$+$include-before$++$endfor$+$body$+$for(include-after)$+$include-after$++$endfor$
@@ -1,14 +1,17 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">-<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ xml:lang="$lang$"$endif$>+<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$$if(dir)$ dir="$dir$"$endif$> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <meta name="generator" content="pandoc" /> <title>$pagetitle$</title> <style type="text/css">- $styles.html()$+$if(csl-css)$+ $styles.citations.html()$+$endif$ $if(highlighting-css)$+ /* CSS for syntax highlighting */ $highlighting-css$ $endif$ </style>
@@ -1,13 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html>-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"$if(lang)$ xml:lang="$lang$"$endif$>+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$$if(dir)$ dir="$dir$"$endif$> <head> <meta charset="utf-8" /> <meta name="generator" content="pandoc" /> <title>$pagetitle$</title> <style>- $styles.html()$+$if(csl-css)$+ $styles.citations.html()$+$endif$ $if(highlighting-css)$+ /* CSS for syntax highlighting */ $highlighting-css$ $endif$ </style>
@@ -3,7 +3,7 @@ <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" />- <meta name="generator" content="pandoc" />+ <meta name="generator" content="pandoc $pandoc-version$" /> $for(author-meta)$ <meta name="author" content="$author-meta$" /> $endfor$
@@ -1,8 +1,8 @@ <!DOCTYPE html>-<html xmlns="http://www.w3.org/1999/xhtml" lang="$lang$" xml:lang="$lang$"$if(dir)$ dir="$dir$"$endif$>+<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$$if(dir)$ dir="$dir$"$endif$> <head> <meta charset="utf-8" />- <meta name="generator" content="pandoc" />+ <meta name="generator" content="pandoc $pandoc-version$" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> $for(author-meta)$ <meta name="author" content="$author-meta$" />@@ -29,9 +29,6 @@ $if(math)$ $math$ $endif$- <!--[if lt IE 9]>- <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>- <![endif]--> </head> <body> $for(include-before)$
@@ -28,6 +28,11 @@ <RootCellStyleGroup Self="pandoc_cell_styles"> <CellStyle Self="CellStyle/Cell" AppliedParagraphStyle="ParagraphStyle/$$ID/[No paragraph style]" Name="Cell" /> </RootCellStyleGroup>+$if(objectStyles)$+ <RootObjectStyleGroup Self="pandoc_object_styles">+ $objectStyles$+ </RootObjectStyleGroup>+$endif$ <Story Self="pandoc_story" TrackChanges="false" StoryTitle="$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$"
@@ -31,7 +31,7 @@ <surname>$if(author.non-dropping-particle)$${author.non-dropping-particle} $endif$${author.surname}</surname> <given-names>${author.given-names}$if(author.dropping-particle)$ ${author.dropping-particle}$endif$</given-names> $if(author.prefix)$-<prefix>${author.suffix}</prefix>+<prefix>${author.prefix}</prefix> $endif$ $if(author.suffix)$ <suffix>${author.suffix}</suffix>@@ -90,6 +90,11 @@ <funding-group> <funding-statement>$article.funding-statement$</funding-statement> </funding-group>+$endif$+$if(supplementary-material)$+<supplementary-material>+$supplementary-material$+</supplementary-material> $endif$ </article-meta> </front>
@@ -1,455 +1,84 @@-% Options for packages loaded elsewhere-\PassOptionsToPackage{unicode$for(hyperrefoptions)$,$hyperrefoptions$$endfor$}{hyperref}-\PassOptionsToPackage{hyphens}{url}-$if(colorlinks)$-\PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor}-$endif$-$if(CJKmainfont)$-\PassOptionsToPackage{space}{xeCJK}-$endif$-%+$document-metadata.latex()$+$passoptions.latex()$ \documentclass[+$for(babel-otherlangs)$+ $babel-otherlangs$,+$endfor$+$if(babel-lang)$+ $babel-lang$,+$endif$ $if(fontsize)$ $fontsize$, $endif$ $if(papersize)$ $papersize$paper, $endif$-$if(beamer)$- ignorenonframetext,-$if(handout)$- handout,-$endif$-$if(aspectratio)$- aspectratio=$aspectratio$,-$endif$-$endif$ $for(classoption)$ $classoption$$sep$, $endfor$ ]{$documentclass$}-$if(beamer)$-$if(background-image)$-\usebackgroundtemplate{%- \includegraphics[width=\paperwidth]{$background-image$}%-}-$endif$-\usepackage{pgfpages}-\setbeamertemplate{caption}[numbered]-\setbeamertemplate{caption label separator}{: }-\setbeamercolor{caption name}{fg=normal text.fg}-\beamertemplatenavigationsymbols$if(navigation)$$navigation$$else$empty$endif$-$for(beameroption)$-\setbeameroption{$beameroption$}-$endfor$-% Prevent slide breaks in the middle of a paragraph-\widowpenalties 1 10000-\raggedbottom-$if(section-titles)$-\setbeamertemplate{part page}{- \centering- \begin{beamercolorbox}[sep=16pt,center]{part title}- \usebeamerfont{part title}\insertpart\par- \end{beamercolorbox}-}-\setbeamertemplate{section page}{- \centering- \begin{beamercolorbox}[sep=12pt,center]{part title}- \usebeamerfont{section title}\insertsection\par- \end{beamercolorbox}-}-\setbeamertemplate{subsection page}{- \centering- \begin{beamercolorbox}[sep=8pt,center]{part title}- \usebeamerfont{subsection title}\insertsubsection\par- \end{beamercolorbox}-}-\AtBeginPart{- \frame{\partpage}-}-\AtBeginSection{- \ifbibliography- \else- \frame{\sectionpage}- \fi-}-\AtBeginSubsection{- \frame{\subsectionpage}-}-$endif$-$endif$ $if(beamerarticle)$ \usepackage{beamerarticle} % needs to be loaded first $endif$-\usepackage{amsmath,amssymb}-$if(fontfamily)$-\usepackage[$for(fontfamilyoptions)$$fontfamilyoptions$$sep$,$endfor$]{$fontfamily$}-$else$-\usepackage{lmodern}-$endif$-$if(linestretch)$-\usepackage{setspace}-$endif$-\usepackage{iftex}-\ifPDFTeX- \usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc}- \usepackage[utf8]{inputenc}- \usepackage{textcomp} % provide euro and other symbols-\else % if luatex or xetex-$if(mathspec)$- \ifXeTeX- \usepackage{mathspec}- \else- \usepackage{unicode-math}- \fi-$else$- \usepackage{unicode-math}-$endif$- \defaultfontfeatures{Scale=MatchLowercase}- \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}-$if(mainfont)$- \setmainfont[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$]{$mainfont$}-$endif$-$if(sansfont)$- \setsansfont[$for(sansfontoptions)$$sansfontoptions$$sep$,$endfor$]{$sansfont$}-$endif$-$if(monofont)$- \setmonofont[$for(monofontoptions)$$monofontoptions$$sep$,$endfor$]{$monofont$}-$endif$-$for(fontfamilies)$- \newfontfamily{$fontfamilies.name$}[$for(fontfamilies.options)$$fontfamilies.options$$sep$,$endfor$]{$fontfamilies.font$}-$endfor$-$if(mathfont)$-$if(mathspec)$- \ifXeTeX- \setmathfont(Digits,Latin,Greek)[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}- \else- \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}- \fi-$else$- \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}-$endif$-$endif$-$if(CJKmainfont)$- \ifXeTeX- \usepackage{xeCJK}- \setCJKmainfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}- \fi-$endif$-$if(luatexjapresetoptions)$- \ifLuaTeX- \usepackage[$for(luatexjapresetoptions)$$luatexjapresetoptions$$sep$,$endfor$]{luatexja-preset}- \fi-$endif$-$if(CJKmainfont)$- \ifLuaTeX- \usepackage[$for(luatexjafontspecoptions)$$luatexjafontspecoptions$$sep$,$endfor$]{luatexja-fontspec}- \setmainjfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}- \fi-$endif$-\fi-$if(zero-width-non-joiner)$-%% Support for zero-width non-joiner characters.-\makeatletter-\def\zerowidthnonjoiner{%- % Prevent ligatures and adjust kerning, but still support hyphenating.- \texorpdfstring{%- \TextOrMath{\nobreak\discretionary{-}{}{\kern.03em}%- \ifvmode\else\nobreak\hskip\z@skip\fi}{}%- }{}%-}-\makeatother-\ifPDFTeX- \DeclareUnicodeCharacter{200C}{\zerowidthnonjoiner}-\else- \catcode`^^^^200c=\active- \protected\def ^^^^200c{\zerowidthnonjoiner}-\fi-%% End of ZWNJ support-$endif$-$if(beamer)$-$if(theme)$-\usetheme[$for(themeoptions)$$themeoptions$$sep$,$endfor$]{$theme$}-$endif$-$if(colortheme)$-\usecolortheme{$colortheme$}-$endif$-$if(fonttheme)$-\usefonttheme{$fonttheme$}-$endif$-$if(mainfont)$-\usefonttheme{serif} % use mainfont rather than sansfont for slide text-$endif$-$if(innertheme)$-\useinnertheme{$innertheme$}-$endif$-$if(outertheme)$-\useoutertheme{$outertheme$}-$endif$-$endif$-% Use upquote if available, for straight quotes in verbatim environments-\IfFileExists{upquote.sty}{\usepackage{upquote}}{}-\IfFileExists{microtype.sty}{% use microtype if available- \usepackage[$for(microtypeoptions)$$microtypeoptions$$sep$,$endfor$]{microtype}- \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts-}{}-$if(indent)$-$else$-\makeatletter-\@ifundefined{KOMAClassName}{% if non-KOMA class- \IfFileExists{parskip.sty}{%- \usepackage{parskip}- }{% else- \setlength{\parindent}{0pt}- \setlength{\parskip}{6pt plus 2pt minus 1pt}}-}{% if KOMA class- \KOMAoptions{parskip=half}}-\makeatother-$endif$-$if(verbatim-in-note)$-\usepackage{fancyvrb}-$endif$ \usepackage{xcolor} $if(geometry)$-$if(beamer)$-\geometry{$for(geometry)$$geometry$$sep$,$endfor$}-$else$ \usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry} $endif$-$endif$-$if(beamer)$-\newif\ifbibliography-$endif$-$if(listings)$-\usepackage{listings}-\newcommand{\passthrough}[1]{#1}-\lstset{defaultdialect=[5.3]Lua}-\lstset{defaultdialect=[x86masm]Assembler}-$endif$-$if(lhs)$-\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}-$endif$-$if(highlighting-macros)$-$highlighting-macros$-$endif$-$if(tables)$-\usepackage{longtable,booktabs,array}-$if(multirow)$-\usepackage{multirow}-$endif$-\usepackage{calc} % for calculating minipage widths-$if(beamer)$-\usepackage{caption}-% Make caption package work with longtable-\makeatletter-\def\fnum@table{\tablename~\thetable}-\makeatother-$else$-% Correct order of tables after \paragraph or \subparagraph-\usepackage{etoolbox}-\makeatletter-\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}-\makeatother-% Allow footnotes in longtable head/foot-\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}}-\makesavenoteenv{longtable}-$endif$-$endif$-$if(graphics)$-\usepackage{graphicx}-\makeatletter-\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}-\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}-\makeatother-% Scale images if necessary, so that they will not overflow the page-% margins by default, and it is still possible to overwrite the defaults-% using explicit options in \includegraphics[width, height, ...]{}-\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}-% Set default figure placement to htbp-\makeatletter-\def\fps@figure{htbp}-\makeatother-$endif$-$if(strikeout)$-$-- also used for underline-\usepackage[normalem]{ulem}+\usepackage{amsmath,amssymb}+$if(cancel)$+\usepackage{cancel} $endif$-\setlength{\emergencystretch}{3em} % prevent overfull lines-\providecommand{\tightlist}{%- \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+$--+$-- section numbering+$-- $if(numbersections)$ \setcounter{secnumdepth}{$if(secnumdepth)$$secnumdepth$$else$5$endif$} $else$ \setcounter{secnumdepth}{-\maxdimen} % remove section numbering $endif$-$if(beamer)$-$else$-$if(block-headings)$-% Make \paragraph and \subparagraph free-standing-\ifx\paragraph\undefined\else- \let\oldparagraph\paragraph- \renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}}-\fi-\ifx\subparagraph\undefined\else- \let\oldsubparagraph\subparagraph- \renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}}-\fi-$endif$-$endif$-$if(pagestyle)$-\pagestyle{$pagestyle$}-$endif$-$if(csl-refs)$-\newlength{\cslhangindent}-\setlength{\cslhangindent}{1.5em}-\newlength{\csllabelwidth}-\setlength{\csllabelwidth}{3em}-\newlength{\cslentryspacingunit} % times entry-spacing-\setlength{\cslentryspacingunit}{\parskip}-\newenvironment{CSLReferences}[2] % #1 hanging-ident, #2 entry spacing- {% don't indent paragraphs- \setlength{\parindent}{0pt}- % turn on hanging indent if param 1 is 1- \ifodd #1- \let\oldpar\par- \def\par{\hangindent=\cslhangindent\oldpar}- \fi- % set entry spacing- \setlength{\parskip}{#2\cslentryspacingunit}- }%- {}-\usepackage{calc}-\newcommand{\CSLBlock}[1]{#1\hfill\break}-\newcommand{\CSLLeftMargin}[1]{\parbox[t]{\csllabelwidth}{#1}}-\newcommand{\CSLRightInline}[1]{\parbox[t]{\linewidth - \csllabelwidth}{#1}\break}-\newcommand{\CSLIndent}[1]{\hspace{\cslhangindent}#1}-$endif$-$if(lang)$-\ifLuaTeX-\usepackage[bidi=basic]{babel}-\else-\usepackage[bidi=default]{babel}-\fi-$if(babel-lang)$-\babelprovide[main,import]{$babel-lang$}-$endif$-$for(babel-otherlangs)$-\babelprovide[import]{$babel-otherlangs$}-$endfor$-% get rid of language-specific shorthands (see #6817):-\let\LanguageShortHands\languageshorthands-\def\languageshorthands#1{}-$endif$+$fonts.latex()$+$font-settings.latex()$+$common.latex()$ $for(header-includes)$ $header-includes$ $endfor$-\ifLuaTeX- \usepackage{selnolig} % disable illegal ligatures+$after-header-includes.latex()$+$hypersetup.latex()$+$if(pdf-trailer-id)$++\ifXeTeX+\special{pdf:trailerid [ $pdf-trailer-id$ ]} \fi-$if(dir)$ \ifPDFTeX- \TeXXeTstate=1- \newcommand{\RL}[1]{\beginR #1\endR}- \newcommand{\LR}[1]{\beginL #1\endL}- \newenvironment{RTL}{\beginR}{\endR}- \newenvironment{LTR}{\beginL}{\endL}+\pdftrailerid{}+\pdftrailer{/ID [ $pdf-trailer-id$ ]} \fi-$endif$-$if(natbib)$-\usepackage[$natbiboptions$]{natbib}-\bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$}-$endif$-$if(biblatex)$-\usepackage[$if(biblio-style)$style=$biblio-style$,$endif$$for(biblatexoptions)$$biblatexoptions$$sep$,$endfor$]{biblatex}-$for(bibliography)$-\addbibresource{$bibliography$}-$endfor$-$endif$-$if(nocite-ids)$-\nocite{$for(nocite-ids)$$it$$sep$, $endfor$}-$endif$-$if(csquotes)$-\usepackage{csquotes}-$endif$-\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}}-\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available-\urlstyle{same} % disable monospaced font for URLs-$if(links-as-notes)$-% Make links footnotes instead of hotlinks:-\DeclareRobustCommand{\href}[2]{#2\footnote{\url{#1}}}-$endif$-$if(verbatim-in-note)$-\VerbatimFootnotes % allow verbatim text in footnotes-$endif$-\hypersetup{-$if(title-meta)$- pdftitle={$title-meta$},-$endif$-$if(author-meta)$- pdfauthor={$author-meta$},-$endif$-$if(lang)$- pdflang={$lang$},-$endif$-$if(subject)$- pdfsubject={$subject$},-$endif$-$if(keywords)$- pdfkeywords={$for(keywords)$$keywords$$sep$, $endfor$},-$endif$-$if(colorlinks)$- colorlinks=true,- linkcolor={$if(linkcolor)$$linkcolor$$else$Maroon$endif$},- filecolor={$if(filecolor)$$filecolor$$else$Maroon$endif$},- citecolor={$if(citecolor)$$citecolor$$else$Blue$endif$},- urlcolor={$if(urlcolor)$$urlcolor$$else$Blue$endif$},-$else$-$if(boxlinks)$-$else$- hidelinks,-$endif$+\ifLuaTeX+\pdfvariable trailerid {[ $pdf-trailer-id$ ]}+\fi $endif$- pdfcreator={LaTeX via pandoc}} $if(title)$ \title{$title$$if(thanks)$\thanks{$thanks$}$endif$} $endif$ $if(subtitle)$-$if(beamer)$-$else$ \usepackage{etoolbox} \makeatletter \providecommand{\subtitle}[1]{% add subtitle to \maketitle \apptocmd{\@title}{\par {\large #1 \par}}{}{} } \makeatother-$endif$ \subtitle{$subtitle$} $endif$ \author{$for(author)$$author$$sep$ \and $endfor$} \date{$date$}-$if(beamer)$-$if(institute)$-\institute{$for(institute)$$institute$$sep$ \and $endfor$}-$endif$-$if(titlegraphic)$-\titlegraphic{\includegraphics{$titlegraphic$}}-$endif$-$if(logo)$-\logo{\includegraphics{$logo$}}-$endif$-$endif$ \begin{document} $if(has-frontmatter)$ \frontmatter $endif$ $if(title)$-$if(beamer)$-\frame{\titlepage}-$else$ \maketitle-$endif$ $if(abstract)$ \begin{abstract} $abstract$@@ -465,23 +94,16 @@ $if(toc-title)$ \renewcommand*\contentsname{$toc-title$} $endif$-$if(beamer)$-\begin{frame}[allowframebreaks]-$if(toc-title)$- \frametitle{$toc-title$}-$endif$- \tableofcontents[hideallsubsections]-\end{frame}-$else$ { $if(colorlinks)$-\hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$$endif$}+$if(toccolor)$+\hypersetup{linkcolor=$toccolor$} $endif$+$endif$ \setcounter{tocdepth}{$toc-depth$} \tableofcontents } $endif$-$endif$ $if(lof)$ \listoffigures $endif$@@ -499,6 +121,9 @@ $if(has-frontmatter)$ \backmatter $endif$+$if(nocite-ids)$+\nocite{$for(nocite-ids)$$it$$sep$, $endfor$}+$endif$ $if(natbib)$ $if(bibliography)$ $if(biblio-title)$@@ -508,26 +133,12 @@ \renewcommand\refname{$biblio-title$} $endif$ $endif$-$if(beamer)$-\begin{frame}[allowframebreaks]{$biblio-title$}- \bibliographytrue-$endif$- \bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$}-$if(beamer)$-\end{frame}-$endif$+\bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$} $endif$ $endif$ $if(biblatex)$-$if(beamer)$-\begin{frame}[allowframebreaks]{$biblio-title$}- \bibliographytrue- \printbibliography[heading=none]-\end{frame}-$else$ \printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$-$endif$ $endif$ $for(include-after)$
@@ -5,29 +5,10 @@ .\" Automatically generated by Pandoc $pandoc-version$ .\" $endif$-.\" Define V font for inline verbatim, using C font in formats-.\" that render this, and otherwise B font.-.ie "\f[CB]x\f[]"x" \{\-. ftr V B-. ftr VI BI-. ftr VB B-. ftr VBI BI-.\}-.el \{\-. ftr V CR-. ftr VI CI-. ftr VB CB-. ftr VBI CBI-.\} $if(adjusting)$ .ad $adjusting$ $endif$-.TH "$title/nowrap$" "$section/nowrap$" "$date/nowrap$" "$footer/nowrap$" "$header/nowrap$"-$if(hyphenate)$-.hy-$else$-.nh-$endif$+.TH "$title/nowrap$" "$section/nowrap$" "$date/nowrap$" "$footer/nowrap$"$if(header)$ "$header/nowrap$"$endif$ $for(header-includes)$ $header-includes$ $endfor$
@@ -35,7 +35,7 @@ .\" line height .nr VS $if(lineheight)$$lineheight$$else$12p$endif$ .\" font family: A, BM, H, HN, N, P, T, ZCM-.fam $if(fontfamily)$$fontfamily$$else$P$endif$+.fam $if(fontfamily)$$fontfamily$$else$T$endif$ .\" paragraph indent .nr PI $if(indent)$$indent$$else$0m$endif$ .\" interparagraph space@@ -50,10 +50,6 @@ $endif$ .\" color used for strikeout .defcolor strikecolor rgb 0.7 0.7 0.7-.\" color for links (rgb)-.ds PDFHREF.COLOUR 0.35 0.00 0.60-.\" border for links (default none)-.ds PDFHREF.BORDER 0 0 0 .\" point size difference between heading levels .nr PSINCR 1p .\" heading level above which point size no longer changes@@ -64,14 +60,6 @@ .\" page numbers in footer, centered .ds CH .ds CF %-.\" pdf outline fold level-.nr PDFOUTLINE.FOLDLEVEL 3-.\" start out in outline view-.pdfview /PageMode /UseOutlines-.\" ***************************************************************-.\" PDF metadata-.pdfinfo /Title "$title-meta$"-.pdfinfo /Author "$author-meta$" $if(adjusting)$ .ad $adjusting$ $endif$@@ -84,6 +72,20 @@ .EQ delim @@ .EN+$endif$+$if(pdf-engine)$+.\" color for links (rgb)+.ds PDFHREF.COLOUR 0.35 0.00 0.60+.\" border for links (default none)+.ds PDFHREF.BORDER 0 0 0+.\" pdf outline fold level+.nr PDFOUTLINE.FOLDLEVEL 3+.\" start out in outline view+.pdfview /PageMode /UseOutlines+.\" ***************************************************************+.\" PDF metadata+.pdfinfo /Title "$title-meta$"+.pdfinfo /Author "$author-meta$" $endif$ $for(header-includes)$ $header-includes$
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" ?>-<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.2">+<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.3"> <office:font-face-decls> <style:font-face style:name="Courier New" style:font-family-generic="modern" style:font-pitch="fixed" svg:font-family="'Courier New'" /> </office:font-face-decls>
@@ -0,0 +1,65 @@+<?xml version="1.0" encoding="UTF-8"?>+<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">+<w:body>+$if(title)$+ <w:p>+ <w:pPr>+ <w:pStyle w:val="$title-style-id$" />+ </w:pPr>+ $title$+ </w:p>+$endif$+$if(subtitle)$+ <w:p>+ <w:pPr>+ <w:pStyle w:val="$subtitle-style-id$" />+ </w:pPr>+ $subtitle$+ </w:p>+$endif$+$for(author)$+ <w:p>+ <w:pPr>+ <w:pStyle w:val="$author-style-id$" />+ </w:pPr>+ $author$+ </w:p>+$endfor$+$if(date)$+ <w:p>+ <w:pPr>+ <w:pStyle w:val="$date-style-id$" />+ </w:pPr>+ $date$+ </w:p>+$endif$+$if(abstract)$+$if(abstract-title)$+ <w:p>+ <w:pPr>+ <w:pStyle w:val="$abstract-title-style-id$" />+ </w:pPr>+ <w:r><w:t xml:space="preserve">$abstract-title$</w:t></w:r>+ </w:p>+$endif$+ $abstract$+$endif$+$for(include-before)$+ $include-before$+$endfor$+$if(toc)$+ $toc$+$endif$+$if(lof)$+ $lof$+$endif$+$if(lot)$+ $lot$+$endif$+ $body$+$for(include-after)$+ $include-after$+$endfor$+ $sectpr$+ </w:body>+</w:document>
@@ -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$
@@ -29,6 +29,9 @@ $else$ <link rel="stylesheet" href="$revealjs-url$/dist/theme/black.css" id="theme"> $endif$+$if(highlight-js)$+ <link rel="stylesheet" href="$revealjs-url$/plugin/highlight/$highlightjs-theme$.css">+$endif$ $for(css)$ <link rel="stylesheet" href="$css$"/> $endfor$@@ -87,6 +90,9 @@ $if(mathjax)$ <script src="$revealjs-url$/plugin/math/math.js"></script> $endif$+$if(highlight-js)$+ <script src="$revealjs-url$/plugin/highlight/highlight.js"></script>+$endif$ <script> @@ -232,31 +238,54 @@ // devices. It is advisable to set this to a lower number than // viewDistance in order to save resources. mobileViewDistance: $mobileViewDistance$,+$if(view)$++ // Enable scroll view+ view: '$view/nowrap$',+ // see https://revealjs.com/scroll-view/#scrollbar+$if(scrollProgressAuto)$+ scrollProgress: 'auto',+$elseif(scrollProgress)$+ scrollProgress: $scrollProgress$,+$else$+ scrollProgress: false,+$endif$+ // see https://revealjs.com/scroll-view/#url-activation+ scrollActivationWidth: $scrollActivationWidth$,+ // see https://revealjs.com/scroll-view/#scroll-snapping+$if(scrollSnap)$+ scrollSnap: '$scrollSnap/nowrap$',+$else$+ scrollSnap: false,+$endif$+ // Experimental. see https://revealjs.com/scroll-view/#scroll-snapping+ scrollLayout: '$scrollLayout/nowrap$',+$endif$ $if(parallaxBackgroundImage)$ // Parallax background image- parallaxBackgroundImage: '$parallaxBackgroundImage$', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'"+ parallaxBackgroundImage: '$parallaxBackgroundImage/nowrap$', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'" $else$ $if(background-image)$ // Parallax background image- parallaxBackgroundImage: '$background-image$', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'"+ parallaxBackgroundImage: '$background-image/nowrap$', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'" $endif$ $endif$ $if(parallaxBackgroundSize)$ // Parallax background size- parallaxBackgroundSize: '$parallaxBackgroundSize$', // CSS syntax, e.g. "2100px 900px"+ parallaxBackgroundSize: '$parallaxBackgroundSize/nowrap$', // CSS syntax, e.g. "2100px 900px" $endif$ $if(parallaxBackgroundHorizontal)$ // Amount to move parallax background (horizontal and vertical) on slide change // Number, e.g. 100- parallaxBackgroundHorizontal: $parallaxBackgroundHorizontal$,+ parallaxBackgroundHorizontal: $parallaxBackgroundHorizontal/nowrap$, $endif$ $if(parallaxBackgroundVertical)$ - parallaxBackgroundVertical: $parallaxBackgroundVertical$,+ parallaxBackgroundVertical: $parallaxBackgroundVertical/nowrap$, $endif$ $if(width)$ @@ -307,6 +336,9 @@ plugins: [ $if(mathjax)$ RevealMath,+$endif$+$if(highlight-js)$+ RevealHighlight, $endif$ RevealNotes, RevealSearch,
@@ -1,4 +1,11 @@-\input texinfo+\input texinfo @c -*-texinfo-*-+$if(filename)$+@setfilename $filename$+$endif$+$if(title)$+@settitle $title$$if(version)$ $version$$endif$+$endif$+ @documentencoding UTF-8 $for(header-includes)$ $header-includes$@@ -16,6 +23,9 @@ $if(titlepage)$ @titlepage @title $title$+$if(version)$+@subtitle $version$+$endif$ $for(author)$ @author $author$ $endfor$
@@ -0,0 +1,154 @@+#let horizontalrule = line(start: (25%,0%), end: (75%,0%))++#show terms.item: it => block(breakable: false)[+ #text(weight: "bold")[#it.term]+ #block(inset: (left: 1.5em, top: -0.4em))[#it.description]+]++#set table(+ inset: 6pt,+ stroke: none+)++#show figure.where(+ kind: table+): set figure.caption(position: $if(table-caption-position)$$table-caption-position$$else$top$endif$)++#show figure.where(+ kind: image+): set figure.caption(position: $if(figure-caption-position)$$figure-caption-position$$else$bottom$endif$)++$if(highlighting-definitions)$+// syntax highlighting functions from skylighting:+$highlighting-definitions$++$endif$+$if(template)$+#import "$template$": conf+$else$+$template.typst()$+$endif$++$if(smart)$+$else$+#set smartquote(enabled: false)++$endif$+$for(header-includes)$+$header-includes$++$endfor$+#show: doc => conf(+$if(title)$+ title: [$title$],+$endif$+$if(subtitle)$+ subtitle: [$subtitle$],+$endif$+$if(author)$+ authors: (+$for(author)$+$if(author.name)$+ ( name: [$author.name$],+ affiliation: [$author.affiliation$],+ email: [$author.email$] ),+$else$+ ( name: [$author$],+ affiliation: "",+ email: "" ),+$endif$+$endfor$+ ),+$endif$+$if(keywords)$+ keywords: ($for(keywords)$$keywords$$sep$,$endfor$),+$endif$+$if(date)$+ date: [$date$],+$endif$+$if(lang)$+ lang: "$lang$",+$endif$+$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$+$if(papersize)$+ paper: "$papersize$",+$endif$+$if(mainfont)$+ font: ("$mainfont$",),+$endif$+$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,+)++$for(include-before)$+$include-before$++$endfor$+$if(toc)$+#outline(+ title: auto,+ depth: $toc-depth$+);+$endif$++$body$++$if(citations)$+$for(nocite-ids)$+#cite(label("${it}"), form: none)+$endfor$+$if(csl)$++#set bibliography(style: "$csl$")+$elseif(bibliographystyle)$++#set bibliography(style: "$bibliographystyle$")+$endif$+$if(bibliography)$++#bibliography(($for(bibliography)$"$bibliography$"$sep$,$endfor$)$if(full-bibliography)$, full: true$endif$)+$endif$+$endif$+$for(include-after)$++$include-after$+$endfor$
@@ -0,0 +1,16 @@+$if(filename)$*${filename}* $endif$$if(abstract)$${abstract}$endif$$if(filename)$+++$endif$$if(combined-title)$${combined-title}+++$endif$$toc-reminder$++$if(toc)$+$toc$++$endif$++$body$++ $modeline$
@@ -0,0 +1,20 @@+$--+$-- PDF standard support (PDF/A, PDF/UA, PDF/X)+$-- Requires LuaLaTeX and recent LaTeX (2023+)+$--+$if(pdfstandard)$+\DocumentMetadata{+$if(pdfstandard.version)$+ pdfversion=$pdfstandard.version$,+$endif$+$if(pdfstandard.standards)$+ pdfstandard={$for(pdfstandard.standards)$$it$$sep$,$endfor$},+$endif$+$if(pdfstandard.tagging)$+ tagging=on,+$endif$+$if(lang)$+ lang=$lang$,+$endif$+ xmp=true}+$endif$
@@ -0,0 +1,103 @@+$-- User font settings (must come after default font and Beamer theme)+$if(fontfamily)$+\usepackage[$for(fontfamilyoptions)$$fontfamilyoptions$$sep$,$endfor$]{$fontfamily$}+$endif$+\ifPDFTeX\else+ % xetex/luatex font selection+$if(mainfont)$+$if(mainfontfallback)$+ \ifLuaTeX+ \usepackage{luaotfload}+ \directlua{luaotfload.add_fallback("mainfontfallback",{+ $for(mainfontfallback)$"$mainfontfallback$"$sep$,$endfor$+ })}+ \fi+$endif$+ \setmainfont[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$$if(mainfontfallback)$,RawFeature={fallback=mainfontfallback}$endif$]{$mainfont$}+$endif$+$if(sansfont)$+$if(sansfontfallback)$+ \ifLuaTeX+ \usepackage{luaotfload}+ \directlua{luaotfload.add_fallback("sansfontfallback",{+ $for(sansfontfallback)$"$sansfontfallback$"$sep$,$endfor$+ })}+ \fi+$endif$+ \setsansfont[$for(sansfontoptions)$$sansfontoptions$$sep$,$endfor$$if(sansfontfallback)$,RawFeature={fallback=sansfontfallback}$endif$]{$sansfont$}+$endif$+$if(monofont)$+$if(monofontfallback)$+ \ifLuaTeX+ \usepackage{luaotfload}+ \directlua{luaotfload.add_fallback("monofontfallback",{+ $for(monofontfallback)$"$monofontfallback$"$sep$,$endfor$+ })}+ \fi+$endif$+ \setmonofont[$for(monofontoptions)$$monofontoptions$$sep$,$endfor$$if(monofontfallback)$,RawFeature={fallback=monofontfallback}$endif$]{$monofont$}+$endif$+$for(fontfamilies)$+ \newfontfamily{$fontfamilies.name$}[$for(fontfamilies.options)$$fontfamilies.options$$sep$,$endfor$]{$fontfamilies.font$}+$endfor$+$if(mathfont)$+$if(mathspec)$+ \ifXeTeX+ \setmathfont(Digits,Latin,Greek)[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}+ \else+ \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}+ \fi+$else$+ \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}+$endif$+$endif$+$if(CJKmainfont)$+ \ifXeTeX+ \usepackage{xeCJK}+ \setCJKmainfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}+$if(CJKsansfont)$+ \setCJKsansfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKsansfont$}+$endif$+$if(CJKmonofont)$+ \setCJKmonofont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmonofont$}+$endif$+ \fi+$endif$+$if(luatexjapresetoptions)$+ \ifLuaTeX+ \usepackage[$for(luatexjapresetoptions)$$luatexjapresetoptions$$sep$,$endfor$]{luatexja-preset}+ \fi+$endif$+$if(CJKmainfont)$+ \ifLuaTeX+ \usepackage[$for(luatexjafontspecoptions)$$luatexjafontspecoptions$$sep$,$endfor$]{luatexja-fontspec}+ \setmainjfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}+ \fi+$endif$+\fi+$if(zero-width-non-joiner)$+%% Support for zero-width non-joiner characters.+\makeatletter+\def\zerowidthnonjoiner{%+ % Prevent ligatures and adjust kerning, but still support hyphenating.+ \texorpdfstring{%+ \TextOrMath{\nobreak\discretionary{-}{}{\kern.03em}%+ \ifvmode\else\nobreak\hskip\z@skip\fi}{}%+ }{}%+}+\makeatother+\ifPDFTeX+ \DeclareUnicodeCharacter{200C}{\zerowidthnonjoiner}+\else+ \catcode`^^^^200c=\active+ \protected\def ^^^^200c{\zerowidthnonjoiner}+\fi+%% End of ZWNJ support+$endif$+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+ \usepackage[$for(microtypeoptions)$$microtypeoptions$$sep$,$endfor$]{microtype}+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+
@@ -0,0 +1,23 @@+\usepackage{iftex}+\ifPDFTeX+ \usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc}+ \usepackage[utf8]{inputenc}+ \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+$if(mathspec)$+ \ifXeTeX+ \usepackage{mathspec} % this also loads fontspec+ \else+ \usepackage{unicode-math} % this also loads fontspec+ \fi+$else$+ \usepackage{unicode-math} % this also loads fontspec+$endif$+ \defaultfontfeatures{Scale=MatchLowercase}$-- must come before Beamer theme+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+$if(fontfamily)$+$else$+$-- Set default font before Beamer theme so the theme can override it+\usepackage{lmodern}+$endif$
@@ -0,0 +1,34 @@+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+$if(title-meta)$+ pdftitle={$title-meta$},+$endif$+$if(author-meta)$+ pdfauthor={$author-meta$},+$endif$+$if(lang)$+ pdflang={$lang$},+$endif$+$if(subject)$+ pdfsubject={$subject$},+$endif$+$if(keywords)$+ pdfkeywords={$for(keywords)$\xmpquote{$keywords$}$sep$, $endfor$},+$endif$+$if(colorlinks)$+ colorlinks=true,+ linkcolor={$if(linkcolor)$$linkcolor$$else$Maroon$endif$},+ filecolor={$if(filecolor)$$filecolor$$else$Maroon$endif$},+ citecolor={$if(citecolor)$$citecolor$$else$Blue$endif$},+ urlcolor={$if(urlcolor)$$urlcolor$$else$Blue$endif$},+$else$+$if(boxlinks)$+$else$+ hidelinks,+$endif$+$endif$+ pdfcreator={LaTeX via pandoc}}+
@@ -0,0 +1,9 @@+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode$for(hyperrefoptions)$,$hyperrefoptions$$endfor$}{hyperref}+\PassOptionsToPackage{hyphens}{url}+$if(colorlinks)$+\PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor}+$endif$+$if(CJKmainfont)$+\PassOptionsToPackage{space}{xeCJK}+$endif$
@@ -0,0 +1,23 @@+/* CSS for citations */+div.csl-bib-body { }+div.csl-entry {+ clear: both;+$if(csl-entry-spacing)$+ margin-bottom: $csl-entry-spacing$;+$endif$+}+.hanging-indent div.csl-entry {+ margin-left:2em;+ text-indent:-2em;+}+div.csl-left-margin {+ min-width:2em;+ float:left;+}+div.csl-right-inline {+ margin-left:2em;+ padding-left:1em;+}+div.csl-indent {+ margin-left: 2em;+}
@@ -1,14 +1,23 @@+/* Default styles provided by pandoc.+** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+*/ $if(document-css)$ html {- line-height: $if(linestretch)$$linestretch$$else$1.5$endif$;- font-family: $if(mainfont)$$mainfont$$else$Georgia, serif$endif$;- font-size: $if(fontsize)$$fontsize$$else$20px$endif$;+$if(mainfont)$+ font-family: $mainfont$;+$endif$+$if(fontsize)$+ font-size: $fontsize$;+$endif$+$if(linestretch)$+ line-height: $linestretch$;+$endif$ color: $if(fontcolor)$$fontcolor$$else$#1a1a1a$endif$; background-color: $if(backgroundcolor)$$backgroundcolor$$else$#fdfdfd$endif$; } body { margin: 0 auto;- max-width: 36em;+ max-width: $if(maxwidth)$$maxwidth$$else$36em$endif$; padding-left: $if(margin-left)$$margin-left$$else$50px$endif$; padding-right: $if(margin-right)$$margin-right$$else$50px$endif$; padding-top: $if(margin-top)$$margin-top$$else$50px$endif$;@@ -21,13 +30,16 @@ @media (max-width: 600px) { body { font-size: 0.9em;- padding: 1em;+ padding: 12px; } h1 { font-size: 1.8em; } } @media print {+ html {+ background-color: $if(backgroundcolor)$$backgroundcolor$$else$white$endif$;+ } body { background-color: transparent; color: black;@@ -53,6 +65,10 @@ img { max-width: 100%; }+svg {+ height: auto;+ max-width: 100%;+} h1, h2, h3, h4, h5, h6 { margin-top: 1.4em; }@@ -90,13 +106,15 @@ } $endif$ code {- font-family: $if(monofont)$$monofont$$else$Menlo, Monaco, 'Lucida Console', Consolas, monospace$endif$;+ white-space: pre-wrap;+ font-family: $if(monofont)$$monofont$$else$Menlo, Monaco, Consolas, 'Lucida Console', monospace$endif$; $if(monobackgroundcolor)$ background-color: $monobackgroundcolor$; padding: .2em .4em; $endif$ font-size: 85%; margin: 0;+ hyphens: manual; } pre { margin: 1em 0;@@ -116,8 +134,8 @@ overflow: visible; } hr {- background-color: #1a1a1a; border: none;+ border-top: 1px solid #1a1a1a; height: 1px; margin: 1em 0; }@@ -130,7 +148,12 @@ font-variant-numeric: lining-nums tabular-nums; } table caption {+$if(table-caption-below)$+ caption-side: bottom;+ margin-top: 0.75em;+$else$ margin-bottom: 0.75em;+$endif$ } tbody { margin-top: 0.5em;@@ -161,13 +184,19 @@ text-decoration: none; } $endif$-code{white-space: pre-wrap;} span.smallcaps{font-variant: small-caps;}-div.columns{display: flex; gap: min(4vw, 1.5em);}-div.column{flex: auto; overflow-x: auto;}+div.columns{display: flex; gap: 1.5em;}+div.column{flex: auto;}+@media screen {+div.columns{gap: min(4vw, 1.5em);}+div.column{overflow-x: auto;}+} div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}-ul.task-list{list-style: none;}+/* The extra [class] is a hack that increases specificity enough to+ override a similar rule in reveal.js */+ul.task-list[class]{list-style: none;} ul.task-list li input[type="checkbox"] {+ font-size: inherit; width: 0.8em; margin: 0 0.8em 0.2em -1.6em; vertical-align: middle;@@ -175,33 +204,13 @@ $if(quotes)$ q { quotes: "“" "”" "‘" "’"; } $endif$-$if(highlighting-css)$-$highlighting-css$-$endif$ $if(displaymath-css)$ .display.math{display: block; text-align: center; margin: 0.5rem auto;} $endif$-$if(csl-css)$-div.csl-bib-body { }-div.csl-entry {- clear: both;-$if(csl-entry-spacing)$- margin-bottom: $csl-entry-spacing$;+$if(highlighting-css)$+/* CSS for syntax highlighting */+$highlighting-css$ $endif$-}-.hanging div.csl-entry {- margin-left:2em;- text-indent:-2em;-}-div.csl-left-margin {- min-width:2em;- float:left;-}-div.csl-right-inline {- margin-left:2em;- padding-left:1em;-}-div.csl-indent {- margin-left: 2em;-}+$if(csl-css)$+$styles.citations.html()$ $endif$
@@ -0,0 +1,120 @@+#let content-to-string(content) = {+ if content.has("text") {+ content.text+ } else if content.has("children") {+ content.children.map(content-to-string).join("")+ } else if content.has("body") {+ content-to-string(content.body)+ } else if content == [ ] {+ " "+ }+}+#let conf(+ title: none,+ subtitle: none,+ authors: (),+ keywords: (),+ date: none,+ abstract-title: none,+ abstract: none,+ thanks: none,+ cols: 1,+ margin: (x: 1.25in, y: 1.25in),+ paper: "us-letter",+ lang: "en",+ region: "US",+ font: none,+ fontsize: 11pt,+ mathfont: none,+ codefont: none,+ linestretch: 1,+ sectionnumbering: none,+ linkcolor: none,+ citecolor: none,+ filecolor: none,+ pagenumbering: "1",+ doc,+) = {+ set document(+ title: title,+ 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,+ leading: linestretch * 0.65em+ )+ set text(lang: lang,+ region: region,+ size: fontsize)++ set text(font: font) if font != none+ show math.equation: set text(font: mathfont) if mathfont != none+ show raw: set text(font: codefont) if codefont != none++ set heading(numbering: sectionnumbering)++ show link: set text(fill: rgb(content-to-string(linkcolor))) if linkcolor != none+ show ref: set text(fill: rgb(content-to-string(citecolor))) if citecolor != none+ show link: this => {+ if filecolor != none and type(this.dest) == label {+ text(this, fill: rgb(content-to-string(filecolor)))+ } else {+ text(this)+ }+ }++ if title != none {+ place(top, float: true, scope: "parent", clearance: 4mm, block(below: 1em, width: 100%)[+ #if title != none {+ align(center, block[+ #text(weight: "bold", size: 1.5em, hyphenate: false)[#title #if thanks != none {+ footnote(thanks, numbering: "*")+ counter(footnote).update(n => n - 1)+ }]+ #(+ if subtitle != none {+ parbreak()+ text(weight: "bold", size: 1.25em, hyphenate: false)[#subtitle]+ }+ )])+ }++ #if authors != none and authors != [] {+ let count = authors.len()+ let ncols = calc.min(count, 3)+ grid(+ columns: (1fr,) * ncols,+ row-gutter: 1.5em,+ ..authors.map(author => align(center)[+ #author.name \+ #author.affiliation \+ #author.email+ ])+ )+ }++ #if date != none {+ align(center)[#block(inset: 1em)[+ #date+ ]]+ }++ #if abstract != none {+ block(inset: 2em)[+ #text(weight: "semibold")[#abstract-title] #h(1em) #abstract+ ]+ }+ ])+ }+ doc+}
@@ -0,0 +1,20 @@+Abstract: Samevatting+Appendix: Bylae+Bibliography: Bibliografie+Cc: a.a.+Chapter: Hoofstuk+Contents: Inhoudsopgawe+Encl: Bylae(n)+Figure: Figuur+Index: Inhoud+ListOfFigures: Lys van figure+ListOfTables: Lys van tabelle+Page: Bladsy+Part: Deel+Preface: Voorwoord+Proof: Bewys+References: Verwysings+See: sien+SeeAlso: sien ook+Table: Tabel+To: Aan
@@ -0,0 +1,5 @@+Chapter: Бажалык+Contents: Бажалыктар+Figure: Јурук+Glossary: Сӧзлик+Preface: Сӧс бажы
@@ -1,20 +1,21 @@-Preface: ﻡﺪﺨﻟ-References: ﺎﻠﻣﺭﺎﺠﻋ-Abstract: ﻢﻠﺨﺻ-Bibliography: ﺎﻠﻤﺻﺍﺩﺭ-Chapter: ﺏﺎﺑ-Appendix: ﺎﻠﻣﻼﺤﻗ-Contents: ﺎﻠﻤﺤﺗﻮﻳﺎﺗ-ListOfFigures: ﻕﺎﺌﻣﺓ ﺍﻸﺸﻛﺎﻟ-ListOfTables: ﻕﺎﺌﻣﺓ ﺎﻠﺟﺩﺍﻮﻟ-Index: ﺎﻠﻔﻫﺮﺳ-Figure: ﺶﻜﻟ-Table: ﺝﺩﻮﻟ-Part: ﺎﻠﻘﺴﻣ-Encl: ﺎﻠﻣﺮﻔﻗﺎﺗ-To: ﺈﻟﻯ-Page: ﺺﻔﺣﺓ-See: ﺭﺎﺠﻋ-SeeAlso: ﺭﺎﺠﻋ ﺄﻴﺿًﺍ-Proof: ﺏﺮﻫﺎﻧ-Glossary: ﻕﺎﻣﻮﺳ+Abstract: ملخص+Appendix: الملاحق+Bibliography: المصادر+Cc: نسخة ل+Chapter: باب+Contents: المحتويات+Encl: المرفقات+Figure: شكل+Glossary: قاموس+Index: الفهرس+ListOfFigures: قائمة الأشكال+ListOfTables: قائمة الجداول+Page: صفحة+Part: القسم+Preface: مدخل+Proof: برهان+References: المراجع+See: راجع+SeeAlso: راجع أيضًا+Table: جدول+To: إلى
@@ -0,0 +1,21 @@+Abstract: মূলভাৱ+Appendix: পৰিশিষ্ট+Bibliography: তথ্যসূত্ৰ+Cc: প্ৰতিলিপি+Chapter: অধ্যায়+Contents: সমল+Encl: সংযোজিত+Figure: চিত্ৰ+Glossary: অৰ্থকোষ+Index: বিষয়সূচী+ListOfFigures: চিত্ৰসূচী+ListOfTables: তালিকাসূচী+Page: পৃষ্ঠা+Part: অংশ+Preface: পাতনি+Proof: প্ৰমাণ+References: প্ৰসংগ+See: চাওক+SeeAlso: ও+Table: তালিকা+To: মুখে
@@ -0,0 +1,21 @@+Abstract: Sumariu+Appendix: Apéndiz+Bibliography: Bibliografía+Cc: cc+Chapter: Capítulu+Contents: Conteníu+Encl: incl.+Figure: Figura+Glossary: Glosariu+Index: Índiz+ListOfFigures: Llista de figures+ListOfTables: Llista de tables+Page: Páxina+Part: Parte+Preface: Entamu+Proof: Demostración+References: Referencies+See: ver+SeeAlso: ver tamién+Table: Tabla+To: Pa
@@ -0,0 +1,21 @@+Abstract: Annotasiya+Appendix: Əlavə+Bibliography: Ədəbiyyat+Cc: cc+Chapter: Fəsil+Contents: Mündəricat+Encl: encl+Figure: Şəkil+Glossary: Terminlər lüğəti+Index: Mövzu göstəricisi+ListOfFigures: Şəkillərin siyahısı+ListOfTables: Cədvəllərin siyahısı+Page: səh.+Part: Hissə+Preface: Ön söz+Proof: İsbatı+References: Ədəbiyyat+See: baxın+SeeAlso: həmçinin baxın+Table: Cədvəl+To: To
@@ -0,0 +1,21 @@+Abstract: Анатацыя+Appendix: Дадатак+Bibliography: Літаратура+Cc: зых.+Chapter: Глава+Contents: Зьмест+Encl: укл.+Figure: Рыс.+Glossary: Слоўнік тэрмінаў+Index: Прадметны паказальнік+ListOfFigures: Сьпіс ілюстрацый+ListOfTables: Сьпіс табліц+Page: с.+Part: Частка+Preface: Прадмова+Proof: Доказ+References: Сьпіс літаратуры+See: гл.+SeeAlso: гл. таксама+Table: Табліца+To: вх.
@@ -6,14 +6,16 @@ Contents: Съдържание Encl: Приложения Figure: Фигура-Glossary: Glossary+Glossary: Притурка Index: Азбучен указател ListOfFigures: Списък на фигурите ListOfTables: Списък на таблиците Page: Стр.+Part: Част Preface: Предговор-Proof: Proof+Proof: Доказателство References: Литература See: вж.-SeeAlso: вж. също и+SeeAlso: вж. също и Table: Таблица+To: За
@@ -0,0 +1,14 @@+Abstract: གནད་བསྡུས།+Appendix: ཞར་བྱུང་།+Bibliography: དཔེ་ཆའི་ཐོ་གཞུང་།+Cc: འདྲ་བཤུས་ལེན་མཁན་+Chapter: ལེའུ་+Contents: དཀར་ཆག།+Figure: པར་རིས་+Glossary: མིང་ཚིག་རེའུ་མིག།+Index: གསུལ་བྱང་།+Page: ཤོག་+Part: ཆ་ཤས་+Preface: དཔེ་དེབ་ཀྱི་གླེང་བརྗོད།+Proof: བདེན་དཔང་།+Table: རེའུ་མིག་
@@ -0,0 +1,21 @@+Abstract: Dvierrañ+Appendix: Stagadenn+Bibliography: Lennadurezh+Cc: Eilskrid da+Chapter: Pennad+Contents: Taolenn+Encl: Dielloù kevret+Figure: Figurenn+Glossary: Glossary+Index: Meneger+ListOfFigures: Listenn ar Figurennoù+ListOfTables: Listenn an taolennoù+Page: Pajenn+Part: Lodenn+Preface: Rakskrid+Proof: Proof+References: Daveennoù+See: Gwelout+SeeAlso: Gwelout ivez+Table: Taolenn+To: evit
@@ -0,0 +1,21 @@+Abstract: Sažetak+Appendix: Dodatak+Bibliography: Bibliografija+Cc: Kopija+Chapter: Poglavlje+Contents: Sadržaj+Encl: Prilozi+Figure: Slika+Glossary: Rječnik+Index: Indeks+ListOfFigures: Popis slika+ListOfTables: Popis tabela+Page: Stranica+Part: Dio+Preface: Predgovor+Proof: Dokaz+References: Literatura+See: Vidjeti+SeeAlso: Također vidjeti+Table: Tabela+To: Prima
@@ -0,0 +1,17 @@+Abstract: Тобшолол+Appendix: Хабсаралта+Bibliography: Ном зүй+Chapter: Бүлэг+Contents: Гаршаг+Encl: Оруулаха+Figure: Зураг+Index: Бүгэд хэлхээс+ListOfFigures: Зурагай жагсаалт+ListOfTables: Хүснэгэтэй жагсаалт+Page: Хуудаһан+Part: Бүлэг+Preface: Оршол+References: Ашаглаһан ном+See: Үз+SeeAlso: Mүн үз+Table: Хүсэнэгт
@@ -0,0 +1,21 @@+Abstract: پوختە+Appendix: پاشکۆ+Bibliography: کتێبنامە+Cc: ڕوونووس+Chapter: بەندی+Contents: نێوەڕۆک+Encl: هاوپێچ+Figure: وێنەی+Glossary: فەرهەنگۆک+Index: پێنوێن+ListOfFigures: لیستی وێنەکان+ListOfTables: لیستی خشتەکان+Page: لاپەڕە+Part: بەشی+Preface: پێشەكی+Proof: سەلماندن+References: سەرچاوەکان+See: چاو لێکەن+SeeAlso: هەروەها چاو لێکەن+Table: خشتەی+To: بۆ
@@ -0,0 +1,21 @@+Abstract: Puxte+Appendix: Paşko+Bibliography: Kitêbname+Cc: Rûnûs+Chapter: Bendî+Contents: Nêwerrok+Encl: Hawpêç+Figure: Wêney+Glossary: Ferhengok+Index: Pêrrist+ListOfFigures: Lîstî Wênekan+ListOfTables: Lîstî Xiştekan+Page: Laperre+Part: Beşî+Preface: Pêşekî+Proof: Selmandin+References: Serçawekan+See: Çaw lêken+SeeAlso: Herweha çaw lêken+Table: Xiştey+To: Bo
@@ -1,13 +1,13 @@ Abstract: Abstrakt-Appendix: Dodatek+Appendix: Příloha Bibliography: Literatura-Cc: Na vědomí:+Cc: Na vědomí Chapter: Kapitola Contents: Obsah Encl: Příloha Figure: Obrázek Glossary: Slovník-Index: Index+Index: Rejstřík ListOfFigures: Seznam obrázků ListOfTables: Seznam tabulek Page: Strana@@ -16,6 +16,6 @@ Proof: Důkaz References: Reference See: viz-SeeAlso: viz+SeeAlso: viz také Table: Tabulka To: Komu
@@ -0,0 +1,21 @@+Abstract: Аннотация+Appendix: Приложение+Bibliography: Литература+Cc: исх.+Chapter: Глава+Contents: Содержание+Encl: вкл.+Figure: Рис.+Glossary: Словарь терминов+Index: Предметный указатель+ListOfFigures: Список иллюстраций+ListOfTables: Список таблиц+Page: с.+Part: Часть+Preface: Предисловие+Proof: Доказательство+References: Список литературы+See: см.+SeeAlso: см. также+Table: Таблица+To: вх.
@@ -0,0 +1,21 @@+Abstract: Crynodeb+Appendix: Atodiad+Bibliography: Llyfryddiaeth+Cc: copïau+Chapter: Pennod+Contents: Cynnwys+Encl: amgaeëdig+Figure: Darlun+Glossary: Rhestr termau+Index: Mynegai+ListOfFigures: Rhestr Ddarluniau+ListOfTables: Rhestr Dablau+Page: tudalen+Part: Rhan+Preface: Rhagair+Proof: Prawf+References: Cyfeiriadau+See: gweler+SeeAlso: gweler hefyd+Table: Taflen+To: At
@@ -0,0 +1,21 @@+Abstract: Abstrakt+Appendix: Dodatek+Bibliography: Literatura+Cc: Na vědomí+Chapter: Kapitola+Contents: Obsah+Encl: Příloha+Figure: Obrázek+Glossary: Slovník+Index: Index+ListOfFigures: Seznam obrázků+ListOfTables: Seznam tabulek+Page: Strana+Part: Část+Preface: Předmluva+Proof: Důkaz+References: Reference+See: viz+SeeAlso: viz+Table: Tabulka+To: Komu
@@ -1,7 +1,7 @@ Abstract: Resumé Appendix: Bilag Bibliography: Litteratur-Cc: Kopi til}+Cc: Kopi til Chapter: Kapitel Contents: Indhold Encl: Vedlagt@@ -18,4 +18,4 @@ See: Se SeeAlso: Se også Table: Tabel-To: Til}+To: Til
@@ -0,0 +1,21 @@+Abstract: Abstrakt+Appendix: Dodawki+Bibliography: Literatura+Cc: CC+Chapter: Kapitl+Contents: Wopśimjeśe+Encl: Pśiłoga+Figure: Wobraz+Glossary: Glossary+Index: Indeks+ListOfFigures: Zapis wobrazow+ListOfTables: Zapis tabulkow+Page: Strona+Part: Źěl+Preface: Zawod+Proof: Proof+References: Referency+See: gl.+SeeAlso: gl.~teke+Table: Tabulka+To: Komu
@@ -8,8 +8,8 @@ Figure: Σχήμα Glossary: Γλωσσάρι Index: Ευρετήριο-ListOfFigures: Κατάλογος σχημάτων-ListOfTables: Κατάλογος πινάκων+ListOfFigures: Κατάλογος Σχημάτων+ListOfTables: Κατάλογος Πινάκων Page: Σελίδα Part: Μέρος Preface: Πρόλογος
@@ -9,8 +9,8 @@ Glossary: Glossary Index: Index Listing: Listing-ListOfFigures: ListOfFigures-ListOfTables: ListOfTables+ListOfFigures: List of Figures+ListOfTables: List of Tables Page: page Part: Part Preface: Preface
@@ -11,10 +11,11 @@ ListOfFigures: Listo de figuroj ListOfTables: Listo de tabeloj Page: Paĝo+Part: Parto Preface: Antaŭparolo Proof: Pruvo References: Citaĵoj See: vidu-SeeAlso: Parto+SeeAlso: vidu ankaŭ Table: Tabelo To: Al
@@ -0,0 +1,21 @@+Abstract: Resumen+Appendix: Apéndice+Bibliography: Bibliografía+Cc: Copia a+Chapter: Capítulo+Contents: Índice general+Encl: Adjunto(s)+Figure: Figura+Glossary: Glosario+Index: Índice alfabético+ListOfFigures: Índice de figuras+ListOfTables: Índice de cuadros+Page: Página+Part: Parte+Preface: Prefacio+Proof: Prueba+References: Referencias+See: véase+SeeAlso: véase también+Table: Cuadro+To: A
@@ -0,0 +1,21 @@+Abstract: Resumen+Appendix: Apéndice+Bibliography: Bibliografía+Cc: Copia a+Chapter: Capítulo+Contents: Índice+Encl: Anexo+Figure: Figura+Glossary: Glosario+Index: Índice Alfabético+ListOfFigures: Índice de Figuras+ListOfTables: Índice de Cuadros+Page: Página+Part: Parte+Preface: Prefacio+Proof: Demostración+References: Referencias+See: véase+SeeAlso: véase también+Table: Cuadro+To: A
@@ -3,17 +3,17 @@ Bibliography: Bibliografía Cc: Copia a Chapter: Capítulo-Contents: Índice general-Encl: Adjunto(s)+Contents: Índice+Encl: Adjunto Figure: Figura Glossary: Glosario Index: Índice alfabético ListOfFigures: Índice de figuras ListOfTables: Índice de cuadros-Page: Página+Page: página Part: Parte Preface: Prefacio-Proof: Prueba+Proof: Demostración References: Referencias See: véase SeeAlso: véase también
@@ -6,8 +6,9 @@ Contents: Sisukord Encl: Lisa(d) Figure: Joonis-Glossary: Glossary+Glossary: Sõnastik Index: Indeks+Listing: Kood ListOfFigures: Joonised ListOfTables: Tabelid Page: Lk.@@ -18,3 +19,4 @@ See: vt. SeeAlso: vt. ka Table: Tabel+To: Saaja
@@ -1,21 +1,21 @@-Abstract: چکیﺪﻫ-Appendix: پیﻮﺴﺗ-Bibliography: کﺕﺎﺑc>ﻧﺎﻤﻫ-Cc: ﺭﻮﻧﻮﺸﺗ-Chapter: ﻒﺼﻟ-Contents: ﻒﻫﺮﺴﺗ ﻢﻃﺎﻠﺑ-Encl: پیﻮﺴﺗ-Figure: ﺶﻜﻟ-Glossary: ﺩﺎﻨﺷc>ﻧﺎﻤﻫ-Index: ﻦﻣﺍیﻩ-ListOfFigures: ﻝیﺲﺗ ﺖﺻﺍﻭیﺭ-ListOfTables: ﻝیﺲﺗ ﺝﺩﺍﻮﻟ-Page: ﺺﻔﺣﺓ-Part: ﺐﺨﺷ-Preface: پیﺵگﻒﺗﺍﺭ-Proof: ﺏﺮﻫﺎﻧ-References: ﻡﺭﺎﺠﻋ-See: ﺐﺑیﻥیﺩ-SeeAlso: ﻥیﺯ ﺐﺑیﻥیﺩ-Table: ﺝﺩﻮﻟ-To: ﺐﻫ+Abstract: چکیده+Appendix: پیوست+Bibliography: کتابنامه+Cc: رونوشت+Chapter: فصل+Contents: فهرست+Encl: پیوست+Figure: شكل+Glossary: فرهنگنامه+Index: نمایه+ListOfFigures: فهرست شکلها+ListOfTables: فهرست جدولها+Page: صفحه+Part: بخش+Preface: پیشگفتار+Proof: اثبات+References: مرجعها+See: ببینید+SeeAlso: نیز ببینید+Table: جدول+To: به
@@ -3,7 +3,7 @@ Bibliography: Kirjallisuutta Cc: Jakelu Chapter: Luku-Contents: Sisältö+Contents: Sisällys Encl: Liitteet Figure: Kuva Glossary: Sanasto
@@ -0,0 +1,18 @@+Abstract: Abstrak+Appendix: Hugpong+Bibliography: Talaaklatan+Chapter: Kabanata+Contents: Talalamanan+Figure: Laraw+Glossary: Glosaryo+Index: Talatuntunan+ListOfFigures: Talalarawan+ListOfTables: Talatalayan+Page: Pahina+Part: Bahagi+Preface: Paunang Salita+Proof: Patunay+References: Talasanggunian+See: tignan ang+SeeAlso: tignan din+Table: Talay
@@ -0,0 +1,21 @@+Abstract: Somari+Appendix: Zonte+Bibliography: Bibliografie+Cc: Cun copie a+Chapter: Cjapitul+Contents: Tabele gjenerâl+Encl: Zonte(is)+Figure: Figure+Glossary: Glossari+Index: Tabele analitiche+ListOfFigures: Liste des figuris+ListOfTables: Liste des tabelis+Page: Pagjine+Part: Part+Preface: Prefazion+Proof: Dimostrazion+References: Riferiments+See: cjale+SeeAlso: cjale ancje+Table: Tabele+To: Par
@@ -0,0 +1,21 @@+Abstract: Achoimre+Appendix: Aguisín+Bibliography: Leabharliosta+Cc: cc+Chapter: Caibidil+Contents: Clár Ábhair+Encl: faoi iamh+Figure: Léaráid+Glossary: Glossary+Index: Innéacs+ListOfFigures: Léaráidí+ListOfTables: Táblaí+Page: Leathanach+Part: Cuid+Preface: Réamhrá+Proof: Cruthúnas+References: Tagairtí+See: féach+SeeAlso: féach freisin+Table: Tábla+To: Go
@@ -0,0 +1,21 @@+Abstract: Brìgh+Appendix: Ath-sgr`ıobhadh+Bibliography: Leabhraichean+Cc: lethbhreac gu+Chapter: Caibideil+Contents: Clàr-obrach+Encl: a-staigh+Figure: Dealbh+Glossary: Glossary+Index: Clàr-innse+ListOfFigures: Liosta Dhealbh+ListOfTables: Liosta Chlàr+Page: t.d.+Part: Cuid+Preface: Preface+Proof: Proof+References: Iomraidh+See: see+SeeAlso: see also+Table: Clàr+To: gu
@@ -0,0 +1,21 @@+Abstract: Resumo+Appendix: Apéndice+Bibliography: Bibliografía+Cc: Copia a+Chapter: Capítulo+Contents: Índice+Encl: Adxunto+Figure: Figura+Glossary: Glosario+Index: Índice alfabético+ListOfFigures: Índice de figuras+ListOfTables: Índice de cadros+Page: Páxina+Part: Parte+Preface: Prefacio+Proof: Demostración+References: Referencias+See: véxase+SeeAlso: véxase tamén+Table: Cadro+To: A
@@ -0,0 +1,21 @@+Abstract: Περίληψις+Appendix: Παράρτημα+Bibliography: Βιβλιογραφία+Cc: Κοινοποίησις+Chapter: Κεφάλαιον+Contents: Περιεχόμενα+Encl: Συνημμένως+Figure: Σχῆμα+Glossary: Γλωσσάριον+Index: Εὑρετήριον+ListOfFigures: Κατάλογος σχημάτων+ListOfTables: Κατάλογος πινάκων+Page: Σελὶς+Part: Μέρος+Preface: Προοίμιον+Proof: Ἀπόδειξις+References: Ἀναφοραὶ+See: ὃρα+SeeAlso: ὃρα ὡσαύτως+Table: Πίναξ+To: Πρὸς
@@ -0,0 +1,9 @@+Appendix: અનુસૂચિ+Chapter: પ્રકરણ+Index: અનુક્રમણિકા+Page: પાનુ+Part: ભાગ+Proof: પુરાવો+See: જુવો+SeeAlso: ઉપરાંત+Table: ટેબલ
@@ -0,0 +1,21 @@+Abstract: Taƙaitawa+Appendix: Ƙarin bayani+Bibliography: Fahirinsa+Cc: cc+Chapter: Babi+Contents: Abin da ke ciki+Encl: saƙe+Figure: Addadi+Glossary: Ƙamus+Index: Fihirinsa+ListOfFigures: Tsarin Addadi+ListOfTables: Tsarin tabili+Page: Shafi+Part: Kashi+Preface: Gabatarwa+Proof: Shaida+References: Nassoshi+See: duba+SeeAlso: kuma+Table: tabili+To: je
@@ -6,17 +6,16 @@ Contents: תוכן העניינים Encl: רצ"ב Figure: איור-Glossary: מילון מונחים}+Glossary: מילון מונחים Index: מפתח ListOfFigures: רשימת האיורים ListOfTables: רשימת הטבלאות Page: עמוד Part: חלק Preface: מבוא-Proof: הוכחה}-Ps: נ.ב.+Proof: הוכחה References: מקורות See: ראה-SeeAlso: ראה גם}+SeeAlso: ראה גם Table: טבלה To: אל
@@ -1,20 +1,18 @@ Abstract: सारांश Appendix: परिशिष्ट-Bibliography: संदर ग्रन्थ}-Cc: +Bibliography: संदर्भ-ग्रन्थ Chapter: अध्याय-Contents: विषय सूची-Encl: -Figure: चित्र}-Headpage: पृषठ+Contents: अनुक्रम+Figure: चित्र+Glossary: शब्दार्थ सूची Index: सूची ListOfFigures: चित्रों की सूची ListOfTables: तालिकाओं की सूची-Page: पृषठ-Part: खणड-Preface: प्रस्तावना}+Page: पृष्ठ+Part: खण्ड+Preface: प्रस्तावना+Proof: प्रमाण References: हवाले See: देखिए SeeAlso: और देखिए Table: तालिका-To:
@@ -0,0 +1,21 @@+Abstract: Abstrakt+Appendix: Dodawki+Bibliography: Literatura+Cc: CC+Chapter: Kapitl+Contents: Wobsah+Encl: Přłoha+Figure: Wobraz+Glossary: Glossary+Index: Indeks+ListOfFigures: Zapis wobrazow+ListOfTables: Zapis tabulkow+Page: Strona+Part: Dźěl+Preface: Zawod+Proof: Proof+References: Referency+See: hl.+SeeAlso: hl.~tež+Table: Tabulka+To: Komu
@@ -1,5 +1,5 @@ Abstract: Kivonat-Appendix: Függelék+Appendix: függelék Bibliography: Irodalomjegyzék Cc: Körlevél–címzettek Chapter: fejezet
@@ -0,0 +1,20 @@+Abstract: Սեղմագիր+Appendix: Հավելված+Bibliography: Գրականություն+Cc: Կրկնօրինակը՝+Chapter: Գլուխ+Contents: Բովանդակություն+Encl: Կից՝+Figure: Նկար+Glossary: Տերմինների ցանկ+Index: Առարկայական ցանկ+ListOfFigures: Նկարների ցանկ+ListOfTables: Աղյուսակների ցանկ+Page: էջ+Part: Մաս+Preface: Նախաբան+Proof: Ապացույց+References: Հղումներ+See: տե՛ս+SeeAlso: տե՛ս նաև+Table: Աղյուսակ
@@ -0,0 +1,21 @@+Abstract: Summario+Appendix: Appendice+Bibliography: Bibliographia+Cc: Copia+Chapter: Capitulo+Contents: Contento+Encl: Incluso+Figure: Figura+Glossary: Glossario+Index: Indice+ListOfFigures: Lista de figuras+ListOfTables: Lista de tabellas+Page: Pagina+Part: Parte+Preface: Prefacio+Proof: Prova+References: Referentias+See: vide+SeeAlso: vide etiam+Table: Tabella+To: A
@@ -0,0 +1,21 @@+Abstract: Ringkasan+Appendix: Lampiran+Bibliography: Bibliografi+Cc: cc+Chapter: Bab+Contents: Daftar Isi+Encl: Lampiran+Figure: Gambar+Glossary: Daftar Istilah+Index: Indeks+ListOfFigures: Daftar Gambar+ListOfTables: Daftar Tabel+Page: Halaman+Part: Bagian+Preface: Pendahuluan+Proof: Bukti+References: Pustaka+See: lihat+SeeAlso: lihat juga+Table: Tabel+To: Kepada
@@ -18,4 +18,4 @@ See: Sjá SeeAlso: Sjá einnig Table: Tafla-To: Til:+To: Til
@@ -1,7 +1,7 @@ Abstract: Sommario Appendix: Appendice Bibliography: Bibliografia-Cc: e p. c.+Cc: e~p.~c. Chapter: Capitolo Contents: Indice Encl: Allegati
@@ -0,0 +1,21 @@+Abstract: 概要+Appendix: 付録+Bibliography: 文献目録+Cc: 同報+Chapter: 章+Contents: 目次+Encl: 添付+Figure: 図+Glossary: 用語集+Index: 索引+ListOfFigures: 図目次+ListOfTables: 表目次+Page: 頁+Part: 部+Preface: 端書き+Proof: 証明+References: 参考文献+See: 参照+SeeAlso: 参照+Table: 表+To: 宛先
@@ -0,0 +1,21 @@+Abstract: ანოტაცია+Appendix: დანართი+Bibliography: ლიტერატურა+Cc: წყარ.+Chapter: თავი+Contents: შინაარსი+Encl: ჩათვ.+Figure: სურ.+Glossary: ტერმინები+Index: საძიებელი+ListOfFigures: სურათი+ListOfTables: ცხრილი+Page: გვ.+Part: ნაწილი+Preface: წინასიტყვაობა+Proof: დამტკიცება+References: ლიტერატურა+See: იხ.+SeeAlso: იხ. ასევე+Table: ცხრ.+To: შ.
@@ -0,0 +1,21 @@+Abstract: کورتەبیر+Appendix: پاشکۆ+Bibliography: چاڤکانییا پرتووکان+Cc: بەلاڤکەر+Chapter: سەرێ+Contents: ناڤێرۆک+Encl: دوماهک+Figure: دیمەنێ+Glossary: چاڤکانییا لێکۆلینێ+Index: پێرست+ListOfFigures: هەژمارا دیمەنا+ListOfTables: هەژمارا کەڤالێن+Page: رووپەلێ+Part: بەشا+Preface: پێشگۆتن+Proof: دەلیل+References: پرتووکێن بژارتی+See: بنێرا+SeeAlso: لە ڤێیا ژ بنێرا+Table: کەڤالا+To: ژ بۆ
@@ -0,0 +1,21 @@+Abstract: Kurtebîr+Appendix: Tebînîya+Bibliography: Çavkanîya Pirtukan+Cc: Belavker+Chapter: Serê+Contents: Navêrok+Encl: Dumahik+Figure: Dimenê+Glossary: Çavkanîya lêkolînê+Index: Endeks+ListOfFigures: Hejmara Dimena+ListOfTables: Hejmara Kevalen+Page: Rûpelê+Part: Bêşa+Preface: Peşgotin+Proof: Delîl+References: Pirtuken bijartî+See: binêra+SeeAlso: le vêya ji binêra+Table: Kevala+To: Ji bo
@@ -0,0 +1,20 @@+Abstract: ಸಾರಾಂಶ+Appendix: ಅನುಬಂಧ+Bibliography: ಗ್ರಂಥಸೂಚಿ+Cc: cc+Chapter: ಅಧ್ಯಾಯ+Contents: ವಿಷಯಗಳು+Encl: encl+Figure: ಚಿತ್ರ+Index: ಸೂಚಿ+ListOfFigures: ಚಿತ್ರಗಳ ಪಟ್ಟಿ+ListOfTables: ಕೋಷ್ಟಕಗಳ ಪಟ್ಟಿ+Page: ಪುಟ+Part: ಭಾಗ+Preface: ಮುನ್ನುಡಿ+Proof: ಕರಡುಪ್ರತಿ+References: ಉಲ್ಲೇಖಗಳು+See: ನೋಡು+SeeAlso: ಇದನ್ನೂ ಸಹ ನೋಡು+Table: ಕೋಷ್ಟಕ+To: ಗೆ
@@ -14,4 +14,4 @@ Proof: 증명 References: 참고문헌 Table: 표-To: 수신:+To: 수신
@@ -0,0 +1,20 @@+Abstract: Summarium+Appendix: Additamentum+Bibliography: Conspectus librorum+Cc: Exemplar+Chapter: Caput+Contents: Index+Encl: Additur+Figure: Descriptio+Glossary: Glossarium+Index: Index rerum notabilium+ListOfFigures: Conspectus descriptionum+ListOfTables: Conspectus tabularum+Page: charta+Part: Pars+Preface: Praefatio+Proof: Demonstratio+References: Conspectus librorum+See: cfr.+SeeAlso: cfr.+Table: Tabula
@@ -0,0 +1,21 @@+Abstract: Resümee+Appendix: Annex+Bibliography: Bibliographie+Cc: Distributeur+Chapter: Kapitel+Contents: Contenue+Encl: Annex(en)+Figure: Bild+Glossary: Glossär+Index: Index+ListOfFigures: Lëscht vun de Biller+ListOfTables: Lëscht vun den Tabellen+Page: Säit+Part: Deel+Preface: Virwuert+Proof: Beweis+References: Literatur+See: kuck+SeeAlso: kuck och+Table: Tabell+To: Un
@@ -1,12 +1,12 @@ Abstract: Anotācija Appendix: Pielikums Bibliography: Literatūra-Cc: cc+Cc: Kopija(s) Chapter: Nodaļa Contents: Saturs-Encl: encl+Encl: Pielikumā Figure: Att.-Index: Index+Index: Priekšmetu rādītājs ListOfFigures: Attēlu saraksts ListOfTables: Tabulu saraksts Page: lpp.
@@ -0,0 +1,21 @@+Abstract: Апстракт+Appendix: Прилог+Bibliography: Библиографиjа+Cc: копиjа+Chapter: Глава+Contents: Содржина+Encl: Прилози+Figure: Слика+Glossary: Речник+Index: Индекс на термини+ListOfFigures: Листа на слики+ListOfTables: Листа на табели+Page: стр.+Part: Дел+Preface: Предговор+Proof: доказ+References: Литература+See: види+SeeAlso: види исто така+Table: Табела+To: За
@@ -0,0 +1,12 @@+Abstract: സാരാംശം+Appendix: ശിഷ്ടം+Chapter: അദ്ധ്യായം+Contents: ഉള്ളടക്കം+Figure: ചിത്രം+Index: സൂചിക+ListOfFigures: ചിത്രസൂചിക+ListOfTables: പട്ടികകളുടെ സൂചിക+Part: ഭാഗം+See: കാണുക+SeeAlso: ഇതും കാണുക+Table: പട്ടിക
@@ -0,0 +1,19 @@+Abstract: Удиртгал+Appendix: Хавсралт+Bibliography: Номзүй+Cc: э.с.+Chapter: Бүлэг+Contents: Гарчиг+Encl: Ишлэл+Figure: Зураг+Index: Товъёг+ListOfFigures: Зургийн жагсаалт+ListOfTables: Хүснэгтийн жагсаалт+Page: тал+Part: Хэсэг+Preface: Өмнөх үг+Proof: Баталгаа+References: Ашигласан ном+See: талд үз+SeeAlso: мөн талд үз+Table: Хүснэгт
@@ -0,0 +1,21 @@+Abstract: सारांश+Appendix: परिशिष्ट+Bibliography: संदर्भसूची+Cc: प्रत+Chapter: प्रकरण+Contents: अनुक्रमणिका+Encl: समाविष्ट+Figure: आकृती+Glossary: संज्ञासूची+Index: सूची+ListOfFigures: आकृत्यांची सूची+ListOfTables: कोष्टकसूची+Page: पृष्ठ+Part: खंड+Preface: प्रस्तावना+Proof: सिद्धता+References: संदर्भ+See: पाहा+SeeAlso: हेदेखील पाहा+Table: कोष्टक+To: प्रति
@@ -0,0 +1,21 @@+Abstract: Abstrak+Appendix: Lampiran+Bibliography: Bibliografi+Cc: sk+Chapter: Bab+Contents: Kandungan+Encl: Lampiran+Figure: Gambar+Glossary: Istilah+Index: Indeks+ListOfFigures: Senarai Gambar+ListOfTables: Senarai Jadual+Page: Halaman+Part: Bahagian+Preface: Prakata+Proof: Bukti+References: Rujukan+See: sila rujuk+SeeAlso: rujuk juga+Table: Jadual+To: Kepada
@@ -0,0 +1,21 @@+Abstract: Sammendrag+Appendix: Tillegg+Bibliography: Bibliografi+Cc: Kopi sendt+Chapter: Kapittel+Contents: Innhold+Encl: Vedlegg+Figure: Figur+Glossary: Ordliste+Index: Register+ListOfFigures: Figurer+ListOfTables: Tabeller+Page: Side+Part: Del+Preface: Forord+Proof: Bevis+References: Referanser+See: Se+SeeAlso: Se også+Table: Tabell+To: Til
@@ -0,0 +1,21 @@+Abstract: ߓߊߕߐߡߐ߲+Appendix: ߘߋ߬ߙߋ+Bibliography: ߟߍߙߊߥߙߍߟߐ߲߲+Cc: ߓߊ ߘߏ߫ ߘߌ߫+Chapter: ߛߌ߰ߘߊ+Contents: ߞߣߐߘߐ+Encl: ߝߍ߬ߕߊ+Figure: ߢߊ+Glossary: ߞߘߐߝߐߟߊ߲+Index: ߛߙߍߘߍ+ListOfFigures: ߢߊ ߟߎ߬ ߛߙߍߘߍ+ListOfTables: ߦߌ߬ߘߊ߬ߥߟߊ ߟߎ߬ ߛߙߍߘߍ+Page: ߞߐߜߍ+Part: ߛߌ߰ߘߊ߬ߙߋ߲+Preface: ߢߍߛߓߍ+Proof: ߦߌ߬ߘߊ߬ߞߏ+References: ߞߐߡߊߛߙߋ+See: ߡߊߝߟߍ߫+SeeAlso: ߝߟߍߡߊߛߊ߬ߦߌ߬+Table: ߦߌ߬ߘߊ߬ߥߟߊ+To: ߞߊߕߙߍ߬
@@ -1,19 +1,19 @@ Abstract: Samenvatting-Appendix: Bijlage+Appendix: Bijlage Bibliography: Bibliografie Cc: cc Chapter: Hoofdstuk Contents: Inhoudsopgave-Encl: Bijlage(n)+Encl: Bijlage(n) Figure: Figuur-Glossary: Verklarende woordenlijst+Glossary: Verklarende Woordenlijst Index: Index-ListOfFigures: Lijst van figuren-ListOfTables: Lijst van tabellen+ListOfFigures: Lijst van figuren+ListOfTables: Lijst van tabellen Page: Pagina Part: Deel Preface: Voorwoord-Proof: Bewijs+Proof: Bewijs References: Referenties See: zie SeeAlso: zie ook
@@ -0,0 +1,21 @@+Abstract: Samandrag+Appendix: Tillegg+Bibliography: Litteratur+Cc: Kopi til+Chapter: Kapittel+Contents: Innhald+Encl: Vedlegg+Figure: Figur+Glossary: Ordliste+Index: Register+ListOfFigures: Figurar+ListOfTables: Tabellar+Page: Side+Part: Del+Preface: Forord+Proof: Bevis+References: Referansar+See: Sjå+SeeAlso: Sjå òg+Table: Tabell+To: Til
@@ -0,0 +1,21 @@+Abstract: Resumit+Appendix: Annèx+Bibliography: Bibliografia+Cc: còpia a+Chapter: Capítol+Contents: Ensenhador+Encl: Pèça junta+Figure: Figura+Glossary: Glossari+Index: Indèx+ListOfFigures: Taula de las figuras+ListOfTables: Taula dels tablèus+Page: Pagina+Part: Partida+Preface: Prefàcia+Proof: Demostracion+References: Referéncias+See: vejatz+SeeAlso: vejatz tanben+Table: Tablèu+To: A
@@ -0,0 +1,21 @@+Abstract: ସାରାଂଶ+Appendix: ପରିଶିଷ୍ଟ+Bibliography: ସୂଚନା+Cc: କପି କରନ୍ତୁ+Chapter: ଅଧ୍ୟାୟ+Contents: ସୁଚୀ ପତ୍ର+Encl: ସଂଲଗ୍ନ+Figure: ପ୍ରତିଛବି+Glossary: ଶବ୍ଦର ଶବ୍ଦକୋଷ+Index: ସୂଚକାଙ୍କ+ListOfFigures: ପ୍ରତିଛବି ତାଲିକା+ListOfTables: ଟେବୁଲ ତାଲିକା+Page: ପୃଷ୍ଠା+Part: ବିଭାଗ+Preface: ପ୍ରାରମ୍ଭ+Proof: ପ୍ରମାଣ+References: ସନ୍ଦର୍ଭ+See: ଦେଖନ୍ତୁ+SeeAlso: ଅଧିକ ଦେଖନ୍ତୁ+Table: ଟେବୁଲ୍+To: ପ୍ରତି
@@ -0,0 +1,20 @@+Abstract: ਨਿਚੋੜ+Appendix: ਲੜੀਵਾਰ+Bibliography: ਸੰਬੰਧਤ ਹਵਾਲੇ+Cc: ਕਾਪੀ+Chapter: ਪਾਠ+Contents: ਸਮਗਰੀ+Encl: ਨੱਥੀ+Figure: ਸ਼ਕਲ+Glossary: ਕੁੰਜੀ+Index: ਸੂਚੀ+ListOfFigures: ਸ਼ਕਲਾਂ ਦੀ ਲੜੀ+ListOfTables: ਲੜੀਆਂ ਦਾ ਲੇਖਾ+Page: ਵਰਕਾ+Part: ਹਿੱਸਾ+Preface: ਮੁੱਖਬੰਦ+Proof: ਪਰਮਾਣ+References: ਹਵਾਲਾ+See: ਵੇਖੋ+SeeAlso: ਹੋਰ+Table: ਲੇਖਾ
@@ -1,7 +1,7 @@ Abstract: Streszczenie Appendix: Dodatek Bibliography: Bibliografia-Cc: Kopie:+Cc: Kopie Chapter: Rozdział Contents: Spis treści Encl: Załącznik
@@ -0,0 +1,21 @@+Abstract: Somari+Appendix: Gionta+Bibliography: Bibliografìa+Cc: Con còpia a+Chapter: Capìtol+Contents: Tàula+Encl: Gionta/e+Figure: Figura+Glossary: Glossari+Index: Tàula analìtica+ListOfFigures: Lista dle figure+ListOfTables: Lista dle tabele+Page: Pàgina+Part: Part+Preface: Prefassion+Proof: Dimostrassion+References: Riferiment+See: vëd+SeeAlso: vëd anche+Table: Tabela+To: Për
@@ -0,0 +1,21 @@+Abstract: Resumo+Appendix: Apêndice+Bibliography: Referências Bibliográficas+Cc: Cópia para+Chapter: Capítulo+Contents: Sumário+Encl: Anexo+Figure: Figura+Glossary: Glossário+Index: Índice Remissivo+ListOfFigures: Lista de Figuras+ListOfTables: Lista de Tabelas+Page: Página+Part: Parte+Preface: Prefácio+Proof: Demonstração+References: Referências+See: veja+SeeAlso: veja também+Table: Tabela+To: Para
@@ -0,0 +1,21 @@+Abstract: Resumo+Appendix: Apêndice+Bibliography: Bibliografia+Cc: Com cópia a+Chapter: Capítulo+Contents: Conteúdo+Encl: Anexo+Figure: Figura+Glossary: Glossário+Index: Índice+ListOfFigures: Lista de Figuras+ListOfTables: Lista de Tabelas+Page: Página+Part: Parte+Preface: Prefácio+Proof: Demonstração+References: Referências+See: ver+SeeAlso: ver também+Table: Tabela+To: Para
@@ -12,8 +12,8 @@ ListOfTables: Listă de tabele Page: Pagina Part: Partea-Preface: Prefață-Proof: Demonstrație+Preface: Prefaţă+Proof: Demonstraţie References: Bibliografie See: Vezi SeeAlso: Vezi de asemenea
@@ -3,9 +3,10 @@ Bibliography: Литература Cc: исх. Chapter: Глава-Contents: Оглавление+Contents: Содержание Encl: вкл. Figure: Рис.+Glossary: Словарь терминов Index: Предметный указатель ListOfFigures: Список иллюстраций ListOfTables: Список таблиц@@ -15,6 +16,6 @@ Proof: Доказательство References: Список литературы See: см.-SeeAlso: см. также+SeeAlso: см. также Table: Таблица To: вх.
@@ -0,0 +1,21 @@+Abstract: Čoahkkáigeassu+Appendix: Čuovus+Bibliography: Girjjálašvuohta+Cc: Kopia sáddejuvvon+Chapter: Kapihttal+Contents: Sisdoallu+Encl: Mielddus+Figure: Govus+Glossary: Sátnelistu+Index: Registtar+ListOfFigures: Govvosat+ListOfTables: Tabeallat+Page: Siidu+Part: Oassi+Preface: Ovdasátni+Proof: Duođaštus+References: Čujuhusat+See: geahča+SeeAlso: geahča maiddái+Table: Tabealla+To: Vuostáiváldi
@@ -0,0 +1,21 @@+Abstract: සංක්ෂෙපය+Appendix: උපග්රන්ථය+Bibliography: ග්රන්ථ නාමාවලිය+Cc: පිටපත්+Chapter: පරිච්ඡේදය+Contents: පටුන+Encl: ඇමුණුම+Figure: සටහන+Glossary: පදමාලාව+Index: සූචිය+ListOfFigures: සටහන් ලේඛනය+ListOfTables: වගු ලේඛනය+Page: පිට+Part: කොටස+Preface: පෙරවදන+Proof: සාධනය+References: යොමුව+See: බලනු+SeeAlso: තවද+Table: වගුව+To: වෙත
@@ -4,17 +4,17 @@ Cc: cc. Chapter: Kapitola Contents: Obsah-Encl: Prílohy-Figure: Obrázok+Encl: Príloha+Figure: Obr. Glossary: Slovník-Index: Index+Index: Register ListOfFigures: Zoznam obrázkov ListOfTables: Zoznam tabuliek-Page: Strana+Page: Str. Part: Časť-Preface: Úvod+Preface: Predhovor Proof: Dôkaz-References: Referencie+References: Literatúra See: viď SeeAlso: viď tiež Table: Tabuľka
@@ -1,8 +1,10 @@ Abstract: Përmbledhja Appendix: Shtesa Bibliography: Bibliografia+Cc: Kopja Chapter: Kapitulli-Contents: Përmbajta+Contents: Përmbajtja+Encl: Lidhja Figure: Figura Glossary: Përhasja e Fjalëve Index: Indeksi@@ -16,3 +18,4 @@ See: shiko SeeAlso: shiko dhe Table: Tabela+To: Për
@@ -0,0 +1,21 @@+Abstract: Сажетак+Appendix: Додатак+Bibliography: Библиографиjа+Cc: Копиjе+Chapter: Глава+Contents: Садржаj+Encl: Прилози+Figure: Слика+Glossary: Речник+Index: Индекс+ListOfFigures: Списак слика+ListOfTables: Списак табела+Page: страна+Part: Део+Preface: Предговор+Proof: Доказ+References: Литература+See: види+SeeAlso: видитакође+Table: Табела+To: Прима
@@ -0,0 +1,21 @@+Abstract: Sažetak+Appendix: Dodatak+Bibliography: Bibliografija+Cc: Kopije+Chapter: Glava+Contents: Sadržaj+Encl: Prilozi+Figure: Slika+Glossary: Rečnik+Index: Indeks+ListOfFigures: Spisak slika+ListOfTables: Spisak tabela+Page: strana+Part: Deo+Preface: Predgovor+Proof: Dokaz+References: Literatura+See: vidi+SeeAlso: vidi takođe+Table: Tabela+To: Prima
@@ -1,21 +0,0 @@-Abstract: Сажетак-Appendix: Додатак-Bibliography: Литература-Cc: Копије-Chapter: Глава-Contents: Садржај-Encl: Прилози-Figure: Слика-Glossary: Речник непознатих речи-Index: Регистар-ListOfFigures: Списак слика-ListOfTables: Списак табела-Page: Страна-Part: Део-Preface: Предговор-Proof: Доказ-References: Библиографија-See: Види-SeeAlso: Види такође-Table: Табела-To: Прима
@@ -1,21 +1,21 @@-Abstract: Sažetak-Appendix: Dodatak-Bibliography: Literatura-Cc: Kopije-Chapter: Glava-Contents: Sadržaj-Encl: Prilozi-Figure: Slika-Glossary: Rečnik nepoznatih reči-Index: Registar-ListOfFigures: Spisak slika-ListOfTables: Spisak tabela-Page: Strana-Part: Deo-Preface: Predgovor-Proof: Dokaz-References: Bibliografija-See: Vidi-SeeAlso: Vidi takođe-Table: Tabela-To: Prima+Abstract: Сажетак+Appendix: Додатак+Bibliography: Библиографиjа+Cc: Копиjе+Chapter: Глава+Contents: Садржаj+Encl: Прилози+Figure: Слика+Glossary: Речник+Index: Индекс+ListOfFigures: Списак слика+ListOfTables: Списак табела+Page: страна+Part: Део+Preface: Предговор+Proof: Доказ+References: Литература+See: види+SeeAlso: видитакође+Table: Табела+To: Прима
@@ -0,0 +1,11 @@+Abstract: சாராம்சம்+Appendix: பிற்சேர்க்கை+Chapter: அத்தியாயம்+Contents: உள்ளே+Figure: படம்+Index: சுட்டி+ListOfFigures: படங்களின் பட்டியல்+ListOfTables: அட்டவணை பட்டியல்+Part: பகுதி+See: பார்க்க+Table: அட்டவணை
@@ -0,0 +1,21 @@+Abstract: సారాంశం+Appendix: అదనంగా+Bibliography: గ్రంథాల జాబితా+Cc: సిసి+Chapter: అధ్యాయము+Contents: విషయాలు+Encl: ఎంక్లోజర్*+Figure: ఆకృతి+Glossary: నిఘంటువు+Index: విషయ సూచిక+ListOfFigures: ఆకృతుల జాబితా+ListOfTables: పట్టికల జాబితా+Page: పేజి+Part: భాగం+Preface: ముందుమాట+Proof: రుజువు+References: ఆధారాలు+See: చూడండి+SeeAlso: కూడా చూడండి+Table: పట్టిక+To: కి
@@ -11,7 +11,7 @@ ListOfTables: สารบัญตาราง Page: หน้า Part: ภาค-Preface: คำนำ+Preface: บทนำ Proof: พิสูจน์ References: หนังสืออ้างอิง See: ดู
@@ -0,0 +1,21 @@+Abstract: Gysgaça manysy+Appendix: Goşmaça+Bibliography: Çeşmeler+Cc: Iberilenler+Chapter: Bap+Contents: Mazmuny+Encl: Goşmaça+Figure: Surat+Glossary: Sözlük+Index: Indeks+ListOfFigures: Suratlaryň sanawy+ListOfTables: Tablisalaryň sanawy+Page: Sahypa+Part: Bölüm+Preface: Sözbaşy+Proof: Delil+References: Çeşmeler+See: ser.+SeeAlso: şuňa-da ser.+Table: Tablisa+To: Kime
@@ -17,6 +17,5 @@ References: Kaynaklar See: bkz. SeeAlso: ayrıca bkz.-Subject: İlgili Table: Tablo To: Alıcı
@@ -0,0 +1,22 @@+Abstract: Резюме+Appendix: Додаток+Bibliography: Бібліографія+Cc: Розповсюджувач+Chapter: Розділ+Contents: Зміст+Encl: Додаток(и)+Figure: Ілюстрація+Glossary: Глосарій+Index: Індекс+Listing: Список+ListOfFigures: Список рисунків+ListOfTables: Список таблиць+Page: Сторінка+Part: Частина+Preface: Передмова+Proof: Докази+References: Література+See: див.+SeeAlso: див. також+Table: Таблиця+To: До
@@ -0,0 +1,21 @@+Abstract: ئابستراكت+Appendix: قوشۇمچە+Bibliography: پايدىلانما+Cc: باشقا تاپشۇرۇۋالغۇچى+Chapter: باب+Contents: مۇندەرىجە+Encl: قوشۇمچە ھۆججەت+Figure: رەسىم+Glossary: لۇغەت+Index: ئىندېكىس+ListOfFigures: رەسىملەر+ListOfTables: جەدۋەللەر+Page: بەت+Part: قىسىم+Preface: كىرىش سۆز+Proof: ئىسپات+References: پايدىلانما+See: قاراڭ+SeeAlso: ئايرىم قاراڭ+Table: جەدۋەل+To: تاپشۇرۇۋالغۇچى
@@ -16,6 +16,6 @@ Proof: Доведення References: Література See: див.-SeeAlso: див. також+SeeAlso: див. також Table: Табл. To: До
@@ -1,22 +1,21 @@-Abstract: ﻢﻠﺨّﺻ-Appendix: ﺾﻣیﻡہ-Bibliography: کﺕﺎﺑیﺎﺗ-Cc: ﻦﻘﻟ-Chapter: ﺏﺎﺑ-Contents: ﻑہﺮﺴﺗ ﻊﻧﻭﺎﻧﺎﺗ-Encl: ﻢﻨﺴﻟک-Figure: ﺶﻜﻟ-Glossary: ﻞﻐﺗ-Index: ﺎﺷﺍﺭیہ-ListOfFigures: ﻑہﺮﺴﺗ ﺎﺷکﺎﻟ-ListOfTables: ﻑہﺮﺴﺗ ﺝﺩﺍﻮﻟ-Page: ﺺﻔﺣہ-Part: ﺢﺻّہ-Preface: ﺩیﺏﺍچہ-Proof: ﺚﺑﻮﺗ-References: ﺡﻭﺎﻟہ ﺝﺎﺗ-Section: ﻒﺼﻟ-See: ﻡﻼﺤﻇہ ہﻭ-SeeAlso: ﺍیﺽﺍً-Table: ﺝﺩﻮﻟ-To: ﺐﻣﻼﺤﻇہ+Abstract: ملخّص+Appendix: ضمیمہ+Bibliography: کتابیات+Cc: نقل+Chapter: باب+Contents: فہرست عنوانات+Encl: منسلک+Figure: شكل+Glossary: لغت+Index: اشاریہ+ListOfFigures: فہرست اشکال+ListOfTables: فہرست جداول+Page: صفحہ+Part: حصّہ+Preface: دیباچہ+Proof: ثبوت+References: حوالہ جات+See: ملاحظہ ہو+SeeAlso: ایضاً+Table: جدول+To: بملاحظہ
@@ -1,21 +1,21 @@ Abstract: Tóm tắt nội dung-Also: Xem thêm Appendix: Phụ lục-Bib: Tài liệu tham khảo+Bibliography: Tài liệu tham khảo Cc: Cùng gửi Chapter: Chương Contents: Mục lục Encl: Kèm theo Figure: Hình Glossary: Từ điển chú giải-Headto: Gửi Index: Chỉ mục-Listfigure: Danh sách hình vẽ-Listtable: Danh sách bẳng+ListOfFigures: Danh sách hình vẽ+ListOfTables: Danh sách bảng Page: Trang Part: Phần Preface: Lời nói đầu Proof: Chứng minh References: Tài liệu See: Xem-Table: Bẳng+SeeAlso: Xem thêm+Table: Bảng+To: Gửi
@@ -1,44 +0,0 @@--- we use preloaded text to get a UTF-8 aware 'upper' function-local text = require('text')---- capitalize level 1 headers-function Header(el)- if el.level == 1 then- return pandoc.walk_block(el, {- Str = function(el)- return pandoc.Str(text.upper(el.text))- end })- end-end---- For portability with mandoc, which doesn't allow man commands--- inside table cells, we convert all tables to code blocks.-function Table(el)- local rendered = pandoc.write(pandoc.Pandoc({el}), "plain")- local adjusted = rendered -- tame grid table lines- :gsub("%+([=:][=:]+)",- function(s)- return " " .. string.rep("-", #s - 1)- end)- :gsub("(%+[-:][-:]+)",- function(s)- return ""- end)- :gsub("%+\n","\n")- :gsub("\n| ","\n|")- :gsub("|","")- return { pandoc.RawBlock("man", ".RS -14n"),- pandoc.CodeBlock(adjusted),- pandoc.RawBlock("man", ".RE") }-end----- replace links with link text-function Link(el)- return el.content-end---- remove notes-function Note(el)- return {}-end
@@ -1,8040 +0,0 @@-.\" Automatically generated by Pandoc 2.19-.\"-.\" Define V font for inline verbatim, using C font in formats-.\" that render this, and otherwise B font.-.ie "\f[CB]x\f[]"x" \{\-. ftr V B-. ftr VI BI-. ftr VB B-. ftr VBI BI-.\}-.el \{\-. ftr V CR-. ftr VI CI-. ftr VB CB-. ftr VBI CBI-.\}-.TH "Pandoc User\[cq]s Guide" "" "August 22, 2022" "pandoc 2.19.2" ""-.hy-.SH NAME-pandoc - general markup converter-.SH SYNOPSIS-.PP-\f[V]pandoc\f[R] [\f[I]options\f[R]] [\f[I]input-file\f[R]]\&...-.SH DESCRIPTION-.PP-Pandoc is a Haskell library for converting from one markup format to-another, and a command-line tool that uses this library.-.PP-Pandoc can convert between numerous markup and word processing formats,-including, but not limited to, various flavors of Markdown, HTML, LaTeX-and Word docx.-For the full lists of input and output formats, see the \f[V]--from\f[R]-and \f[V]--to\f[R] options below.-Pandoc can also produce PDF output: see creating a PDF, below.-.PP-Pandoc\[cq]s enhanced version of Markdown includes syntax for tables,-definition lists, metadata blocks, footnotes, citations, math, and much-more.-See below under Pandoc\[cq]s Markdown.-.PP-Pandoc has a modular design: it consists of a set of readers, which-parse text in a given format and produce a native representation of the-document (an \f[I]abstract syntax tree\f[R] or AST), and a set of-writers, which convert this native representation into a target format.-Thus, adding an input or output format requires only adding a reader or-writer.-Users can also run custom pandoc filters to modify the intermediate AST.-.PP-Because pandoc\[cq]s intermediate representation of a document is less-expressive than many of the formats it converts between, one should not-expect perfect conversions between every format and every other.-Pandoc attempts to preserve the structural elements of a document, but-not formatting details such as margin size.-And some document elements, such as complex tables, may not fit into-pandoc\[cq]s simple document model.-While conversions from pandoc\[cq]s Markdown to all formats aspire to be-perfect, conversions from formats more expressive than pandoc\[cq]s-Markdown can be expected to be lossy.-.SS Using pandoc-.PP-If no \f[I]input-files\f[R] are specified, input is read from-\f[I]stdin\f[R].-Output goes to \f[I]stdout\f[R] by default.-For output to a file, use the \f[V]-o\f[R] option:-.IP-.nf-\f[C]-pandoc -o output.html input.txt-\f[R]-.fi-.PP-By default, pandoc produces a document fragment.-To produce a standalone document (e.g.\ a valid HTML file including-\f[V]<head>\f[R] and \f[V]<body>\f[R]), use the \f[V]-s\f[R] or-\f[V]--standalone\f[R] flag:-.IP-.nf-\f[C]-pandoc -s -o output.html input.txt-\f[R]-.fi-.PP-For more information on how standalone documents are produced, see-Templates below.-.PP-If multiple input files are given, pandoc will concatenate them all-(with blank lines between them) before parsing.-(Use \f[V]--file-scope\f[R] to parse files individually.)-.SS Specifying formats-.PP-The format of the input and output can be specified explicitly using-command-line options.-The input format can be specified using the \f[V]-f/--from\f[R] option,-the output format using the \f[V]-t/--to\f[R] option.-Thus, to convert \f[V]hello.txt\f[R] from Markdown to LaTeX, you could-type:-.IP-.nf-\f[C]-pandoc -f markdown -t latex hello.txt-\f[R]-.fi-.PP-To convert \f[V]hello.html\f[R] from HTML to Markdown:-.IP-.nf-\f[C]-pandoc -f html -t markdown hello.html-\f[R]-.fi-.PP-Supported input and output formats are listed below under Options (see-\f[V]-f\f[R] for input formats and \f[V]-t\f[R] for output formats).-You can also use \f[V]pandoc --list-input-formats\f[R] and-\f[V]pandoc --list-output-formats\f[R] to print lists of supported-formats.-.PP-If the input or output format is not specified explicitly, pandoc will-attempt to guess it from the extensions of the filenames.-Thus, for example,-.IP-.nf-\f[C]-pandoc -o hello.tex hello.txt-\f[R]-.fi-.PP-will convert \f[V]hello.txt\f[R] from Markdown to LaTeX.-If no output file is specified (so that output goes to-\f[I]stdout\f[R]), or if the output file\[cq]s extension is unknown, the-output format will default to HTML.-If no input file is specified (so that input comes from-\f[I]stdin\f[R]), or if the input files\[cq] extensions are unknown, the-input format will be assumed to be Markdown.-.SS Character encoding-.PP-Pandoc uses the UTF-8 character encoding for both input and output.-If your local character encoding is not UTF-8, you should pipe input and-output through \f[V]iconv\f[R]:-.IP-.nf-\f[C]-iconv -t utf-8 input.txt | pandoc | iconv -f utf-8-\f[R]-.fi-.PP-Note that in some output formats (such as HTML, LaTeX, ConTeXt, RTF,-OPML, DocBook, and Texinfo), information about the character encoding is-included in the document header, which will only be included if you use-the \f[V]-s/--standalone\f[R] option.-.SS Creating a PDF-.PP-To produce a PDF, specify an output file with a \f[V].pdf\f[R]-extension:-.IP-.nf-\f[C]-pandoc test.txt -o test.pdf-\f[R]-.fi-.PP-By default, pandoc will use LaTeX to create the PDF, which requires that-a LaTeX engine be installed (see \f[V]--pdf-engine\f[R] below).-Alternatively, pandoc can use ConTeXt, roff ms, or HTML as an-intermediate format.-To do this, specify an output file with a \f[V].pdf\f[R] extension, as-before, but add the \f[V]--pdf-engine\f[R] option or-\f[V]-t context\f[R], \f[V]-t html\f[R], or \f[V]-t ms\f[R] to the-command line.-The tool used to generate the PDF from the intermediate format may be-specified using \f[V]--pdf-engine\f[R].-.PP-You can control the PDF style using variables, depending on the-intermediate format used: see variables for LaTeX, variables for-ConTeXt, variables for \f[V]wkhtmltopdf\f[R], variables for ms.-When HTML is used as an intermediate format, the output can be styled-using \f[V]--css\f[R].-.PP-To debug the PDF creation, it can be useful to look at the intermediate-representation: instead of \f[V]-o test.pdf\f[R], use for example-\f[V]-s -o test.tex\f[R] to output the generated LaTeX.-You can then test it with \f[V]pdflatex test.tex\f[R].-.PP-When using LaTeX, the following packages need to be available (they are-included with all recent versions of TeX Live): \f[V]amsfonts\f[R],-\f[V]amsmath\f[R], \f[V]lm\f[R], \f[V]unicode-math\f[R],-\f[V]iftex\f[R], \f[V]listings\f[R] (if the \f[V]--listings\f[R] option-is used), \f[V]fancyvrb\f[R], \f[V]longtable\f[R], \f[V]booktabs\f[R],-\f[V]graphicx\f[R] (if the document contains images),-\f[V]hyperref\f[R], \f[V]xcolor\f[R], \f[V]ulem\f[R], \f[V]geometry\f[R]-(with the \f[V]geometry\f[R] variable set), \f[V]setspace\f[R] (with-\f[V]linestretch\f[R]), and \f[V]babel\f[R] (with \f[V]lang\f[R]).-If \f[V]CJKmainfont\f[R] is set, \f[V]xeCJK\f[R] is needed.-The use of \f[V]xelatex\f[R] or \f[V]lualatex\f[R] as the PDF engine-requires \f[V]fontspec\f[R].-\f[V]lualatex\f[R] uses \f[V]selnolig\f[R].-\f[V]xelatex\f[R] uses \f[V]bidi\f[R] (with the \f[V]dir\f[R] variable-set).-If the \f[V]mathspec\f[R] variable is set, \f[V]xelatex\f[R] will use-\f[V]mathspec\f[R] instead of \f[V]unicode-math\f[R].-The \f[V]upquote\f[R] and \f[V]microtype\f[R] packages are used if-available, and \f[V]csquotes\f[R] will be used for typography if the-\f[V]csquotes\f[R] variable or metadata field is set to a true value.-The \f[V]natbib\f[R], \f[V]biblatex\f[R], \f[V]bibtex\f[R], and-\f[V]biber\f[R] packages can optionally be used for citation rendering.-The following packages will be used to improve output quality if-present, but pandoc does not require them to be present:-\f[V]upquote\f[R] (for straight quotes in verbatim environments),-\f[V]microtype\f[R] (for better spacing adjustments), \f[V]parskip\f[R]-(for better inter-paragraph spaces), \f[V]xurl\f[R] (for better line-breaks in URLs), \f[V]bookmark\f[R] (for better PDF bookmarks), and-\f[V]footnotehyper\f[R] or \f[V]footnote\f[R] (to allow footnotes in-tables).-.SS Reading from the Web-.PP-Instead of an input file, an absolute URI may be given.-In this case pandoc will fetch the content using HTTP:-.IP-.nf-\f[C]-pandoc -f html -t markdown https://www.fsf.org-\f[R]-.fi-.PP-It is possible to supply a custom User-Agent string or other header when-requesting a document from a URL:-.IP-.nf-\f[C]-pandoc -f html -t markdown --request-header User-Agent:\[dq]Mozilla/5.0\[dq] \[rs]- https://www.fsf.org-\f[R]-.fi-.SH OPTIONS-.SS General options-.TP-\f[V]-f\f[R] \f[I]FORMAT\f[R], \f[V]-r\f[R] \f[I]FORMAT\f[R], \f[V]--from=\f[R]\f[I]FORMAT\f[R], \f[V]--read=\f[R]\f[I]FORMAT\f[R]-Specify input format.-\f[I]FORMAT\f[R] can be:-.RS-.IP \[bu] 2-\f[V]bibtex\f[R] (BibTeX bibliography)-.IP \[bu] 2-\f[V]biblatex\f[R] (BibLaTeX bibliography)-.IP \[bu] 2-\f[V]commonmark\f[R] (CommonMark Markdown)-.IP \[bu] 2-\f[V]commonmark_x\f[R] (CommonMark Markdown with extensions)-.IP \[bu] 2-\f[V]creole\f[R] (Creole 1.0)-.IP \[bu] 2-\f[V]csljson\f[R] (CSL JSON bibliography)-.IP \[bu] 2-\f[V]csv\f[R] (CSV table)-.IP \[bu] 2-\f[V]tsv\f[R] (TSV table)-.IP \[bu] 2-\f[V]docbook\f[R] (DocBook)-.IP \[bu] 2-\f[V]docx\f[R] (Word docx)-.IP \[bu] 2-\f[V]dokuwiki\f[R] (DokuWiki markup)-.IP \[bu] 2-\f[V]endnotexml\f[R] (EndNote XML bibliography)-.IP \[bu] 2-\f[V]epub\f[R] (EPUB)-.IP \[bu] 2-\f[V]fb2\f[R] (FictionBook2 e-book)-.IP \[bu] 2-\f[V]gfm\f[R] (GitHub-Flavored Markdown), or the deprecated and less-accurate \f[V]markdown_github\f[R]; use \f[V]markdown_github\f[R] only-if you need extensions not supported in \f[V]gfm\f[R].-.IP \[bu] 2-\f[V]haddock\f[R] (Haddock markup)-.IP \[bu] 2-\f[V]html\f[R] (HTML)-.IP \[bu] 2-\f[V]ipynb\f[R] (Jupyter notebook)-.IP \[bu] 2-\f[V]jats\f[R] (JATS XML)-.IP \[bu] 2-\f[V]jira\f[R] (Jira/Confluence wiki markup)-.IP \[bu] 2-\f[V]json\f[R] (JSON version of native AST)-.IP \[bu] 2-\f[V]latex\f[R] (LaTeX)-.IP \[bu] 2-\f[V]markdown\f[R] (Pandoc\[cq]s Markdown)-.IP \[bu] 2-\f[V]markdown_mmd\f[R] (MultiMarkdown)-.IP \[bu] 2-\f[V]markdown_phpextra\f[R] (PHP Markdown Extra)-.IP \[bu] 2-\f[V]markdown_strict\f[R] (original unextended Markdown)-.IP \[bu] 2-\f[V]mediawiki\f[R] (MediaWiki markup)-.IP \[bu] 2-\f[V]man\f[R] (roff man)-.IP \[bu] 2-\f[V]muse\f[R] (Muse)-.IP \[bu] 2-\f[V]native\f[R] (native Haskell)-.IP \[bu] 2-\f[V]odt\f[R] (ODT)-.IP \[bu] 2-\f[V]opml\f[R] (OPML)-.IP \[bu] 2-\f[V]org\f[R] (Emacs Org mode)-.IP \[bu] 2-\f[V]ris\f[R] (RIS bibliography)-.IP \[bu] 2-\f[V]rtf\f[R] (Rich Text Format)-.IP \[bu] 2-\f[V]rst\f[R] (reStructuredText)-.IP \[bu] 2-\f[V]t2t\f[R] (txt2tags)-.IP \[bu] 2-\f[V]textile\f[R] (Textile)-.IP \[bu] 2-\f[V]tikiwiki\f[R] (TikiWiki markup)-.IP \[bu] 2-\f[V]twiki\f[R] (TWiki markup)-.IP \[bu] 2-\f[V]vimwiki\f[R] (Vimwiki)-.IP \[bu] 2-the path of a custom Lua reader, see Custom readers and writers below-.PP-Extensions can be individually enabled or disabled by appending-\f[V]+EXTENSION\f[R] or \f[V]-EXTENSION\f[R] to the format name.-See Extensions below, for a list of extensions and their names.-See \f[V]--list-input-formats\f[R] and \f[V]--list-extensions\f[R],-below.-.RE-.TP-\f[V]-t\f[R] \f[I]FORMAT\f[R], \f[V]-w\f[R] \f[I]FORMAT\f[R], \f[V]--to=\f[R]\f[I]FORMAT\f[R], \f[V]--write=\f[R]\f[I]FORMAT\f[R]-Specify output format.-\f[I]FORMAT\f[R] can be:-.RS-.IP \[bu] 2-\f[V]asciidoc\f[R] (AsciiDoc) or \f[V]asciidoctor\f[R] (AsciiDoctor)-.IP \[bu] 2-\f[V]beamer\f[R] (LaTeX beamer slide show)-.IP \[bu] 2-\f[V]bibtex\f[R] (BibTeX bibliography)-.IP \[bu] 2-\f[V]biblatex\f[R] (BibLaTeX bibliography)-.IP \[bu] 2-\f[V]commonmark\f[R] (CommonMark Markdown)-.IP \[bu] 2-\f[V]commonmark_x\f[R] (CommonMark Markdown with extensions)-.IP \[bu] 2-\f[V]context\f[R] (ConTeXt)-.IP \[bu] 2-\f[V]csljson\f[R] (CSL JSON bibliography)-.IP \[bu] 2-\f[V]docbook\f[R] or \f[V]docbook4\f[R] (DocBook 4)-.IP \[bu] 2-\f[V]docbook5\f[R] (DocBook 5)-.IP \[bu] 2-\f[V]docx\f[R] (Word docx)-.IP \[bu] 2-\f[V]dokuwiki\f[R] (DokuWiki markup)-.IP \[bu] 2-\f[V]epub\f[R] or \f[V]epub3\f[R] (EPUB v3 book)-.IP \[bu] 2-\f[V]epub2\f[R] (EPUB v2)-.IP \[bu] 2-\f[V]fb2\f[R] (FictionBook2 e-book)-.IP \[bu] 2-\f[V]gfm\f[R] (GitHub-Flavored Markdown), or the deprecated and less-accurate \f[V]markdown_github\f[R]; use \f[V]markdown_github\f[R] only-if you need extensions not supported in \f[V]gfm\f[R].-.IP \[bu] 2-\f[V]haddock\f[R] (Haddock markup)-.IP \[bu] 2-\f[V]html\f[R] or \f[V]html5\f[R] (HTML, i.e.\ HTML5/XHTML polyglot-markup)-.IP \[bu] 2-\f[V]html4\f[R] (XHTML 1.0 Transitional)-.IP \[bu] 2-\f[V]icml\f[R] (InDesign ICML)-.IP \[bu] 2-\f[V]ipynb\f[R] (Jupyter notebook)-.IP \[bu] 2-\f[V]jats_archiving\f[R] (JATS XML, Archiving and Interchange Tag Set)-.IP \[bu] 2-\f[V]jats_articleauthoring\f[R] (JATS XML, Article Authoring Tag Set)-.IP \[bu] 2-\f[V]jats_publishing\f[R] (JATS XML, Journal Publishing Tag Set)-.IP \[bu] 2-\f[V]jats\f[R] (alias for \f[V]jats_archiving\f[R])-.IP \[bu] 2-\f[V]jira\f[R] (Jira/Confluence wiki markup)-.IP \[bu] 2-\f[V]json\f[R] (JSON version of native AST)-.IP \[bu] 2-\f[V]latex\f[R] (LaTeX)-.IP \[bu] 2-\f[V]man\f[R] (roff man)-.IP \[bu] 2-\f[V]markdown\f[R] (Pandoc\[cq]s Markdown)-.IP \[bu] 2-\f[V]markdown_mmd\f[R] (MultiMarkdown)-.IP \[bu] 2-\f[V]markdown_phpextra\f[R] (PHP Markdown Extra)-.IP \[bu] 2-\f[V]markdown_strict\f[R] (original unextended Markdown)-.IP \[bu] 2-\f[V]markua\f[R] (Markua)-.IP \[bu] 2-\f[V]mediawiki\f[R] (MediaWiki markup)-.IP \[bu] 2-\f[V]ms\f[R] (roff ms)-.IP \[bu] 2-\f[V]muse\f[R] (Muse)-.IP \[bu] 2-\f[V]native\f[R] (native Haskell)-.IP \[bu] 2-\f[V]odt\f[R] (OpenOffice text document)-.IP \[bu] 2-\f[V]opml\f[R] (OPML)-.IP \[bu] 2-\f[V]opendocument\f[R] (OpenDocument)-.IP \[bu] 2-\f[V]org\f[R] (Emacs Org mode)-.IP \[bu] 2-\f[V]pdf\f[R] (PDF)-.IP \[bu] 2-\f[V]plain\f[R] (plain text)-.IP \[bu] 2-\f[V]pptx\f[R] (PowerPoint slide show)-.IP \[bu] 2-\f[V]rst\f[R] (reStructuredText)-.IP \[bu] 2-\f[V]rtf\f[R] (Rich Text Format)-.IP \[bu] 2-\f[V]texinfo\f[R] (GNU Texinfo)-.IP \[bu] 2-\f[V]textile\f[R] (Textile)-.IP \[bu] 2-\f[V]slideous\f[R] (Slideous HTML and JavaScript slide show)-.IP \[bu] 2-\f[V]slidy\f[R] (Slidy HTML and JavaScript slide show)-.IP \[bu] 2-\f[V]dzslides\f[R] (DZSlides HTML5 + JavaScript slide show)-.IP \[bu] 2-\f[V]revealjs\f[R] (reveal.js HTML5 + JavaScript slide show)-.IP \[bu] 2-\f[V]s5\f[R] (S5 HTML and JavaScript slide show)-.IP \[bu] 2-\f[V]tei\f[R] (TEI Simple)-.IP \[bu] 2-\f[V]xwiki\f[R] (XWiki markup)-.IP \[bu] 2-\f[V]zimwiki\f[R] (ZimWiki markup)-.IP \[bu] 2-the path of a custom Lua writer, see Custom readers and writers below-.PP-Note that \f[V]odt\f[R], \f[V]docx\f[R], \f[V]epub\f[R], and-\f[V]pdf\f[R] output will not be directed to \f[I]stdout\f[R] unless-forced with \f[V]-o -\f[R].-.PP-Extensions can be individually enabled or disabled by appending-\f[V]+EXTENSION\f[R] or \f[V]-EXTENSION\f[R] to the format name.-See Extensions below, for a list of extensions and their names.-See \f[V]--list-output-formats\f[R] and \f[V]--list-extensions\f[R],-below.-.RE-.TP-\f[V]-o\f[R] \f[I]FILE\f[R], \f[V]--output=\f[R]\f[I]FILE\f[R]-Write output to \f[I]FILE\f[R] instead of \f[I]stdout\f[R].-If \f[I]FILE\f[R] is \f[V]-\f[R], output will go to \f[I]stdout\f[R],-even if a non-textual format (\f[V]docx\f[R], \f[V]odt\f[R],-\f[V]epub2\f[R], \f[V]epub3\f[R]) is specified.-.TP-\f[V]--data-dir=\f[R]\f[I]DIRECTORY\f[R]-Specify the user data directory to search for pandoc data files.-If this option is not specified, the default user data directory will be-used.-On *nix and macOS systems this will be the \f[V]pandoc\f[R] subdirectory-of the XDG data directory (by default, \f[V]$HOME/.local/share\f[R],-overridable by setting the \f[V]XDG_DATA_HOME\f[R] environment-variable).-If that directory does not exist and \f[V]$HOME/.pandoc\f[R] exists, it-will be used (for backwards compatibility).-On Windows the default user data directory is-\f[V]C:\[rs]Users\[rs]USERNAME\[rs]AppData\[rs]Roaming\[rs]pandoc\f[R].-You can find the default user data directory on your system by looking-at the output of \f[V]pandoc --version\f[R].-Data files placed in this directory (for example,-\f[V]reference.odt\f[R], \f[V]reference.docx\f[R], \f[V]epub.css\f[R],-\f[V]templates\f[R]) will override pandoc\[cq]s normal defaults.-.TP-\f[V]-d\f[R] \f[I]FILE\f[R], \f[V]--defaults=\f[R]\f[I]FILE\f[R]-Specify a set of default option settings.-\f[I]FILE\f[R] is a YAML file whose fields correspond to command-line-option settings.-All options for document conversion, including input and output files,-can be set using a defaults file.-The file will be searched for first in the working directory, and then-in the \f[V]defaults\f[R] subdirectory of the user data directory (see-\f[V]--data-dir\f[R]).-The \f[V].yaml\f[R] extension may be omitted.-See the section Defaults files for more information on the file format.-Settings from the defaults file may be overridden or extended by-subsequent options on the command line.-.TP-\f[V]--bash-completion\f[R]-Generate a bash completion script.-To enable bash completion with pandoc, add this to your-\f[V].bashrc\f[R]:-.RS-.IP-.nf-\f[C]-eval \[dq]$(pandoc --bash-completion)\[dq]-\f[R]-.fi-.RE-.TP-\f[V]--verbose\f[R]-Give verbose debugging output.-.TP-\f[V]--quiet\f[R]-Suppress warning messages.-.TP-\f[V]--fail-if-warnings\f[R]-Exit with error status if there are any warnings.-.TP-\f[V]--log=\f[R]\f[I]FILE\f[R]-Write log messages in machine-readable JSON format to \f[I]FILE\f[R].-All messages above DEBUG level will be written, regardless of verbosity-settings (\f[V]--verbose\f[R], \f[V]--quiet\f[R]).-.TP-\f[V]--list-input-formats\f[R]-List supported input formats, one per line.-.TP-\f[V]--list-output-formats\f[R]-List supported output formats, one per line.-.TP-\f[V]--list-extensions\f[R][\f[V]=\f[R]\f[I]FORMAT\f[R]]-List supported extensions for \f[I]FORMAT\f[R], one per line, preceded-by a \f[V]+\f[R] or \f[V]-\f[R] indicating whether it is enabled by-default in \f[I]FORMAT\f[R].-If \f[I]FORMAT\f[R] is not specified, defaults for pandoc\[cq]s Markdown-are given.-.TP-\f[V]--list-highlight-languages\f[R]-List supported languages for syntax highlighting, one per line.-.TP-\f[V]--list-highlight-styles\f[R]-List supported styles for syntax highlighting, one per line.-See \f[V]--highlight-style\f[R].-.TP-\f[V]-v\f[R], \f[V]--version\f[R]-Print version.-.TP-\f[V]-h\f[R], \f[V]--help\f[R]-Show usage message.-.SS Reader options-.TP-\f[V]--shift-heading-level-by=\f[R]\f[I]NUMBER\f[R]-Shift heading levels by a positive or negative integer.-For example, with \f[V]--shift-heading-level-by=-1\f[R], level 2-headings become level 1 headings, and level 3 headings become level 2-headings.-Headings cannot have a level less than 1, so a heading that would be-shifted below level 1 becomes a regular paragraph.-Exception: with a shift of -N, a level-N heading at the beginning of the-document replaces the metadata title.-\f[V]--shift-heading-level-by=-1\f[R] is a good choice when converting-HTML or Markdown documents that use an initial level-1 heading for the-document title and level-2+ headings for sections.-\f[V]--shift-heading-level-by=1\f[R] may be a good choice for converting-Markdown documents that use level-1 headings for sections to HTML, since-pandoc uses a level-1 heading to render the document title.-.TP-\f[V]--base-header-level=\f[R]\f[I]NUMBER\f[R]-\f[I]Deprecated.-Use \f[VI]--shift-heading-level-by\f[I]=X instead, where X = NUMBER --1.\f[R] Specify the base level for headings (defaults to 1).-.TP-\f[V]--strip-empty-paragraphs\f[R]-\f[I]Deprecated.-Use the \f[VI]+empty_paragraphs\f[I] extension instead.\f[R] Ignore-paragraphs with no content.-This option is useful for converting word processing documents where-users have used empty paragraphs to create inter-paragraph space.-.TP-\f[V]--indented-code-classes=\f[R]\f[I]CLASSES\f[R]-Specify classes to use for indented code blocks\[en]for example,-\f[V]perl,numberLines\f[R] or \f[V]haskell\f[R].-Multiple classes may be separated by spaces or commas.-.TP-\f[V]--default-image-extension=\f[R]\f[I]EXTENSION\f[R]-Specify a default extension to use when image paths/URLs have no-extension.-This allows you to use the same source for formats that require-different kinds of images.-Currently this option only affects the Markdown and LaTeX readers.-.TP-\f[V]--file-scope\f[R]-Parse each file individually before combining for multifile documents.-This will allow footnotes in different files with the same identifiers-to work as expected.-If this option is set, footnotes and links will not work across files.-Reading binary files (docx, odt, epub) implies \f[V]--file-scope\f[R].-.TP-\f[V]-F\f[R] \f[I]PROGRAM\f[R], \f[V]--filter=\f[R]\f[I]PROGRAM\f[R]-Specify an executable to be used as a filter transforming the pandoc AST-after the input is parsed and before the output is written.-The executable should read JSON from stdin and write JSON to stdout.-The JSON must be formatted like pandoc\[cq]s own JSON input and output.-The name of the output format will be passed to the filter as the first-argument.-Hence,-.RS-.IP-.nf-\f[C]-pandoc --filter ./caps.py -t latex-\f[R]-.fi-.PP-is equivalent to-.IP-.nf-\f[C]-pandoc -t json | ./caps.py latex | pandoc -f json -t latex-\f[R]-.fi-.PP-The latter form may be useful for debugging filters.-.PP-Filters may be written in any language.-\f[V]Text.Pandoc.JSON\f[R] exports \f[V]toJSONFilter\f[R] to facilitate-writing filters in Haskell.-Those who would prefer to write filters in python can use the module-\f[V]pandocfilters\f[R], installable from PyPI.-There are also pandoc filter libraries in PHP, perl, and-JavaScript/node.js.-.PP-In order of preference, pandoc will look for filters in-.IP "1." 3-a specified full or relative path (executable or non-executable),-.IP "2." 3-\f[V]$DATADIR/filters\f[R] (executable or non-executable) where-\f[V]$DATADIR\f[R] is the user data directory (see \f[V]--data-dir\f[R],-above),-.IP "3." 3-\f[V]$PATH\f[R] (executable only).-.PP-Filters, Lua-filters, and citeproc processing are applied in the order-specified on the command line.-.RE-.TP-\f[V]-L\f[R] \f[I]SCRIPT\f[R], \f[V]--lua-filter=\f[R]\f[I]SCRIPT\f[R]-Transform the document in a similar fashion as JSON filters (see-\f[V]--filter\f[R]), but use pandoc\[cq]s built-in Lua filtering system.-The given Lua script is expected to return a list of Lua filters which-will be applied in order.-Each Lua filter must contain element-transforming functions indexed by-the name of the AST element on which the filter function should be-applied.-.RS-.PP-The \f[V]pandoc\f[R] Lua module provides helper functions for element-creation.-It is always loaded into the script\[cq]s Lua environment.-.PP-See the Lua filters documentation for further details.-.PP-In order of preference, pandoc will look for Lua filters in-.IP "1." 3-a specified full or relative path,-.IP "2." 3-\f[V]$DATADIR/filters\f[R] where \f[V]$DATADIR\f[R] is the user data-directory (see \f[V]--data-dir\f[R], above).-.PP-Filters, Lua filters, and citeproc processing are applied in the order-specified on the command line.-.RE-.TP-\f[V]-M\f[R] \f[I]KEY\f[R][\f[V]=\f[R]\f[I]VAL\f[R]], \f[V]--metadata=\f[R]\f[I]KEY\f[R][\f[V]:\f[R]\f[I]VAL\f[R]]-Set the metadata field \f[I]KEY\f[R] to the value \f[I]VAL\f[R].-A value specified on the command line overrides a value specified in the-document using YAML metadata blocks.-Values will be parsed as YAML boolean or string values.-If no value is specified, the value will be treated as Boolean true.-Like \f[V]--variable\f[R], \f[V]--metadata\f[R] causes template-variables to be set.-But unlike \f[V]--variable\f[R], \f[V]--metadata\f[R] affects the-metadata of the underlying document (which is accessible from filters-and may be printed in some output formats) and metadata values will be-escaped when inserted into the template.-.TP-\f[V]--metadata-file=\f[R]\f[I]FILE\f[R]-Read metadata from the supplied YAML (or JSON) file.-This option can be used with every input format, but string scalars in-the YAML file will always be parsed as Markdown.-(If the input format is Markdown or a Markdown variant, then the same-variant will be used to parse the metadata file; if it is a non-Markdown-format, pandoc\[cq]s default Markdown extensions will be used.)-This option can be used repeatedly to include multiple metadata files;-values in files specified later on the command line will be preferred-over those specified in earlier files.-Metadata values specified inside the document, or by using \f[V]-M\f[R],-overwrite values specified with this option.-The file will be searched for first in the working directory, and then-in the \f[V]metadata\f[R] subdirectory of the user data directory (see-\f[V]--data-dir\f[R]).-.TP-\f[V]-p\f[R], \f[V]--preserve-tabs\f[R]-Preserve tabs instead of converting them to spaces.-(By default, pandoc converts tabs to spaces before parsing its input.)-Note that this will only affect tabs in literal code spans and code-blocks.-Tabs in regular text are always treated as spaces.-.TP-\f[V]--tab-stop=\f[R]\f[I]NUMBER\f[R]-Specify the number of spaces per tab (default is 4).-.TP-\f[V]--track-changes=accept\f[R]|\f[V]reject\f[R]|\f[V]all\f[R]-Specifies what to do with insertions, deletions, and comments produced-by the MS Word \[lq]Track Changes\[rq] feature.-\f[V]accept\f[R] (the default) processes all the insertions and-deletions.-\f[V]reject\f[R] ignores them.-Both \f[V]accept\f[R] and \f[V]reject\f[R] ignore comments.-\f[V]all\f[R] includes all insertions, deletions, and comments, wrapped-in spans with \f[V]insertion\f[R], \f[V]deletion\f[R],-\f[V]comment-start\f[R], and \f[V]comment-end\f[R] classes,-respectively.-The author and time of change is included.-\f[V]all\f[R] is useful for scripting: only accepting changes from a-certain reviewer, say, or before a certain date.-If a paragraph is inserted or deleted, \f[V]track-changes=all\f[R]-produces a span with the class-\f[V]paragraph-insertion\f[R]/\f[V]paragraph-deletion\f[R] before the-affected paragraph break.-This option only affects the docx reader.-.TP-\f[V]--extract-media=\f[R]\f[I]DIR\f[R]-Extract images and other media contained in or linked from the source-document to the path \f[I]DIR\f[R], creating it if necessary, and adjust-the images references in the document so they point to the extracted-files.-Media are downloaded, read from the file system, or extracted from a-binary container (e.g.\ docx), as needed.-The original file paths are used if they are relative paths not-containing \f[V]..\f[R].-Otherwise filenames are constructed from the SHA1 hash of the contents.-.TP-\f[V]--abbreviations=\f[R]\f[I]FILE\f[R]-Specifies a custom abbreviations file, with abbreviations one to a line.-If this option is not specified, pandoc will read the data file-\f[V]abbreviations\f[R] from the user data directory or fall back on a-system default.-To see the system default, use-\f[V]pandoc --print-default-data-file=abbreviations\f[R].-The only use pandoc makes of this list is in the Markdown reader.-Strings found in this list will be followed by a nonbreaking space, and-the period will not produce sentence-ending space in formats like LaTeX.-The strings may not contain spaces.-.TP-\f[V]--trace\f[R]-Print diagnostic output tracing parser progress to stderr.-This option is intended for use by developers in diagnosing performance-issues.-.SS General writer options-.TP-\f[V]-s\f[R], \f[V]--standalone\f[R]-Produce output with an appropriate header and footer (e.g.\ a standalone-HTML, LaTeX, TEI, or RTF file, not a fragment).-This option is set automatically for \f[V]pdf\f[R], \f[V]epub\f[R],-\f[V]epub3\f[R], \f[V]fb2\f[R], \f[V]docx\f[R], and \f[V]odt\f[R]-output.-For \f[V]native\f[R] output, this option causes metadata to be included;-otherwise, metadata is suppressed.-.TP-\f[V]--template=\f[R]\f[I]FILE\f[R]|\f[I]URL\f[R]-Use the specified file as a custom template for the generated document.-Implies \f[V]--standalone\f[R].-See Templates, below, for a description of template syntax.-If no extension is specified, an extension corresponding to the writer-will be added, so that \f[V]--template=special\f[R] looks for-\f[V]special.html\f[R] for HTML output.-If the template is not found, pandoc will search for it in the-\f[V]templates\f[R] subdirectory of the user data directory (see-\f[V]--data-dir\f[R]).-If this option is not used, a default template appropriate for the-output format will be used (see \f[V]-D/--print-default-template\f[R]).-.TP-\f[V]-V\f[R] \f[I]KEY\f[R][\f[V]=\f[R]\f[I]VAL\f[R]], \f[V]--variable=\f[R]\f[I]KEY\f[R][\f[V]:\f[R]\f[I]VAL\f[R]]-Set the template variable \f[I]KEY\f[R] to the value \f[I]VAL\f[R] when-rendering the document in standalone mode.-If no \f[I]VAL\f[R] is specified, the key will be given the value-\f[V]true\f[R].-.TP-\f[V]--sandbox\f[R]-Run pandoc in a sandbox, limiting IO operations in readers and writers-to reading the files specified on the command line.-Note that this option does not limit IO operations by filters or in the-production of PDF documents.-But it does offer security against, for example, disclosure of files-through the use of \f[V]include\f[R] directives.-Anyone using pandoc on untrusted user input should use this option.-.RS-.PP-Note: some readers and writers (e.g., \f[V]docx\f[R]) need access to-data files.-If these are stored on the file system, then pandoc will not be able to-find them when run in \f[V]--sandbox\f[R] mode and will raise an error.-For these applications, we recommend using a pandoc binary compiled with-the \f[V]embed_data_files\f[R] option, which causes the data files to be-baked into the binary instead of being stored on the file system.-.RE-.TP-\f[V]-D\f[R] \f[I]FORMAT\f[R], \f[V]--print-default-template=\f[R]\f[I]FORMAT\f[R]-Print the system default template for an output \f[I]FORMAT\f[R].-(See \f[V]-t\f[R] for a list of possible \f[I]FORMAT\f[R]s.)-Templates in the user data directory are ignored.-This option may be used with \f[V]-o\f[R]/\f[V]--output\f[R] to redirect-output to a file, but \f[V]-o\f[R]/\f[V]--output\f[R] must come before-\f[V]--print-default-template\f[R] on the command line.-.RS-.PP-Note that some of the default templates use partials, for example-\f[V]styles.html\f[R].-To print the partials, use \f[V]--print-default-data-file\f[R]: for-example, \f[V]--print-default-data-file=templates/styles.html\f[R].-.RE-.TP-\f[V]--print-default-data-file=\f[R]\f[I]FILE\f[R]-Print a system default data file.-Files in the user data directory are ignored.-This option may be used with \f[V]-o\f[R]/\f[V]--output\f[R] to redirect-output to a file, but \f[V]-o\f[R]/\f[V]--output\f[R] must come before-\f[V]--print-default-data-file\f[R] on the command line.-.TP-\f[V]--eol=crlf\f[R]|\f[V]lf\f[R]|\f[V]native\f[R]-Manually specify line endings: \f[V]crlf\f[R] (Windows), \f[V]lf\f[R]-(macOS/Linux/UNIX), or \f[V]native\f[R] (line endings appropriate to the-OS on which pandoc is being run).-The default is \f[V]native\f[R].-.TP-\f[V]--dpi\f[R]=\f[I]NUMBER\f[R]-Specify the default dpi (dots per inch) value for conversion from pixels-to inch/centimeters and vice versa.-(Technically, the correct term would be ppi: pixels per inch.)-The default is 96dpi.-When images contain information about dpi internally, the encoded value-is used instead of the default specified by this option.-.TP-\f[V]--wrap=auto\f[R]|\f[V]none\f[R]|\f[V]preserve\f[R]-Determine how text is wrapped in the output (the source code, not the-rendered version).-With \f[V]auto\f[R] (the default), pandoc will attempt to wrap lines to-the column width specified by \f[V]--columns\f[R] (default 72).-With \f[V]none\f[R], pandoc will not wrap lines at all.-With \f[V]preserve\f[R], pandoc will attempt to preserve the wrapping-from the source document (that is, where there are nonsemantic newlines-in the source, there will be nonsemantic newlines in the output as-well).-In \f[V]ipynb\f[R] output, this option affects wrapping of the contents-of markdown cells.-.TP-\f[V]--columns=\f[R]\f[I]NUMBER\f[R]-Specify length of lines in characters.-This affects text wrapping in the generated source code (see-\f[V]--wrap\f[R]).-It also affects calculation of column widths for plain text tables (see-Tables below).-.TP-\f[V]--toc\f[R], \f[V]--table-of-contents\f[R]-Include an automatically generated table of contents (or, in the case of-\f[V]latex\f[R], \f[V]context\f[R], \f[V]docx\f[R], \f[V]odt\f[R],-\f[V]opendocument\f[R], \f[V]rst\f[R], or \f[V]ms\f[R], an instruction-to create one) in the output document.-This option has no effect unless \f[V]-s/--standalone\f[R] is used, and-it has no effect on \f[V]man\f[R], \f[V]docbook4\f[R],-\f[V]docbook5\f[R], or \f[V]jats\f[R] output.-.RS-.PP-Note that if you are producing a PDF via \f[V]ms\f[R], the table of-contents will appear at the beginning of the document, before the title.-If you would prefer it to be at the end of the document, use the option-\f[V]--pdf-engine-opt=--no-toc-relocation\f[R].-.RE-.TP-\f[V]--toc-depth=\f[R]\f[I]NUMBER\f[R]-Specify the number of section levels to include in the table of-contents.-The default is 3 (which means that level-1, 2, and 3 headings will be-listed in the contents).-.TP-\f[V]--strip-comments\f[R]-Strip out HTML comments in the Markdown or Textile source, rather than-passing them on to Markdown, Textile or HTML output as raw HTML.-This does not apply to HTML comments inside raw HTML blocks when the-\f[V]markdown_in_html_blocks\f[R] extension is not set.-.TP-\f[V]--no-highlight\f[R]-Disables syntax highlighting for code blocks and inlines, even when a-language attribute is given.-.TP-\f[V]--highlight-style=\f[R]\f[I]STYLE\f[R]|\f[I]FILE\f[R]-Specifies the coloring style to be used in highlighted source code.-Options are \f[V]pygments\f[R] (the default), \f[V]kate\f[R],-\f[V]monochrome\f[R], \f[V]breezeDark\f[R], \f[V]espresso\f[R],-\f[V]zenburn\f[R], \f[V]haddock\f[R], and \f[V]tango\f[R].-For more information on syntax highlighting in pandoc, see Syntax-highlighting, below.-See also \f[V]--list-highlight-styles\f[R].-.RS-.PP-Instead of a \f[I]STYLE\f[R] name, a JSON file with extension-\f[V].theme\f[R] may be supplied.-This will be parsed as a KDE syntax highlighting theme and (if valid)-used as the highlighting style.-.PP-To generate the JSON version of an existing style, use-\f[V]--print-highlight-style\f[R].-.RE-.TP-\f[V]--print-highlight-style=\f[R]\f[I]STYLE\f[R]|\f[I]FILE\f[R]-Prints a JSON version of a highlighting style, which can be modified,-saved with a \f[V].theme\f[R] extension, and used with-\f[V]--highlight-style\f[R].-This option may be used with \f[V]-o\f[R]/\f[V]--output\f[R] to redirect-output to a file, but \f[V]-o\f[R]/\f[V]--output\f[R] must come before-\f[V]--print-highlight-style\f[R] on the command line.-.TP-\f[V]--syntax-definition=\f[R]\f[I]FILE\f[R]-Instructs pandoc to load a KDE XML syntax definition file, which will be-used for syntax highlighting of appropriately marked code blocks.-This can be used to add support for new languages or to use altered-syntax definitions for existing languages.-This option may be repeated to add multiple syntax definitions.-.TP-\f[V]-H\f[R] \f[I]FILE\f[R], \f[V]--include-in-header=\f[R]\f[I]FILE\f[R]|\f[I]URL\f[R]-Include contents of \f[I]FILE\f[R], verbatim, at the end of the header.-This can be used, for example, to include special CSS or JavaScript in-HTML documents.-This option can be used repeatedly to include multiple files in the-header.-They will be included in the order specified.-Implies \f[V]--standalone\f[R].-.TP-\f[V]-B\f[R] \f[I]FILE\f[R], \f[V]--include-before-body=\f[R]\f[I]FILE\f[R]|\f[I]URL\f[R]-Include contents of \f[I]FILE\f[R], verbatim, at the beginning of the-document body (e.g.\ after the \f[V]<body>\f[R] tag in HTML, or the-\f[V]\[rs]begin{document}\f[R] command in LaTeX).-This can be used to include navigation bars or banners in HTML-documents.-This option can be used repeatedly to include multiple files.-They will be included in the order specified.-Implies \f[V]--standalone\f[R].-.TP-\f[V]-A\f[R] \f[I]FILE\f[R], \f[V]--include-after-body=\f[R]\f[I]FILE\f[R]|\f[I]URL\f[R]-Include contents of \f[I]FILE\f[R], verbatim, at the end of the document-body (before the \f[V]</body>\f[R] tag in HTML, or the-\f[V]\[rs]end{document}\f[R] command in LaTeX).-This option can be used repeatedly to include multiple files.-They will be included in the order specified.-Implies \f[V]--standalone\f[R].-.TP-\f[V]--resource-path=\f[R]\f[I]SEARCHPATH\f[R]-List of paths to search for images and other resources.-The paths should be separated by \f[V]:\f[R] on Linux, UNIX, and macOS-systems, and by \f[V];\f[R] on Windows.-If \f[V]--resource-path\f[R] is not specified, the default resource path-is the working directory.-Note that, if \f[V]--resource-path\f[R] is specified, the working-directory must be explicitly listed or it will not be searched.-For example: \f[V]--resource-path=.:test\f[R] will search the working-directory and the \f[V]test\f[R] subdirectory, in that order.-This option can be used repeatedly.-Search path components that come later on the command line will be-searched before those that come earlier, so-\f[V]--resource-path foo:bar --resource-path baz:bim\f[R] is equivalent-to \f[V]--resource-path baz:bim:foo:bar\f[R].-.TP-\f[V]--request-header=\f[R]\f[I]NAME\f[R]\f[V]:\f[R]\f[I]VAL\f[R]-Set the request header \f[I]NAME\f[R] to the value \f[I]VAL\f[R] when-making HTTP requests (for example, when a URL is given on the command-line, or when resources used in a document must be downloaded).-If you\[cq]re behind a proxy, you also need to set the environment-variable \f[V]http_proxy\f[R] to \f[V]http://...\f[R].-.TP-\f[V]--no-check-certificate\f[R]-Disable the certificate verification to allow access to unsecure HTTP-resources (for example when the certificate is no longer valid or self-signed).-.SS Options affecting specific writers-.TP-\f[V]--self-contained\f[R]-\f[I]Deprecated synonym for-\f[VI]--embed-resources --standalone\f[I].\f[R]-.TP-\f[V]--embed-resources\f[R]-Produce a standalone HTML file with no external dependencies, using-\f[V]data:\f[R] URIs to incorporate the contents of linked scripts,-stylesheets, images, and videos.-The resulting file should be \[lq]self-contained,\[rq] in the sense that-it needs no external files and no net access to be displayed properly by-a browser.-This option works only with HTML output formats, including-\f[V]html4\f[R], \f[V]html5\f[R], \f[V]html+lhs\f[R],-\f[V]html5+lhs\f[R], \f[V]s5\f[R], \f[V]slidy\f[R], \f[V]slideous\f[R],-\f[V]dzslides\f[R], and \f[V]revealjs\f[R].-Scripts, images, and stylesheets at absolute URLs will be downloaded;-those at relative URLs will be sought relative to the working directory-(if the first source file is local) or relative to the base URL (if the-first source file is remote).-Elements with the attribute \f[V]data-external=\[dq]1\[dq]\f[R] will be-left alone; the documents they link to will not be incorporated in the-document.-Limitation: resources that are loaded dynamically through JavaScript-cannot be incorporated; as a result, some advanced features (e.g.\ zoom-or speaker notes) may not work in an offline \[lq]self-contained\[rq]-\f[V]reveal.js\f[R] slide show.-.TP-\f[V]--html-q-tags\f[R]-Use \f[V]<q>\f[R] tags for quotes in HTML.-(This option only has an effect if the \f[V]smart\f[R] extension is-enabled for the input format used.)-.TP-\f[V]--ascii\f[R]-Use only ASCII characters in output.-Currently supported for XML and HTML formats (which use entities instead-of UTF-8 when this option is selected), CommonMark, gfm, and Markdown-(which use entities), roff ms (which use hexadecimal escapes), and to a-limited degree LaTeX (which uses standard commands for accented-characters when possible).-roff man output uses ASCII by default.-.TP-\f[V]--reference-links\f[R]-Use reference-style links, rather than inline links, in writing Markdown-or reStructuredText.-By default inline links are used.-The placement of link references is affected by the-\f[V]--reference-location\f[R] option.-.TP-\f[V]--reference-location=block\f[R]|\f[V]section\f[R]|\f[V]document\f[R]-Specify whether footnotes (and references, if \f[V]reference-links\f[R]-is set) are placed at the end of the current (top-level) block, the-current section, or the document.-The default is \f[V]document\f[R].-Currently this option only affects the \f[V]markdown\f[R],-\f[V]muse\f[R], \f[V]html\f[R], \f[V]epub\f[R], \f[V]slidy\f[R],-\f[V]s5\f[R], \f[V]slideous\f[R], \f[V]dzslides\f[R], and-\f[V]revealjs\f[R] writers.-.TP-\f[V]--markdown-headings=setext\f[R]|\f[V]atx\f[R]-Specify whether to use ATX-style (\f[V]#\f[R]-prefixed) or Setext-style-(underlined) headings for level 1 and 2 headings in Markdown output.-(The default is \f[V]atx\f[R].)-ATX-style headings are always used for levels 3+.-This option also affects Markdown cells in \f[V]ipynb\f[R] output.-.TP-\f[V]--atx-headers\f[R]-\f[I]Deprecated synonym for \f[VI]--markdown-headings=atx\f[I].\f[R]-.TP-\f[V]--top-level-division=default\f[R]|\f[V]section\f[R]|\f[V]chapter\f[R]|\f[V]part\f[R]-Treat top-level headings as the given division type in LaTeX, ConTeXt,-DocBook, and TEI output.-The hierarchy order is part, chapter, then section; all headings are-shifted such that the top-level heading becomes the specified type.-The default behavior is to determine the best division type via-heuristics: unless other conditions apply, \f[V]section\f[R] is chosen.-When the \f[V]documentclass\f[R] variable is set to \f[V]report\f[R],-\f[V]book\f[R], or \f[V]memoir\f[R] (unless the \f[V]article\f[R] option-is specified), \f[V]chapter\f[R] is implied as the setting for this-option.-If \f[V]beamer\f[R] is the output format, specifying either-\f[V]chapter\f[R] or \f[V]part\f[R] will cause top-level headings to-become \f[V]\[rs]part{..}\f[R], while second-level headings remain as-their default type.-.TP-\f[V]-N\f[R], \f[V]--number-sections\f[R]-Number section headings in LaTeX, ConTeXt, HTML, Docx, ms, or EPUB-output.-By default, sections are not numbered.-Sections with class \f[V]unnumbered\f[R] will never be numbered, even if-\f[V]--number-sections\f[R] is specified.-.TP-\f[V]--number-offset=\f[R]\f[I]NUMBER\f[R][\f[V],\f[R]\f[I]NUMBER\f[R]\f[V],\f[R]\f[I]\&...\f[R]]-Offset for section headings in HTML output (ignored in other output-formats).-The first number is added to the section number for top-level headings,-the second for second-level headings, and so on.-So, for example, if you want the first top-level heading in your-document to be numbered \[lq]6\[rq], specify-\f[V]--number-offset=5\f[R].-If your document starts with a level-2 heading which you want to be-numbered \[lq]1.5\[rq], specify \f[V]--number-offset=1,4\f[R].-Offsets are 0 by default.-Implies \f[V]--number-sections\f[R].-.TP-\f[V]--listings\f[R]-Use the \f[V]listings\f[R] 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.-.TP-\f[V]-i\f[R], \f[V]--incremental\f[R]-Make list items in slide shows display incrementally (one by one).-The default is for lists to be displayed all at once.-.TP-\f[V]--slide-level=\f[R]\f[I]NUMBER\f[R]-Specifies that headings with the specified level create slides (for-\f[V]beamer\f[R], \f[V]s5\f[R], \f[V]slidy\f[R], \f[V]slideous\f[R],-\f[V]dzslides\f[R]).-Headings above this level in the hierarchy are used to divide the slide-show into sections; headings below this level create subheads within a-slide.-Valid values are 0-6.-If a slide level of 0 is specified, slides will not be split-automatically on headings, and horizontal rules must be used to indicate-slide boundaries.-If a slide level is not specified explicitly, the slide level will be-set automatically based on the contents of the document; see Structuring-the slide show.-.TP-\f[V]--section-divs\f[R]-Wrap sections in \f[V]<section>\f[R] tags (or \f[V]<div>\f[R] tags for-\f[V]html4\f[R]), and attach identifiers to the enclosing-\f[V]<section>\f[R] (or \f[V]<div>\f[R]) rather than the heading itself.-See Heading identifiers, below.-.TP-\f[V]--email-obfuscation=none\f[R]|\f[V]javascript\f[R]|\f[V]references\f[R]-Specify a method for obfuscating \f[V]mailto:\f[R] links in HTML-documents.-\f[V]none\f[R] leaves \f[V]mailto:\f[R] links as they are.-\f[V]javascript\f[R] obfuscates them using JavaScript.-\f[V]references\f[R] obfuscates them by printing their letters as-decimal or hexadecimal character references.-The default is \f[V]none\f[R].-.TP-\f[V]--id-prefix=\f[R]\f[I]STRING\f[R]-Specify a prefix to be added to all identifiers and internal links in-HTML and DocBook output, and to footnote numbers in Markdown and Haddock-output.-This is useful for preventing duplicate identifiers when generating-fragments to be included in other pages.-.TP-\f[V]-T\f[R] \f[I]STRING\f[R], \f[V]--title-prefix=\f[R]\f[I]STRING\f[R]-Specify \f[I]STRING\f[R] as a prefix at the beginning of the title that-appears in the HTML header (but not in the title as it appears at the-beginning of the HTML body).-Implies \f[V]--standalone\f[R].-.TP-\f[V]-c\f[R] \f[I]URL\f[R], \f[V]--css=\f[R]\f[I]URL\f[R]-Link to a CSS style sheet.-This option can be used repeatedly to include multiple files.-They will be included in the order specified.-.RS-.PP-A stylesheet is required for generating EPUB.-If none is provided using this option (or the \f[V]css\f[R] or-\f[V]stylesheet\f[R] metadata fields), pandoc will look for a file-\f[V]epub.css\f[R] in the user data directory (see-\f[V]--data-dir\f[R]).-If it is not found there, sensible defaults will be used.-.RE-.TP-\f[V]--reference-doc=\f[R]\f[I]FILE\f[R]-Use the specified file as a style reference in producing a docx or ODT-file.-.RS-.TP-Docx-For best results, the reference docx should be a modified version of a-docx file produced using pandoc.-The contents of the reference docx are ignored, but its stylesheets and-document properties (including margins, page size, header, and footer)-are used in the new docx.-If no reference docx is specified on the command line, pandoc will look-for a file \f[V]reference.docx\f[R] in the user data directory (see-\f[V]--data-dir\f[R]).-If this is not found either, sensible defaults will be used.-.RS-.PP-To produce a custom \f[V]reference.docx\f[R], first get a copy of the-default \f[V]reference.docx\f[R]:-\f[V]pandoc -o custom-reference.docx --print-default-data-file reference.docx\f[R].-Then open \f[V]custom-reference.docx\f[R] in Word, modify the styles as-you wish, and save the file.-For best results, do not make changes to this file other than modifying-the styles used by pandoc:-.PP-Paragraph styles:-.IP \[bu] 2-Normal-.IP \[bu] 2-Body Text-.IP \[bu] 2-First Paragraph-.IP \[bu] 2-Compact-.IP \[bu] 2-Title-.IP \[bu] 2-Subtitle-.IP \[bu] 2-Author-.IP \[bu] 2-Date-.IP \[bu] 2-Abstract-.IP \[bu] 2-Bibliography-.IP \[bu] 2-Heading 1-.IP \[bu] 2-Heading 2-.IP \[bu] 2-Heading 3-.IP \[bu] 2-Heading 4-.IP \[bu] 2-Heading 5-.IP \[bu] 2-Heading 6-.IP \[bu] 2-Heading 7-.IP \[bu] 2-Heading 8-.IP \[bu] 2-Heading 9-.IP \[bu] 2-Block Text-.IP \[bu] 2-Source Code-.IP \[bu] 2-Footnote Text-.IP \[bu] 2-Definition Term-.IP \[bu] 2-Definition-.IP \[bu] 2-Caption-.IP \[bu] 2-Table Caption-.IP \[bu] 2-Image Caption-.IP \[bu] 2-Figure-.IP \[bu] 2-Captioned Figure-.IP \[bu] 2-TOC Heading-.PP-Character styles:-.IP \[bu] 2-Default Paragraph Font-.IP \[bu] 2-Body Text Char-.IP \[bu] 2-Verbatim Char-.IP \[bu] 2-Footnote Reference-.IP \[bu] 2-Hyperlink-.IP \[bu] 2-Section Number-.PP-Table style:-.IP \[bu] 2-Table-.RE-.TP-ODT-For best results, the reference ODT should be a modified version of an-ODT produced using pandoc.-The contents of the reference ODT are ignored, but its stylesheets are-used in the new ODT.-If no reference ODT is specified on the command line, pandoc will look-for a file \f[V]reference.odt\f[R] in the user data directory (see-\f[V]--data-dir\f[R]).-If this is not found either, sensible defaults will be used.-.RS-.PP-To produce a custom \f[V]reference.odt\f[R], first get a copy of the-default \f[V]reference.odt\f[R]:-\f[V]pandoc -o custom-reference.odt --print-default-data-file reference.odt\f[R].-Then open \f[V]custom-reference.odt\f[R] in LibreOffice, modify the-styles as you wish, and save the file.-.RE-.TP-PowerPoint-Templates included with Microsoft PowerPoint 2013 (either with-\f[V].pptx\f[R] or \f[V].potx\f[R] extension) are known to work, as are-most templates derived from these.-.RS-.PP-The specific requirement is that the template should contain layouts-with the following names (as seen within PowerPoint):-.IP \[bu] 2-Title Slide-.IP \[bu] 2-Title and Content-.IP \[bu] 2-Section Header-.IP \[bu] 2-Two Content-.IP \[bu] 2-Comparison-.IP \[bu] 2-Content with Caption-.IP \[bu] 2-Blank-.PP-For each name, the first layout found with that name will be used.-If no layout is found with one of the names, pandoc will output a-warning and use the layout with that name from the default reference doc-instead.-(How these layouts are used is described in PowerPoint layout choice.)-.PP-All templates included with a recent version of MS PowerPoint will fit-these criteria.-(You can click on \f[V]Layout\f[R] under the \f[V]Home\f[R] menu to-check.)-.PP-You can also modify the default \f[V]reference.pptx\f[R]: first run-\f[V]pandoc -o custom-reference.pptx --print-default-data-file reference.pptx\f[R],-and then modify \f[V]custom-reference.pptx\f[R] in MS PowerPoint (pandoc-will use the layouts with the names listed above).-.RE-.RE-.TP-\f[V]--epub-cover-image=\f[R]\f[I]FILE\f[R]-Use the specified image as the EPUB cover.-It is recommended that the image be less than 1000px in width and-height.-Note that in a Markdown source document you can also specify-\f[V]cover-image\f[R] in a YAML metadata block (see EPUB Metadata,-below).-.TP-\f[V]--epub-metadata=\f[R]\f[I]FILE\f[R]-Look in the specified XML file for metadata for the EPUB.-The file should contain a series of Dublin Core elements.-For example:-.RS-.IP-.nf-\f[C]- <dc:rights>Creative Commons</dc:rights>- <dc:language>es-AR</dc:language>-\f[R]-.fi-.PP-By default, pandoc will include the following metadata elements:-\f[V]<dc:title>\f[R] (from the document title), \f[V]<dc:creator>\f[R]-(from the document authors), \f[V]<dc:date>\f[R] (from the document-date, which should be in ISO 8601 format), \f[V]<dc:language>\f[R] (from-the \f[V]lang\f[R] variable, or, if is not set, the locale), and-\f[V]<dc:identifier id=\[dq]BookId\[dq]>\f[R] (a randomly generated-UUID).-Any of these may be overridden by elements in the metadata file.-.PP-Note: if the source document is Markdown, a YAML metadata block in the-document can be used instead.-See below under EPUB Metadata.-.RE-.TP-\f[V]--epub-embed-font=\f[R]\f[I]FILE\f[R]-Embed the specified font in the EPUB.-This option can be repeated to embed multiple fonts.-Wildcards can also be used: for example, \f[V]DejaVuSans-*.ttf\f[R].-However, if you use wildcards on the command line, be sure to escape-them or put the whole filename in single quotes, to prevent them from-being interpreted by the shell.-To use the embedded fonts, you will need to add declarations like the-following to your CSS (see \f[V]--css\f[R]):-.RS-.IP-.nf-\f[C]-\[at]font-face {-font-family: DejaVuSans;-font-style: normal;-font-weight: normal;-src:url(\[dq]DejaVuSans-Regular.ttf\[dq]);-}-\[at]font-face {-font-family: DejaVuSans;-font-style: normal;-font-weight: bold;-src:url(\[dq]DejaVuSans-Bold.ttf\[dq]);-}-\[at]font-face {-font-family: DejaVuSans;-font-style: italic;-font-weight: normal;-src:url(\[dq]DejaVuSans-Oblique.ttf\[dq]);-}-\[at]font-face {-font-family: DejaVuSans;-font-style: italic;-font-weight: bold;-src:url(\[dq]DejaVuSans-BoldOblique.ttf\[dq]);-}-body { font-family: \[dq]DejaVuSans\[dq]; }-\f[R]-.fi-.RE-.TP-\f[V]--epub-chapter-level=\f[R]\f[I]NUMBER\f[R]-Specify the heading level at which to split the EPUB into separate-\[lq]chapter\[rq] files.-The default is to split into chapters at level-1 headings.-This option only affects the internal composition of the EPUB, not the-way chapters and sections are displayed to users.-Some readers may be slow if the chapter files are too large, so for-large documents with few level-1 headings, one might want to use a-chapter level of 2 or 3.-.TP-\f[V]--epub-subdirectory=\f[R]\f[I]DIRNAME\f[R]-Specify the subdirectory in the OCF container that is to hold the-EPUB-specific contents.-The default is \f[V]EPUB\f[R].-To put the EPUB contents in the top level, use an empty string.-.TP-\f[V]--ipynb-output=all|none|best\f[R]-Determines how ipynb output cells are treated.-\f[V]all\f[R] means that all of the data formats included in the-original are preserved.-\f[V]none\f[R] means that the contents of data cells are omitted.-\f[V]best\f[R] causes pandoc to try to pick the richest data block in-each output cell that is compatible with the output format.-The default is \f[V]best\f[R].-.TP-\f[V]--pdf-engine=\f[R]\f[I]PROGRAM\f[R]-Use the specified engine when producing PDF output.-Valid values are \f[V]pdflatex\f[R], \f[V]lualatex\f[R],-\f[V]xelatex\f[R], \f[V]latexmk\f[R], \f[V]tectonic\f[R],-\f[V]wkhtmltopdf\f[R], \f[V]weasyprint\f[R], \f[V]pagedjs-cli\f[R],-\f[V]prince\f[R], \f[V]context\f[R], and \f[V]pdfroff\f[R].-If the engine is not in your PATH, the full path of the engine may be-specified here.-If this option is not specified, pandoc uses the following defaults-depending on the output format specified using \f[V]-t/--to\f[R]:-.RS-.IP \[bu] 2-\f[V]-t latex\f[R] or none: \f[V]pdflatex\f[R] (other options:-\f[V]xelatex\f[R], \f[V]lualatex\f[R], \f[V]tectonic\f[R],-\f[V]latexmk\f[R])-.IP \[bu] 2-\f[V]-t context\f[R]: \f[V]context\f[R]-.IP \[bu] 2-\f[V]-t html\f[R]: \f[V]wkhtmltopdf\f[R] (other options:-\f[V]prince\f[R], \f[V]weasyprint\f[R], \f[V]pagedjs-cli\f[R]; see-print-css.rocks for a good introduction to PDF generation from HTML/CSS)-.IP \[bu] 2-\f[V]-t ms\f[R]: \f[V]pdfroff\f[R]-.RE-.TP-\f[V]--pdf-engine-opt=\f[R]\f[I]STRING\f[R]-Use the given string as a command-line argument to the-\f[V]pdf-engine\f[R].-For example, to use a persistent directory \f[V]foo\f[R] for-\f[V]latexmk\f[R]\[cq]s auxiliary files, use-\f[V]--pdf-engine-opt=-outdir=foo\f[R].-Note that no check for duplicate options is done.-.SS Citation rendering-.TP-\f[V]-C\f[R], \f[V]--citeproc\f[R]-Process the citations in the file, replacing them with rendered-citations and adding a bibliography.-Citation processing will not take place unless bibliographic data is-supplied, either through an external file specified using the-\f[V]--bibliography\f[R] option or the \f[V]bibliography\f[R] field in-metadata, or via a \f[V]references\f[R] section in metadata containing a-list of citations in CSL YAML format with Markdown formatting.-The style is controlled by a CSL stylesheet specified using the-\f[V]--csl\f[R] option or the \f[V]csl\f[R] field in metadata.-(If no stylesheet is specified, the \f[V]chicago-author-date\f[R] style-will be used by default.)-The citation processing transformation may be applied before or after-filters or Lua filters (see \f[V]--filter\f[R], \f[V]--lua-filter\f[R]):-these transformations are applied in the order they appear on the-command line.-For more information, see the section on Citations.-.TP-\f[V]--bibliography=\f[R]\f[I]FILE\f[R]-Set the \f[V]bibliography\f[R] field in the document\[cq]s metadata to-\f[I]FILE\f[R], overriding any value set in the metadata.-If you supply this argument multiple times, each \f[I]FILE\f[R] will be-added to bibliography.-If \f[I]FILE\f[R] is a URL, it will be fetched via HTTP.-If \f[I]FILE\f[R] is not found relative to the working directory, it-will be sought in the resource path (see \f[V]--resource-path\f[R]).-.TP-\f[V]--csl=\f[R]\f[I]FILE\f[R]-Set the \f[V]csl\f[R] field in the document\[cq]s metadata to-\f[I]FILE\f[R], overriding any value set in the metadata.-(This is equivalent to \f[V]--metadata csl=FILE\f[R].)-If \f[I]FILE\f[R] is a URL, it will be fetched via HTTP.-If \f[I]FILE\f[R] is not found relative to the working directory, it-will be sought in the resource path (see \f[V]--resource-path\f[R]) and-finally in the \f[V]csl\f[R] subdirectory of the pandoc user data-directory.-.TP-\f[V]--citation-abbreviations=\f[R]\f[I]FILE\f[R]-Set the \f[V]citation-abbreviations\f[R] field in the document\[cq]s-metadata to \f[I]FILE\f[R], overriding any value set in the metadata.-(This is equivalent to-\f[V]--metadata citation-abbreviations=FILE\f[R].)-If \f[I]FILE\f[R] is a URL, it will be fetched via HTTP.-If \f[I]FILE\f[R] is not found relative to the working directory, it-will be sought in the resource path (see \f[V]--resource-path\f[R]) and-finally in the \f[V]csl\f[R] subdirectory of the pandoc user data-directory.-.TP-\f[V]--natbib\f[R]-Use \f[V]natbib\f[R] for citations in LaTeX output.-This option is not for use with the \f[V]--citeproc\f[R] option or with-PDF output.-It is intended for use in producing a LaTeX file that can be processed-with \f[V]bibtex\f[R].-.TP-\f[V]--biblatex\f[R]-Use \f[V]biblatex\f[R] for citations in LaTeX output.-This option is not for use with the \f[V]--citeproc\f[R] option or with-PDF output.-It is intended for use in producing a LaTeX file that can be processed-with \f[V]bibtex\f[R] or \f[V]biber\f[R].-.SS Math rendering in HTML-.PP-The default is to render TeX math as far as possible using Unicode-characters.-Formulas are put inside a \f[V]span\f[R] with-\f[V]class=\[dq]math\[dq]\f[R], so that they may be styled differently-from the surrounding text if needed.-However, this gives acceptable results only for basic math, usually you-will want to use \f[V]--mathjax\f[R] or another of the following-options.-.TP-\f[V]--mathjax\f[R][\f[V]=\f[R]\f[I]URL\f[R]]-Use MathJax to display embedded TeX math in HTML output.-TeX math will be put between \f[V]\[rs](...\[rs])\f[R] (for inline math)-or \f[V]\[rs][...\[rs]]\f[R] (for display math) and wrapped in-\f[V]<span>\f[R] tags with class \f[V]math\f[R].-Then the MathJax JavaScript will render it.-The \f[I]URL\f[R] should point to the \f[V]MathJax.js\f[R] load script.-If a \f[I]URL\f[R] is not provided, a link to the Cloudflare CDN will be-inserted.-.TP-\f[V]--mathml\f[R]-Convert TeX math to MathML (in \f[V]epub3\f[R], \f[V]docbook4\f[R],-\f[V]docbook5\f[R], \f[V]jats\f[R], \f[V]html4\f[R] and-\f[V]html5\f[R]).-This is the default in \f[V]odt\f[R] output.-Note that currently only Firefox and Safari (and select e-book readers)-natively support MathML.-.TP-\f[V]--webtex\f[R][\f[V]=\f[R]\f[I]URL\f[R]]-Convert TeX formulas to \f[V]<img>\f[R] tags that link to an external-script that converts formulas to images.-The formula will be URL-encoded and concatenated with the URL provided.-For SVG images you can for example use-\f[V]--webtex https://latex.codecogs.com/svg.latex?\f[R].-If no URL is specified, the CodeCogs URL generating PNGs will be used-(\f[V]https://latex.codecogs.com/png.latex?\f[R]).-Note: the \f[V]--webtex\f[R] option will affect Markdown output as well-as HTML, which is useful if you\[cq]re targeting a version of Markdown-without native math support.-.TP-\f[V]--katex\f[R][\f[V]=\f[R]\f[I]URL\f[R]]-Use KaTeX to display embedded TeX math in HTML output.-The \f[I]URL\f[R] is the base URL for the KaTeX library.-That directory should contain a \f[V]katex.min.js\f[R] and a-\f[V]katex.min.css\f[R] file.-If a \f[I]URL\f[R] is not provided, a link to the KaTeX CDN will be-inserted.-.TP-\f[V]--gladtex\f[R]-Enclose TeX math in \f[V]<eq>\f[R] tags in HTML output.-The resulting HTML can then be processed by GladTeX to produce SVG-images of the typeset formulas and an HTML file with these images-embedded.-.RS-.IP-.nf-\f[C]-pandoc -s --gladtex input.md -o myfile.htex-gladtex -d image_dir myfile.htex-# produces myfile.html and images in image_dir-\f[R]-.fi-.RE-.SS Options for wrapper scripts-.TP-\f[V]--dump-args\f[R]-Print information about command-line arguments to \f[I]stdout\f[R], then-exit.-This option is intended primarily for use in wrapper scripts.-The first line of output contains the name of the output file specified-with the \f[V]-o\f[R] option, or \f[V]-\f[R] (for \f[I]stdout\f[R]) if-no output file was specified.-The remaining lines contain the command-line arguments, one per line, in-the order they appear.-These do not include regular pandoc options and their arguments, but do-include any options appearing after a \f[V]--\f[R] separator at the end-of the line.-.TP-\f[V]--ignore-args\f[R]-Ignore command-line arguments (for use in wrapper scripts).-Regular pandoc options are not ignored.-Thus, for example,-.RS-.IP-.nf-\f[C]-pandoc --ignore-args -o foo.html -s foo.txt -- -e latin1-\f[R]-.fi-.PP-is equivalent to-.IP-.nf-\f[C]-pandoc -o foo.html -s-\f[R]-.fi-.RE-.SH EXIT CODES-.PP-If pandoc completes successfully, it will return exit code 0.-Nonzero exit codes have the following meanings:-.RS -14n-.IP-.nf-\f[C]- Code Error- ------ -------------------------------------- 1 PandocIOError- 3 PandocFailOnWarningError- 4 PandocAppError- 5 PandocTemplateError- 6 PandocOptionError- 21 PandocUnknownReaderError- 22 PandocUnknownWriterError- 23 PandocUnsupportedExtensionError- 24 PandocCiteprocError- 25 PandocBibliographyError- 31 PandocEpubSubdirectoryError- 43 PandocPDFError- 44 PandocXMLError- 47 PandocPDFProgramNotFoundError- 61 PandocHttpError- 62 PandocShouldNeverHappenError- 63 PandocSomeError- 64 PandocParseError- 65 PandocParsecError- 66 PandocMakePDFError- 67 PandocSyntaxMapError- 83 PandocFilterError- 84 PandocLuaError- 91 PandocMacroLoop- 92 PandocUTF8DecodingError- 93 PandocIpynbDecodingError- 94 PandocUnsupportedCharsetError- 97 PandocCouldNotFindDataFileError- 98 PandocCouldNotFindMetadataFileError- 99 PandocResourceNotFound-\f[R]-.fi-.RE-.SH DEFAULTS FILES-.PP-The \f[V]--defaults\f[R] option may be used to specify a package of-options, in the form of a YAML file.-.PP-Fields that are omitted will just have their regular default values.-So a defaults file can be as simple as one line:-.IP-.nf-\f[C]-verbosity: INFO-\f[R]-.fi-.PP-In fields that expect a file path (or list of file paths), the following-syntax may be used to interpolate environment variables:-.IP-.nf-\f[C]-csl: ${HOME}/mycsldir/special.csl-\f[R]-.fi-.PP-\f[V]${USERDATA}\f[R] may also be used; this will always resolve to the-user data directory that is current when the defaults file is parsed,-regardless of the setting of the environment variable-\f[V]USERDATA\f[R].-.PP-\f[V]${.}\f[R] will resolve to the directory containing the defaults-file itself.-This allows you to refer to resources contained in that directory:-.IP-.nf-\f[C]-epub-cover-image: ${.}/cover.jpg-epub-metadata: ${.}/meta.xml-resource-path:-- . # the working directory from which pandoc is run-- ${.}/images # the images subdirectory of the directory- # containing this defaults file-\f[R]-.fi-.PP-This environment variable interpolation syntax \f[I]only\f[R] works in-fields that expect file paths.-.PP-Defaults files can be placed in the \f[V]defaults\f[R] subdirectory of-the user data directory and used from any directory.-For example, one could create a file specifying defaults for writing-letters, save it as \f[V]letter.yaml\f[R] in the \f[V]defaults\f[R]-subdirectory of the user data directory, and then invoke these defaults-from any directory using \f[V]pandoc --defaults letter\f[R] or-\f[V]pandoc -dletter\f[R].-.PP-When multiple defaults are used, their contents will be combined.-.PP-Note that, where command-line arguments may be repeated-(\f[V]--metadata-file\f[R], \f[V]--css\f[R],-\f[V]--include-in-header\f[R], \f[V]--include-before-body\f[R],-\f[V]--include-after-body\f[R], \f[V]--variable\f[R],-\f[V]--metadata\f[R], \f[V]--syntax-definition\f[R]), the values-specified on the command line will combine with values specified in the-defaults file, rather than replacing them.-.PP-The following tables show the mapping between the command line and-defaults file entries.-.RS -14n-.IP-.nf-\f[C]-- command line defaults file - --------------------------------- ----------------------------------- foo.md input-file: foo.md -- foo.md bar.md input-files: - - foo.md - - bar.md --\f[R]-.fi-.RE-.PP-The value of \f[V]input-files\f[R] may be left empty to indicate input-from stdin, and it can be an empty sequence \f[V][]\f[R] for no input.-.SS General options-.RS -14n-.IP-.nf-\f[C]-- command line defaults file - --------------------------------- ----------------------------------- --from markdown+emoji from: markdown+emoji - - reader: markdown+emoji -- to: markdown+hard_line_breaks - --to markdown+hard_line_breaks - - writer: markdown+hard_line_breaks -- --output foo.pdf output-file: foo.pdf -- --output - output-file: -- --data-dir dir data-dir: dir -- --defaults file defaults: - - file -- --verbose verbosity: INFO -- --quiet verbosity: ERROR -- --fail-if-warnings fail-if-warnings: true -- --sandbox sandbox: true -- --log=FILE log-file: FILE --\f[R]-.fi-.RE-.PP-Options specified in a defaults file itself always have priority over-those in another file included with a \f[V]defaults:\f[R] entry.-.PP-\f[V]verbosity\f[R] can have the values \f[V]ERROR\f[R],-\f[V]WARNING\f[R], or \f[V]INFO\f[R].-.SS Reader options-.RS -14n-.IP-.nf-\f[C]-- command line defaults file - --------------------------------- ----------------------------------- --shift-heading-level-by -1 shift-heading-level-by: -1 -- indented-code-classes: - --indented-code-classes python - python -- - --default-image-extension \[dq].jpg\[dq] default-image-extension: \[aq].jpg\[aq] -- --file-scope file-scope: true -- --filter pandoc-citeproc \[rs] filters: - - pandoc-citeproc - --lua-filter count-words.lua \[rs] - count-words.lua - --filter special.lua - type: json - path: special.lua -- --metadata key=value \[rs] metadata: - --metadata key2 key: value - key2: true -- --metadata-file meta.yaml metadata-files: - - meta.yaml - - metadata-file: meta.yaml -- --preserve-tabs preserve-tabs: true -- --tab-stop 8 tab-stop: 8 -- --track-changes accept track-changes: accept -- --extract-media dir extract-media: dir -- --abbreviations abbrevs.txt abbreviations: abbrevs.txt -- --trace trace: true --\f[R]-.fi-.RE-.PP-Metadata values specified in a defaults file are parsed as literal-string text, not Markdown.-.PP-Filters will be assumed to be Lua filters if they have the-\f[V].lua\f[R] extension, and JSON filters otherwise.-But the filter type can also be specified explicitly, as shown.-Filters are run in the order specified.-To include the built-in citeproc filter, use either \f[V]citeproc\f[R]-or \f[V]{type: citeproc}\f[R].-.SS General writer options-.RS -14n-.IP-.nf-\f[C]-- command line defaults file - --------------------------------- ----------------------------------- --standalone standalone: true -- --template letter template: letter -- --variable key=val \[rs] variables: - --variable key2 key: val - key2: true -- --eol nl eol: nl -- --dpi 300 dpi: 300 -- --wrap 60 wrap: 60 -- --columns 72 columns: 72 -- --table-of-contents table-of-contents: true -- --toc toc: true -- --toc-depth 3 toc-depth: 3 -- --strip-comments strip-comments: true -- --no-highlight highlight-style: null -- --highlight-style kate highlight-style: kate -- syntax-definitions: - --syntax-definition mylang.xml - mylang.xml - - syntax-definition: mylang.xml -- --include-in-header inc.tex include-in-header: - - inc.tex -- include-before-body: ---include-before-body inc.tex - inc.tex -- --include-after-body inc.tex include-after-body: - - inc.tex -- --resource-path .:foo resource-path: [\[aq].\[aq],\[aq]foo\[aq]] -- --request-header foo:bar request-headers: - - - [\[dq]User-Agent\[dq], \[dq]Mozilla/5.0\[dq]] -- --no-check-certificate no-check-certificate: true --\f[R]-.fi-.RE-.SS Options affecting specific writers-.RS -14n-.IP-.nf-\f[C]-- command line defaults file - --------------------------------- ----------------------------------- --self-contained self-contained: true -- --html-q-tags html-q-tags: true -- --ascii ascii: true -- --reference-links reference-links: true -- --reference-location block reference-location: block -- --markdown-headings atx markdown-headings: atx -- --top-level-division chapter top-level-division: chapter -- --number-sections number-sections: true -- --number-offset=1,4 number-offset: \[rs][1,4\[rs]] -- --listings listings: true -- --incremental incremental: true -- --slide-level 2 slide-level: 2 -- --section-divs section-divs: true -- email-obfuscation: references - --email-obfuscation references -- --id-prefix ch1 identifier-prefix: ch1 -- --title-prefix MySite title-prefix: MySite -- --css styles/screen.css \[rs] css: - --css styles/special.css - styles/screen.css - - styles/special.css -- --reference-doc my.docx reference-doc: my.docx -- --epub-cover-image cover.jpg epub-cover-image: cover.jpg -- --epub-metadata meta.xml epub-metadata: meta.xml -- epub-fonts: - --epub-embed-font special.otf \[rs] - special.otf - - headline.otf - --epub-embed-font headline.otf -- --epub-chapter-level 2 epub-chapter-level: 2 -- --epub-subdirectory=\[dq]\[dq] epub-subdirectory: \[aq]\[aq] -- --ipynb-output best ipynb-output: best -- --pdf-engine xelatex pdf-engine: xelatex -- pdf-engine-opts: - --pdf-engine-opt=--shell-escape - \[aq]-shell-escape\[aq] - - - pdf-engine-opt: \[aq]-shell-escape\[aq] --\f[R]-.fi-.RE-.SS Citation rendering-.RS -14n-.IP-.nf-\f[C]-- command line defaults file - --------------------------------- ----------------------------------- --citeproc citeproc: true -- --bibliography logic.bib metadata: - bibliography: logic.bib -- --csl ieee.csl metadata: - csl: ieee.csl -- metadata: - --citation-abbreviations ab.json - citation-abbreviations: ab.json -- --natbib cite-method: natbib -- --biblatex cite-method: biblatex --\f[R]-.fi-.RE-.PP-\f[V]cite-method\f[R] can be \f[V]citeproc\f[R], \f[V]natbib\f[R], or-\f[V]biblatex\f[R].-This only affects LaTeX output.-If you want to use citeproc to format citations, you should also set-`citeproc: true'.-.PP-If you need control over when the citeproc processing is done relative-to other filters, you should instead use \f[V]citeproc\f[R] in the list-of \f[V]filters\f[R] (see above).-.SS Math rendering in HTML-.RS -14n-.IP-.nf-\f[C]-- command line defaults file - --------------------------------- ----------------------------------- --mathjax html-math-method: - method: mathjax -- --mathml html-math-method: - method: mathml -- --webtex html-math-method: - method: webtex -- --katex html-math-method: - method: katex -- --gladtex html-math-method: - method: gladtex --\f[R]-.fi-.RE-.PP-In addition to the values listed above, \f[V]method\f[R] can have the-value \f[V]plain\f[R].-.PP-If the command line option accepts a URL argument, an \f[V]url:\f[R]-field can be added to \f[V]html-math-method:\f[R].-.SS Options for wrapper scripts-.RS -14n-.IP-.nf-\f[C]-- command line defaults file - --------------------------------- ----------------------------------- --dump-args dump-args: true -- --ignore-args ignore-args: true --\f[R]-.fi-.RE-.SH TEMPLATES-.PP-When the \f[V]-s/--standalone\f[R] option is used, pandoc uses a-template to add header and footer material that is needed for a-self-standing document.-To see the default template that is used, just type-.IP-.nf-\f[C]-pandoc -D *FORMAT*-\f[R]-.fi-.PP-where \f[I]FORMAT\f[R] is the name of the output format.-A custom template can be specified using the \f[V]--template\f[R]-option.-You can also override the system default templates for a given output-format \f[I]FORMAT\f[R] by putting a file-\f[V]templates/default.*FORMAT*\f[R] in the user data directory (see-\f[V]--data-dir\f[R], above).-\f[I]Exceptions:\f[R]-.IP \[bu] 2-For \f[V]odt\f[R] output, customize the \f[V]default.opendocument\f[R]-template.-.IP \[bu] 2-For \f[V]pdf\f[R] output, customize the \f[V]default.latex\f[R] template-(or the \f[V]default.context\f[R] template, if you use-\f[V]-t context\f[R], or the \f[V]default.ms\f[R] template, if you use-\f[V]-t ms\f[R], or the \f[V]default.html\f[R] template, if you use-\f[V]-t html\f[R]).-.IP \[bu] 2-\f[V]docx\f[R] and \f[V]pptx\f[R] have no template (however, you can use-\f[V]--reference-doc\f[R] to customize the output).-.PP-Templates contain \f[I]variables\f[R], which allow for the inclusion of-arbitrary information at any point in the file.-They may be set at the command line using the \f[V]-V/--variable\f[R]-option.-If a variable is not set, pandoc will look for the key in the-document\[cq]s metadata, which can be set using either YAML metadata-blocks or with the \f[V]-M/--metadata\f[R] option.-In addition, some variables are given default values by pandoc.-See Variables below for a list of variables used in pandoc\[cq]s default-templates.-.PP-If you use custom templates, you may need to revise them as pandoc-changes.-We recommend tracking the changes in the default templates, and-modifying your custom templates accordingly.-An easy way to do this is to fork the pandoc-templates repository and-merge in changes after each pandoc release.-.SS Template syntax-.SS Comments-.PP-Anything between the sequence \f[V]$--\f[R] and the end of the line will-be treated as a comment and omitted from the output.-.SS Delimiters-.PP-To mark variables and control structures in the template, either-\f[V]$\f[R]\&...\f[V]$\f[R] or \f[V]${\f[R]\&...\f[V]}\f[R] may be used-as delimiters.-The styles may also be mixed in the same template, but the opening and-closing delimiter must match in each case.-The opening delimiter may be followed by one or more spaces or tabs,-which will be ignored.-The closing delimiter may be followed by one or more spaces or tabs,-which will be ignored.-.PP-To include a literal \f[V]$\f[R] in the document, use \f[V]$$\f[R].-.SS Interpolated variables-.PP-A slot for an interpolated variable is a variable name surrounded by-matched delimiters.-Variable names must begin with a letter and can contain letters,-numbers, \f[V]_\f[R], \f[V]-\f[R], and \f[V].\f[R].-The keywords \f[V]it\f[R], \f[V]if\f[R], \f[V]else\f[R],-\f[V]endif\f[R], \f[V]for\f[R], \f[V]sep\f[R], and \f[V]endfor\f[R] may-not be used as variable names.-Examples:-.IP-.nf-\f[C]-$foo$-$foo.bar.baz$-$foo_bar.baz-bim$-$ foo $-${foo}-${foo.bar.baz}-${foo_bar.baz-bim}-${ foo }-\f[R]-.fi-.PP-Variable names with periods are used to get at structured variable-values.-So, for example, \f[V]employee.salary\f[R] will return the value of the-\f[V]salary\f[R] field of the object that is the value of the-\f[V]employee\f[R] field.-.IP \[bu] 2-If the value of the variable is a simple value, it will be rendered-verbatim.-(Note that no escaping is done; the assumption is that the calling-program will escape the strings appropriately for the output format.)-.IP \[bu] 2-If the value is a list, the values will be concatenated.-.IP \[bu] 2-If the value is a map, the string \f[V]true\f[R] will be rendered.-.IP \[bu] 2-Every other value will be rendered as the empty string.-.SS Conditionals-.PP-A conditional begins with \f[V]if(variable)\f[R] (enclosed in matched-delimiters) and ends with \f[V]endif\f[R] (enclosed in matched-delimiters).-It may optionally contain an \f[V]else\f[R] (enclosed in matched-delimiters).-The \f[V]if\f[R] section is used if \f[V]variable\f[R] has a non-empty-value, otherwise the \f[V]else\f[R] section is used (if present).-Examples:-.IP-.nf-\f[C]-$if(foo)$bar$endif$--$if(foo)$- $foo$-$endif$--$if(foo)$-part one-$else$-part two-$endif$--${if(foo)}bar${endif}--${if(foo)}- ${foo}-${endif}--${if(foo)}-${ foo.bar }-${else}-no foo!-${endif}-\f[R]-.fi-.PP-The keyword \f[V]elseif\f[R] may be used to simplify complex nested-conditionals:-.IP-.nf-\f[C]-$if(foo)$-XXX-$elseif(bar)$-YYY-$else$-ZZZ-$endif$-\f[R]-.fi-.SS For loops-.PP-A for loop begins with \f[V]for(variable)\f[R] (enclosed in matched-delimiters) and ends with \f[V]endfor\f[R] (enclosed in matched-delimiters).-.IP \[bu] 2-If \f[V]variable\f[R] is an array, the material inside the loop will be-evaluated repeatedly, with \f[V]variable\f[R] being set to each value of-the array in turn, and concatenated.-.IP \[bu] 2-If \f[V]variable\f[R] is a map, the material inside will be set to the-map.-.IP \[bu] 2-If the value of the associated variable is not an array or a map, a-single iteration will be performed on its value.-.PP-Examples:-.IP-.nf-\f[C]-$for(foo)$$foo$$sep$, $endfor$--$for(foo)$- - $foo.last$, $foo.first$-$endfor$--${ for(foo.bar) }- - ${ foo.bar.last }, ${ foo.bar.first }-${ endfor }--$for(mymap)$-$it.name$: $it.office$-$endfor$-\f[R]-.fi-.PP-You may optionally specify a separator between consecutive values using-\f[V]sep\f[R] (enclosed in matched delimiters).-The material between \f[V]sep\f[R] and the \f[V]endfor\f[R] is the-separator.-.IP-.nf-\f[C]-${ for(foo) }${ foo }${ sep }, ${ endfor }-\f[R]-.fi-.PP-Instead of using \f[V]variable\f[R] inside the loop, the special-anaphoric keyword \f[V]it\f[R] may be used.-.IP-.nf-\f[C]-${ for(foo.bar) }- - ${ it.last }, ${ it.first }-${ endfor }-\f[R]-.fi-.SS Partials-.PP-Partials (subtemplates stored in different files) may be included by-using the name of the partial, followed by \f[V]()\f[R], for example:-.IP-.nf-\f[C]-${ styles() }-\f[R]-.fi-.PP-Partials will be sought in the directory containing the main template.-The file name will be assumed to have the same extension as the main-template if it lacks an extension.-When calling the partial, the full name including file extension can-also be used:-.IP-.nf-\f[C]-${ styles.html() }-\f[R]-.fi-.PP-(If a partial is not found in the directory of the template and the-template path is given as a relative path, it will also be sought in the-\f[V]templates\f[R] subdirectory of the user data directory.)-.PP-Partials may optionally be applied to variables using a colon:-.IP-.nf-\f[C]-${ date:fancy() }--${ articles:bibentry() }-\f[R]-.fi-.PP-If \f[V]articles\f[R] is an array, this will iterate over its values,-applying the partial \f[V]bibentry()\f[R] to each one.-So the second example above is equivalent to-.IP-.nf-\f[C]-${ for(articles) }-${ it:bibentry() }-${ endfor }-\f[R]-.fi-.PP-Note that the anaphoric keyword \f[V]it\f[R] must be used when iterating-over partials.-In the above examples, the \f[V]bibentry\f[R] partial should contain-\f[V]it.title\f[R] (and so on) instead of \f[V]articles.title\f[R].-.PP-Final newlines are omitted from included partials.-.PP-Partials may include other partials.-.PP-A separator between values of an array may be specified in square-brackets, immediately after the variable name or partial:-.IP-.nf-\f[C]-${months[, ]}$--${articles:bibentry()[; ]$-\f[R]-.fi-.PP-The separator in this case is literal and (unlike with \f[V]sep\f[R] in-an explicit \f[V]for\f[R] loop) cannot contain interpolated variables or-other template directives.-.SS Nesting-.PP-To ensure that content is \[lq]nested,\[rq] that is, subsequent lines-indented, use the \f[V]\[ha]\f[R] directive:-.IP-.nf-\f[C]-$item.number$ $\[ha]$$item.description$ ($item.price$)-\f[R]-.fi-.PP-In this example, if \f[V]item.description\f[R] has multiple lines, they-will all be indented to line up with the first line:-.IP-.nf-\f[C]-00123 A fine bottle of 18-year old- Oban whiskey. ($148)-\f[R]-.fi-.PP-To nest multiple lines to the same level, align them with the-\f[V]\[ha]\f[R] directive in the template.-For example:-.IP-.nf-\f[C]-$item.number$ $\[ha]$$item.description$ ($item.price$)- (Available til $item.sellby$.)-\f[R]-.fi-.PP-will produce-.IP-.nf-\f[C]-00123 A fine bottle of 18-year old- Oban whiskey. ($148)- (Available til March 30, 2020.)-\f[R]-.fi-.PP-If a variable occurs by itself on a line, preceded by whitespace and not-followed by further text or directives on the same line, and the-variable\[cq]s value contains multiple lines, it will be nested-automatically.-.SS Breakable spaces-.PP-Normally, spaces in the template itself (as opposed to values of the-interpolated variables) are not breakable, but they can be made-breakable in part of the template by using the \f[V]\[ti]\f[R] keyword-(ended with another \f[V]\[ti]\f[R]).-.IP-.nf-\f[C]-$\[ti]$This long line may break if the document is rendered-with a short line length.$\[ti]$-\f[R]-.fi-.SS Pipes-.PP-A pipe transforms the value of a variable or partial.-Pipes are specified using a slash (\f[V]/\f[R]) between the variable-name (or partial) and the pipe name.-Example:-.IP-.nf-\f[C]-$for(name)$-$name/uppercase$-$endfor$--$for(metadata/pairs)$-- $it.key$: $it.value$-$endfor$--$employee:name()/uppercase$-\f[R]-.fi-.PP-Pipes may be chained:-.IP-.nf-\f[C]-$for(employees/pairs)$-$it.key/alpha/uppercase$. $it.name$-$endfor$-\f[R]-.fi-.PP-Some pipes take parameters:-.IP-.nf-\f[C]-|----------------------|------------|-$for(employee)$-$it.name.first/uppercase/left 20 \[dq]| \[dq]$$it.name.salary/right 10 \[dq] | \[dq] \[dq] |\[dq]$-$endfor$-|----------------------|------------|-\f[R]-.fi-.PP-Currently the following pipes are predefined:-.IP \[bu] 2-\f[V]pairs\f[R]: Converts a map or array to an array of maps, each with-\f[V]key\f[R] and \f[V]value\f[R] fields.-If the original value was an array, the \f[V]key\f[R] will be the array-index, starting with 1.-.IP \[bu] 2-\f[V]uppercase\f[R]: Converts text to uppercase.-.IP \[bu] 2-\f[V]lowercase\f[R]: Converts text to lowercase.-.IP \[bu] 2-\f[V]length\f[R]: Returns the length of the value: number of characters-for a textual value, number of elements for a map or array.-.IP \[bu] 2-\f[V]reverse\f[R]: Reverses a textual value or array, and has no effect-on other values.-.IP \[bu] 2-\f[V]first\f[R]: Returns the first value of an array, if applied to a-non-empty array; otherwise returns the original value.-.IP \[bu] 2-\f[V]last\f[R]: Returns the last value of an array, if applied to a-non-empty array; otherwise returns the original value.-.IP \[bu] 2-\f[V]rest\f[R]: Returns all but the first value of an array, if applied-to a non-empty array; otherwise returns the original value.-.IP \[bu] 2-\f[V]allbutlast\f[R]: Returns all but the last value of an array, if-applied to a non-empty array; otherwise returns the original value.-.IP \[bu] 2-\f[V]chomp\f[R]: Removes trailing newlines (and breakable space).-.IP \[bu] 2-\f[V]nowrap\f[R]: Disables line wrapping on breakable spaces.-.IP \[bu] 2-\f[V]alpha\f[R]: Converts textual values that can be read as an integer-into lowercase alphabetic characters \f[V]a..z\f[R] (mod 26).-This can be used to get lettered enumeration from array indices.-To get uppercase letters, chain with \f[V]uppercase\f[R].-.IP \[bu] 2-\f[V]roman\f[R]: Converts textual values that can be read as an integer-into lowercase roman numerals.-This can be used to get lettered enumeration from array indices.-To get uppercase roman, chain with \f[V]uppercase\f[R].-.IP \[bu] 2-\f[V]left n \[dq]leftborder\[dq] \[dq]rightborder\[dq]\f[R]: Renders a-textual value in a block of width \f[V]n\f[R], aligned to the left, with-an optional left and right border.-Has no effect on other values.-This can be used to align material in tables.-Widths are positive integers indicating the number of characters.-Borders are strings inside double quotes; literal \f[V]\[dq]\f[R] and-\f[V]\[rs]\f[R] characters must be backslash-escaped.-.IP \[bu] 2-\f[V]right n \[dq]leftborder\[dq] \[dq]rightborder\[dq]\f[R]: Renders a-textual value in a block of width \f[V]n\f[R], aligned to the right, and-has no effect on other values.-.IP \[bu] 2-\f[V]center n \[dq]leftborder\[dq] \[dq]rightborder\[dq]\f[R]: Renders a-textual value in a block of width \f[V]n\f[R], aligned to the center,-and has no effect on other values.-.SS Variables-.SS Metadata variables-.TP-\f[V]title\f[R], \f[V]author\f[R], \f[V]date\f[R]-allow identification of basic aspects of the document.-Included in PDF metadata through LaTeX and ConTeXt.-These can be set through a pandoc title block, which allows for multiple-authors, or through a YAML metadata block:-.RS-.IP-.nf-\f[C]-----author:-- Aristotle-- Peter Abelard-\&...-\f[R]-.fi-.PP-Note that if you just want to set PDF or HTML metadata, without-including a title block in the document itself, you can set the-\f[V]title-meta\f[R], \f[V]author-meta\f[R], and \f[V]date-meta\f[R]-variables.-(By default these are set automatically, based on \f[V]title\f[R],-\f[V]author\f[R], and \f[V]date\f[R].)-The page title in HTML is set by \f[V]pagetitle\f[R], which is equal to-\f[V]title\f[R] by default.-.RE-.TP-\f[V]subtitle\f[R]-document subtitle, included in HTML, EPUB, LaTeX, ConTeXt, and docx-documents-.TP-\f[V]abstract\f[R]-document summary, included in HTML, LaTeX, ConTeXt, AsciiDoc, and docx-documents-.TP-\f[V]abstract-title\f[R]-title of abstract, currently used only in HTML and EPUB.-This will be set automatically to a localized value, depending on-\f[V]lang\f[R], but can be manually overridden.-.TP-\f[V]keywords\f[R]-list of keywords to be included in HTML, PDF, ODT, pptx, docx and-AsciiDoc metadata; repeat as for \f[V]author\f[R], above-.TP-\f[V]subject\f[R]-document subject, included in ODT, PDF, docx, EPUB, and pptx metadata-.TP-\f[V]description\f[R]-document description, included in ODT, docx and pptx metadata.-Some applications show this as \f[V]Comments\f[R] metadata.-.TP-\f[V]category\f[R]-document category, included in docx and pptx metadata-.PP-Additionally, any root-level string metadata, not included in ODT, docx-or pptx metadata is added as a \f[I]custom property\f[R].-The following YAML metadata block for instance:-.IP-.nf-\f[C]-----title: \[aq]This is the title\[aq]-subtitle: \[dq]This is the subtitle\[dq]-author:-- Author One-- Author Two-description: |- This is a long- description.-- It consists of two paragraphs-\&...-\f[R]-.fi-.PP-will include \f[V]title\f[R], \f[V]author\f[R] and \f[V]description\f[R]-as standard document properties and \f[V]subtitle\f[R] as a custom-property when converting to docx, ODT or pptx.-.SS Language variables-.TP-\f[V]lang\f[R]-identifies the main language of the document using IETF language tags-(following the BCP 47 standard), such as \f[V]en\f[R] or-\f[V]en-GB\f[R].-The Language subtag lookup tool can look up or verify these tags.-This affects most formats, and controls hyphenation in PDF output when-using LaTeX (through \f[V]babel\f[R] and \f[V]polyglossia\f[R]) or-ConTeXt.-.RS-.PP-Use native pandoc Divs and Spans with the \f[V]lang\f[R] attribute to-switch the language:-.IP-.nf-\f[C]-----lang: en-GB-\&...--Text in the main document language (British English).--::: {lang=fr-CA}-> Cette citation est \['e]crite en fran\[,c]ais canadien.-:::--More text in English. [\[aq]Zitat auf Deutsch.\[aq]]{lang=de}-\f[R]-.fi-.RE-.TP-\f[V]dir\f[R]-the base script direction, either \f[V]rtl\f[R] (right-to-left) or-\f[V]ltr\f[R] (left-to-right).-.RS-.PP-For bidirectional documents, native pandoc \f[V]span\f[R]s and-\f[V]div\f[R]s with the \f[V]dir\f[R] attribute (value \f[V]rtl\f[R] or-\f[V]ltr\f[R]) can be used to override the base direction in some output-formats.-This may not always be necessary if the final renderer (e.g.\ the-browser, when generating HTML) supports the Unicode Bidirectional-Algorithm.-.PP-When using LaTeX for bidirectional documents, only the \f[V]xelatex\f[R]-engine is fully supported (use \f[V]--pdf-engine=xelatex\f[R]).-.RE-.SS Variables for HTML-.TP-\f[V]document-css\f[R]-Enables inclusion of most of the CSS in the \f[V]styles.html\f[R]-partial (have a look with-\f[V]pandoc --print-default-data-file=templates/styles.html\f[R]).-Unless you use \f[V]--css\f[R], this variable is set to \f[V]true\f[R]-by default.-You can disable it with e.g.\ \f[V]pandoc -M document-css=false\f[R].-.TP-\f[V]mainfont\f[R]-sets the CSS \f[V]font-family\f[R] property on the \f[V]html\f[R]-element.-.TP-\f[V]fontsize\f[R]-sets the base CSS \f[V]font-size\f[R], which you\[cq]d usually set to-e.g.\ \f[V]20px\f[R], but it also accepts \f[V]pt\f[R] (12pt = 16px in-most browsers).-.TP-\f[V]fontcolor\f[R]-sets the CSS \f[V]color\f[R] property on the \f[V]html\f[R] element.-.TP-\f[V]linkcolor\f[R]-sets the CSS \f[V]color\f[R] property on all links.-.TP-\f[V]monofont\f[R]-sets the CSS \f[V]font-family\f[R] property on \f[V]code\f[R] elements.-.TP-\f[V]monobackgroundcolor\f[R]-sets the CSS \f[V]background-color\f[R] property on \f[V]code\f[R]-elements and adds extra padding.-.TP-\f[V]linestretch\f[R]-sets the CSS \f[V]line-height\f[R] property on the \f[V]html\f[R]-element, which is preferred to be unitless.-.TP-\f[V]backgroundcolor\f[R]-sets the CSS \f[V]background-color\f[R] property on the \f[V]html\f[R]-element.-.TP-\f[V]margin-left\f[R], \f[V]margin-right\f[R], \f[V]margin-top\f[R], \f[V]margin-bottom\f[R]-sets the corresponding CSS \f[V]padding\f[R] properties on the-\f[V]body\f[R] element.-.PP-To override or extend some CSS for just one document, include for-example:-.IP-.nf-\f[C]-----header-includes: |- <style>- blockquote {- font-style: italic;- }- tr.even {- background-color: #f0f0f0;- }- td, th {- padding: 0.5em 2em 0.5em 0.5em;- }- tbody {- border-bottom: none;- }- </style>-----\f[R]-.fi-.SS Variables for HTML math-.TP-\f[V]classoption\f[R]-when using KaTeX, you can render display math equations flush left using-YAML metadata or with \f[V]-M classoption=fleqn\f[R].-.SS Variables for HTML slides-.PP-These affect HTML output when producing slide shows with pandoc.-.TP-\f[V]institute\f[R]-author affiliations: can be a list when there are multiple authors-.TP-\f[V]revealjs-url\f[R]-base URL for reveal.js documents (defaults to-\f[V]https://unpkg.com/reveal.js\[at]\[ha]4/\f[R])-.TP-\f[V]s5-url\f[R]-base URL for S5 documents (defaults to \f[V]s5/default\f[R])-.TP-\f[V]slidy-url\f[R]-base URL for Slidy documents (defaults to-\f[V]https://www.w3.org/Talks/Tools/Slidy2\f[R])-.TP-\f[V]slideous-url\f[R]-base URL for Slideous documents (defaults to \f[V]slideous\f[R])-.TP-\f[V]title-slide-attributes\f[R]-additional attributes for the title slide of reveal.js slide shows.-See background in reveal.js, beamer, and pptx for an example.-.PP-All reveal.js configuration options are available as variables.-To turn off boolean flags that default to true in reveal.js, use-\f[V]0\f[R].-.SS Variables for Beamer slides-.PP-These variables change the appearance of PDF slides using-\f[V]beamer\f[R].-.TP-\f[V]aspectratio\f[R]-slide aspect ratio (\f[V]43\f[R] for 4:3 [default], \f[V]169\f[R] for-16:9, \f[V]1610\f[R] for 16:10, \f[V]149\f[R] for 14:9, \f[V]141\f[R]-for 1.41:1, \f[V]54\f[R] for 5:4, \f[V]32\f[R] for 3:2)-.TP-\f[V]beameroption\f[R]-add extra beamer option with \f[V]\[rs]setbeameroption{}\f[R]-.TP-\f[V]institute\f[R]-author affiliations: can be a list when there are multiple authors-.TP-\f[V]logo\f[R]-logo image for slides-.TP-\f[V]navigation\f[R]-controls navigation symbols (default is \f[V]empty\f[R] for no-navigation symbols; other valid values are \f[V]frame\f[R],-\f[V]vertical\f[R], and \f[V]horizontal\f[R])-.TP-\f[V]section-titles\f[R]-enables \[lq]title pages\[rq] for new sections (default is true)-.TP-\f[V]theme\f[R], \f[V]colortheme\f[R], \f[V]fonttheme\f[R], \f[V]innertheme\f[R], \f[V]outertheme\f[R]-beamer themes-.TP-\f[V]themeoptions\f[R]-options for LaTeX beamer themes (a list).-.TP-\f[V]titlegraphic\f[R]-image for title slide-.SS Variables for PowerPoint-.PP-These variables control the visual aspects of a slide show that are not-easily controlled via templates.-.TP-\f[V]monofont\f[R]-font to use for code.-.SS Variables for LaTeX-.PP-Pandoc uses these variables when creating a PDF with a LaTeX engine.-.SS Layout-.TP-\f[V]block-headings\f[R]-make \f[V]\[rs]paragraph\f[R] and \f[V]\[rs]subparagraph\f[R] (fourth--and fifth-level headings, or fifth- and sixth-level with book classes)-free-standing rather than run-in; requires further formatting to-distinguish from \f[V]\[rs]subsubsection\f[R] (third- or fourth-level-headings).-Instead of using this option, KOMA-Script can adjust headings more-extensively:-.RS-.IP-.nf-\f[C]-----documentclass: scrartcl-header-includes: |- \[rs]RedeclareSectionCommand[- beforeskip=-10pt plus -2pt minus -1pt,- afterskip=1sp plus -1sp minus 1sp,- font=\[rs]normalfont\[rs]itshape]{paragraph}- \[rs]RedeclareSectionCommand[- beforeskip=-10pt plus -2pt minus -1pt,- afterskip=1sp plus -1sp minus 1sp,- font=\[rs]normalfont\[rs]scshape,- indent=0pt]{subparagraph}-\&...-\f[R]-.fi-.RE-.TP-\f[V]classoption\f[R]-option for document class, e.g.\ \f[V]oneside\f[R]; repeat for multiple-options:-.RS-.IP-.nf-\f[C]-----classoption:-- twocolumn-- landscape-\&...-\f[R]-.fi-.RE-.TP-\f[V]documentclass\f[R]-document class: usually one of the standard classes, \f[V]article\f[R],-\f[V]book\f[R], and \f[V]report\f[R]; the KOMA-Script equivalents,-\f[V]scrartcl\f[R], \f[V]scrbook\f[R], and \f[V]scrreprt\f[R], which-default to smaller margins; or \f[V]memoir\f[R]-.TP-\f[V]geometry\f[R]-option for \f[V]geometry\f[R] package, e.g.\ \f[V]margin=1in\f[R];-repeat for multiple options:-.RS-.IP-.nf-\f[C]-----geometry:-- top=30mm-- left=20mm-- heightrounded-\&...-\f[R]-.fi-.RE-.TP-\f[V]hyperrefoptions\f[R]-option for \f[V]hyperref\f[R] package, e.g.\ \f[V]linktoc=all\f[R];-repeat for multiple options:-.RS-.IP-.nf-\f[C]-----hyperrefoptions:-- linktoc=all-- pdfwindowui-- pdfpagemode=FullScreen-\&...-\f[R]-.fi-.RE-.TP-\f[V]indent\f[R]-if true, pandoc will use document class settings for indentation (the-default LaTeX template otherwise removes indentation and adds space-between paragraphs)-.TP-\f[V]linestretch\f[R]-adjusts line spacing using the \f[V]setspace\f[R] package,-e.g.\ \f[V]1.25\f[R], \f[V]1.5\f[R]-.TP-\f[V]margin-left\f[R], \f[V]margin-right\f[R], \f[V]margin-top\f[R], \f[V]margin-bottom\f[R]-sets margins if \f[V]geometry\f[R] is not used (otherwise-\f[V]geometry\f[R] overrides these)-.TP-\f[V]pagestyle\f[R]-control \f[V]\[rs]pagestyle{}\f[R]: the default article class supports-\f[V]plain\f[R] (default), \f[V]empty\f[R] (no running heads or page-numbers), and \f[V]headings\f[R] (section titles in running heads)-.TP-\f[V]papersize\f[R]-paper size, e.g.\ \f[V]letter\f[R], \f[V]a4\f[R]-.TP-\f[V]secnumdepth\f[R]-numbering depth for sections (with \f[V]--number-sections\f[R] option or-\f[V]numbersections\f[R] variable)-.TP-\f[V]beamerarticle\f[R]-produce an article from Beamer slides-.SS Fonts-.TP-\f[V]fontenc\f[R]-allows font encoding to be specified through \f[V]fontenc\f[R] package-(with \f[V]pdflatex\f[R]); default is \f[V]T1\f[R] (see LaTeX font-encodings guide)-.TP-\f[V]fontfamily\f[R]-font package for use with \f[V]pdflatex\f[R]: TeX Live includes many-options, documented in the LaTeX Font Catalogue.-The default is Latin Modern.-.TP-\f[V]fontfamilyoptions\f[R]-options for package used as \f[V]fontfamily\f[R]; repeat for multiple-options.-For example, to use the Libertine font with proportional lowercase-(old-style) figures through the \f[V]libertinus\f[R] package:-.RS-.IP-.nf-\f[C]-----fontfamily: libertinus-fontfamilyoptions:-- osf-- p-\&...-\f[R]-.fi-.RE-.TP-\f[V]fontsize\f[R]-font size for body text.-The standard classes allow 10pt, 11pt, and 12pt.-To use another size, set \f[V]documentclass\f[R] to one of the-KOMA-Script classes, such as \f[V]scrartcl\f[R] or \f[V]scrbook\f[R].-.TP-\f[V]mainfont\f[R], \f[V]sansfont\f[R], \f[V]monofont\f[R], \f[V]mathfont\f[R], \f[V]CJKmainfont\f[R]-font families for use with \f[V]xelatex\f[R] or \f[V]lualatex\f[R]: take-the name of any system font, using the \f[V]fontspec\f[R] package.-\f[V]CJKmainfont\f[R] uses the \f[V]xecjk\f[R] package.-.TP-\f[V]mainfontoptions\f[R], \f[V]sansfontoptions\f[R], \f[V]monofontoptions\f[R], \f[V]mathfontoptions\f[R], \f[V]CJKoptions\f[R]-options to use with \f[V]mainfont\f[R], \f[V]sansfont\f[R],-\f[V]monofont\f[R], \f[V]mathfont\f[R], \f[V]CJKmainfont\f[R] in-\f[V]xelatex\f[R] and \f[V]lualatex\f[R].-Allow for any choices available through \f[V]fontspec\f[R]; repeat for-multiple options.-For example, to use the TeX Gyre version of Palatino with lowercase-figures:-.RS-.IP-.nf-\f[C]-----mainfont: TeX Gyre Pagella-mainfontoptions:-- Numbers=Lowercase-- Numbers=Proportional-\&...-\f[R]-.fi-.RE-.TP-\f[V]microtypeoptions\f[R]-options to pass to the microtype package-.SS Links-.TP-\f[V]colorlinks\f[R]-add color to link text; automatically enabled if any of-\f[V]linkcolor\f[R], \f[V]filecolor\f[R], \f[V]citecolor\f[R],-\f[V]urlcolor\f[R], or \f[V]toccolor\f[R] are set-.TP-\f[V]boxlinks\f[R]-add visible box around links (has no effect if \f[V]colorlinks\f[R] is-set)-.TP-\f[V]linkcolor\f[R], \f[V]filecolor\f[R], \f[V]citecolor\f[R], \f[V]urlcolor\f[R], \f[V]toccolor\f[R]-color for internal links, external links, citation links, linked URLs,-and links in table of contents, respectively: uses options allowed by-\f[V]xcolor\f[R], including the \f[V]dvipsnames\f[R],-\f[V]svgnames\f[R], and \f[V]x11names\f[R] lists-.TP-\f[V]links-as-notes\f[R]-causes links to be printed as footnotes-.SS Front matter-.TP-\f[V]lof\f[R], \f[V]lot\f[R]-include list of figures, list of tables-.TP-\f[V]thanks\f[R]-contents of acknowledgments footnote after document title-.TP-\f[V]toc\f[R]-include table of contents (can also be set using-\f[V]--toc/--table-of-contents\f[R])-.TP-\f[V]toc-depth\f[R]-level of section to include in table of contents-.SS BibLaTeX Bibliographies-.PP-These variables function when using BibLaTeX for citation rendering.-.TP-\f[V]biblatexoptions\f[R]-list of options for biblatex-.TP-\f[V]biblio-style\f[R]-bibliography style, when used with \f[V]--natbib\f[R] and-\f[V]--biblatex\f[R]-.TP-\f[V]biblio-title\f[R]-bibliography title, when used with \f[V]--natbib\f[R] and-\f[V]--biblatex\f[R]-.TP-\f[V]bibliography\f[R]-bibliography to use for resolving references-.TP-\f[V]natbiboptions\f[R]-list of options for natbib-.SS Variables for ConTeXt-.PP-Pandoc uses these variables when creating a PDF with ConTeXt.-.TP-\f[V]fontsize\f[R]-font size for body text (e.g.\ \f[V]10pt\f[R], \f[V]12pt\f[R])-.TP-\f[V]headertext\f[R], \f[V]footertext\f[R]-text to be placed in running header or footer (see ConTeXt Headers and-Footers); repeat up to four times for different placement-.TP-\f[V]indenting\f[R]-controls indentation of paragraphs, e.g.\ \f[V]yes,small,next\f[R] (see-ConTeXt Indentation); repeat for multiple options-.TP-\f[V]interlinespace\f[R]-adjusts line spacing, e.g.\ \f[V]4ex\f[R] (using-\f[V]setupinterlinespace\f[R]); repeat for multiple options-.TP-\f[V]layout\f[R]-options for page margins and text arrangement (see ConTeXt Layout);-repeat for multiple options-.TP-\f[V]linkcolor\f[R], \f[V]contrastcolor\f[R]-color for links outside and inside a page, e.g.\ \f[V]red\f[R],-\f[V]blue\f[R] (see ConTeXt Color)-.TP-\f[V]linkstyle\f[R]-typeface style for links, e.g.\ \f[V]normal\f[R], \f[V]bold\f[R],-\f[V]slanted\f[R], \f[V]boldslanted\f[R], \f[V]type\f[R], \f[V]cap\f[R],-\f[V]small\f[R]-.TP-\f[V]lof\f[R], \f[V]lot\f[R]-include list of figures, list of tables-.TP-\f[V]mainfont\f[R], \f[V]sansfont\f[R], \f[V]monofont\f[R], \f[V]mathfont\f[R]-font families: take the name of any system font (see ConTeXt Font-Switching)-.TP-\f[V]margin-left\f[R], \f[V]margin-right\f[R], \f[V]margin-top\f[R], \f[V]margin-bottom\f[R]-sets margins, if \f[V]layout\f[R] is not used (otherwise-\f[V]layout\f[R] overrides these)-.TP-\f[V]pagenumbering\f[R]-page number style and location (using \f[V]setuppagenumbering\f[R]);-repeat for multiple options-.TP-\f[V]papersize\f[R]-paper size, e.g.\ \f[V]letter\f[R], \f[V]A4\f[R], \f[V]landscape\f[R]-(see ConTeXt Paper Setup); repeat for multiple options-.TP-\f[V]pdfa\f[R]-adds to the preamble the setup necessary to generate PDF/A of the type-specified, e.g.\ \f[V]1a:2005\f[R], \f[V]2a\f[R].-If no type is specified (i.e.\ the value is set to True, by e.g.-\f[V]--metadata=pdfa\f[R] or \f[V]pdfa: true\f[R] in a YAML metadata-block), \f[V]1b:2005\f[R] will be used as default, for reasons of-backwards compatibility.-Using \f[V]--variable=pdfa\f[R] without specified value is not-supported.-To successfully generate PDF/A the required ICC color profiles have to-be available and the content and all included files (such as images)-have to be standard-conforming.-The ICC profiles and output intent may be specified using the variables-\f[V]pdfaiccprofile\f[R] and \f[V]pdfaintent\f[R].-See also ConTeXt PDFA for more details.-.TP-\f[V]pdfaiccprofile\f[R]-when used in conjunction with \f[V]pdfa\f[R], specifies the ICC profile-to use in the PDF, e.g.\ \f[V]default.cmyk\f[R].-If left unspecified, \f[V]sRGB.icc\f[R] is used as default.-May be repeated to include multiple profiles.-Note that the profiles have to be available on the system.-They can be obtained from ConTeXt ICC Profiles.-.TP-\f[V]pdfaintent\f[R]-when used in conjunction with \f[V]pdfa\f[R], specifies the output-intent for the colors,-e.g.\ \f[V]ISO coated v2 300\[rs]letterpercent\[rs]space (ECI)\f[R] If-left unspecified, \f[V]sRGB IEC61966-2.1\f[R] is used as default.-.TP-\f[V]toc\f[R]-include table of contents (can also be set using-\f[V]--toc/--table-of-contents\f[R])-.TP-\f[V]whitespace\f[R]-spacing between paragraphs, e.g.\ \f[V]none\f[R], \f[V]small\f[R] (using-\f[V]setupwhitespace\f[R])-.TP-\f[V]includesource\f[R]-include all source documents as file attachments in the PDF file-.SS Variables for \f[V]wkhtmltopdf\f[R]-.PP-Pandoc uses these variables when creating a PDF with-\f[V]wkhtmltopdf\f[R].-The \f[V]--css\f[R] option also affects the output.-.TP-\f[V]footer-html\f[R], \f[V]header-html\f[R]-add information to the header and footer-.TP-\f[V]margin-left\f[R], \f[V]margin-right\f[R], \f[V]margin-top\f[R], \f[V]margin-bottom\f[R]-set the page margins-.TP-\f[V]papersize\f[R]-sets the PDF paper size-.SS Variables for man pages-.TP-\f[V]adjusting\f[R]-adjusts text to left (\f[V]l\f[R]), right (\f[V]r\f[R]), center-(\f[V]c\f[R]), or both (\f[V]b\f[R]) margins-.TP-\f[V]footer\f[R]-footer in man pages-.TP-\f[V]header\f[R]-header in man pages-.TP-\f[V]hyphenate\f[R]-if \f[V]true\f[R] (the default), hyphenation will be used-.TP-\f[V]section\f[R]-section number in man pages-.SS Variables for ms-.TP-\f[V]fontfamily\f[R]-font family (e.g.\ \f[V]T\f[R] or \f[V]P\f[R])-.TP-\f[V]indent\f[R]-paragraph indent (e.g.\ \f[V]2m\f[R])-.TP-\f[V]lineheight\f[R]-line height (e.g.\ \f[V]12p\f[R])-.TP-\f[V]pointsize\f[R]-point size (e.g.\ \f[V]10p\f[R])-.SS Variables set automatically-.PP-Pandoc sets these variables automatically in response to options or-document contents; users can also modify them.-These vary depending on the output format, and include the following:-.TP-\f[V]body\f[R]-body of document-.TP-\f[V]date-meta\f[R]-the \f[V]date\f[R] variable converted to ISO 8601 YYYY-MM-DD, included-in all HTML based formats (dzslides, epub, html, html4, html5, revealjs,-s5, slideous, slidy).-The recognized formats for \f[V]date\f[R] are: \f[V]mm/dd/yyyy\f[R],-\f[V]mm/dd/yy\f[R], \f[V]yyyy-mm-dd\f[R] (ISO 8601),-\f[V]dd MM yyyy\f[R] (e.g.\ either \f[V]02 Apr 2018\f[R] or-\f[V]02 April 2018\f[R]), \f[V]MM dd, yyyy\f[R]-(e.g.\ \f[V]Apr. 02, 2018\f[R] or-\f[V]April 02, 2018),\f[R]yyyy[mm[dd]]\f[V](e.g.\f[R]20180402,-\f[V]201804\f[R] or \f[V]2018\f[R]).-.TP-\f[V]header-includes\f[R]-contents specified by \f[V]-H/--include-in-header\f[R] (may have-multiple values)-.TP-\f[V]include-before\f[R]-contents specified by \f[V]-B/--include-before-body\f[R] (may have-multiple values)-.TP-\f[V]include-after\f[R]-contents specified by \f[V]-A/--include-after-body\f[R] (may have-multiple values)-.TP-\f[V]meta-json\f[R]-JSON representation of all of the document\[cq]s metadata.-Field values are transformed to the selected output format.-.TP-\f[V]numbersections\f[R]-non-null value if \f[V]-N/--number-sections\f[R] was specified-.TP-\f[V]sourcefile\f[R], \f[V]outputfile\f[R]-source and destination filenames, as given on the command line.-\f[V]sourcefile\f[R] can also be a list if input comes from multiple-files, or empty if input is from stdin.-You can use the following snippet in your template to distinguish them:-.RS-.IP-.nf-\f[C]-$if(sourcefile)$-$for(sourcefile)$-$sourcefile$-$endfor$-$else$-(stdin)-$endif$-\f[R]-.fi-.PP-Similarly, \f[V]outputfile\f[R] can be \f[V]-\f[R] if output goes to the-terminal.-.PP-If you need absolute paths, use e.g.\ \f[V]$curdir$/$sourcefile$\f[R].-.RE-.TP-\f[V]curdir\f[R]-working directory from which pandoc is run.-.TP-\f[V]toc\f[R]-non-null value if \f[V]--toc/--table-of-contents\f[R] was specified-.TP-\f[V]toc-title\f[R]-title of table of contents (works only with EPUB, HTML, revealjs,-opendocument, odt, docx, pptx, beamer, LaTeX)-.SH EXTENSIONS-.PP-The behavior of some of the readers and writers can be adjusted by-enabling or disabling various extensions.-.PP-An extension can be enabled by adding \f[V]+EXTENSION\f[R] to the format-name and disabled by adding \f[V]-EXTENSION\f[R].-For example, \f[V]--from markdown_strict+footnotes\f[R] is strict-Markdown with footnotes enabled, while-\f[V]--from markdown-footnotes-pipe_tables\f[R] is pandoc\[cq]s Markdown-without footnotes or pipe tables.-.PP-The markdown reader and writer make by far the most use of extensions.-Extensions only used by them are therefore covered in the section-Pandoc\[cq]s Markdown below (see Markdown variants for-\f[V]commonmark\f[R] and \f[V]gfm\f[R]).-In the following, extensions that also work for other formats are-covered.-.PP-Note that markdown extensions added to the \f[V]ipynb\f[R] format affect-Markdown cells in Jupyter notebooks (as do command-line options like-\f[V]--atx-headers\f[R]).-.SS Typography-.SS Extension: \f[V]smart\f[R]-.PP-Interpret straight quotes as curly quotes, \f[V]---\f[R] as em-dashes,-\f[V]--\f[R] as en-dashes, and \f[V]...\f[R] as ellipses.-Nonbreaking spaces are inserted after certain abbreviations, such as-\[lq]Mr.\[rq]-.PP-This extension can be enabled/disabled for the following formats:-.TP-input formats-\f[V]markdown\f[R], \f[V]commonmark\f[R], \f[V]latex\f[R],-\f[V]mediawiki\f[R], \f[V]org\f[R], \f[V]rst\f[R], \f[V]twiki\f[R],-\f[V]html\f[R]-.TP-output formats-\f[V]markdown\f[R], \f[V]latex\f[R], \f[V]context\f[R], \f[V]rst\f[R]-.TP-enabled by default in-\f[V]markdown\f[R], \f[V]latex\f[R], \f[V]context\f[R] (both input and-output)-.PP-Note: If you are \f[I]writing\f[R] Markdown, then the \f[V]smart\f[R]-extension has the reverse effect: what would have been curly quotes-comes out straight.-.PP-In LaTeX, \f[V]smart\f[R] means to use the standard TeX ligatures for-quotation marks (\f[V]\[ga]\[ga]\f[R] and \f[V]\[aq]\[aq]\f[R] for-double quotes, \f[V]\[ga]\f[R] and \f[V]\[aq]\f[R] for single quotes)-and dashes (\f[V]--\f[R] for en-dash and \f[V]---\f[R] for em-dash).-If \f[V]smart\f[R] is disabled, then in reading LaTeX pandoc will parse-these characters literally.-In writing LaTeX, enabling \f[V]smart\f[R] tells pandoc to use the-ligatures when possible; if \f[V]smart\f[R] is disabled pandoc will use-unicode quotation mark and dash characters.-.SS Headings and sections-.SS Extension: \f[V]auto_identifiers\f[R]-.PP-A heading without an explicitly specified identifier will be-automatically assigned a unique identifier based on the heading text.-.PP-This extension can be enabled/disabled for the following formats:-.TP-input formats-\f[V]markdown\f[R], \f[V]latex\f[R], \f[V]rst\f[R], \f[V]mediawiki\f[R],-\f[V]textile\f[R]-.TP-output formats-\f[V]markdown\f[R], \f[V]muse\f[R]-.TP-enabled by default in-\f[V]markdown\f[R], \f[V]muse\f[R]-.PP-The default algorithm used to derive the identifier from the heading-text is:-.IP \[bu] 2-Remove all formatting, links, etc.-.IP \[bu] 2-Remove all footnotes.-.IP \[bu] 2-Remove all non-alphanumeric characters, except underscores, hyphens, and-periods.-.IP \[bu] 2-Replace all spaces and newlines with hyphens.-.IP \[bu] 2-Convert all alphabetic characters to lowercase.-.IP \[bu] 2-Remove everything up to the first letter (identifiers may not begin with-a number or punctuation mark).-.IP \[bu] 2-If nothing is left after this, use the identifier \f[V]section\f[R].-.PP-Thus, for example,-.RS -14n-.IP-.nf-\f[C]- Heading Identifier- ----------------------------- ------------------------------ Heading identifiers in HTML heading-identifiers-in-html- Ma\[^i]tre d\[aq]h\[^o]tel ma\[^i]tre-dh\[^o]tel- *Dogs*?--in *my* house? dogs--in-my-house- [HTML], [S5], or [RTF]? html-s5-or-rtf- 3. Applications applications- 33 section-\f[R]-.fi-.RE-.PP-These rules should, in most cases, allow one to determine the identifier-from the heading text.-The exception is when several headings have the same text; in this case,-the first will get an identifier as described above; the second will get-the same identifier with \f[V]-1\f[R] appended; the third with-\f[V]-2\f[R]; and so on.-.PP-(However, a different algorithm is used if-\f[V]gfm_auto_identifiers\f[R] is enabled; see below.)-.PP-These identifiers are used to provide link targets in the table of-contents generated by the \f[V]--toc|--table-of-contents\f[R] option.-They also make it easy to provide links from one section of a document-to another.-A link to this section, for example, might look like this:-.IP-.nf-\f[C]-See the section on-[heading identifiers](#heading-identifiers-in-html-latex-and-context).-\f[R]-.fi-.PP-Note, however, that this method of providing links to sections works-only in HTML, LaTeX, and ConTeXt formats.-.PP-If the \f[V]--section-divs\f[R] option is specified, then each section-will be wrapped in a \f[V]section\f[R] (or a \f[V]div\f[R], if-\f[V]html4\f[R] was specified), and the identifier will be attached to-the enclosing \f[V]<section>\f[R] (or \f[V]<div>\f[R]) tag rather than-the heading itself.-This allows entire sections to be manipulated using JavaScript or-treated differently in CSS.-.SS Extension: \f[V]ascii_identifiers\f[R]-.PP-Causes the identifiers produced by \f[V]auto_identifiers\f[R] to be pure-ASCII.-Accents are stripped off of accented Latin letters, and non-Latin-letters are omitted.-.SS Extension: \f[V]gfm_auto_identifiers\f[R]-.PP-Changes the algorithm used by \f[V]auto_identifiers\f[R] to conform to-GitHub\[cq]s method.-Spaces are converted to dashes (\f[V]-\f[R]), uppercase characters to-lowercase characters, and punctuation characters other than \f[V]-\f[R]-and \f[V]_\f[R] are removed.-Emojis are replaced by their names.-.SS Math Input-.PP-The extensions \f[V]tex_math_dollars\f[R],-\f[V]tex_math_single_backslash\f[R], and-\f[V]tex_math_double_backslash\f[R] are described in the section about-Pandoc\[cq]s Markdown.-.PP-However, they can also be used with HTML input.-This is handy for reading web pages formatted using MathJax, for-example.-.SS Raw HTML/TeX-.PP-The following extensions are described in more detail in their-respective sections of Pandoc\[cq]s Markdown:-.IP \[bu] 2-\f[V]raw_html\f[R] allows HTML elements which are not representable in-pandoc\[cq]s AST to be parsed as raw HTML.-By default, this is disabled for HTML input.-.IP \[bu] 2-\f[V]raw_tex\f[R] allows raw LaTeX, TeX, and ConTeXt to be included in a-document.-This extension can be enabled/disabled for the following formats (in-addition to \f[V]markdown\f[R]):-.RS 2-.TP-input formats-\f[V]latex\f[R], \f[V]textile\f[R], \f[V]html\f[R] (environments,-\f[V]\[rs]ref\f[R], and \f[V]\[rs]eqref\f[R] only), \f[V]ipynb\f[R]-.TP-output formats-\f[V]textile\f[R], \f[V]commonmark\f[R]-.PP-Note: as applied to \f[V]ipynb\f[R], \f[V]raw_html\f[R] and-\f[V]raw_tex\f[R] affect not only raw TeX in markdown cells, but data-with mime type \f[V]text/html\f[R] in output cells.-Since the \f[V]ipynb\f[R] reader attempts to preserve the richest-possible outputs when several options are given, you will get best-results if you disable \f[V]raw_html\f[R] and \f[V]raw_tex\f[R] when-converting to formats like \f[V]docx\f[R] which don\[cq]t allow raw-\f[V]html\f[R] or \f[V]tex\f[R].-.RE-.IP \[bu] 2-\f[V]native_divs\f[R] causes HTML \f[V]div\f[R] elements to be parsed as-native pandoc Div blocks.-If you want them to be parsed as raw HTML, use-\f[V]-f html-native_divs+raw_html\f[R].-.IP \[bu] 2-\f[V]native_spans\f[R] causes HTML \f[V]span\f[R] elements to be parsed-as native pandoc Span inlines.-If you want them to be parsed as raw HTML, use-\f[V]-f html-native_spans+raw_html\f[R].-If you want to drop all \f[V]div\f[R]s and \f[V]span\f[R]s when-converting HTML to Markdown, you can use-\f[V]pandoc -f html-native_divs-native_spans -t markdown\f[R].-.SS Literate Haskell support-.SS Extension: \f[V]literate_haskell\f[R]-.PP-Treat the document as literate Haskell source.-.PP-This extension can be enabled/disabled for the following formats:-.TP-input formats-\f[V]markdown\f[R], \f[V]rst\f[R], \f[V]latex\f[R]-.TP-output formats-\f[V]markdown\f[R], \f[V]rst\f[R], \f[V]latex\f[R], \f[V]html\f[R]-.PP-If you append \f[V]+lhs\f[R] (or \f[V]+literate_haskell\f[R]) to one of-the formats above, pandoc will treat the document as literate Haskell-source.-This means that-.IP \[bu] 2-In Markdown input, \[lq]bird track\[rq] sections will be parsed as-Haskell code rather than block quotations.-Text between \f[V]\[rs]begin{code}\f[R] and \f[V]\[rs]end{code}\f[R]-will also be treated as Haskell code.-For ATX-style headings the character `=' will be used instead of `#'.-.IP \[bu] 2-In Markdown output, code blocks with classes \f[V]haskell\f[R] and-\f[V]literate\f[R] will be rendered using bird tracks, and block-quotations will be indented one space, so they will not be treated as-Haskell code.-In addition, headings will be rendered setext-style (with underlines)-rather than ATX-style (with `#' characters).-(This is because ghc treats `#' characters in column 1 as introducing-line numbers.)-.IP \[bu] 2-In restructured text input, \[lq]bird track\[rq] sections will be parsed-as Haskell code.-.IP \[bu] 2-In restructured text output, code blocks with class \f[V]haskell\f[R]-will be rendered using bird tracks.-.IP \[bu] 2-In LaTeX input, text in \f[V]code\f[R] environments will be parsed as-Haskell code.-.IP \[bu] 2-In LaTeX output, code blocks with class \f[V]haskell\f[R] will be-rendered inside \f[V]code\f[R] environments.-.IP \[bu] 2-In HTML output, code blocks with class \f[V]haskell\f[R] will be-rendered with class \f[V]literatehaskell\f[R] and bird tracks.-.PP-Examples:-.IP-.nf-\f[C]-pandoc -f markdown+lhs -t html-\f[R]-.fi-.PP-reads literate Haskell source formatted with Markdown conventions and-writes ordinary HTML (without bird tracks).-.IP-.nf-\f[C]-pandoc -f markdown+lhs -t html+lhs-\f[R]-.fi-.PP-writes HTML with the Haskell code in bird tracks, so it can be copied-and pasted as literate Haskell source.-.PP-Note that GHC expects the bird tracks in the first column, so indented-literate code blocks (e.g.\ inside an itemized environment) will not be-picked up by the Haskell compiler.-.SS Other extensions-.SS Extension: \f[V]empty_paragraphs\f[R]-.PP-Allows empty paragraphs.-By default empty paragraphs are omitted.-.PP-This extension can be enabled/disabled for the following formats:-.TP-input formats-\f[V]docx\f[R], \f[V]html\f[R]-.TP-output formats-\f[V]docx\f[R], \f[V]odt\f[R], \f[V]opendocument\f[R], \f[V]html\f[R]-.SS Extension: \f[V]native_numbering\f[R]-.PP-Enables native numbering of figures and tables.-Enumeration starts at 1.-.PP-This extension can be enabled/disabled for the following formats:-.TP-output formats-\f[V]odt\f[R], \f[V]opendocument\f[R], \f[V]docx\f[R]-.SS Extension: \f[V]xrefs_name\f[R]-.PP-Links to headings, figures and tables inside the document are-substituted with cross-references that will use the name or caption of-the referenced item.-The original link text is replaced once the generated document is-refreshed.-This extension can be combined with \f[V]xrefs_number\f[R] in which case-numbers will appear before the name.-.PP-Text in cross-references is only made consistent with the referenced-item once the document has been refreshed.-.PP-This extension can be enabled/disabled for the following formats:-.TP-output formats-\f[V]odt\f[R], \f[V]opendocument\f[R]-.SS Extension: \f[V]xrefs_number\f[R]-.PP-Links to headings, figures and tables inside the document are-substituted with cross-references that will use the number of the-referenced item.-The original link text is discarded.-This extension can be combined with \f[V]xrefs_name\f[R] in which case-the name or caption numbers will appear after the number.-.PP-For the \f[V]xrefs_number\f[R] to be useful heading numbers must be-enabled in the generated document, also table and figure captions must-be enabled using for example the \f[V]native_numbering\f[R] extension.-.PP-Numbers in cross-references are only visible in the final document once-it has been refreshed.-.PP-This extension can be enabled/disabled for the following formats:-.TP-output formats-\f[V]odt\f[R], \f[V]opendocument\f[R]-.SS Extension: \f[V]styles\f[R]-.PP-When converting from docx, read all docx styles as divs (for paragraph-styles) and spans (for character styles) regardless of whether pandoc-understands the meaning of these styles.-This can be used with docx custom styles.-Disabled by default.-.TP-input formats-\f[V]docx\f[R]-.SS Extension: \f[V]amuse\f[R]-.PP-In the \f[V]muse\f[R] input format, this enables Text::Amuse extensions-to Emacs Muse markup.-.SS Extension: \f[V]raw_markdown\f[R]-.PP-In the \f[V]ipynb\f[R] input format, this causes Markdown cells to be-included as raw Markdown blocks (allowing lossless round-tripping)-rather than being parsed.-Use this only when you are targeting \f[V]ipynb\f[R] or a markdown-based-output format.-.SS Extension: \f[V]citations\f[R]-.PP-When the \f[V]citations\f[R] extension is enabled in \f[V]org\f[R],-org-cite and org-ref style citations will be parsed as native pandoc-citations.-.PP-When \f[V]citations\f[R] is enabled in \f[V]docx\f[R], citations-inserted by Zotero or Mendeley or EndNote plugins will be parsed as-native pandoc citations.-(Otherwise, the formatted citations generated by the bibliographic-software will be parsed as regular text.)-.SS Extension: \f[V]fancy_lists\f[R]-.PP-Some aspects of Pandoc\[cq]s Markdown fancy lists are also accepted in-\f[V]org\f[R] input, mimicking the option-\f[V]org-list-allow-alphabetical\f[R] in Emacs.-As in Org Mode, enabling this extension allows lowercase and uppercase-alphabetical markers for ordered lists to be parsed in addition to-arabic ones.-Note that for Org, this does not include roman numerals or the-\f[V]#\f[R] placeholder that are enabled by the extension in-Pandoc\[cq]s Markdown.-.SS Extension: \f[V]element_citations\f[R]-.PP-In the \f[V]jats\f[R] output formats, this causes reference items to be-replaced with \f[V]<element-citation>\f[R] elements.-These elements are not influenced by CSL styles, but all information on-the item is included in tags.-.SS Extension: \f[V]ntb\f[R]-.PP-In the \f[V]context\f[R] output format this enables the use of Natural-Tables (TABLE) instead of the default Extreme Tables (xtables).-Natural tables allow more fine-grained global customization but come at-a performance penalty compared to extreme tables.-.SH PANDOC\[cq]S MARKDOWN-.PP-Pandoc understands an extended and slightly revised version of John-Gruber\[cq]s Markdown syntax.-This document explains the syntax, noting differences from original-Markdown.-Except where noted, these differences can be suppressed by using the-\f[V]markdown_strict\f[R] format instead of \f[V]markdown\f[R].-Extensions can be enabled or disabled to specify the behavior more-granularly.-They are described in the following.-See also Extensions above, for extensions that work also on other-formats.-.SS Philosophy-.PP-Markdown is designed to be easy to write, and, even more importantly,-easy to read:-.RS-.PP-A Markdown-formatted document should be publishable as-is, as plain-text, without looking like it\[cq]s been marked up with tags or-formatting instructions.-\[en] John Gruber-.RE-.PP-This principle has guided pandoc\[cq]s decisions in finding syntax for-tables, footnotes, and other extensions.-.PP-There is, however, one respect in which pandoc\[cq]s aims are different-from the original aims of Markdown.-Whereas Markdown was originally designed with HTML generation in mind,-pandoc is designed for multiple output formats.-Thus, while pandoc allows the embedding of raw HTML, it discourages it,-and provides other, non-HTMLish ways of representing important document-elements like definition lists, tables, mathematics, and footnotes.-.SS Paragraphs-.PP-A paragraph is one or more lines of text followed by one or more blank-lines.-Newlines are treated as spaces, so you can reflow your paragraphs as you-like.-If you need a hard line break, put two or more spaces at the end of a-line.-.SS Extension: \f[V]escaped_line_breaks\f[R]-.PP-A backslash followed by a newline is also a hard line break.-Note: in multiline and grid table cells, this is the only way to create-a hard line break, since trailing spaces in the cells are ignored.-.SS Headings-.PP-There are two kinds of headings: Setext and ATX.-.SS Setext-style headings-.PP-A setext-style heading is a line of text \[lq]underlined\[rq] with a row-of \f[V]=\f[R] signs (for a level-one heading) or \f[V]-\f[R] signs (for-a level-two heading):-.IP-.nf-\f[C]-A level-one heading-===================--A level-two heading---------------------\f[R]-.fi-.PP-The heading text can contain inline formatting, such as emphasis (see-Inline formatting, below).-.SS ATX-style headings-.PP-An ATX-style heading consists of one to six \f[V]#\f[R] signs and a line-of text, optionally followed by any number of \f[V]#\f[R] signs.-The number of \f[V]#\f[R] signs at the beginning of the line is the-heading level:-.IP-.nf-\f[C]-## A level-two heading--### A level-three heading ###-\f[R]-.fi-.PP-As with setext-style headings, the heading text can contain formatting:-.IP-.nf-\f[C]-# A level-one heading with a [link](/url) and *emphasis*-\f[R]-.fi-.SS Extension: \f[V]blank_before_header\f[R]-.PP-Original Markdown syntax does not require a blank line before a heading.-Pandoc does require this (except, of course, at the beginning of the-document).-The reason for the requirement is that it is all too easy for a-\f[V]#\f[R] to end up at the beginning of a line by accident (perhaps-through line wrapping).-Consider, for example:-.IP-.nf-\f[C]-I like several of their flavors of ice cream:-#22, for example, and #5.-\f[R]-.fi-.SS Extension: \f[V]space_in_atx_header\f[R]-.PP-Many Markdown implementations do not require a space between the opening-\f[V]#\f[R]s of an ATX heading and the heading text, so that-\f[V]#5 bolt\f[R] and \f[V]#hashtag\f[R] count as headings.-With this extension, pandoc does require the space.-.SS Heading identifiers-.PP-See also the \f[V]auto_identifiers\f[R] extension above.-.SS Extension: \f[V]header_attributes\f[R]-.PP-Headings can be assigned attributes using this syntax at the end of the-line containing the heading text:-.IP-.nf-\f[C]-{#identifier .class .class key=value key=value}-\f[R]-.fi-.PP-Thus, for example, the following headings will all be assigned the-identifier \f[V]foo\f[R]:-.IP-.nf-\f[C]-# My heading {#foo}--## My heading ## {#foo}--My other heading {#foo}-----------------\f[R]-.fi-.PP-(This syntax is compatible with PHP Markdown Extra.)-.PP-Note that although this syntax allows assignment of classes and-key/value attributes, writers generally don\[cq]t use all of this-information.-Identifiers, classes, and key/value attributes are used in HTML and-HTML-based formats such as EPUB and slidy.-Identifiers are used for labels and link anchors in the LaTeX, ConTeXt,-Textile, Jira markup, and AsciiDoc writers.-.PP-Headings with the class \f[V]unnumbered\f[R] will not be numbered, even-if \f[V]--number-sections\f[R] is specified.-A single hyphen (\f[V]-\f[R]) in an attribute context is equivalent to-\f[V].unnumbered\f[R], and preferable in non-English documents.-So,-.IP-.nf-\f[C]-# My heading {-}-\f[R]-.fi-.PP-is just the same as-.IP-.nf-\f[C]-# My heading {.unnumbered}-\f[R]-.fi-.PP-If the \f[V]unlisted\f[R] class is present in addition to-\f[V]unnumbered\f[R], the heading will not be included in a table of-contents.-(Currently this feature is only implemented for certain formats: those-based on LaTeX and HTML, PowerPoint, and RTF.)-.SS Extension: \f[V]implicit_header_references\f[R]-.PP-Pandoc behaves as if reference links have been defined for each heading.-So, to link to a heading-.IP-.nf-\f[C]-# Heading identifiers in HTML-\f[R]-.fi-.PP-you can simply write-.IP-.nf-\f[C]-[Heading identifiers in HTML]-\f[R]-.fi-.PP-or-.IP-.nf-\f[C]-[Heading identifiers in HTML][]-\f[R]-.fi-.PP-or-.IP-.nf-\f[C]-[the section on heading identifiers][heading identifiers in-HTML]-\f[R]-.fi-.PP-instead of giving the identifier explicitly:-.IP-.nf-\f[C]-[Heading identifiers in HTML](#heading-identifiers-in-html)-\f[R]-.fi-.PP-If there are multiple headings with identical text, the corresponding-reference will link to the first one only, and you will need to use-explicit links to link to the others, as described above.-.PP-Like regular reference links, these references are case-insensitive.-.PP-Explicit link reference definitions always take priority over implicit-heading references.-So, in the following example, the link will point to \f[V]bar\f[R], not-to \f[V]#foo\f[R]:-.IP-.nf-\f[C]-# Foo--[foo]: bar--See [foo]-\f[R]-.fi-.SS Block quotations-.PP-Markdown uses email conventions for quoting blocks of text.-A block quotation is one or more paragraphs or other block elements-(such as lists or headings), with each line preceded by a \f[V]>\f[R]-character and an optional space.-(The \f[V]>\f[R] need not start at the left margin, but it should not be-indented more than three spaces.)-.IP-.nf-\f[C]-> This is a block quote. This-> paragraph has two lines.->-> 1. This is a list inside a block quote.-> 2. Second item.-\f[R]-.fi-.PP-A \[lq]lazy\[rq] form, which requires the \f[V]>\f[R] character only on-the first line of each block, is also allowed:-.IP-.nf-\f[C]-> This is a block quote. This-paragraph has two lines.--> 1. This is a list inside a block quote.-2. Second item.-\f[R]-.fi-.PP-Among the block elements that can be contained in a block quote are-other block quotes.-That is, block quotes can be nested:-.IP-.nf-\f[C]-> This is a block quote.->-> > A block quote within a block quote.-\f[R]-.fi-.PP-If the \f[V]>\f[R] character is followed by an optional space, that-space will be considered part of the block quote marker and not part of-the indentation of the contents.-Thus, to put an indented code block in a block quote, you need five-spaces after the \f[V]>\f[R]:-.IP-.nf-\f[C]-> code-\f[R]-.fi-.SS Extension: \f[V]blank_before_blockquote\f[R]-.PP-Original Markdown syntax does not require a blank line before a block-quote.-Pandoc does require this (except, of course, at the beginning of the-document).-The reason for the requirement is that it is all too easy for a-\f[V]>\f[R] to end up at the beginning of a line by accident (perhaps-through line wrapping).-So, unless the \f[V]markdown_strict\f[R] format is used, the following-does not produce a nested block quote in pandoc:-.IP-.nf-\f[C]-> This is a block quote.->> Nested.-\f[R]-.fi-.SS Verbatim (code) blocks-.SS Indented code blocks-.PP-A block of text indented four spaces (or one tab) is treated as verbatim-text: that is, special characters do not trigger special formatting, and-all spaces and line breaks are preserved.-For example,-.IP-.nf-\f[C]- if (a > 3) {- moveShip(5 * gravity, DOWN);- }-\f[R]-.fi-.PP-The initial (four space or one tab) indentation is not considered part-of the verbatim text, and is removed in the output.-.PP-Note: blank lines in the verbatim text need not begin with four spaces.-.SS Fenced code blocks-.SS Extension: \f[V]fenced_code_blocks\f[R]-.PP-In addition to standard indented code blocks, pandoc supports-\f[I]fenced\f[R] code blocks.-These begin with a row of three or more tildes (\f[V]\[ti]\f[R]) and end-with a row of tildes that must be at least as long as the starting row.-Everything between these lines is treated as code.-No indentation is necessary:-.IP-.nf-\f[C]-\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]-if (a > 3) {- moveShip(5 * gravity, DOWN);-}-\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]-\f[R]-.fi-.PP-Like regular code blocks, fenced code blocks must be separated from-surrounding text by blank lines.-.PP-If the code itself contains a row of tildes or backticks, just use a-longer row of tildes or backticks at the start and end:-.IP-.nf-\f[C]-\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]-\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]-code including tildes-\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]-\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]-\f[R]-.fi-.SS Extension: \f[V]backtick_code_blocks\f[R]-.PP-Same as \f[V]fenced_code_blocks\f[R], but uses backticks-(\f[V]\[ga]\f[R]) instead of tildes (\f[V]\[ti]\f[R]).-.SS Extension: \f[V]fenced_code_attributes\f[R]-.PP-Optionally, you may attach attributes to fenced or backtick code block-using this syntax:-.IP-.nf-\f[C]-\[ti]\[ti]\[ti]\[ti] {#mycode .haskell .numberLines startFrom=\[dq]100\[dq]}-qsort [] = []-qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++- qsort (filter (>= x) xs)-\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]\[ti]-\f[R]-.fi-.PP-Here \f[V]mycode\f[R] is an identifier, \f[V]haskell\f[R] and-\f[V]numberLines\f[R] are classes, and \f[V]startFrom\f[R] is an-attribute with value \f[V]100\f[R].-Some output formats can use this information to do syntax highlighting.-Currently, the only output formats that use this information are HTML,-LaTeX, Docx, Ms, and PowerPoint.-If highlighting is supported for your output format and language, then-the code block above will appear highlighted, with numbered lines.-(To see which languages are supported, type-\f[V]pandoc --list-highlight-languages\f[R].)-Otherwise, the code block above will appear as follows:-.IP-.nf-\f[C]-<pre id=\[dq]mycode\[dq] class=\[dq]haskell numberLines\[dq] startFrom=\[dq]100\[dq]>- <code>- ...- </code>-</pre>-\f[R]-.fi-.PP-The \f[V]numberLines\f[R] (or \f[V]number-lines\f[R]) class will cause-the lines of the code block to be numbered, starting with \f[V]1\f[R] or-the value of the \f[V]startFrom\f[R] attribute.-The \f[V]lineAnchors\f[R] (or \f[V]line-anchors\f[R]) class will cause-the lines to be clickable anchors in HTML output.-.PP-A shortcut form can also be used for specifying the language of the code-block:-.IP-.nf-\f[C]-\[ga]\[ga]\[ga]haskell-qsort [] = []-\[ga]\[ga]\[ga]-\f[R]-.fi-.PP-This is equivalent to:-.IP-.nf-\f[C]-\[ga]\[ga]\[ga] {.haskell}-qsort [] = []-\[ga]\[ga]\[ga]-\f[R]-.fi-.PP-If the \f[V]fenced_code_attributes\f[R] extension is disabled, but input-contains class attribute(s) for the code block, the first class-attribute will be printed after the opening fence as a bare word.-.PP-To prevent all highlighting, use the \f[V]--no-highlight\f[R] flag.-To set the highlighting style, use \f[V]--highlight-style\f[R].-For more information on highlighting, see Syntax highlighting, below.-.SS Line blocks-.SS Extension: \f[V]line_blocks\f[R]-.PP-A line block is a sequence of lines beginning with a vertical bar-(\f[V]|\f[R]) followed by a space.-The division into lines will be preserved in the output, as will any-leading spaces; otherwise, the lines will be formatted as Markdown.-This is useful for verse and addresses:-.IP-.nf-\f[C]-| The limerick packs laughs anatomical-| In space that is quite economical.-| But the good ones I\[aq]ve seen-| So seldom are clean-| And the clean ones so seldom are comical--| 200 Main St.-| Berkeley, CA 94718-\f[R]-.fi-.PP-The lines can be hard-wrapped if needed, but the continuation line must-begin with a space.-.IP-.nf-\f[C]-| The Right Honorable Most Venerable and Righteous Samuel L.- Constable, Jr.-| 200 Main St.-| Berkeley, CA 94718-\f[R]-.fi-.PP-Inline formatting (such as emphasis) is allowed in the content, but not-block-level formatting (such as block quotes or lists).-.PP-This syntax is borrowed from reStructuredText.-.SS Lists-.SS Bullet lists-.PP-A bullet list is a list of bulleted list items.-A bulleted list item begins with a bullet (\f[V]*\f[R], \f[V]+\f[R], or-\f[V]-\f[R]).-Here is a simple example:-.IP-.nf-\f[C]-* one-* two-* three-\f[R]-.fi-.PP-This will produce a \[lq]compact\[rq] list.-If you want a \[lq]loose\[rq] list, in which each item is formatted as a-paragraph, put spaces between the items:-.IP-.nf-\f[C]-* one--* two--* three-\f[R]-.fi-.PP-The bullets need not be flush with the left margin; they may be indented-one, two, or three spaces.-The bullet must be followed by whitespace.-.PP-List items look best if subsequent lines are flush with the first line-(after the bullet):-.IP-.nf-\f[C]-* here is my first- list item.-* and my second.-\f[R]-.fi-.PP-But Markdown also allows a \[lq]lazy\[rq] format:-.IP-.nf-\f[C]-* here is my first-list item.-* and my second.-\f[R]-.fi-.SS Block content in list items-.PP-A list item may contain multiple paragraphs and other block-level-content.-However, subsequent paragraphs must be preceded by a blank line and-indented to line up with the first non-space content after the list-marker.-.IP-.nf-\f[C]- * First paragraph.-- Continued.-- * Second paragraph. With a code block, which must be indented- eight spaces:-- { code }-\f[R]-.fi-.PP-Exception: if the list marker is followed by an indented code block,-which must begin 5 spaces after the list marker, then subsequent-paragraphs must begin two columns after the last character of the list-marker:-.IP-.nf-\f[C]-* code-- continuation paragraph-\f[R]-.fi-.PP-List items may include other lists.-In this case the preceding blank line is optional.-The nested list must be indented to line up with the first non-space-character after the list marker of the containing list item.-.IP-.nf-\f[C]-* fruits- + apples- - macintosh- - red delicious- + pears- + peaches-* vegetables- + broccoli- + chard-\f[R]-.fi-.PP-As noted above, Markdown allows you to write list items-\[lq]lazily,\[rq] instead of indenting continuation lines.-However, if there are multiple paragraphs or other blocks in a list-item, the first line of each must be indented.-.IP-.nf-\f[C]-+ A lazy, lazy, list-item.--+ Another one; this looks-bad but is legal.-- Second paragraph of second-list item.-\f[R]-.fi-.SS Ordered lists-.PP-Ordered lists work just like bulleted lists, except that the items begin-with enumerators rather than bullets.-.PP-In original Markdown, enumerators are decimal numbers followed by a-period and a space.-The numbers themselves are ignored, so there is no difference between-this list:-.IP-.nf-\f[C]-1. one-2. two-3. three-\f[R]-.fi-.PP-and this one:-.IP-.nf-\f[C]-5. one-7. two-1. three-\f[R]-.fi-.SS Extension: \f[V]fancy_lists\f[R]-.PP-Unlike original Markdown, pandoc allows ordered list items to be marked-with uppercase and lowercase letters and roman numerals, in addition to-Arabic numerals.-List markers may be enclosed in parentheses or followed by a single-right-parenthesis or period.-They must be separated from the text that follows by at least one space,-and, if the list marker is a capital letter with a period, by at least-two spaces.-.PP-The \f[V]fancy_lists\f[R] extension also allows `\f[V]#\f[R]' to be used-as an ordered list marker in place of a numeral:-.IP-.nf-\f[C]-#. one-#. two-\f[R]-.fi-.SS Extension: \f[V]startnum\f[R]-.PP-Pandoc also pays attention to the type of list marker used, and to the-starting number, and both of these are preserved where possible in the-output format.-Thus, the following yields a list with numbers followed by a single-parenthesis, starting with 9, and a sublist with lowercase roman-numerals:-.IP-.nf-\f[C]- 9) Ninth-10) Tenth-11) Eleventh- i. subone- ii. subtwo- iii. subthree-\f[R]-.fi-.PP-Pandoc will start a new list each time a different type of list marker-is used.-So, the following will create three lists:-.IP-.nf-\f[C]-(2) Two-(5) Three-1. Four-* Five-\f[R]-.fi-.PP-If default list markers are desired, use \f[V]#.\f[R]:-.IP-.nf-\f[C]-#. one-#. two-#. three-\f[R]-.fi-.SS Extension: \f[V]task_lists\f[R]-.PP-Pandoc supports task lists, using the syntax of GitHub-Flavored-Markdown.-.IP-.nf-\f[C]-- [ ] an unchecked task list item-- [x] checked item-\f[R]-.fi-.SS Definition lists-.SS Extension: \f[V]definition_lists\f[R]-.PP-Pandoc supports definition lists, using the syntax of PHP Markdown Extra-with some extensions.-.IP-.nf-\f[C]-Term 1--: Definition 1--Term 2 with *inline markup*--: Definition 2-- { some code, part of Definition 2 }-- Third paragraph of definition 2.-\f[R]-.fi-.PP-Each term must fit on one line, which may optionally be followed by a-blank line, and must be followed by one or more definitions.-A definition begins with a colon or tilde, which may be indented one or-two spaces.-.PP-A term may have multiple definitions, and each definition may consist of-one or more block elements (paragraph, code block, list, etc.), each-indented four spaces or one tab stop.-The body of the definition (not including the first line) should be-indented four spaces.-However, as with other Markdown lists, you can \[lq]lazily\[rq] omit-indentation except at the beginning of a paragraph or other block-element:-.IP-.nf-\f[C]-Term 1--: Definition-with lazy continuation.-- Second paragraph of the definition.-\f[R]-.fi-.PP-If you leave space before the definition (as in the example above), the-text of the definition will be treated as a paragraph.-In some output formats, this will mean greater spacing between-term/definition pairs.-For a more compact definition list, omit the space before the-definition:-.IP-.nf-\f[C]-Term 1- \[ti] Definition 1--Term 2- \[ti] Definition 2a- \[ti] Definition 2b-\f[R]-.fi-.PP-Note that space between items in a definition list is required.-(A variant that loosens this requirement, but disallows \[lq]lazy\[rq]-hard wrapping, can be activated with \f[V]compact_definition_lists\f[R]:-see Non-default extensions, below.)-.SS Numbered example lists-.SS Extension: \f[V]example_lists\f[R]-.PP-The special list marker \f[V]\[at]\f[R] can be used for sequentially-numbered examples.-The first list item with a \f[V]\[at]\f[R] marker will be numbered `1',-the next `2', and so on, throughout the document.-The numbered examples need not occur in a single list; each new list-using \f[V]\[at]\f[R] will take up where the last stopped.-So, for example:-.IP-.nf-\f[C]-(\[at]) My first example will be numbered (1).-(\[at]) My second example will be numbered (2).--Explanation of examples.--(\[at]) My third example will be numbered (3).-\f[R]-.fi-.PP-Numbered examples can be labeled and referred to elsewhere in the-document:-.IP-.nf-\f[C]-(\[at]good) This is a good example.--As (\[at]good) illustrates, ...-\f[R]-.fi-.PP-The label can be any string of alphanumeric characters, underscores, or-hyphens.-.PP-Note: continuation paragraphs in example lists must always be indented-four spaces, regardless of the length of the list marker.-That is, example lists always behave as if the \f[V]four_space_rule\f[R]-extension is set.-This is because example labels tend to be long, and indenting content to-the first non-space character after the label would be awkward.-.SS Ending a list-.PP-What if you want to put an indented code block after a list?-.IP-.nf-\f[C]-- item one-- item two-- { my code block }-\f[R]-.fi-.PP-Trouble!-Here pandoc (like other Markdown implementations) will treat-\f[V]{ my code block }\f[R] as the second paragraph of item two, and not-as a code block.-.PP-To \[lq]cut off\[rq] the list after item two, you can insert some-non-indented content, like an HTML comment, which won\[cq]t produce-visible output in any format:-.IP-.nf-\f[C]-- item one-- item two--<!-- end of list -->-- { my code block }-\f[R]-.fi-.PP-You can use the same trick if you want two consecutive lists instead of-one big list:-.IP-.nf-\f[C]-1. one-2. two-3. three--<!-- -->--1. uno-2. dos-3. tres-\f[R]-.fi-.SS Horizontal rules-.PP-A line containing a row of three or more \f[V]*\f[R], \f[V]-\f[R], or-\f[V]_\f[R] characters (optionally separated by spaces) produces a-horizontal rule:-.IP-.nf-\f[C]-* * * *------------------\f[R]-.fi-.PP-We strongly recommend that horizontal rules be separated from-surrounding text by blank lines.-If a horizontal rule is not followed by a blank line, pandoc may try to-interpret the lines that follow as a YAML metadata block or a table.-.SS Tables-.PP-Four kinds of tables may be used.-The first three kinds presuppose the use of a fixed-width font, such as-Courier.-The fourth kind can be used with proportionally spaced fonts, as it does-not require lining up columns.-.SS Extension: \f[V]table_captions\f[R]-.PP-A caption may optionally be provided with all 4 kinds of tables (as-illustrated in the examples below).-A caption is a paragraph beginning with the string \f[V]Table:\f[R] (or-just \f[V]:\f[R]), which will be stripped off.-It may appear either before or after the table.-.SS Extension: \f[V]simple_tables\f[R]-.PP-Simple tables look like this:-.IP-.nf-\f[C]- Right Left Center Default-------- ------ ---------- -------- 12 12 12 12- 123 123 123 123- 1 1 1 1--Table: Demonstration of simple table syntax.-\f[R]-.fi-.PP-The header and table rows must each fit on one line.-Column alignments are determined by the position of the header text-relative to the dashed line below it:-.IP \[bu] 2-If the dashed line is flush with the header text on the right side but-extends beyond it on the left, the column is right-aligned.-.IP \[bu] 2-If the dashed line is flush with the header text on the left side but-extends beyond it on the right, the column is left-aligned.-.IP \[bu] 2-If the dashed line extends beyond the header text on both sides, the-column is centered.-.IP \[bu] 2-If the dashed line is flush with the header text on both sides, the-default alignment is used (in most cases, this will be left).-.PP-The table must end with a blank line, or a line of dashes followed by a-blank line.-.PP-The column header row may be omitted, provided a dashed line is used to-end the table.-For example:-.IP-.nf-\f[C]-------- ------ ---------- -------- 12 12 12 12- 123 123 123 123- 1 1 1 1-------- ------ ---------- --------\f[R]-.fi-.PP-When the header row is omitted, column alignments are determined on the-basis of the first line of the table body.-So, in the tables above, the columns would be right, left, center, and-right aligned, respectively.-.SS Extension: \f[V]multiline_tables\f[R]-.PP-Multiline tables allow header and table rows to span multiple lines of-text (but cells that span multiple columns or rows of the table are not-supported).-Here is an example:-.IP-.nf-\f[C]--------------------------------------------------------------- Centered Default Right Left- Header Aligned Aligned Aligned------------ ------- --------------- -------------------------- First row 12.0 Example of a row that- spans multiple lines.-- Second row 5.0 Here\[aq]s another one. Note- the blank line between- rows.----------------------------------------------------------------Table: Here\[aq]s the caption. It, too, may span-multiple lines.-\f[R]-.fi-.PP-These work like simple tables, but with the following differences:-.IP \[bu] 2-They must begin with a row of dashes, before the header text (unless the-header row is omitted).-.IP \[bu] 2-They must end with a row of dashes, then a blank line.-.IP \[bu] 2-The rows must be separated by blank lines.-.PP-In multiline tables, the table parser pays attention to the widths of-the columns, and the writers try to reproduce these relative widths in-the output.-So, if you find that one of the columns is too narrow in the output, try-widening it in the Markdown source.-.PP-The header may be omitted in multiline tables as well as simple tables:-.IP-.nf-\f[C]------------ ------- --------------- -------------------------- First row 12.0 Example of a row that- spans multiple lines.-- Second row 5.0 Here\[aq]s another one. Note- the blank line between- rows.------------ ------- --------------- ---------------------------: Here\[aq]s a multiline table without a header.-\f[R]-.fi-.PP-It is possible for a multiline table to have just one row, but the row-should be followed by a blank line (and then the row of dashes that ends-the table), or the table may be interpreted as a simple table.-.SS Extension: \f[V]grid_tables\f[R]-.PP-Grid tables look like this:-.IP-.nf-\f[C]-: Sample grid table.--+---------------+---------------+--------------------+-| Fruit | Price | Advantages |-+===============+===============+====================+-| Bananas | $1.34 | - built-in wrapper |-| | | - bright color |-+---------------+---------------+--------------------+-| Oranges | $2.10 | - cures scurvy |-| | | - tasty |-+---------------+---------------+--------------------+-\f[R]-.fi-.PP-The row of \f[V]=\f[R]s separates the header from the table body, and-can be omitted for a headerless table.-The cells of grid tables may contain arbitrary block elements (multiple-paragraphs, code blocks, lists, etc.).-Cells that span multiple columns or rows are not supported.-Grid tables can be created easily using Emacs\[cq] table-mode-(\f[V]M-x table-insert\f[R]).-.PP-Alignments can be specified as with pipe tables, by putting colons at-the boundaries of the separator line after the header:-.IP-.nf-\f[C]-+---------------+---------------+--------------------+-| Right | Left | Centered |-+==============:+:==============+:==================:+-| Bananas | $1.34 | built-in wrapper |-+---------------+---------------+--------------------+-\f[R]-.fi-.PP-For headerless tables, the colons go on the top line instead:-.IP-.nf-\f[C]-+--------------:+:--------------+:------------------:+-| Right | Left | Centered |-+---------------+---------------+--------------------+-\f[R]-.fi-.SS Grid Table Limitations-.PP-Pandoc does not support grid tables with row spans or column spans.-This means that neither variable numbers of columns across rows nor-variable numbers of rows across columns are supported by Pandoc.-All grid tables must have the same number of columns in each row, and-the same number of rows in each column.-For example, the Docutils sample grid tables will not render as expected-with Pandoc.-.SS Extension: \f[V]pipe_tables\f[R]-.PP-Pipe tables look like this:-.IP-.nf-\f[C]-| Right | Left | Default | Center |-|------:|:-----|---------|:------:|-| 12 | 12 | 12 | 12 |-| 123 | 123 | 123 | 123 |-| 1 | 1 | 1 | 1 |-- : Demonstration of pipe table syntax.-\f[R]-.fi-.PP-The syntax is identical to PHP Markdown Extra tables.-The beginning and ending pipe characters are optional, but pipes are-required between all columns.-The colons indicate column alignment as shown.-The header cannot be omitted.-To simulate a headerless table, include a header with blank cells.-.PP-Since the pipes indicate column boundaries, columns need not be-vertically aligned, as they are in the above example.-So, this is a perfectly legal (though ugly) pipe table:-.IP-.nf-\f[C]-fruit| price------|-----:-apple|2.05-pear|1.37-orange|3.09-\f[R]-.fi-.PP-The cells of pipe tables cannot contain block elements like paragraphs-and lists, and cannot span multiple lines.-If any line of the markdown source is longer than the column width (see-\f[V]--columns\f[R]), then the table will take up the full text width-and the cell contents will wrap, with the relative cell widths-determined by the number of dashes in the line separating the table-header from the table body.-(For example \f[V]---|-\f[R] would make the first column 3/4 and the-second column 1/4 of the full text width.)-On the other hand, if no lines are wider than column width, then cell-contents will not be wrapped, and the cells will be sized to their-contents.-.PP-Note: pandoc also recognizes pipe tables of the following form, as can-be produced by Emacs\[cq] orgtbl-mode:-.IP-.nf-\f[C]-| One | Two |-|-----+-------|-| my | table |-| is | nice |-\f[R]-.fi-.PP-The difference is that \f[V]+\f[R] is used instead of \f[V]|\f[R].-Other orgtbl features are not supported.-In particular, to get non-default column alignment, you\[cq]ll need to-add colons as above.-.SS Metadata blocks-.SS Extension: \f[V]pandoc_title_block\f[R]-.PP-If the file begins with a title block-.IP-.nf-\f[C]-% title-% author(s) (separated by semicolons)-% date-\f[R]-.fi-.PP-it will be parsed as bibliographic information, not regular text.-(It will be used, for example, in the title of standalone LaTeX or HTML-output.)-The block may contain just a title, a title and an author, or all three-elements.-If you want to include an author but no title, or a title and a date but-no author, you need a blank line:-.IP-.nf-\f[C]-%-% Author-\f[R]-.fi-.IP-.nf-\f[C]-% My title-%-% June 15, 2006-\f[R]-.fi-.PP-The title may occupy multiple lines, but continuation lines must begin-with leading space, thus:-.IP-.nf-\f[C]-% My title- on multiple lines-\f[R]-.fi-.PP-If a document has multiple authors, the authors may be put on separate-lines with leading space, or separated by semicolons, or both.-So, all of the following are equivalent:-.IP-.nf-\f[C]-% Author One- Author Two-\f[R]-.fi-.IP-.nf-\f[C]-% Author One; Author Two-\f[R]-.fi-.IP-.nf-\f[C]-% Author One;- Author Two-\f[R]-.fi-.PP-The date must fit on one line.-.PP-All three metadata fields may contain standard inline formatting-(italics, links, footnotes, etc.).-.PP-Title blocks will always be parsed, but they will affect the output only-when the \f[V]--standalone\f[R] (\f[V]-s\f[R]) option is chosen.-In HTML output, titles will appear twice: once in the document head-\[en] this is the title that will appear at the top of the window in a-browser \[en] and once at the beginning of the document body.-The title in the document head can have an optional prefix attached-(\f[V]--title-prefix\f[R] or \f[V]-T\f[R] option).-The title in the body appears as an H1 element with class-\[lq]title\[rq], so it can be suppressed or reformatted with CSS.-If a title prefix is specified with \f[V]-T\f[R] and no title block-appears in the document, the title prefix will be used by itself as the-HTML title.-.PP-The man page writer extracts a title, man page section number, and other-header and footer information from the title line.-The title is assumed to be the first word on the title line, which may-optionally end with a (single-digit) section number in parentheses.-(There should be no space between the title and the parentheses.)-Anything after this is assumed to be additional footer and header text.-A single pipe character (\f[V]|\f[R]) should be used to separate the-footer text from the header text.-Thus,-.IP-.nf-\f[C]-% PANDOC(1)-\f[R]-.fi-.PP-will yield a man page with the title \f[V]PANDOC\f[R] and section 1.-.IP-.nf-\f[C]-% PANDOC(1) Pandoc User Manuals-\f[R]-.fi-.PP-will also have \[lq]Pandoc User Manuals\[rq] in the footer.-.IP-.nf-\f[C]-% PANDOC(1) Pandoc User Manuals | Version 4.0-\f[R]-.fi-.PP-will also have \[lq]Version 4.0\[rq] in the header.-.SS Extension: \f[V]yaml_metadata_block\f[R]-.PP-A YAML metadata block is a valid YAML object, delimited by a line of-three hyphens (\f[V]---\f[R]) at the top and a line of three hyphens-(\f[V]---\f[R]) or three dots (\f[V]...\f[R]) at the bottom.-The initial line \f[V]---\f[R] must not be followed by a blank line.-A YAML metadata block may occur anywhere in the document, but if it is-not at the beginning, it must be preceded by a blank line.-.PP-Note that, because of the way pandoc concatenates input files when-several are provided, you may also keep the metadata in a separate YAML-file and pass it to pandoc as an argument, along with your Markdown-files:-.IP-.nf-\f[C]-pandoc chap1.md chap2.md chap3.md metadata.yaml -s -o book.html-\f[R]-.fi-.PP-Just be sure that the YAML file begins with \f[V]---\f[R] and ends with-\f[V]---\f[R] or \f[V]...\f[R].-Alternatively, you can use the \f[V]--metadata-file\f[R] option.-Using that approach however, you cannot reference content (like-footnotes) from the main markdown input document.-.PP-Metadata will be taken from the fields of the YAML object and added to-any existing document metadata.-Metadata can contain lists and objects (nested arbitrarily), but all-string scalars will be interpreted as Markdown.-Fields with names ending in an underscore will be ignored by pandoc.-(They may be given a role by external processors.)-Field names must not be interpretable as YAML numbers or boolean values-(so, for example, \f[V]yes\f[R], \f[V]True\f[R], and \f[V]15\f[R] cannot-be used as field names).-.PP-A document may contain multiple metadata blocks.-If two metadata blocks attempt to set the same field, the value from the-second block will be taken.-.PP-Each metadata block is handled internally as an independent YAML-document.-This means, for example, that any YAML anchors defined in a block cannot-be referenced in another block.-.PP-When pandoc is used with \f[V]-t markdown\f[R] to create a Markdown-document, a YAML metadata block will be produced only if the-\f[V]-s/--standalone\f[R] option is used.-All of the metadata will appear in a single block at the beginning of-the document.-.PP-Note that YAML escaping rules must be followed.-Thus, for example, if a title contains a colon, it must be quoted, and-if it contains a backslash escape, then it must be ensured that it is-not treated as a YAML escape sequence.-The pipe character (\f[V]|\f[R]) can be used to begin an indented block-that will be interpreted literally, without need for escaping.-This form is necessary when the field contains blank lines or-block-level formatting:-.IP-.nf-\f[C]-----title: \[aq]This is the title: it contains a colon\[aq]-author:-- Author One-- Author Two-keywords: [nothing, nothingness]-abstract: |- This is the abstract.-- It consists of two paragraphs.-\&...-\f[R]-.fi-.PP-The literal block after the \f[V]|\f[R] must be indented relative to the-line containing the \f[V]|\f[R].-If it is not, the YAML will be invalid and pandoc will not interpret it-as metadata.-For an overview of the complex rules governing YAML, see the Wikipedia-entry on YAML syntax.-.PP-Template variables will be set automatically from the metadata.-Thus, for example, in writing HTML, the variable \f[V]abstract\f[R] will-be set to the HTML equivalent of the Markdown in the \f[V]abstract\f[R]-field:-.IP-.nf-\f[C]-<p>This is the abstract.</p>-<p>It consists of two paragraphs.</p>-\f[R]-.fi-.PP-Variables can contain arbitrary YAML structures, but the template must-match this structure.-The \f[V]author\f[R] variable in the default templates expects a simple-list or string, but can be changed to support more complicated-structures.-The following combination, for example, would add an affiliation to the-author if one is given:-.IP-.nf-\f[C]-----title: The document title-author:-- name: Author One- affiliation: University of Somewhere-- name: Author Two- affiliation: University of Nowhere-\&...-\f[R]-.fi-.PP-To use the structured authors in the example above, you would need a-custom template:-.IP-.nf-\f[C]-$for(author)$-$if(author.name)$-$author.name$$if(author.affiliation)$ ($author.affiliation$)$endif$-$else$-$author$-$endif$-$endfor$-\f[R]-.fi-.PP-Raw content to include in the document\[cq]s header may be specified-using \f[V]header-includes\f[R]; however, it is important to mark up-this content as raw code for a particular output format, using the-\f[V]raw_attribute\f[R] extension, or it will be interpreted as-markdown.-For example:-.IP-.nf-\f[C]-header-includes:-- |- \[ga]\[ga]\[ga]{=latex}- \[rs]let\[rs]oldsection\[rs]section- \[rs]renewcommand{\[rs]section}[1]{\[rs]clearpage\[rs]oldsection{#1}}- \[ga]\[ga]\[ga]-\f[R]-.fi-.PP-Note: the \f[V]yaml_metadata_block\f[R] extension works with-\f[V]commonmark\f[R] as well as \f[V]markdown\f[R] (and it is enabled by-default in \f[V]gfm\f[R] and \f[V]commonmark_x\f[R]).-However, in these formats the following restrictions apply:-.IP \[bu] 2-The YAML metadata block must occur at the beginning of the document (and-there can be only one).-If multiple files are given as arguments to pandoc, only the first can-be a YAML metadata block.-.IP \[bu] 2-The leaf nodes of the YAML structure are parsed in isolation from each-other and from the rest of the document.-So, for example, you can\[cq]t use a reference link in these contexts if-the link definition is somewhere else in the document.-.SS Backslash escapes-.SS Extension: \f[V]all_symbols_escapable\f[R]-.PP-Except inside a code block or inline code, any punctuation or space-character preceded by a backslash will be treated literally, even if it-would normally indicate formatting.-Thus, for example, if one writes-.IP-.nf-\f[C]-*\[rs]*hello\[rs]**-\f[R]-.fi-.PP-one will get-.IP-.nf-\f[C]-<em>*hello*</em>-\f[R]-.fi-.PP-instead of-.IP-.nf-\f[C]-<strong>hello</strong>-\f[R]-.fi-.PP-This rule is easier to remember than original Markdown\[cq]s rule, which-allows only the following characters to be backslash-escaped:-.IP-.nf-\f[C]-\[rs]\[ga]*_{}[]()>#+-.!-\f[R]-.fi-.PP-(However, if the \f[V]markdown_strict\f[R] format is used, the original-Markdown rule will be used.)-.PP-A backslash-escaped space is parsed as a nonbreaking space.-In TeX output, it will appear as \f[V]\[ti]\f[R].-In HTML and XML output, it will appear as a literal unicode nonbreaking-space character (note that it will thus actually look-\[lq]invisible\[rq] in the generated HTML source; you can still use the-\f[V]--ascii\f[R] command-line option to make it appear as an explicit-entity).-.PP-A backslash-escaped newline (i.e.\ a backslash occurring at the end of a-line) is parsed as a hard line break.-It will appear in TeX output as \f[V]\[rs]\[rs]\f[R] and in HTML as-\f[V]<br />\f[R].-This is a nice alternative to Markdown\[cq]s \[lq]invisible\[rq] way of-indicating hard line breaks using two trailing spaces on a line.-.PP-Backslash escapes do not work in verbatim contexts.-.SS Inline formatting-.SS Emphasis-.PP-To \f[I]emphasize\f[R] some text, surround it with \f[V]*\f[R]s or-\f[V]_\f[R], like this:-.IP-.nf-\f[C]-This text is _emphasized with underscores_, and this-is *emphasized with asterisks*.-\f[R]-.fi-.PP-Double \f[V]*\f[R] or \f[V]_\f[R] produces \f[B]strong emphasis\f[R]:-.IP-.nf-\f[C]-This is **strong emphasis** and __with underscores__.-\f[R]-.fi-.PP-A \f[V]*\f[R] or \f[V]_\f[R] character surrounded by spaces, or-backslash-escaped, will not trigger emphasis:-.IP-.nf-\f[C]-This is * not emphasized *, and \[rs]*neither is this\[rs]*.-\f[R]-.fi-.SS Extension: \f[V]intraword_underscores\f[R]-.PP-Because \f[V]_\f[R] is sometimes used inside words and identifiers,-pandoc does not interpret a \f[V]_\f[R] surrounded by alphanumeric-characters as an emphasis marker.-If you want to emphasize just part of a word, use \f[V]*\f[R]:-.IP-.nf-\f[C]-feas*ible*, not feas*able*.-\f[R]-.fi-.SS Highlighting-.PP-To highlight text, use the \f[V]mark\f[R] class:-.IP-.nf-\f[C]-[Mark]{.mark}-\f[R]-.fi-.PP-Or, without the \f[V]bracketed_spans\f[R] extension (but with-\f[V]native_spans\f[R]):-.IP-.nf-\f[C]-<span class=\[dq]mark\[dq]>Mark</span>-\f[R]-.fi-.PP-This will work in html output.-.SS Strikeout-.SS Extension: \f[V]strikeout\f[R]-.PP-To strike out a section of text with a horizontal line, begin and end it-with \f[V]\[ti]\[ti]\f[R].-Thus, for example,-.IP-.nf-\f[C]-This \[ti]\[ti]is deleted text.\[ti]\[ti]-\f[R]-.fi-.SS Superscripts and subscripts-.SS Extension: \f[V]superscript\f[R], \f[V]subscript\f[R]-.PP-Superscripts may be written by surrounding the superscripted text by-\f[V]\[ha]\f[R] characters; subscripts may be written by surrounding the-subscripted text by \f[V]\[ti]\f[R] characters.-Thus, for example,-.IP-.nf-\f[C]-H\[ti]2\[ti]O is a liquid. 2\[ha]10\[ha] is 1024.-\f[R]-.fi-.PP-The text between \f[V]\[ha]...\[ha]\f[R] or \f[V]\[ti]...\[ti]\f[R] may-not contain spaces or newlines.-If the superscripted or subscripted text contains spaces, these spaces-must be escaped with backslashes.-(This is to prevent accidental superscripting and subscripting through-the ordinary use of \f[V]\[ti]\f[R] and \f[V]\[ha]\f[R], and also bad-interactions with footnotes.)-Thus, if you want the letter P with `a cat' in subscripts, use-\f[V]P\[ti]a\[rs] cat\[ti]\f[R], not \f[V]P\[ti]a cat\[ti]\f[R].-.SS Verbatim-.PP-To make a short span of text verbatim, put it inside backticks:-.IP-.nf-\f[C]-What is the difference between \[ga]>>=\[ga] and \[ga]>>\[ga]?-\f[R]-.fi-.PP-If the verbatim text includes a backtick, use double backticks:-.IP-.nf-\f[C]-Here is a literal backtick \[ga]\[ga] \[ga] \[ga]\[ga].-\f[R]-.fi-.PP-(The spaces after the opening backticks and before the closing backticks-will be ignored.)-.PP-The general rule is that a verbatim span starts with a string of-consecutive backticks (optionally followed by a space) and ends with a-string of the same number of backticks (optionally preceded by a space).-.PP-Note that backslash-escapes (and other Markdown constructs) do not work-in verbatim contexts:-.IP-.nf-\f[C]-This is a backslash followed by an asterisk: \[ga]\[rs]*\[ga].-\f[R]-.fi-.SS Extension: \f[V]inline_code_attributes\f[R]-.PP-Attributes can be attached to verbatim text, just as with fenced code-blocks:-.IP-.nf-\f[C]-\[ga]<$>\[ga]{.haskell}-\f[R]-.fi-.SS Underline-.PP-To underline text, use the \f[V]underline\f[R] class:-.IP-.nf-\f[C]-[Underline]{.underline}-\f[R]-.fi-.PP-Or, without the \f[V]bracketed_spans\f[R] extension (but with-\f[V]native_spans\f[R]):-.IP-.nf-\f[C]-<span class=\[dq]underline\[dq]>Underline</span>-\f[R]-.fi-.PP-This will work in all output formats that support underline.-.SS Small caps-.PP-To write small caps, use the \f[V]smallcaps\f[R] class:-.IP-.nf-\f[C]-[Small caps]{.smallcaps}-\f[R]-.fi-.PP-Or, without the \f[V]bracketed_spans\f[R] extension:-.IP-.nf-\f[C]-<span class=\[dq]smallcaps\[dq]>Small caps</span>-\f[R]-.fi-.PP-For compatibility with other Markdown flavors, CSS is also supported:-.IP-.nf-\f[C]-<span style=\[dq]font-variant:small-caps;\[dq]>Small caps</span>-\f[R]-.fi-.PP-This will work in all output formats that support small caps.-.SS Math-.SS Extension: \f[V]tex_math_dollars\f[R]-.PP-Anything between two \f[V]$\f[R] characters will be treated as TeX math.-The opening \f[V]$\f[R] must have a non-space character immediately to-its right, while the closing \f[V]$\f[R] must have a non-space character-immediately to its left, and must not be followed immediately by a-digit.-Thus, \f[V]$20,000 and $30,000\f[R] won\[cq]t parse as math.-If for some reason you need to enclose text in literal \f[V]$\f[R]-characters, backslash-escape them and they won\[cq]t be treated as math-delimiters.-.PP-For display math, use \f[V]$$\f[R] delimiters.-(In this case, the delimiters may be separated from the formula by-whitespace.-However, there can be no blank lines between the opening and closing-\f[V]$$\f[R] delimiters.)-.PP-TeX math will be printed in all output formats.-How it is rendered depends on the output format:-.TP-LaTeX-It will appear verbatim surrounded by \f[V]\[rs](...\[rs])\f[R] (for-inline math) or \f[V]\[rs][...\[rs]]\f[R] (for display math).-.TP-Markdown, Emacs Org mode, ConTeXt, ZimWiki-It will appear verbatim surrounded by \f[V]$...$\f[R] (for inline math)-or \f[V]$$...$$\f[R] (for display math).-.TP-XWiki-It will appear verbatim surrounded by-\f[V]{{formula}}..{{/formula}}\f[R].-.TP-reStructuredText-It will be rendered using an interpreted text role \f[V]:math:\f[R].-.TP-AsciiDoc-For AsciiDoc output format (\f[V]-t asciidoc\f[R]) it will appear-verbatim surrounded by \f[V]latexmath:[$...$]\f[R] (for inline math) or-\f[V][latexmath]++++\[rs][...\[rs]]+++\f[R] (for display math).-For AsciiDoctor output format (\f[V]-t asciidoctor\f[R]) the LaTeX-delimiters (\f[V]$..$\f[R] and \f[V]\[rs][..\[rs]]\f[R]) are omitted.-.TP-Texinfo-It will be rendered inside a \f[V]\[at]math\f[R] command.-.TP-roff man, Jira markup-It will be rendered verbatim without \f[V]$\f[R]\[cq]s.-.TP-MediaWiki, DokuWiki-It will be rendered inside \f[V]<math>\f[R] tags.-.TP-Textile-It will be rendered inside \f[V]<span class=\[dq]math\[dq]>\f[R] tags.-.TP-RTF, OpenDocument-It will be rendered, if possible, using Unicode characters, and will-otherwise appear verbatim.-.TP-ODT-It will be rendered, if possible, using MathML.-.TP-DocBook-If the \f[V]--mathml\f[R] flag is used, it will be rendered using MathML-in an \f[V]inlineequation\f[R] or \f[V]informalequation\f[R] tag.-Otherwise it will be rendered, if possible, using Unicode characters.-.TP-Docx and PowerPoint-It will be rendered using OMML math markup.-.TP-FictionBook2-If the \f[V]--webtex\f[R] option is used, formulas are rendered as-images using CodeCogs or other compatible web service, downloaded and-embedded in the e-book.-Otherwise, they will appear verbatim.-.TP-HTML, Slidy, DZSlides, S5, EPUB-The way math is rendered in HTML will depend on the command-line options-selected.-Therefore see Math rendering in HTML above.-.SS Raw HTML-.SS Extension: \f[V]raw_html\f[R]-.PP-Markdown allows you to insert raw HTML (or DocBook) anywhere in a-document (except verbatim contexts, where \f[V]<\f[R], \f[V]>\f[R], and-\f[V]&\f[R] are interpreted literally).-(Technically this is not an extension, since standard Markdown allows-it, but it has been made an extension so that it can be disabled if-desired.)-.PP-The raw HTML is passed through unchanged in HTML, S5, Slidy, Slideous,-DZSlides, EPUB, Markdown, CommonMark, Emacs Org mode, and Textile-output, and suppressed in other formats.-.PP-For a more explicit way of including raw HTML in a Markdown document,-see the \f[V]raw_attribute\f[R] extension.-.PP-In the CommonMark format, if \f[V]raw_html\f[R] is enabled,-superscripts, subscripts, strikeouts and small capitals will be-represented as HTML.-Otherwise, plain-text fallbacks will be used.-Note that even if \f[V]raw_html\f[R] is disabled, tables will be-rendered with HTML syntax if they cannot use pipe syntax.-.SS Extension: \f[V]markdown_in_html_blocks\f[R]-.PP-Original Markdown allows you to include HTML \[lq]blocks\[rq]: blocks of-HTML between balanced tags that are separated from the surrounding text-with blank lines, and start and end at the left margin.-Within these blocks, everything is interpreted as HTML, not Markdown; so-(for example), \f[V]*\f[R] does not signify emphasis.-.PP-Pandoc behaves this way when the \f[V]markdown_strict\f[R] format is-used; but by default, pandoc interprets material between HTML block tags-as Markdown.-Thus, for example, pandoc will turn-.IP-.nf-\f[C]-<table>-<tr>-<td>*one*</td>-<td>[a link](https://google.com)</td>-</tr>-</table>-\f[R]-.fi-.PP-into-.IP-.nf-\f[C]-<table>-<tr>-<td><em>one</em></td>-<td><a href=\[dq]https://google.com\[dq]>a link</a></td>-</tr>-</table>-\f[R]-.fi-.PP-whereas \f[V]Markdown.pl\f[R] will preserve it as is.-.PP-There is one exception to this rule: text between \f[V]<script>\f[R],-\f[V]<style>\f[R], and \f[V]<textarea>\f[R] tags is not interpreted as-Markdown.-.PP-This departure from original Markdown should make it easier to mix-Markdown with HTML block elements.-For example, one can surround a block of Markdown text with-\f[V]<div>\f[R] tags without preventing it from being interpreted as-Markdown.-.SS Extension: \f[V]native_divs\f[R]-.PP-Use native pandoc \f[V]Div\f[R] blocks for content inside-\f[V]<div>\f[R] tags.-For the most part this should give the same output as-\f[V]markdown_in_html_blocks\f[R], but it makes it easier to write-pandoc filters to manipulate groups of blocks.-.SS Extension: \f[V]native_spans\f[R]-.PP-Use native pandoc \f[V]Span\f[R] blocks for content inside-\f[V]<span>\f[R] tags.-For the most part this should give the same output as-\f[V]raw_html\f[R], but it makes it easier to write pandoc filters to-manipulate groups of inlines.-.SS Extension: \f[V]raw_tex\f[R]-.PP-In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be-included in a document.-Inline TeX commands will be preserved and passed unchanged to the LaTeX-and ConTeXt writers.-Thus, for example, you can use LaTeX to include BibTeX citations:-.IP-.nf-\f[C]-This result was proved in \[rs]cite{jones.1967}.-\f[R]-.fi-.PP-Note that in LaTeX environments, like-.IP-.nf-\f[C]-\[rs]begin{tabular}{|l|l|}\[rs]hline-Age & Frequency \[rs]\[rs] \[rs]hline-18--25 & 15 \[rs]\[rs]-26--35 & 33 \[rs]\[rs]-36--45 & 22 \[rs]\[rs] \[rs]hline-\[rs]end{tabular}-\f[R]-.fi-.PP-the material between the begin and end tags will be interpreted as raw-LaTeX, not as Markdown.-.PP-For a more explicit and flexible way of including raw TeX in a Markdown-document, see the \f[V]raw_attribute\f[R] extension.-.PP-Inline LaTeX is ignored in output formats other than Markdown, LaTeX,-Emacs Org mode, and ConTeXt.-.SS Generic raw attribute-.SS Extension: \f[V]raw_attribute\f[R]-.PP-Inline spans and fenced code blocks with a special kind of attribute-will be parsed as raw content with the designated format.-For example, the following produces a raw roff \f[V]ms\f[R] block:-.IP-.nf-\f[C]-\[ga]\[ga]\[ga]{=ms}-\&.MYMACRO-blah blah-\[ga]\[ga]\[ga]-\f[R]-.fi-.PP-And the following produces a raw \f[V]html\f[R] inline element:-.IP-.nf-\f[C]-This is \[ga]<a>html</a>\[ga]{=html}-\f[R]-.fi-.PP-This can be useful to insert raw xml into \f[V]docx\f[R] documents, e.g.-a pagebreak:-.IP-.nf-\f[C]-\[ga]\[ga]\[ga]{=openxml}-<w:p>- <w:r>- <w:br w:type=\[dq]page\[dq]/>- </w:r>-</w:p>-\[ga]\[ga]\[ga]-\f[R]-.fi-.PP-The format name should match the target format name (see-\f[V]-t/--to\f[R], above, for a list, or use-\f[V]pandoc --list-output-formats\f[R]).-Use \f[V]openxml\f[R] for \f[V]docx\f[R] output, \f[V]opendocument\f[R]-for \f[V]odt\f[R] output, \f[V]html5\f[R] for \f[V]epub3\f[R] output,-\f[V]html4\f[R] for \f[V]epub2\f[R] output, and \f[V]latex\f[R],-\f[V]beamer\f[R], \f[V]ms\f[R], or \f[V]html5\f[R] for \f[V]pdf\f[R]-output (depending on what you use for \f[V]--pdf-engine\f[R]).-.PP-This extension presupposes that the relevant kind of inline code or-fenced code block is enabled.-Thus, for example, to use a raw attribute with a backtick code block,-\f[V]backtick_code_blocks\f[R] must be enabled.-.PP-The raw attribute cannot be combined with regular attributes.-.SS LaTeX macros-.SS Extension: \f[V]latex_macros\f[R]-.PP-When this extension is enabled, pandoc will parse LaTeX macro-definitions and apply the resulting macros to all LaTeX math and raw-LaTeX.-So, for example, the following will work in all output formats, not just-LaTeX:-.IP-.nf-\f[C]-\[rs]newcommand{\[rs]tuple}[1]{\[rs]langle #1 \[rs]rangle}--$\[rs]tuple{a, b, c}$-\f[R]-.fi-.PP-Note that LaTeX macros will not be applied if they occur inside a raw-span or block marked with the \f[V]raw_attribute\f[R] extension.-.PP-When \f[V]latex_macros\f[R] is disabled, the raw LaTeX and math will not-have macros applied.-This is usually a better approach when you are targeting LaTeX or PDF.-.PP-Macro definitions in LaTeX will be passed through as raw LaTeX only if-\f[V]latex_macros\f[R] is not enabled.-Macro definitions in Markdown source (or other formats allowing-\f[V]raw_tex\f[R]) will be passed through regardless of whether-\f[V]latex_macros\f[R] is enabled.-.SS Links-.PP-Markdown allows links to be specified in several ways.-.SS Automatic links-.PP-If you enclose a URL or email address in pointy brackets, it will become-a link:-.IP-.nf-\f[C]-<https://google.com>-<sam\[at]green.eggs.ham>-\f[R]-.fi-.SS Inline links-.PP-An inline link consists of the link text in square brackets, followed by-the URL in parentheses.-(Optionally, the URL can be followed by a link title, in quotes.)-.IP-.nf-\f[C]-This is an [inline link](/url), and here\[aq]s [one with-a title](https://fsf.org \[dq]click here for a good time!\[dq]).-\f[R]-.fi-.PP-There can be no space between the bracketed part and the parenthesized-part.-The link text can contain formatting (such as emphasis), but the title-cannot.-.PP-Email addresses in inline links are not autodetected, so they have to be-prefixed with \f[V]mailto\f[R]:-.IP-.nf-\f[C]-[Write me!](mailto:sam\[at]green.eggs.ham)-\f[R]-.fi-.SS Reference links-.PP-An \f[I]explicit\f[R] reference link has two parts, the link itself and-the link definition, which may occur elsewhere in the document (either-before or after the link).-.PP-The link consists of link text in square brackets, followed by a label-in square brackets.-(There cannot be space between the two unless the-\f[V]spaced_reference_links\f[R] extension is enabled.)-The link definition consists of the bracketed label, followed by a colon-and a space, followed by the URL, and optionally (after a space) a link-title either in quotes or in parentheses.-The label must not be parseable as a citation (assuming the-\f[V]citations\f[R] extension is enabled): citations take precedence-over link labels.-.PP-Here are some examples:-.IP-.nf-\f[C]-[my label 1]: /foo/bar.html \[dq]My title, optional\[dq]-[my label 2]: /foo-[my label 3]: https://fsf.org (The Free Software Foundation)-[my label 4]: /bar#special \[aq]A title in single quotes\[aq]-\f[R]-.fi-.PP-The URL may optionally be surrounded by angle brackets:-.IP-.nf-\f[C]-[my label 5]: <http://foo.bar.baz>-\f[R]-.fi-.PP-The title may go on the next line:-.IP-.nf-\f[C]-[my label 3]: https://fsf.org- \[dq]The Free Software Foundation\[dq]-\f[R]-.fi-.PP-Note that link labels are not case sensitive.-So, this will work:-.IP-.nf-\f[C]-Here is [my link][FOO]--[Foo]: /bar/baz-\f[R]-.fi-.PP-In an \f[I]implicit\f[R] reference link, the second pair of brackets is-empty:-.IP-.nf-\f[C]-See [my website][].--[my website]: http://foo.bar.baz-\f[R]-.fi-.PP-Note: In \f[V]Markdown.pl\f[R] and most other Markdown implementations,-reference link definitions cannot occur in nested constructions such as-list items or block quotes.-Pandoc lifts this arbitrary-seeming restriction.-So the following is fine in pandoc, though not in most other-implementations:-.IP-.nf-\f[C]-> My block [quote].->-> [quote]: /foo-\f[R]-.fi-.SS Extension: \f[V]shortcut_reference_links\f[R]-.PP-In a \f[I]shortcut\f[R] reference link, the second pair of brackets may-be omitted entirely:-.IP-.nf-\f[C]-See [my website].--[my website]: http://foo.bar.baz-\f[R]-.fi-.SS Internal links-.PP-To link to another section of the same document, use the automatically-generated identifier (see Heading identifiers).-For example:-.IP-.nf-\f[C]-See the [Introduction](#introduction).-\f[R]-.fi-.PP-or-.IP-.nf-\f[C]-See the [Introduction].--[Introduction]: #introduction-\f[R]-.fi-.PP-Internal links are currently supported for HTML formats (including HTML-slide shows and EPUB), LaTeX, and ConTeXt.-.SS Images-.PP-A link immediately preceded by a \f[V]!\f[R] will be treated as an-image.-The link text will be used as the image\[cq]s alt text:-.IP-.nf-\f[C]---![movie reel]--[movie reel]: movie.gif-\f[R]-.fi-.SS Extension: \f[V]implicit_figures\f[R]-.PP-An image with nonempty alt text, occurring by itself in a paragraph,-will be rendered as a figure with a caption.-The image\[cq]s alt text will be used as the caption.-.IP-.nf-\f[C]--\f[R]-.fi-.PP-How this is rendered depends on the output format.-Some output formats (e.g.\ RTF) do not yet support figures.-In those formats, you\[cq]ll just get an image in a paragraph by itself,-with no caption.-.PP-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:-.IP-.nf-\f[C]-![This image won\[aq]t be a figure](/url/of/image.png)\[rs]-\f[R]-.fi-.PP-Note that in reveal.js slide shows, an image in a paragraph by itself-that has the \f[V]r-stretch\f[R] class will fill the screen, and the-caption and figure tags will be omitted.-.SS Extension: \f[V]link_attributes\f[R]-.PP-Attributes can be set on links and images:-.IP-.nf-\f[C]-An inline {#id .class width=30 height=20px}-and a reference ![image][ref] with attributes.--[ref]: foo.jpg \[dq]optional title\[dq] {#id .class key=val key2=\[dq]val 2\[dq]}-\f[R]-.fi-.PP-(This syntax is compatible with PHP Markdown Extra when only-\f[V]#id\f[R] and \f[V].class\f[R] are used.)-.PP-For HTML and EPUB, all known HTML5 attributes except \f[V]width\f[R] and-\f[V]height\f[R] (but including \f[V]srcset\f[R] and \f[V]sizes\f[R])-are passed through as is.-Unknown attributes are passed through as custom attributes, with-\f[V]data-\f[R] prepended.-The other writers ignore attributes that are not specifically supported-by their output format.-.PP-The \f[V]width\f[R] and \f[V]height\f[R] attributes on images are-treated specially.-When used without a unit, the unit is assumed to be pixels.-However, any of the following unit identifiers can be used:-\f[V]px\f[R], \f[V]cm\f[R], \f[V]mm\f[R], \f[V]in\f[R], \f[V]inch\f[R]-and \f[V]%\f[R].-There must not be any spaces between the number and the unit.-For example:-.IP-.nf-\f[C]-{ width=50% }-\f[R]-.fi-.IP \[bu] 2-Dimensions may be converted to a form that is compatible with the output-format (for example, dimensions given in pixels will be converted to-inches when converting HTML to LaTeX).-Conversion between pixels and physical measurements is affected by the-\f[V]--dpi\f[R] option (by default, 96 dpi is assumed, unless the image-itself contains dpi information).-.IP \[bu] 2-The \f[V]%\f[R] unit is generally relative to some available space.-For example the above example will render to the following.-.RS 2-.IP \[bu] 2-HTML:-\f[V]<img href=\[dq]file.jpg\[dq] style=\[dq]width: 50%;\[dq] />\f[R]-.IP \[bu] 2-LaTeX:-\f[V]\[rs]includegraphics[width=0.5\[rs]textwidth,height=\[rs]textheight]{file.jpg}\f[R]-(If you\[cq]re using a custom template, you need to configure-\f[V]graphicx\f[R] as in the default template.)-.IP \[bu] 2-ConTeXt:-\f[V]\[rs]externalfigure[file.jpg][width=0.5\[rs]textwidth]\f[R]-.RE-.IP \[bu] 2-Some output formats have a notion of a class (ConTeXt) or a unique-identifier (LaTeX \f[V]\[rs]caption\f[R]), or both (HTML).-.IP \[bu] 2-When no \f[V]width\f[R] or \f[V]height\f[R] attributes are specified,-the fallback is to look at the image resolution and the dpi metadata-embedded in the image file.-.SS Divs and Spans-.PP-Using the \f[V]native_divs\f[R] and \f[V]native_spans\f[R] extensions-(see above), HTML syntax can be used as part of markdown to create-native \f[V]Div\f[R] and \f[V]Span\f[R] elements in the pandoc AST (as-opposed to raw HTML).-However, there is also nicer syntax available:-.SS Extension: \f[V]fenced_divs\f[R]-.PP-Allow special fenced syntax for native \f[V]Div\f[R] blocks.-A Div starts with a fence containing at least three consecutive colons-plus some attributes.-The attributes may optionally be followed by another string of-consecutive colons.-The attribute syntax is exactly as in fenced code blocks (see Extension:-\f[V]fenced_code_attributes\f[R]).-As with fenced code blocks, one can use either attributes in curly-braces or a single unbraced word, which will be treated as a class name.-The Div ends with another line containing a string of at least three-consecutive colons.-The fenced Div should be separated by blank lines from preceding and-following blocks.-.PP-Example:-.IP-.nf-\f[C]-::::: {#special .sidebar}-Here is a paragraph.--And another.-:::::-\f[R]-.fi-.PP-Fenced divs can be nested.-Opening fences are distinguished because they \f[I]must\f[R] have-attributes:-.IP-.nf-\f[C]-::: Warning ::::::-This is a warning.--::: Danger-This is a warning within a warning.-:::-::::::::::::::::::-\f[R]-.fi-.PP-Fences without attributes are always closing fences.-Unlike with fenced code blocks, the number of colons in the closing-fence need not match the number in the opening fence.-However, it can be helpful for visual clarity to use fences of different-lengths to distinguish nested divs from their parents.-.SS Extension: \f[V]bracketed_spans\f[R]-.PP-A bracketed sequence of inlines, as one would use to begin a link, will-be treated as a \f[V]Span\f[R] with attributes if it is followed-immediately by attributes:-.IP-.nf-\f[C]-[This is *some text*]{.class key=\[dq]val\[dq]}-\f[R]-.fi-.SS Footnotes-.SS Extension: \f[V]footnotes\f[R]-.PP-Pandoc\[cq]s Markdown allows footnotes, using the following syntax:-.IP-.nf-\f[C]-Here is a footnote reference,[\[ha]1] and another.[\[ha]longnote]--[\[ha]1]: Here is the footnote.--[\[ha]longnote]: Here\[aq]s one with multiple blocks.-- Subsequent paragraphs are indented to show that they-belong to the previous footnote.-- { some.code }-- The whole paragraph can be indented, or just the first- line. In this way, multi-paragraph footnotes work like- multi-paragraph list items.--This paragraph won\[aq]t be part of the note, because it-isn\[aq]t indented.-\f[R]-.fi-.PP-The identifiers in footnote references may not contain spaces, tabs, or-newlines.-These identifiers are used only to correlate the footnote reference with-the note itself; in the output, footnotes will be numbered sequentially.-.PP-The footnotes themselves need not be placed at the end of the document.-They may appear anywhere except inside other block elements (lists,-block quotes, tables, etc.).-Each footnote should be separated from surrounding content (including-other footnotes) by blank lines.-.SS Extension: \f[V]inline_notes\f[R]-.PP-Inline footnotes are also allowed (though, unlike regular notes, they-cannot contain multiple paragraphs).-The syntax is as follows:-.IP-.nf-\f[C]-Here is an inline note.\[ha][Inline notes are easier to write, since-you don\[aq]t have to pick an identifier and move down to type the-note.]-\f[R]-.fi-.PP-Inline and regular footnotes may be mixed freely.-.SS Citation syntax-.SS Extension: \f[V]citations\f[R]-.PP-To cite a bibliographic item with an identifier foo, use the syntax-\f[V]\[at]foo\f[R].-Normal citations should be included in square brackets, with semicolons-separating distinct items:-.IP-.nf-\f[C]-Blah blah [\[at]doe99; \[at]smith2000; \[at]smith2004].-\f[R]-.fi-.PP-How this is rendered depends on the citation style.-In an author-date style, it might render as-.IP-.nf-\f[C]-Blah blah (Doe 1999, Smith 2000, 2004).-\f[R]-.fi-.PP-In a footnote style, it might render as-.IP-.nf-\f[C]-Blah blah.[\[ha]1]--[\[ha]1]: John Doe, \[dq]Frogs,\[dq] *Journal of Amphibians* 44 (1999);-Susan Smith, \[dq]Flies,\[dq] *Journal of Insects* (2000);-Susan Smith, \[dq]Bees,\[dq] *Journal of Insects* (2004).-\f[R]-.fi-.PP-See the CSL user documentation for more information about CSL styles and-how they affect rendering.-.PP-Unless a citation key starts with a letter, digit, or \f[V]_\f[R], and-contains only alphanumerics and single internal punctuation characters-(\f[V]:.#$%&-+?<>\[ti]/\f[R]), it must be surrounded by curly braces,-which are not considered part of the key.-In \f[V]\[at]Foo_bar.baz.\f[R], the key is \f[V]Foo_bar.baz\f[R] because-the final period is not \f[I]internal\f[R] punctuation, so it is not-included in the key.-In \f[V]\[at]{Foo_bar.baz.}\f[R], the key is \f[V]Foo_bar.baz.\f[R],-including the final period.-In \f[V]\[at]Foo_bar--baz\f[R], the key is \f[V]Foo_bar\f[R] because the-repeated internal punctuation characters terminate the key.-The curly braces are recommended if you use URLs as keys:-\f[V][\[at]{https://example.com/bib?name=foobar&date=2000}, p. 33]\f[R].-.PP-Citation items may optionally include a prefix, a locator, and a suffix.-In-.IP-.nf-\f[C]-Blah blah [see \[at]doe99, pp. 33-35 and *passim*; \[at]smith04, chap. 1].-\f[R]-.fi-.PP-the first item (\f[V]doe99\f[R]) has prefix \f[V]see\f[R], locator-\f[V]pp. 33-35\f[R], and suffix \f[V]and *passim*\f[R].-The second item (\f[V]smith04\f[R]) has locator \f[V]chap. 1\f[R] and no-prefix or suffix.-.PP-Pandoc uses some heuristics to separate the locator from the rest of the-subject.-It is sensitive to the locator terms defined in the CSL locale files.-Either abbreviated or unabbreviated forms are accepted.-In the \f[V]en-US\f[R] locale, locator terms can be written in either-singular or plural forms, as \f[V]book\f[R],-\f[V]bk.\f[R]/\f[V]bks.\f[R]; \f[V]chapter\f[R],-\f[V]chap.\f[R]/\f[V]chaps.\f[R]; \f[V]column\f[R],-\f[V]col.\f[R]/\f[V]cols.\f[R]; \f[V]figure\f[R],-\f[V]fig.\f[R]/\f[V]figs.\f[R]; \f[V]folio\f[R],-\f[V]fol.\f[R]/\f[V]fols.\f[R]; \f[V]number\f[R],-\f[V]no.\f[R]/\f[V]nos.\f[R]; \f[V]line\f[R],-\f[V]l.\f[R]/\f[V]ll.\f[R]; \f[V]note\f[R], \f[V]n.\f[R]/\f[V]nn.\f[R];-\f[V]opus\f[R], \f[V]op.\f[R]/\f[V]opp.\f[R]; \f[V]page\f[R],-\f[V]p.\f[R]/\f[V]pp.\f[R]; \f[V]paragraph\f[R],-\f[V]para.\f[R]/\f[V]paras.\f[R]; \f[V]part\f[R],-\f[V]pt.\f[R]/\f[V]pts.\f[R]; \f[V]section\f[R],-\f[V]sec.\f[R]/\f[V]secs.\f[R]; \f[V]sub verbo\f[R],-\f[V]s.v.\f[R]/\f[V]s.vv.\f[R]; \f[V]verse\f[R],-\f[V]v.\f[R]/\f[V]vv.\f[R]; \f[V]volume\f[R],-\f[V]vol.\f[R]/\f[V]vols.\f[R]; \f[V]\[ps]\f[R]/\f[V]\[ps]\[ps]\f[R];-\f[V]\[sc]\f[R]/\f[V]\[sc]\[sc]\f[R].-If no locator term is used, \[lq]page\[rq] is assumed.-.PP-In complex cases, you can force something to be treated as a locator by-enclosing it in curly braces or prevent parsing the suffix as locator by-prepending curly braces:-.IP-.nf-\f[C]-[\[at]smith{ii, A, D-Z}, with a suffix]-[\[at]smith, {pp. iv, vi-xi, (xv)-(xvii)} with suffix here]-[\[at]smith{}, 99 years later]-\f[R]-.fi-.PP-A minus sign (\f[V]-\f[R]) before the \f[V]\[at]\f[R] will suppress-mention of the author in the citation.-This can be useful when the author is already mentioned in the text:-.IP-.nf-\f[C]-Smith says blah [-\[at]smith04].-\f[R]-.fi-.PP-You can also write an author-in-text citation, by omitting the square-brackets:-.IP-.nf-\f[C]-\[at]smith04 says blah.--\[at]smith04 [p. 33] says blah.-\f[R]-.fi-.PP-This will cause the author\[cq]s name to be rendered, followed by the-bibliographical details.-Use this form when you want to make the citation the subject of a-sentence.-.PP-When you are using a note style, it is usually better to let citeproc-create the footnotes from citations rather than writing an explicit-note.-If you do write an explicit note that contains a citation, note that-normal citations will be put in parentheses, while author-in-text-citations will not.-For this reason, it is sometimes preferable to use the author-in-text-style inside notes when using a note style.-.SS Non-default extensions-.PP-The following Markdown syntax extensions are not enabled by default in-pandoc, but may be enabled by adding \f[V]+EXTENSION\f[R] to the format-name, where \f[V]EXTENSION\f[R] is the name of the extension.-Thus, for example, \f[V]markdown+hard_line_breaks\f[R] is Markdown with-hard line breaks.-.SS Extension: \f[V]rebase_relative_paths\f[R]-.PP-Rewrite relative paths for Markdown links and images, depending on the-path of the file containing the link or image link.-For each link or image, pandoc will compute the directory of the-containing file, relative to the working directory, and prepend the-resulting path to the link or image path.-.PP-The use of this extension is best understood by example.-Suppose you have a subdirectory for each chapter of a book,-\f[V]chap1\f[R], \f[V]chap2\f[R], \f[V]chap3\f[R].-Each contains a file \f[V]text.md\f[R] and a number of images used in-the chapter.-You would like to have \f[V]\f[R] in-\f[V]chap1/text.md\f[R] refer to \f[V]chap1/spider.jpg\f[R] and-\f[V]\f[R] in \f[V]chap2/text.md\f[R] refer to-\f[V]chap2/spider.jpg\f[R].-To do this, use-.IP-.nf-\f[C]-pandoc chap*/*.md -f markdown+rebase_relative_paths-\f[R]-.fi-.PP-Without this extension, you would have to use-\f[V]\f[R] in \f[V]chap1/text.md\f[R] and-\f[V]\f[R] in \f[V]chap2/text.md\f[R].-Links with relative paths will be rewritten in the same way as images.-.PP-Absolute paths and URLs are not changed.-Neither are empty paths or paths consisting entirely of a fragment,-e.g., \f[V]#foo\f[R].-.PP-Note that relative paths in reference links and images will be rewritten-relative to the file containing the link reference definition, not the-file containing the reference link or image itself, if these differ.-.SS Extension: \f[V]attributes\f[R]-.PP-Allows attributes to be attached to any inline or block-level element-when parsing \f[V]commonmark\f[R].-The syntax for the attributes is the same as that used in-\f[V]header_attributes\f[R].-.IP \[bu] 2-Attributes that occur immediately after an inline element affect that-element.-If they follow a space, then they belong to the space.-(Hence, this option subsumes \f[V]inline_code_attributes\f[R] and-\f[V]link_attributes\f[R].)-.IP \[bu] 2-Attributes that occur immediately before a block element, on a line by-themselves, affect that element.-.IP \[bu] 2-Consecutive attribute specifiers may be used, either for blocks or for-inlines.-Their attributes will be combined.-.IP \[bu] 2-Attributes that occur at the end of the text of a Setext or ATX heading-(separated by whitespace from the text) affect the heading element.-(Hence, this option subsumes \f[V]header_attributes\f[R].)-.IP \[bu] 2-Attributes that occur after the opening fence in a fenced code block-affect the code block element.-(Hence, this option subsumes \f[V]fenced_code_attributes\f[R].)-.IP \[bu] 2-Attributes that occur at the end of a reference link definition affect-links that refer to that definition.-.PP-Note that pandoc\[cq]s AST does not currently allow attributes to be-attached to arbitrary elements.-Hence a Span or Div container will be added if needed.-.SS Extension: \f[V]old_dashes\f[R]-.PP-Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes:-\f[V]-\f[R] before a numeral is an en-dash, and \f[V]--\f[R] is an-em-dash.-This option only has an effect if \f[V]smart\f[R] is enabled.-It is selected automatically for \f[V]textile\f[R] input.-.SS Extension: \f[V]angle_brackets_escapable\f[R]-.PP-Allow \f[V]<\f[R] and \f[V]>\f[R] to be backslash-escaped, as they can-be in GitHub flavored Markdown but not original Markdown.-This is implied by pandoc\[cq]s default \f[V]all_symbols_escapable\f[R].-.SS Extension: \f[V]lists_without_preceding_blankline\f[R]-.PP-Allow a list to occur right after a paragraph, with no intervening blank-space.-.SS Extension: \f[V]four_space_rule\f[R]-.PP-Selects the pandoc <= 2.0 behavior for parsing lists, so that four-spaces indent are needed for list item continuation paragraphs.-.SS Extension: \f[V]spaced_reference_links\f[R]-.PP-Allow whitespace between the two components of a reference link, for-example,-.IP-.nf-\f[C]-[foo] [bar].-\f[R]-.fi-.SS Extension: \f[V]hard_line_breaks\f[R]-.PP-Causes all newlines within a paragraph to be interpreted as hard line-breaks instead of spaces.-.SS Extension: \f[V]ignore_line_breaks\f[R]-.PP-Causes newlines within a paragraph to be ignored, rather than being-treated as spaces or as hard line breaks.-This option is intended for use with East Asian languages where spaces-are not used between words, but text is divided into lines for-readability.-.SS Extension: \f[V]east_asian_line_breaks\f[R]-.PP-Causes newlines within a paragraph to be ignored, rather than being-treated as spaces or as hard line breaks, when they occur between two-East Asian wide characters.-This is a better choice than \f[V]ignore_line_breaks\f[R] for texts that-include a mix of East Asian wide characters and other characters.-.SS Extension: \f[V]emoji\f[R]-.PP-Parses textual emojis like \f[V]:smile:\f[R] as Unicode emoticons.-.SS Extension: \f[V]tex_math_single_backslash\f[R]-.PP-Causes anything between \f[V]\[rs](\f[R] and \f[V]\[rs])\f[R] to be-interpreted as inline TeX math, and anything between \f[V]\[rs][\f[R]-and \f[V]\[rs]]\f[R] to be interpreted as display TeX math.-Note: a drawback of this extension is that it precludes escaping-\f[V](\f[R] and \f[V][\f[R].-.SS Extension: \f[V]tex_math_double_backslash\f[R]-.PP-Causes anything between \f[V]\[rs]\[rs](\f[R] and \f[V]\[rs]\[rs])\f[R]-to be interpreted as inline TeX math, and anything between-\f[V]\[rs]\[rs][\f[R] and \f[V]\[rs]\[rs]]\f[R] to be interpreted as-display TeX math.-.SS Extension: \f[V]markdown_attribute\f[R]-.PP-By default, pandoc interprets material inside block-level tags as-Markdown.-This extension changes the behavior so that Markdown is only parsed-inside block-level tags if the tags have the attribute-\f[V]markdown=1\f[R].-.SS Extension: \f[V]mmd_title_block\f[R]-.PP-Enables a MultiMarkdown style title block at the top of the document,-for example:-.IP-.nf-\f[C]-Title: My title-Author: John Doe-Date: September 1, 2008-Comment: This is a sample mmd title block, with- a field spanning multiple lines.-\f[R]-.fi-.PP-See the MultiMarkdown documentation for details.-If \f[V]pandoc_title_block\f[R] or \f[V]yaml_metadata_block\f[R] is-enabled, it will take precedence over \f[V]mmd_title_block\f[R].-.SS Extension: \f[V]abbreviations\f[R]-.PP-Parses PHP Markdown Extra abbreviation keys, like-.IP-.nf-\f[C]-*[HTML]: Hypertext Markup Language-\f[R]-.fi-.PP-Note that the pandoc document model does not support abbreviations, so-if this extension is enabled, abbreviation keys are simply skipped (as-opposed to being parsed as paragraphs).-.SS Extension: \f[V]autolink_bare_uris\f[R]-.PP-Makes all absolute URIs into links, even when not surrounded by pointy-braces \f[V]<...>\f[R].-.SS Extension: \f[V]mmd_link_attributes\f[R]-.PP-Parses multimarkdown style key-value attributes on link and image-references.-This extension should not be confused with the \f[V]link_attributes\f[R]-extension.-.IP-.nf-\f[C]-This is a reference ![image][ref] with multimarkdown attributes.--[ref]: https://path.to/image \[dq]Image title\[dq] width=20px height=30px- id=myId class=\[dq]myClass1 myClass2\[dq]-\f[R]-.fi-.SS Extension: \f[V]mmd_header_identifiers\f[R]-.PP-Parses multimarkdown style heading identifiers (in square brackets,-after the heading but before any trailing \f[V]#\f[R]s in an ATX-heading).-.SS Extension: \f[V]compact_definition_lists\f[R]-.PP-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:-.IP \[bu] 2-No blank line is required between consecutive items of the definition-list.-.IP \[bu] 2-To get a \[lq]tight\[rq] or \[lq]compact\[rq] list, omit space between-consecutive items; the space between a term and its definition does not-affect anything.-.IP \[bu] 2-Lazy wrapping of paragraphs is not allowed: the entire definition must-be indented four spaces.-.SS Extension: \f[V]gutenberg\f[R]-.PP-Use Project Gutenberg conventions for \f[V]plain\f[R] output: all-caps-for strong emphasis, surround by underscores for regular emphasis, add-extra blank space around headings.-.SS Extension: \f[V]sourcepos\f[R]-.PP-Include source position attributes when parsing \f[V]commonmark\f[R].-For elements that accept attributes, a \f[V]data-pos\f[R] attribute is-added; other elements are placed in a surrounding Div or Span element-with a \f[V]data-pos\f[R] attribute.-.SS Extension: \f[V]short_subsuperscripts\f[R]-.PP-Parse multimarkdown style subscripts and superscripts, which start with-a `\[ti]' or `\[ha]' character, respectively, and include the-alphanumeric sequence that follows.-For example:-.IP-.nf-\f[C]-x\[ha]2 = 4-\f[R]-.fi-.PP-or-.IP-.nf-\f[C]-Oxygen is O\[ti]2.-\f[R]-.fi-.SS Markdown variants-.PP-In addition to pandoc\[cq]s extended Markdown, the following Markdown-variants are supported:-.IP \[bu] 2-\f[V]markdown_phpextra\f[R] (PHP Markdown Extra)-.IP \[bu] 2-\f[V]markdown_github\f[R] (deprecated GitHub-Flavored Markdown)-.IP \[bu] 2-\f[V]markdown_mmd\f[R] (MultiMarkdown)-.IP \[bu] 2-\f[V]markdown_strict\f[R] (Markdown.pl)-.IP \[bu] 2-\f[V]commonmark\f[R] (CommonMark)-.IP \[bu] 2-\f[V]gfm\f[R] (Github-Flavored Markdown)-.IP \[bu] 2-\f[V]commonmark_x\f[R] (CommonMark with many pandoc extensions)-.PP-To see which extensions are supported for a given format, and which are-enabled by default, you can use the command-.IP-.nf-\f[C]-pandoc --list-extensions=FORMAT-\f[R]-.fi-.PP-where \f[V]FORMAT\f[R] is replaced with the name of the format.-.PP-Note that the list of extensions for \f[V]commonmark\f[R],-\f[V]gfm\f[R], and \f[V]commonmark_x\f[R] are defined relative to-default commonmark.-So, for example, \f[V]backtick_code_blocks\f[R] does not appear as an-extension, since it is enabled by default and cannot be disabled.-.SH CITATIONS-.PP-When the \f[V]--citeproc\f[R] option is used, pandoc can automatically-generate citations and a bibliography in a number of styles.-Basic usage is-.IP-.nf-\f[C]-pandoc --citeproc myinput.txt-\f[R]-.fi-.PP-To use this feature, you will need to have-.IP \[bu] 2-a document containing citations (see Extension: \f[V]citations\f[R]);-.IP \[bu] 2-a source of bibliographic data: either an external bibliography file or-a list of \f[V]references\f[R] in the document\[cq]s YAML metadata;-.IP \[bu] 2-optionally, a CSL citation style.-.SS Specifying bibliographic data-.PP-You can specify an external bibliography using the-\f[V]bibliography\f[R] metadata field in a YAML metadata section or the-\f[V]--bibliography\f[R] command line argument.-If you want to use multiple bibliography files, you can supply multiple-\f[V]--bibliography\f[R] arguments or set \f[V]bibliography\f[R]-metadata field to YAML array.-A bibliography may have any of these formats:-.RS -14n-.IP-.nf-\f[C]- Format File extension- ---------- ----------------- BibLaTeX .bib- BibTeX .bibtex- CSL JSON .json- CSL YAML .yaml- RIS .ris-\f[R]-.fi-.RE-.PP-Note that \f[V].bib\f[R] can be used with both BibTeX and BibLaTeX-files; use the extension \f[V].bibtex\f[R] to force interpretation as-BibTeX.-.PP-In BibTeX and BibLaTeX databases, pandoc parses LaTeX markup inside-fields such as \f[V]title\f[R]; in CSL YAML databases, pandoc Markdown;-and in CSL JSON databases, an HTML-like markup:-.TP-\f[V]<i>...</i>\f[R]-italics-.TP-\f[V]<b>...</b>\f[R]-bold-.TP-\f[V]<span style=\[dq]font-variant:small-caps;\[dq]>...</span>\f[R] or \f[V]<sc>...</sc>\f[R]-small capitals-.TP-\f[V]<sub>...</sub>\f[R]-subscript-.TP-\f[V]<sup>...</sup>\f[R]-superscript-.TP-\f[V]<span class=\[dq]nocase\[dq]>...</span>\f[R]-prevent a phrase from being capitalized as title case-.PP-As an alternative to specifying a bibliography file using-\f[V]--bibliography\f[R] or the YAML metadata field-\f[V]bibliography\f[R], you can include the citation data directly in-the \f[V]references\f[R] field of the document\[cq]s YAML metadata.-The field should contain an array of YAML-encoded references, for-example:-.IP-.nf-\f[C]-----references:-- type: article-journal- id: WatsonCrick1953- author:- - family: Watson- given: J. D.- - family: Crick- given: F. H. C.- issued:- date-parts:- - - 1953- - 4- - 25- title: \[aq]Molecular structure of nucleic acids: a structure for- deoxyribose nucleic acid\[aq]- title-short: Molecular structure of nucleic acids- container-title: Nature- volume: 171- issue: 4356- page: 737-738- DOI: 10.1038/171737a0- URL: https://www.nature.com/articles/171737a0- language: en-GB-\&...-\f[R]-.fi-.PP-If both an external bibliography and inline (YAML metadata) references-are provided, both will be used.-In case of conflicting \f[V]id\f[R]s, the inline references will take-precedence.-.PP-Note that pandoc can be used to produce such a YAML metadata section-from a BibTeX, BibLaTeX, or CSL JSON bibliography:-.IP-.nf-\f[C]-pandoc chem.bib -s -f biblatex -t markdown-pandoc chem.json -s -f csljson -t markdown-\f[R]-.fi-.PP-Indeed, pandoc can convert between any of these citation formats:-.IP-.nf-\f[C]-pandoc chem.bib -s -f biblatex -t csljson-pandoc chem.yaml -s -f markdown -t biblatex-\f[R]-.fi-.PP-Running pandoc on a bibliography file with the \f[V]--citeproc\f[R]-option will create a formatted bibliography in the format of your-choice:-.IP-.nf-\f[C]-pandoc chem.bib -s --citeproc -o chem.html-pandoc chem.bib -s --citeproc -o chem.pdf-\f[R]-.fi-.SS Capitalization in titles-.PP-If you are using a bibtex or biblatex bibliography, then observe the-following rules:-.IP \[bu] 2-English titles should be in title case.-Non-English titles should be in sentence case, and the \f[V]langid\f[R]-field in biblatex should be set to the relevant language.-(The following values are treated as English: \f[V]american\f[R],-\f[V]british\f[R], \f[V]canadian\f[R], \f[V]english\f[R],-\f[V]australian\f[R], \f[V]newzealand\f[R], \f[V]USenglish\f[R], or-\f[V]UKenglish\f[R].)-.IP \[bu] 2-As is standard with bibtex/biblatex, proper names should be protected-with curly braces so that they won\[cq]t be lowercased in styles that-call for sentence case.-For example:-.RS 2-.IP-.nf-\f[C]-title = {My Dinner with {Andre}}-\f[R]-.fi-.RE-.IP \[bu] 2-In addition, words that should remain lowercase (or camelCase) should be-protected:-.RS 2-.IP-.nf-\f[C]-title = {Spin Wave Dispersion on the {nm} Scale}-\f[R]-.fi-.PP-Though this is not necessary in bibtex/biblatex, it is necessary with-citeproc, which stores titles internally in sentence case, and converts-to title case in styles that require it.-Here we protect \[lq]nm\[rq] so that it doesn\[cq]t get converted to-\[lq]Nm\[rq] at this stage.-.RE-.PP-If you are using a CSL bibliography (either JSON or YAML), then observe-the following rules:-.IP \[bu] 2-All titles should be in sentence case.-.IP \[bu] 2-Use the \f[V]language\f[R] field for non-English titles to prevent their-conversion to title case in styles that call for this.-(Conversion happens only if \f[V]language\f[R] begins with \f[V]en\f[R]-or is left empty.)-.IP \[bu] 2-Protect words that should not be converted to title case using this-syntax:-.RS 2-.IP-.nf-\f[C]-Spin wave dispersion on the <span class=\[dq]nocase\[dq]>nm</span> scale-\f[R]-.fi-.RE-.SS Conference Papers, Published vs.\ Unpublished-.PP-For a formally published conference paper, use the biblatex entry type-\f[V]inproceedings\f[R] (which will be mapped to CSL-\f[V]paper-conference\f[R]).-.PP-For an unpublished manuscript, use the biblatex entry type-\f[V]unpublished\f[R] without an \f[V]eventtitle\f[R] field (this entry-type will be mapped to CSL \f[V]manuscript\f[R]).-.PP-For a talk, an unpublished conference paper, or a poster presentation,-use the biblatex entry type \f[V]unpublished\f[R] with an-\f[V]eventtitle\f[R] field (this entry type will be mapped to CSL-\f[V]speech\f[R]).-Use the biblatex \f[V]type\f[R] field to indicate the type,-e.g.\ \[lq]Paper\[rq], or \[lq]Poster\[rq].-\f[V]venue\f[R] and \f[V]eventdate\f[R] may be useful too, though-\f[V]eventdate\f[R] will not be rendered by most CSL styles.-Note that \f[V]venue\f[R] is for the event\[cq]s venue, unlike-\f[V]location\f[R] which describes the publisher\[cq]s location; do not-use the latter for an unpublished conference paper.-.SS Specifying a citation style-.PP-Citations and references can be formatted using any style supported by-the Citation Style Language, listed in the Zotero Style Repository.-These files are specified using the \f[V]--csl\f[R] option or the-\f[V]csl\f[R] (or \f[V]citation-style\f[R]) metadata field.-By default, pandoc will use the Chicago Manual of Style author-date-format.-(You can override this default by copying a CSL style of your choice to-\f[V]default.csl\f[R] in your user data directory.)-The CSL project provides further information on finding and editing-styles.-.PP-The \f[V]--citation-abbreviations\f[R] option (or the-\f[V]citation-abbreviations\f[R] metadata field) may be used to specify-a JSON file containing abbreviations of journals that should be used in-formatted bibliographies when \f[V]form=\[dq]short\[dq]\f[R] is-specified.-The format of the file can be illustrated with an example:-.IP-.nf-\f[C]-{ \[dq]default\[dq]: {- \[dq]container-title\[dq]: {- \[dq]Lloyd\[aq]s Law Reports\[dq]: \[dq]Lloyd\[aq]s Rep\[dq],- \[dq]Estates Gazette\[dq]: \[dq]EG\[dq],- \[dq]Scots Law Times\[dq]: \[dq]SLT\[dq]- }- }-}-\f[R]-.fi-.SS Citations in note styles-.PP-Pandoc\[cq]s citation processing is designed to allow you to move-between author-date, numerical, and note styles without modifying the-markdown source.-When you\[cq]re using a note style, avoid inserting footnotes manually.-Instead, insert citations just as you would in an author-date-style\[em]for example,-.IP-.nf-\f[C]-Blah blah [\[at]foo, p. 33].-\f[R]-.fi-.PP-The footnote will be created automatically.-Pandoc will take care of removing the space and moving the note before-or after the period, depending on the setting of-\f[V]notes-after-punctuation\f[R], as described below in Other relevant-metadata fields.-.PP-In some cases you may need to put a citation inside a regular footnote.-Normal citations in footnotes (such as \f[V][\[at]foo, p. 33]\f[R]) will-be rendered in parentheses.-In-text citations (such as \f[V]\[at]foo [p. 33]\f[R]) will be rendered-without parentheses.-(A comma will be added if appropriate.)-Thus:-.IP-.nf-\f[C]-[\[ha]1]: Some studies [\[at]foo; \[at]bar, p. 33] show that-frubulicious zoosnaps are quantical. For a survey-of the literature, see \[at]baz [chap. 1].-\f[R]-.fi-.SS Raw content in a style-.PP-To include raw content in a prefix, suffix, delimiter, or term, surround-it with these tags indicating the format:-.IP-.nf-\f[C]-{{jats}}<ref>{{/jats}}-\f[R]-.fi-.PP-Without the tags, the string will be interpreted as a string and escaped-in the output, rather than being passed through raw.-.PP-This feature allows stylesheets to be customized to give different-output for different output formats.-However, stylesheets customized in this way will not be usable by other-CSL implementations.-.SS Placement of the bibliography-.PP-If the style calls for a list of works cited, it will be placed in a div-with id \f[V]refs\f[R], if one exists:-.IP-.nf-\f[C]-::: {#refs}-:::-\f[R]-.fi-.PP-Otherwise, it will be placed at the end of the document.-Generation of the bibliography can be suppressed by setting-\f[V]suppress-bibliography: true\f[R] in the YAML metadata.-.PP-If you wish the bibliography to have a section heading, you can set-\f[V]reference-section-title\f[R] in the metadata, or put the heading at-the beginning of the div with id \f[V]refs\f[R] (if you are using it) or-at the end of your document:-.IP-.nf-\f[C]-last paragraph...--# References-\f[R]-.fi-.PP-The bibliography will be inserted after this heading.-Note that the \f[V]unnumbered\f[R] class will be added to this heading,-so that the section will not be numbered.-.PP-If you want to put the bibliography into a variable in your template,-one way to do that is to put the div with id \f[V]refs\f[R] into a-metadata field, e.g.-.IP-.nf-\f[C]-----refs: |- ::: {#refs}- :::-\&...-\f[R]-.fi-.PP-You can then put the variable \f[V]$refs$\f[R] into your template where-you want the bibliography to be placed.-.SS Including uncited items in the bibliography-.PP-If you want to include items in the bibliography without actually citing-them in the body text, you can define a dummy \f[V]nocite\f[R] metadata-field and put the citations there:-.IP-.nf-\f[C]-----nocite: |- \[at]item1, \[at]item2-\&...--\[at]item3-\f[R]-.fi-.PP-In this example, the document will contain a citation for-\f[V]item3\f[R] only, but the bibliography will contain entries for-\f[V]item1\f[R], \f[V]item2\f[R], and \f[V]item3\f[R].-.PP-It is possible to create a bibliography with all the citations, whether-or not they appear in the document, by using a wildcard:-.IP-.nf-\f[C]-----nocite: |- \[at]*-\&...-\f[R]-.fi-.PP-For LaTeX output, you can also use \f[V]natbib\f[R] or-\f[V]biblatex\f[R] to render the bibliography.-In order to do so, specify bibliography files as outlined above, and add-\f[V]--natbib\f[R] or \f[V]--biblatex\f[R] argument to pandoc-invocation.-Bear in mind that bibliography files have to be in either BibTeX (for-\f[V]--natbib\f[R]) or BibLaTeX (for \f[V]--biblatex\f[R]) format.-.SS Other relevant metadata fields-.PP-A few other metadata fields affect bibliography formatting:-.TP-\f[V]link-citations\f[R]-If true, citations will be hyperlinked to the corresponding bibliography-entries (for author-date and numerical styles only).-Defaults to false.-.TP-\f[V]link-bibliography\f[R]-If true, DOIs, PMCIDs, PMID, and URLs in bibliographies will be rendered-as hyperlinks.-(If an entry contains a DOI, PMCID, PMID, or URL, but none of these-fields are rendered by the style, then the title, or in the absence of a-title the whole entry, will be hyperlinked.)-Defaults to true.-.TP-\f[V]lang\f[R]-The \f[V]lang\f[R] field will affect how the style is localized, for-example in the translation of labels, the use of quotation marks, and-the way items are sorted.-(For backwards compatibility, \f[V]locale\f[R] may be used instead of-\f[V]lang\f[R], but this use is deprecated.)-.RS-.PP-A BCP 47 language tag is expected: for example, \f[V]en\f[R],-\f[V]de\f[R], \f[V]en-US\f[R], \f[V]fr-CA\f[R], \f[V]ug-Cyrl\f[R].-The unicode extension syntax (after \f[V]-u-\f[R]) may be used to-specify options for collation (sorting) more precisely.-Here are some examples:-.IP \[bu] 2-\f[V]zh-u-co-pinyin\f[R] \[en] Chinese with the Pinyin collation.-.IP \[bu] 2-\f[V]es-u-co-trad\f[R] \[en] Spanish with the traditional collation-(with \f[V]Ch\f[R] sorting after \f[V]C\f[R]).-.IP \[bu] 2-\f[V]fr-u-kb\f[R] \[en] French with \[lq]backwards\[rq] accent sorting-(with \f[V]cot\['e]\f[R] sorting after \f[V]c\[^o]te\f[R]).-.IP \[bu] 2-\f[V]en-US-u-kf-upper\f[R] \[en] English with uppercase letters sorting-before lower (default is lower before upper).-.RE-.TP-\f[V]notes-after-punctuation\f[R]-If true (the default for note styles), pandoc will put footnote-references or superscripted numerical citations after following-punctuation.-For example, if the source contains \f[V]blah blah [\[at]jones99].\f[R],-the result will look like \f[V]blah blah.[\[ha]1]\f[R], with the note-moved after the period and the space collapsed.-If false, the space will still be collapsed, but the footnote will not-be moved after the punctuation.-The option may also be used in numerical styles that use superscripts-for citation numbers (but for these styles the default is not to move-the citation).-.SH SLIDE SHOWS-.PP-You can use pandoc to produce an HTML + JavaScript slide presentation-that can be viewed via a web browser.-There are five ways to do this, using S5, DZSlides, Slidy, Slideous, or-reveal.js.-You can also produce a PDF slide show using LaTeX \f[V]beamer\f[R], or-slide shows in Microsoft PowerPoint format.-.PP-Here\[cq]s the Markdown source for a simple slide show,-\f[V]habits.txt\f[R]:-.IP-.nf-\f[C]-% Habits-% John Doe-% March 22, 2005--# In the morning--## Getting up--- Turn off alarm-- Get out of bed--## Breakfast--- Eat eggs-- Drink coffee--# In the evening--## Dinner--- Eat spaghetti-- Drink wine------------------------## Going to sleep--- Get in bed-- Count sheep-\f[R]-.fi-.PP-To produce an HTML/JavaScript slide show, simply type-.IP-.nf-\f[C]-pandoc -t FORMAT -s habits.txt -o habits.html-\f[R]-.fi-.PP-where \f[V]FORMAT\f[R] is either \f[V]s5\f[R], \f[V]slidy\f[R],-\f[V]slideous\f[R], \f[V]dzslides\f[R], or \f[V]revealjs\f[R].-.PP-For Slidy, Slideous, reveal.js, and S5, the file produced by pandoc with-the \f[V]-s/--standalone\f[R] option embeds a link to JavaScript and CSS-files, which are assumed to be available at the relative path-\f[V]s5/default\f[R] (for S5), \f[V]slideous\f[R] (for Slideous),-\f[V]reveal.js\f[R] (for reveal.js), or at the Slidy website at-\f[V]w3.org\f[R] (for Slidy).-(These paths can be changed by setting the \f[V]slidy-url\f[R],-\f[V]slideous-url\f[R], \f[V]revealjs-url\f[R], or \f[V]s5-url\f[R]-variables; see Variables for HTML slides, above.)-For DZSlides, the (relatively short) JavaScript and CSS are included in-the file by default.-.PP-With all HTML slide formats, the \f[V]--self-contained\f[R] option can-be used to produce a single file that contains all of the data necessary-to display the slide show, including linked scripts, stylesheets,-images, and videos.-.PP-To produce a PDF slide show using beamer, type-.IP-.nf-\f[C]-pandoc -t beamer habits.txt -o habits.pdf-\f[R]-.fi-.PP-Note that a reveal.js slide show can also be converted to a PDF by-printing it to a file from the browser.-.PP-To produce a PowerPoint slide show, type-.IP-.nf-\f[C]-pandoc habits.txt -o habits.pptx-\f[R]-.fi-.SS Structuring the slide show-.PP-By default, the \f[I]slide level\f[R] is the highest heading level in-the hierarchy that is followed immediately by content, and not another-heading, somewhere in the document.-In the example above, level-1 headings are always followed by level-2-headings, which are followed by content, so the slide level is 2.-This default can be overridden using the \f[V]--slide-level\f[R] option.-.PP-The document is carved up into slides according to the following rules:-.IP \[bu] 2-A horizontal rule always starts a new slide.-.IP \[bu] 2-A heading at the slide level always starts a new slide.-.IP \[bu] 2-Headings \f[I]below\f[R] the slide level in the hierarchy create-headings \f[I]within\f[R] a slide.-(In beamer, a \[lq]block\[rq] will be created.-If the heading has the class \f[V]example\f[R], an-\f[V]exampleblock\f[R] environment will be used; if it has the class-\f[V]alert\f[R], an \f[V]alertblock\f[R] will be used; otherwise a-regular \f[V]block\f[R] will be used.)-.IP \[bu] 2-Headings \f[I]above\f[R] the slide level in the hierarchy create-\[lq]title slides,\[rq] which just contain the section title and help to-break the slide show into sections.-Non-slide content under these headings will be included on the title-slide (for HTML slide shows) or in a subsequent slide with the same-title (for beamer).-.IP \[bu] 2-A title page is constructed automatically from the document\[cq]s title-block, if present.-(In the case of beamer, this can be disabled by commenting out some-lines in the default template.)-.PP-These rules are designed to support many different styles of slide show.-If you don\[cq]t care about structuring your slides into sections and-subsections, you can either just use level-1 headings for all slides (in-that case, level 1 will be the slide level) or you can set-\f[V]--slide-level=0\f[R].-.PP-Note: in reveal.js slide shows, if slide level is 2, a two-dimensional-layout will be produced, with level-1 headings building horizontally and-level-2 headings building vertically.-It is not recommended that you use deeper nesting of section levels with-reveal.js unless you set \f[V]--slide-level=0\f[R] (which lets reveal.js-produce a one-dimensional layout and only interprets horizontal rules as-slide boundaries).-.SS PowerPoint layout choice-.PP-When creating slides, the pptx writer chooses from a number of-pre-defined layouts, based on the content of the slide:-.TP-Title Slide-This layout is used for the initial slide, which is generated and filled-from the metadata fields \f[V]date\f[R], \f[V]author\f[R], and-\f[V]title\f[R], if they are present.-.TP-Section Header-This layout is used for what pandoc calls \[lq]title slides\[rq], i.e.-slides which start with a header which is above the slide level in the-hierarchy.-.TP-Two Content-This layout is used for two-column slides, i.e.\ slides containing a div-with class \f[V]columns\f[R] which contains at least two divs with class-\f[V]column\f[R].-.TP-Comparison-This layout is used instead of \[lq]Two Content\[rq] for any two-column-slides in which at least one column contains text followed by non-text-(e.g.\ an image or a table).-.TP-Content with Caption-This layout is used for any non-two-column slides which contain text-followed by non-text (e.g.\ an image or a table).-.TP-Blank-This layout is used for any slides which only contain blank content,-e.g.\ a slide containing only speaker notes, or a slide containing only-a non-breaking space.-.TP-Title and Content-This layout is used for all slides which do not match the criteria for-another layout.-.PP-These layouts are chosen from the default pptx reference doc included-with pandoc, unless an alternative reference doc is specified using-\f[V]--reference-doc\f[R].-.SS Incremental lists-.PP-By default, these writers produce lists that display \[lq]all at-once.\[rq] If you want your lists to display incrementally (one item at-a time), use the \f[V]-i\f[R] option.-If you want a particular list to depart from the default, put it in a-\f[V]div\f[R] block with class \f[V]incremental\f[R] or-\f[V]nonincremental\f[R].-So, for example, using the \f[V]fenced div\f[R] syntax, the following-would be incremental regardless of the document default:-.IP-.nf-\f[C]-::: incremental--- Eat spaghetti-- Drink wine--:::-\f[R]-.fi-.PP-or-.IP-.nf-\f[C]-::: nonincremental--- Eat spaghetti-- Drink wine--:::-\f[R]-.fi-.PP-While using \f[V]incremental\f[R] and \f[V]nonincremental\f[R] divs is-the recommended method of setting incremental lists on a per-case basis,-an older method is also supported: putting lists inside a blockquote-will depart from the document default (that is, it will display-incrementally without the \f[V]-i\f[R] option and all at once with the-\f[V]-i\f[R] option):-.IP-.nf-\f[C]-> - Eat spaghetti-> - Drink wine-\f[R]-.fi-.PP-Both methods allow incremental and nonincremental lists to be mixed in a-single document.-.PP-If you want to include a block-quoted list, you can work around this-behavior by putting the list inside a fenced div, so that it is not the-direct child of the block quote:-.IP-.nf-\f[C]-> ::: wrapper-> - a-> - list in a quote-> :::-\f[R]-.fi-.SS Inserting pauses-.PP-You can add \[lq]pauses\[rq] within a slide by including a paragraph-containing three dots, separated by spaces:-.IP-.nf-\f[C]-# Slide with a pause--content before the pause--\&. . .--content after the pause-\f[R]-.fi-.PP-Note: this feature is not yet implemented for PowerPoint output.-.SS Styling the slides-.PP-You can change the style of HTML slides by putting customized CSS files-in \f[V]$DATADIR/s5/default\f[R] (for S5), \f[V]$DATADIR/slidy\f[R] (for-Slidy), or \f[V]$DATADIR/slideous\f[R] (for Slideous), where-\f[V]$DATADIR\f[R] is the user data directory (see \f[V]--data-dir\f[R],-above).-The originals may be found in pandoc\[cq]s system data directory-(generally \f[V]$CABALDIR/pandoc-VERSION/s5/default\f[R]).-Pandoc will look there for any files it does not find in the user data-directory.-.PP-For dzslides, the CSS is included in the HTML file itself, and may be-modified there.-.PP-All reveal.js configuration options can be set through variables.-For example, themes can be used by setting the \f[V]theme\f[R] variable:-.IP-.nf-\f[C]--V theme=moon-\f[R]-.fi-.PP-Or you can specify a custom stylesheet using the \f[V]--css\f[R] option.-.PP-To style beamer slides, you can specify a \f[V]theme\f[R],-\f[V]colortheme\f[R], \f[V]fonttheme\f[R], \f[V]innertheme\f[R], and-\f[V]outertheme\f[R], using the \f[V]-V\f[R] option:-.IP-.nf-\f[C]-pandoc -t beamer habits.txt -V theme:Warsaw -o habits.pdf-\f[R]-.fi-.PP-Note that heading attributes will turn into slide attributes (on a-\f[V]<div>\f[R] or \f[V]<section>\f[R]) in HTML slide formats, allowing-you to style individual slides.-In beamer, a number of heading classes and attributes are recognized as-frame options and will be passed through as options to the frame: see-Frame attributes in beamer, below.-.SS Speaker notes-.PP-Speaker notes are supported in reveal.js, PowerPoint (pptx), and beamer-output.-You can add notes to your Markdown document thus:-.IP-.nf-\f[C]-::: notes--This is my note.--- It can contain Markdown-- like this list--:::-\f[R]-.fi-.PP-To show the notes window in reveal.js, press \f[V]s\f[R] while viewing-the presentation.-Speaker notes in PowerPoint will be available, as usual, in handouts and-presenter view.-.PP-Notes are not yet supported for other slide formats, but the notes will-not appear on the slides themselves.-.SS Columns-.PP-To put material in side by side columns, you can use a native div-container with class \f[V]columns\f[R], containing two or more div-containers with class \f[V]column\f[R] and a \f[V]width\f[R] attribute:-.IP-.nf-\f[C]-:::::::::::::: {.columns}-::: {.column width=\[dq]40%\[dq]}-contents...-:::-::: {.column width=\[dq]60%\[dq]}-contents...-:::-::::::::::::::-\f[R]-.fi-.SS Additional columns attributes in beamer-.PP-The div containers with classes \f[V]columns\f[R] and \f[V]column\f[R]-can optionally have an \f[V]align\f[R] attribute.-The class \f[V]columns\f[R] can optionally have a \f[V]totalwidth\f[R]-attribute or an \f[V]onlytextwidth\f[R] class.-.IP-.nf-\f[C]-:::::::::::::: {.columns align=center totalwidth=8em}-::: {.column width=\[dq]40%\[dq]}-contents...-:::-::: {.column width=\[dq]60%\[dq] align=bottom}-contents...-:::-::::::::::::::-\f[R]-.fi-.PP-The \f[V]align\f[R] attributes on \f[V]columns\f[R] and \f[V]column\f[R]-can be used with the values \f[V]top\f[R], \f[V]top-baseline\f[R],-\f[V]center\f[R] and \f[V]bottom\f[R] to vertically align the columns.-It defaults to \f[V]top\f[R] in \f[V]columns\f[R].-.PP-The \f[V]totalwidth\f[R] attribute limits the width of the columns to-the given value.-.IP-.nf-\f[C]-:::::::::::::: {.columns align=top .onlytextwidth}-::: {.column width=\[dq]40%\[dq] align=center}-contents...-:::-::: {.column width=\[dq]60%\[dq]}-contents...-:::-::::::::::::::-\f[R]-.fi-.PP-The class \f[V]onlytextwidth\f[R] sets the \f[V]totalwidth\f[R] to-\f[V]\[rs]textwidth\f[R].-.PP-See Section 12.7 of the Beamer User\[cq]s Guide for more details.-.SS Frame attributes in beamer-.PP-Sometimes it is necessary to add the LaTeX \f[V][fragile]\f[R] option to-a frame in beamer (for example, when using the \f[V]minted\f[R]-environment).-This can be forced by adding the \f[V]fragile\f[R] class to the heading-introducing the slide:-.IP-.nf-\f[C]-# Fragile slide {.fragile}-\f[R]-.fi-.PP-All of the other frame attributes described in Section 8.1 of the Beamer-User\[cq]s Guide may also be used: \f[V]allowdisplaybreaks\f[R],-\f[V]allowframebreaks\f[R], \f[V]b\f[R], \f[V]c\f[R], \f[V]s\f[R],-\f[V]t\f[R], \f[V]environment\f[R], \f[V]label\f[R], \f[V]plain\f[R],-\f[V]shrink\f[R], \f[V]standout\f[R], \f[V]noframenumbering\f[R],-\f[V]squeeze\f[R].-\f[V]allowframebreaks\f[R] is recommended especially for bibliographies,-as it allows multiple slides to be created if the content overfills the-frame:-.IP-.nf-\f[C]-# References {.allowframebreaks}-\f[R]-.fi-.PP-In addition, the \f[V]frameoptions\f[R] attribute may be used to pass-arbitrary frame options to a beamer slide:-.IP-.nf-\f[C]-# Heading {frameoptions=\[dq]squeeze,shrink,customoption=foobar\[dq]}-\f[R]-.fi-.SS Background in reveal.js, beamer, and pptx-.PP-Background images can be added to self-contained reveal.js slide shows,-beamer slide shows, and pptx slide shows.-.SS On all slides (beamer, reveal.js, pptx)-.PP-With beamer and reveal.js, the configuration option-\f[V]background-image\f[R] can be used either in the YAML metadata block-or as a command-line variable to get the same image on every slide.-.PP-For pptx, you can use a reference doc in which background images have-been set on the relevant layouts.-.SS \f[V]parallaxBackgroundImage\f[R] (reveal.js)-.PP-For reveal.js, there is also the reveal.js-native option-\f[V]parallaxBackgroundImage\f[R], which can be used instead of-\f[V]background-image\f[R] to produce a parallax scrolling background.-You must also set \f[V]parallaxBackgroundSize\f[R], and can optionally-set \f[V]parallaxBackgroundHorizontal\f[R] and-\f[V]parallaxBackgroundVertical\f[R] to configure the scrolling-behaviour.-See the reveal.js documentation for more details about the meaning of-these options.-.PP-In reveal.js\[cq]s overview mode, the parallaxBackgroundImage will show-up only on the first slide.-.SS On individual slides (reveal.js, pptx)-.PP-To set an image for a particular reveal.js or pptx slide, add-\f[V]{background-image=\[dq]/path/to/image\[dq]}\f[R] to the first-slide-level heading on the slide (which may even be empty).-.PP-As the HTML writers pass unknown attributes through, other reveal.js-background settings also work on individual slides, including-\f[V]background-size\f[R], \f[V]background-repeat\f[R],-\f[V]background-color\f[R], \f[V]transition\f[R], and-\f[V]transition-speed\f[R].-(The \f[V]data-\f[R] prefix will automatically be added.)-.PP-Note: \f[V]data-background-image\f[R] is also supported in pptx for-consistency with reveal.js \[en] if \f[V]background-image\f[R] isn\[cq]t-found, \f[V]data-background-image\f[R] will be checked.-.SS On the title slide (reveal.js, pptx)-.PP-To add a background image to the automatically generated title slide for-reveal.js, use the \f[V]title-slide-attributes\f[R] variable in the YAML-metadata block.-It must contain a map of attribute names and values.-(Note that the \f[V]data-\f[R] prefix is required here, as it isn\[cq]t-added automatically.)-.PP-For pptx, pass a reference doc with the background image set on the-\[lq]Title Slide\[rq] layout.-.SS Example (reveal.js)-.IP-.nf-\f[C]-----title: My Slide Show-parallaxBackgroundImage: /path/to/my/background_image.png-title-slide-attributes:- data-background-image: /path/to/title_image.png- data-background-size: contain------## Slide One--Slide 1 has background_image.png as its background.--## {background-image=\[dq]/path/to/special_image.jpg\[dq]}--Slide 2 has a special image for its background, even though the heading has no content.-\f[R]-.fi-.SH EPUBS-.SS EPUB Metadata-.PP-EPUB metadata may be specified using the \f[V]--epub-metadata\f[R]-option, but if the source document is Markdown, it is better to use a-YAML metadata block.-Here is an example:-.IP-.nf-\f[C]-----title:-- type: main- text: My Book-- type: subtitle- text: An investigation of metadata-creator:-- role: author- text: John Smith-- role: editor- text: Sarah Jones-identifier:-- scheme: DOI- text: doi:10.234234.234/33-publisher: My Press-rights: \[co] 2007 John Smith, CC BY-NC-ibooks:- version: 1.3.4-\&...-\f[R]-.fi-.PP-The following fields are recognized:-.TP-\f[V]identifier\f[R]-Either a string value or an object with fields \f[V]text\f[R] and-\f[V]scheme\f[R].-Valid values for \f[V]scheme\f[R] are \f[V]ISBN-10\f[R],-\f[V]GTIN-13\f[R], \f[V]UPC\f[R], \f[V]ISMN-10\f[R], \f[V]DOI\f[R],-\f[V]LCCN\f[R], \f[V]GTIN-14\f[R], \f[V]ISBN-13\f[R],-\f[V]Legal deposit number\f[R], \f[V]URN\f[R], \f[V]OCLC\f[R],-\f[V]ISMN-13\f[R], \f[V]ISBN-A\f[R], \f[V]JP\f[R], \f[V]OLCC\f[R].-.TP-\f[V]title\f[R]-Either a string value, or an object with fields \f[V]file-as\f[R] and-\f[V]type\f[R], or a list of such objects.-Valid values for \f[V]type\f[R] are \f[V]main\f[R], \f[V]subtitle\f[R],-\f[V]short\f[R], \f[V]collection\f[R], \f[V]edition\f[R],-\f[V]extended\f[R].-.TP-\f[V]creator\f[R]-Either a string value, or an object with fields \f[V]role\f[R],-\f[V]file-as\f[R], and \f[V]text\f[R], or a list of such objects.-Valid values for \f[V]role\f[R] are MARC relators, but pandoc will-attempt to translate the human-readable versions (like \[lq]author\[rq]-and \[lq]editor\[rq]) to the appropriate marc relators.-.TP-\f[V]contributor\f[R]-Same format as \f[V]creator\f[R].-.TP-\f[V]date\f[R]-A string value in \f[V]YYYY-MM-DD\f[R] format.-(Only the year is necessary.)-Pandoc will attempt to convert other common date formats.-.TP-\f[V]lang\f[R] (or legacy: \f[V]language\f[R])-A string value in BCP 47 format.-Pandoc will default to the local language if nothing is specified.-.TP-\f[V]subject\f[R]-Either a string value, or an object with fields \f[V]text\f[R],-\f[V]authority\f[R], and \f[V]term\f[R], or a list of such objects.-Valid values for \f[V]authority\f[R] are either a reserved authority-value (currently \f[V]AAT\f[R], \f[V]BIC\f[R], \f[V]BISAC\f[R],-\f[V]CLC\f[R], \f[V]DDC\f[R], \f[V]CLIL\f[R], \f[V]EuroVoc\f[R],-\f[V]MEDTOP\f[R], \f[V]LCSH\f[R], \f[V]NDC\f[R], \f[V]Thema\f[R],-\f[V]UDC\f[R], and \f[V]WGS\f[R]) or an absolute IRI identifying a-custom scheme.-Valid values for \f[V]term\f[R] are defined by the scheme.-.TP-\f[V]description\f[R]-A string value.-.TP-\f[V]type\f[R]-A string value.-.TP-\f[V]format\f[R]-A string value.-.TP-\f[V]relation\f[R]-A string value.-.TP-\f[V]coverage\f[R]-A string value.-.TP-\f[V]rights\f[R]-A string value.-.TP-\f[V]belongs-to-collection\f[R]-A string value.-Identifies the name of a collection to which the EPUB Publication-belongs.-.TP-\f[V]group-position\f[R]-The \f[V]group-position\f[R] field indicates the numeric position in-which the EPUB Publication belongs relative to other works belonging to-the same \f[V]belongs-to-collection\f[R] field.-.TP-\f[V]cover-image\f[R]-A string value (path to cover image).-.TP-\f[V]css\f[R] (or legacy: \f[V]stylesheet\f[R])-A string value (path to CSS stylesheet).-.TP-\f[V]page-progression-direction\f[R]-Either \f[V]ltr\f[R] or \f[V]rtl\f[R].-Specifies the \f[V]page-progression-direction\f[R] attribute for the-\f[V]spine\f[R] element.-.TP-\f[V]ibooks\f[R]-iBooks-specific metadata, with the following fields:-.RS-.IP \[bu] 2-\f[V]version\f[R]: (string)-.IP \[bu] 2-\f[V]specified-fonts\f[R]: \f[V]true\f[R]|\f[V]false\f[R] (default-\f[V]false\f[R])-.IP \[bu] 2-\f[V]ipad-orientation-lock\f[R]:-\f[V]portrait-only\f[R]|\f[V]landscape-only\f[R]-.IP \[bu] 2-\f[V]iphone-orientation-lock\f[R]:-\f[V]portrait-only\f[R]|\f[V]landscape-only\f[R]-.IP \[bu] 2-\f[V]binding\f[R]: \f[V]true\f[R]|\f[V]false\f[R] (default-\f[V]true\f[R])-.IP \[bu] 2-\f[V]scroll-axis\f[R]:-\f[V]vertical\f[R]|\f[V]horizontal\f[R]|\f[V]default\f[R]-.RE-.SS The \f[V]epub:type\f[R] attribute-.PP-For \f[V]epub3\f[R] output, you can mark up the heading that corresponds-to an EPUB chapter using the \f[V]epub:type\f[R] attribute.-For example, to set the attribute to the value \f[V]prologue\f[R], use-this markdown:-.IP-.nf-\f[C]-# My chapter {epub:type=prologue}-\f[R]-.fi-.PP-Which will result in:-.IP-.nf-\f[C]-<body epub:type=\[dq]frontmatter\[dq]>- <section epub:type=\[dq]prologue\[dq]>- <h1>My chapter</h1>-\f[R]-.fi-.PP-Pandoc will output \f[V]<body epub:type=\[dq]bodymatter\[dq]>\f[R],-unless you use one of the following values, in which case either-\f[V]frontmatter\f[R] or \f[V]backmatter\f[R] will be output.-.RS -14n-.IP-.nf-\f[C]- epub:type of first section epub:type of body- ---------------------------- -------------------- prologue frontmatter- abstract frontmatter- acknowledgments frontmatter- copyright-page frontmatter- dedication frontmatter- credits frontmatter- keywords frontmatter- imprint frontmatter- contributors frontmatter- other-credits frontmatter- errata frontmatter- revision-history frontmatter- titlepage frontmatter- halftitlepage frontmatter- seriespage frontmatter- foreword frontmatter- preface frontmatter- frontispiece frontmatter- appendix backmatter- colophon backmatter- bibliography backmatter- index backmatter-\f[R]-.fi-.RE-.SS Linked media-.PP-By default, pandoc will download media referenced from any-\f[V]<img>\f[R], \f[V]<audio>\f[R], \f[V]<video>\f[R] or-\f[V]<source>\f[R] element present in the generated EPUB, and include it-in the EPUB container, yielding a completely self-contained EPUB.-If you want to link to external media resources instead, use raw HTML in-your source and add \f[V]data-external=\[dq]1\[dq]\f[R] to the tag with-the \f[V]src\f[R] attribute.-For example:-.IP-.nf-\f[C]-<audio controls=\[dq]1\[dq]>- <source src=\[dq]https://example.com/music/toccata.mp3\[dq]- data-external=\[dq]1\[dq] type=\[dq]audio/mpeg\[dq]>- </source>-</audio>-\f[R]-.fi-.PP-If the input format already is HTML then-\f[V]data-external=\[dq]1\[dq]\f[R] will work as expected for-\f[V]<img>\f[R] elements.-Similarly, for Markdown, external images can be declared with-\f[V]{external=1}\f[R].-Note that this only works for images; the other media elements have no-native representation in pandoc\[cq]s AST and require the use of raw-HTML.-.SS EPUB styling-.PP-By default, pandoc will include some basic styling contained in its-\f[V]epub.css\f[R] data file.-(To see this, use \f[V]pandoc --print-default-data-file epub.css\f[R].)-To use a different CSS file, just use the \f[V]--css\f[R] command line-option.-A few inline styles are defined in addition; these are essential for-correct formatting of pandoc\[cq]s HTML output.-.PP-The \f[V]document-css\f[R] variable may be set if the more opinionated-styling of pandoc\[cq]s default HTML templates is desired (and in that-case the variables defined in Variables for HTML may be used to-fine-tune the style).-.SH JUPYTER NOTEBOOKS-.PP-When creating a Jupyter notebook, pandoc will try to infer the notebook-structure.-Code blocks with the class \f[V]code\f[R] will be taken as code cells,-and intervening content will be taken as Markdown cells.-Attachments will automatically be created for images in Markdown cells.-Metadata will be taken from the \f[V]jupyter\f[R] metadata field.-For example:-.IP-.nf-\f[C]-----title: My notebook-jupyter:- nbformat: 4- nbformat_minor: 5- kernelspec:- display_name: Python 2- language: python- name: python2- language_info:- codemirror_mode:- name: ipython- version: 2- file_extension: \[dq].py\[dq]- mimetype: \[dq]text/x-python\[dq]- name: \[dq]python\[dq]- nbconvert_exporter: \[dq]python\[dq]- pygments_lexer: \[dq]ipython2\[dq]- version: \[dq]2.7.15\[dq]------# Lorem ipsum--**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus-bibendum felis dictum sodales.--\[ga]\[ga]\[ga] code-print(\[dq]hello\[dq])-\[ga]\[ga]\[ga]--## Pyout--\[ga]\[ga]\[ga] code-from IPython.display import HTML-HTML(\[dq]\[dq]\[dq]-<script>-console.log(\[dq]hello\[dq]);-</script>-<b>HTML</b>-\[dq]\[dq]\[dq])-\[ga]\[ga]\[ga]--## Image--This image  will be-included as a cell attachment.-\f[R]-.fi-.PP-If you want to add cell attributes, group cells differently, or add-output to code cells, then you need to include divs to indicate the-structure.-You can use either fenced divs or native divs for this.-Here is an example:-.IP-.nf-\f[C]-:::::: {.cell .markdown}-# Lorem--**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus-bibendum felis dictum sodales.-::::::--:::::: {.cell .code execution_count=1}-\[ga]\[ga]\[ga] {.python}-print(\[dq]hello\[dq])-\[ga]\[ga]\[ga]--::: {.output .stream .stdout}-\[ga]\[ga]\[ga]-hello-\[ga]\[ga]\[ga]-:::-::::::--:::::: {.cell .code execution_count=2}-\[ga]\[ga]\[ga] {.python}-from IPython.display import HTML-HTML(\[dq]\[dq]\[dq]-<script>-console.log(\[dq]hello\[dq]);-</script>-<b>HTML</b>-\[dq]\[dq]\[dq])-\[ga]\[ga]\[ga]--::: {.output .execute_result execution_count=2}-\[ga]\[ga]\[ga]{=html}-<script>-console.log(\[dq]hello\[dq]);-</script>-<b>HTML</b>-hello-\[ga]\[ga]\[ga]-:::-::::::-\f[R]-.fi-.PP-If you include raw HTML or TeX in an output cell, use the [raw-attribute][Extension: \f[V]fenced_attribute\f[R]], as shown in the last-cell of the example above.-Although pandoc can process \[lq]bare\[rq] raw HTML and TeX, the result-is often interspersed raw elements and normal textual elements, and in-an output cell pandoc expects a single, connected raw block.-To avoid using raw HTML or TeX except when marked explicitly using raw-attributes, we recommend specifying the extensions-\f[V]-raw_html-raw_tex+raw_attribute\f[R] when translating between-Markdown and ipynb notebooks.-.PP-Note that options and extensions that affect reading and writing of-Markdown will also affect Markdown cells in ipynb notebooks.-For example, \f[V]--wrap=preserve\f[R] will preserve soft line breaks in-Markdown cells; \f[V]--atx-headers\f[R] will cause ATX-style headings to-be used; and \f[V]--preserve-tabs\f[R] will prevent tabs from being-turned to spaces.-.SH SYNTAX HIGHLIGHTING-.PP-Pandoc will automatically highlight syntax in fenced code blocks that-are marked with a language name.-The Haskell library skylighting is used for highlighting.-Currently highlighting is supported only for HTML, EPUB, Docx, Ms, and-LaTeX/PDF output.-To see a list of language names that pandoc will recognize, type-\f[V]pandoc --list-highlight-languages\f[R].-.PP-The color scheme can be selected using the \f[V]--highlight-style\f[R]-option.-The default color scheme is \f[V]pygments\f[R], 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-\f[V]pandoc --list-highlight-styles\f[R].-.PP-If you are not satisfied with the predefined styles, you can use-\f[V]--print-highlight-style\f[R] to generate a JSON \f[V].theme\f[R]-file which can be modified and used as the argument to-\f[V]--highlight-style\f[R].-To get a JSON version of the \f[V]pygments\f[R] style, for example:-.IP-.nf-\f[C]-pandoc --print-highlight-style pygments > my.theme-\f[R]-.fi-.PP-Then edit \f[V]my.theme\f[R] and use it like this:-.IP-.nf-\f[C]-pandoc --highlight-style my.theme-\f[R]-.fi-.PP-If you are not satisfied with the built-in highlighting, or you want to-highlight a language that isn\[cq]t supported, you can use the-\f[V]--syntax-definition\f[R] option to load a KDE-style XML syntax-definition file.-Before writing your own, have a look at KDE\[cq]s repository of syntax-definitions.-.PP-To disable highlighting, use the \f[V]--no-highlight\f[R] option.-.SH CUSTOM STYLES-.PP-Custom styles can be used in the docx and ICML formats.-.SS Output-.PP-By default, pandoc\[cq]s docx and ICML output applies a predefined set-of styles for blocks such as paragraphs and block quotes, and uses-largely default formatting (italics, bold) for inlines.-This will work for most purposes, especially alongside a-\f[V]reference.docx\f[R] file.-However, if you need to apply your own styles to blocks, or match a-preexisting set of styles, pandoc allows you to define custom styles for-blocks and text using \f[V]div\f[R]s and \f[V]span\f[R]s, respectively.-.PP-If you define a \f[V]div\f[R] or \f[V]span\f[R] with the attribute-\f[V]custom-style\f[R], pandoc will apply your specified style to the-contained elements (with the exception of elements whose function-depends on a style, like headings, code blocks, block quotes, or links).-So, for example, using the \f[V]bracketed_spans\f[R] syntax,-.IP-.nf-\f[C]-[Get out]{custom-style=\[dq]Emphatically\[dq]}, he said.-\f[R]-.fi-.PP-would produce a docx file with \[lq]Get out\[rq] styled with character-style \f[V]Emphatically\f[R].-Similarly, using the \f[V]fenced_divs\f[R] syntax,-.IP-.nf-\f[C]-Dickinson starts the poem simply:--::: {custom-style=\[dq]Poetry\[dq]}-| A Bird came down the Walk----| He did not know I saw----:::-\f[R]-.fi-.PP-would style the two contained lines with the \f[V]Poetry\f[R] paragraph-style.-.PP-For docx output, styles will be defined in the output file as inheriting-from normal text, if the styles are not yet in your reference.docx.-If they are already defined, pandoc will not alter the definition.-.PP-This feature allows for greatest customization in conjunction with-pandoc filters.-If you want all paragraphs after block quotes to be indented, you can-write a filter to apply the styles necessary.-If you want all italics to be transformed to the \f[V]Emphasis\f[R]-character style (perhaps to change their color), you can write a filter-which will transform all italicized inlines to inlines within an-\f[V]Emphasis\f[R] custom-style \f[V]span\f[R].-.PP-For docx output, you don\[cq]t need to enable any extensions for custom-styles to work.-.SS Input-.PP-The docx reader, by default, only reads those styles that it can convert-into pandoc elements, either by direct conversion or interpreting the-derivation of the input document\[cq]s styles.-.PP-By enabling the \f[V]styles\f[R] extension in the docx reader-(\f[V]-f docx+styles\f[R]), you can produce output that maintains the-styles of the input document, using the \f[V]custom-style\f[R] class.-Paragraph styles are interpreted as divs, while character styles are-interpreted as spans.-.PP-For example, using the \f[V]custom-style-reference.docx\f[R] file in the-test directory, we have the following different outputs:-.PP-Without the \f[V]+styles\f[R] extension:-.IP-.nf-\f[C]-$ pandoc test/docx/custom-style-reference.docx -f docx -t markdown-This is some text.--This is text with an *emphasized* text style. And this is text with a-**strengthened** text style.--> Here is a styled paragraph that inherits from Block Text.-\f[R]-.fi-.PP-And with the extension:-.IP-.nf-\f[C]-$ pandoc test/docx/custom-style-reference.docx -f docx+styles -t markdown--::: {custom-style=\[dq]First Paragraph\[dq]}-This is some text.-:::--::: {custom-style=\[dq]Body Text\[dq]}-This is text with an [emphasized]{custom-style=\[dq]Emphatic\[dq]} text style.-And this is text with a [strengthened]{custom-style=\[dq]Strengthened\[dq]}-text style.-:::--::: {custom-style=\[dq]My Block Style\[dq]}-> Here is a styled paragraph that inherits from Block Text.-:::-\f[R]-.fi-.PP-With these custom styles, you can use your input document as a-reference-doc while creating docx output (see below), and maintain the-same styles in your input and output files.-.SH CUSTOM READERS AND WRITERS-.PP-Pandoc can be extended with custom readers and writers written in Lua.-(Pandoc includes a Lua interpreter, so Lua need not be installed-separately.)-.PP-To use a custom reader or writer, simply specify the path to the Lua-script in place of the input or output format.-For example:-.IP-.nf-\f[C]-pandoc -t data/sample.lua-pandoc -f my_custom_markup_language.lua -t latex -s-\f[R]-.fi-.PP-If the script is not found relative to the working directory, it will be-sought in the \f[V]readers\f[R] or \f[V]writers\f[R] subdirectory of the-user data directory (see \f[V]--data-dir\f[R]).-.PP-A custom reader is a Lua script that defines one function, Reader, which-takes a string as input and returns a Pandoc AST.-See the Lua filters documentation for documentation of the functions-that are available for creating pandoc AST elements.-For parsing, the lpeg parsing library is available by default.-To see a sample custom reader:-.IP-.nf-\f[C]-pandoc --print-default-data-file creole.lua-\f[R]-.fi-.PP-If you want your custom reader to have access to reader options-(e.g.\ the tab stop setting), you give your Reader function a second-\f[V]options\f[R] parameter.-.PP-A custom writer is a Lua script that defines a function that specifies-how to render each element in a Pandoc AST.-To see a documented example which you can modify according to your-needs:-.IP-.nf-\f[C]-pandoc --print-default-data-file sample.lua-\f[R]-.fi-.PP-Note that custom writers have no default template.-If you want to use \f[V]--standalone\f[R] with a custom writer, you will-need to specify a template manually using \f[V]--template\f[R] or add a-new default template with the name-\f[V]default.NAME_OF_CUSTOM_WRITER.lua\f[R] to the \f[V]templates\f[R]-subdirectory of your user data directory (see Templates).-.SH REPRODUCIBLE BUILDS-.PP-Some of the document formats pandoc targets (such as EPUB, docx, and-ODT) include build timestamps in the generated document.-That means that the files generated on successive builds will differ,-even if the source does not.-To avoid this, set the \f[V]SOURCE_DATE_EPOCH\f[R] environment variable,-and the timestamp will be taken from it instead of the current time.-\f[V]SOURCE_DATE_EPOCH\f[R] should contain an integer unix timestamp-(specifying the number of seconds since midnight UTC January 1, 1970).-.PP-Some document formats also include a unique identifier.-For EPUB, this can be set explicitly by setting the \f[V]identifier\f[R]-metadata field (see EPUB Metadata, above).-.SH RUNNING PANDOC AS A WEB SERVER-.PP-If you rename (or symlink) the pandoc executable to-\f[V]pandoc-server\f[R], it will start up a web server with a JSON API.-This server exposes most of the conversion functionality of pandoc.-For full documentation, see the pandoc-server man page.-.PP-If you rename (or symlink) the pandoc executable to-\f[V]pandoc-server.cgi\f[R], it will function as a CGI program exposing-the same API as \f[V]pandoc-server\f[R].-.PP-\f[V]pandoc-server\f[R] is designed to be maximally secure; it uses-Haskell\[cq]s type system to provide strong guarantees that no I/O will-be performed on the server during pandoc conversions.-.SH A NOTE ON SECURITY-.IP "1." 3-Although pandoc itself will not create or modify any files other than-those you explicitly ask it create (with the exception of temporary-files used in producing PDFs), a filter or custom writer could in-principle do anything on your file system.-Please audit filters and custom writers very carefully before using-them.-.IP "2." 3-Several input formats (including HTML, Org, and RST) support-\f[V]include\f[R] directives that allow the contents of a file to be-included in the output.-An untrusted attacker could use these to view the contents of files on-the file system.-(Using the \f[V]--sandbox\f[R] option can protect against this threat.)-.IP "3." 3-Several output formats (including RTF, FB2, HTML with-\f[V]--self-contained\f[R], EPUB, Docx, and ODT) will embed encoded or-raw images into the output file.-An untrusted attacker could exploit this to view the contents of-non-image files on the file system.-(Using the \f[V]--sandbox\f[R] option can protect against this threat,-but will also prevent including images in these formats.)-.IP "4." 3-If your application uses pandoc as a Haskell library (rather than-shelling out to the executable), it is possible to use it in a mode that-fully isolates pandoc from your file system, by running the pandoc-operations in the \f[V]PandocPure\f[R] monad.-See the document Using the pandoc API for more details.-(This corresponds to the use of the \f[V]--sandbox\f[R] option on the-command line.)-.IP "5." 3-Pandoc\[cq]s parsers can exhibit pathological performance on some corner-cases.-It is wise to put any pandoc operations under a timeout, to avoid DOS-attacks that exploit these issues.-If you are using the pandoc executable, you can add the command line-options \f[V]+RTS -M512M -RTS\f[R] (for example) to limit the heap size-to 512MB.-Note that the \f[V]commonmark\f[R] parser (including-\f[V]commonmark_x\f[R] and \f[V]gfm\f[R]) is much less vulnerable to-pathological performance than the \f[V]markdown\f[R] parser, so it is a-better choice when processing untrusted input.-.IP "6." 3-The HTML generated by pandoc is not guaranteed to be safe.-If \f[V]raw_html\f[R] is enabled for the Markdown input, users can-inject arbitrary HTML.-Even if \f[V]raw_html\f[R] is disabled, users can include dangerous-content in URLs and attributes.-To be safe, you should run all HTML generated from untrusted user input-through an HTML sanitizer.-.SH AUTHORS-.PP-Copyright 2006\[en]2022 John MacFarlane (jgm\[at]berkeley.edu).-Released under the GPL, version 2 or greater.-This software carries no warranty of any kind.-(See COPYRIGHT for full copyright and warranty notices.)-For a full list of contributors, see the file AUTHORS.md in the pandoc-source code.-.PP-The Pandoc source code may be downloaded-from <https://hackage.haskell.org/package/pandoc> or-<https://github.com/jgm/pandoc/releases>. Further-documentation is available at <https://pandoc.org>.
@@ -1,5 +0,0 @@-.PP-The Pandoc source code may be downloaded-from <https://hackage.haskell.org/package/pandoc> or-<https://github.com/jgm/pandoc/releases>. Further-documentation is available at <https://pandoc.org>.
@@ -1,2 +0,0 @@-.SH NAME-pandoc - general markup converter
@@ -1,31 +1,30 @@ cabal-version: 2.4 name: pandoc-version: 2.19.2+version: 3.10 build-type: Simple license: GPL-2.0-or-later license-file: COPYING.md-copyright: (c) 2006-2022 John MacFarlane+copyright: (c) 2006-2024 John MacFarlane author: John MacFarlane <jgm@berkeley.edu> maintainer: John MacFarlane <jgm@berkeley.edu> bug-reports: https://github.com/jgm/pandoc/issues stability: alpha homepage: https://pandoc.org category: Text-tested-with: GHC == 8.6.5, GHC == 8.8.4, GHC == 8.10.7, GHC == 9.0.2,- GHC == 9.2.3+tested-with: GHC == 9.6.7, GHC == 9.8.4, GHC == 9.10.3, GHC == 9.12.2 synopsis: Conversion between markup formats description: Pandoc is a Haskell library for converting from one markup- format to another, and a command-line tool that uses- this library. The formats it can handle include+ format to another. The formats it can handle include . - light markup formats (many variants of Markdown, reStructuredText, AsciiDoc, Org-mode, Muse, Textile,- txt2tags)+ txt2tags, djot) - HTML formats (HTML 4 and 5) - Ebook formats (EPUB v2 and v3, FB2)- - Documentation formats (GNU TexInfo, Haddock)+ - Documentation formats (GNU TexInfo, Haddock, Vimdoc) - Roff formats (man, ms) - TeX formats (LaTeX, ConTeXt)+ - Typst - XML formats (DocBook 4 and 5, JATS, TEI Simple, OpenDocument) - Outline formats (OPML) - Bibliography formats (BibTeX, BibLaTeX, CSL JSON, CSL YAML,@@ -37,20 +36,26 @@ Vimwiki, XWiki, ZimWiki, Jira wiki, Creole) - Slide show formats (LaTeX Beamer, PowerPoint, Slidy, reveal.js, Slideous, S5, DZSlides)- - Data formats (CSV and TSV tables)+ - Data formats (CSV and TSV tables, Excel spreadsheets) - PDF (via external programs such as pdflatex or wkhtmltopdf) . Pandoc can convert mathematical content in documents- between TeX, MathML, Word equations, roff eqn, and plain text.- It includes a powerful system for automatic citations- and bibliographies, and it can be customized extensively- using templates, filters, and custom readers and writers- written in Lua.+ between TeX, MathML, Word equations, roff eqn, typst,+ and plain text. It includes a powerful system for automatic+ citations and bibliographies, and it can be customized+ extensively using templates, filters, and custom readers+ and writers written in Lua.+ .+ For the pandoc command-line program, see the+ @pandoc-cli@ package. data-files: -- templates data/templates/styles.html+ data/templates/styles.citations.html data/templates/default.html4 data/templates/default.html5+ data/templates/default.chunkedhtml+ data/templates/default.djot data/templates/default.docbook4 data/templates/default.docbook5 data/templates/default.jats_archiving@@ -58,8 +63,10 @@ data/templates/default.jats_publishing data/templates/default.tei data/templates/default.opendocument+ data/templates/default.openxml data/templates/default.icml data/templates/default.opml+ data/templates/default.beamer data/templates/default.latex data/templates/default.bibtex data/templates/default.biblatex@@ -84,15 +91,27 @@ data/templates/default.revealjs data/templates/default.dzslides data/templates/default.asciidoc- data/templates/default.asciidoctor data/templates/default.haddock data/templates/default.textile data/templates/default.org data/templates/default.epub2 data/templates/default.epub3+ data/templates/default.ansi data/templates/article.jats_publishing data/templates/affiliations.jats data/templates/default.markua+ data/templates/default.typst+ data/templates/document-metadata.latex+ data/templates/template.typst+ data/templates/common.latex+ data/templates/hypersetup.latex+ data/templates/passoptions.latex+ data/templates/fonts.latex+ data/templates/font-settings.latex+ data/templates/after-header-includes.latex+ data/templates/default.vimdoc+ data/templates/default.bbcode+ -- translations data/translations/*.yaml -- entities@@ -120,9 +139,6 @@ data/odt/styles.xml data/odt/content.xml data/odt/meta.xml- data/odt/settings.xml- data/odt/Configurations2/accelerator/current.xml- data/odt/Thumbnails/thumbnail.png data/odt/META-INF/manifest.xml -- source files for reference.pptx data/pptx/_rels/.rels@@ -180,8 +196,6 @@ data/dzslides/template.html -- default abbreviations file data/abbreviations- -- sample lua custom writer- data/sample.lua -- sample lua custom reader data/creole.lua -- lua init script@@ -193,33 +207,35 @@ citeproc/biblatex-localization/*.lbx.strings -- documentation MANUAL.txt, COPYRIGHT+extra-doc-files: changelog.md,+ AUTHORS.md,+ INSTALL.md,+ README.md,+ CONTRIBUTING.md,+ BUGS extra-source-files:- -- documentation- INSTALL.md, AUTHORS.md, README.md,- CONTRIBUTING.md, BUGS, changelog.md,- man/pandoc.1- -- cabal and stack build plans- cabal.project- stack.yaml- -- files needed to build man page- man/manfilter.lua- man/pandoc.1.before- man/pandoc.1.after- -- trypandoc- trypandoc/index.html- trypandoc/trypandoc.js -- tests test/bodybg.gif test/*.native test/command/*.md test/command/*.csl+ test/command/*.svg+ test/command/7691.docx+ test/command/9391.docx+ test/command/9358.docx+ test/command/9002.docx+ test/command/9603.docx+ test/command/11113.docx test/command/biblio.bib test/command/averroes.bib test/command/A.txt test/command/B.txt test/command/C.txt test/command/D.txt+ 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@@ -234,17 +250,14 @@ test/command/defaults7.yaml test/command/defaults8.yaml test/command/defaults9.yaml+ test/command/8024a.yaml+ test/command/8024b.yaml test/command/3533-rst-csv-tables.csv test/command/3880.txt test/command/5182.txt test/command/5700-metadata-file-1.yml test/command/5700-metadata-file-2.yml test/command/abbrevs- test/command/SVG_logo-without-xml-declaration.svg- test/command/SVG_logo.svg- test/command/corrupt.svg- test/command/inkscape-cube.svg- test/command/lua-pandoc-state.lua test/command/sub-file-chapter-1.tex test/command/sub-file-chapter-2.tex test/command/bar.tex@@ -264,6 +277,12 @@ test/command/6466-whole.hs test/command/7861.yaml test/command/7861/metadata/placeholder+ test/command/11486/scroll.revealjs+ test/command/11498.png+ test/asciidoc-reader.adoc+ test/asciidoc-reader.native+ test/asciidoc-reader-include.rb+ test/asciidoc-reader-include.adoc test/docbook-chapter.docbook test/docbook-reader.docbook test/docbook-xref.docbook@@ -279,6 +298,9 @@ test/media/rId25.jpg test/media/rId26.jpg test/media/rId27.jpg+ test/typst-reader.typ+ test/undergradmath.typ+ test/djot-reader.djot test/latex-reader.latex test/textile-reader.textile test/markdown-reader-more.txt@@ -301,6 +323,7 @@ test/tables.jats_articleauthoring test/tables.jats_publishing test/tables.jira+ test/tables.djot test/tables.dokuwiki test/tables.zimwiki test/tables.icml@@ -318,24 +341,31 @@ test/tables.opendocument test/tables.org test/tables.asciidoc- test/tables.asciidoctor+ test/tables.asciidoc_legacy test/tables.haddock test/tables.texinfo+ test/tables.typst test/tables.rst test/tables.rtf test/tables.txt test/tables.fb2 test/tables.muse- test/tables.custom+ test/tables.vimdoc+ test/tables.bbcode test/tables.xwiki test/tables/*.html4 test/tables/*.html5 test/tables/*.latex+ test/tables/*.typst test/tables/*.native+ test/tables/*.mediawiki test/tables/*.jats_archiving+ test/tables/*.markdown test/testsuite.txt+ test/ansi-test.txt test/writer.latex test/writer.context+ test/writer.djot test/writer.docbook4 test/writer.docbook5 test/writer.jats_archiving@@ -351,10 +381,11 @@ test/writer.plain test/writer.mediawiki test/writer.textile+ test/writer.typst test/writer.opendocument test/writer.org test/writer.asciidoc- test/writer.asciidoctor+ test/writer.asciidoc_legacy test/writer.haddock test/writer.rst test/writer.icml@@ -367,7 +398,9 @@ test/writer.zimwiki test/writer.xwiki test/writer.muse- test/writer.custom+ test/writer.vimdoc+ test/writer.bbcode+ test/ansi-test.ansi test/writers-lang-and-dir.latex test/writers-lang-and-dir.context test/dokuwiki_inline_formatting.dokuwiki@@ -401,6 +434,8 @@ test/pptx/*.pptx test/pptx/**/*.pptx test/pptx/**/*.native+ test/pptx-reader/basic.pptx+ test/pptx-reader/basic.native test/ipynb/*.native test/ipynb/*.in.native test/ipynb/*.out.native@@ -413,29 +448,26 @@ test/odt/odt/*.odt test/odt/markdown/*.md test/odt/native/*.native- test/lua/*.lua- test/lua/module/*.lua- test/lua/module/partial.test- test/lua/module/tiny.epub+ test/xlsx-reader/*.xlsx+ test/xlsx-reader/*.native+ test/pod-reader.pod+ test/vimdoc/*.markdown+ test/vimdoc/*.vimdoc source-repository head type: git- location: git://github.com/jgm/pandoc.git+ location: https://github.com/jgm/pandoc.git flag embed_data_files Description: Embed data files in binary for relocatable executable. Default: False -flag lua53- Description: Embed Lua 5.3 instead of 5.4.- Default: False--flag nightly- Description: Add '-nightly-COMPILEDATE' to the output of '--version'.- Default: False+flag http+ Description: Support for fetching resources using HTTP.+ Default: True common common-options default-language: Haskell2010- build-depends: base >= 4.12 && < 5+ build-depends: base >= 4.18 && < 5 ghc-options: -Wall -fno-warn-unused-do-bind -Wincomplete-record-updates -Wnoncanonical-monad-instances@@ -445,13 +477,12 @@ -Wpartial-fields -Wmissing-signatures -fhide-source-paths- -- -Wmissing-export-lists-- if impl(ghc >= 8.10)- ghc-options: -Wunused-packages+ -Wmissing-export-lists+ -Wunused-packages+ -Winvalid-haddock - if impl(ghc >= 9.0)- ghc-options: -Winvalid-haddock+ if impl(ghc >= 9.12)+ ghc-options: -Wno-deriving-typeable if os(windows) cpp-options: -D_WINDOWS@@ -461,110 +492,120 @@ build-depends: pandoc ghc-options: -rtsopts -with-rtsopts=-A8m -threaded +library xml-light+ import: common-options+ build-depends: xml >= 1.3.12 && < 1.4,+ xml-conduit >= 1.9.1.1 && < 1.11,+ xml-types >= 0.3 && < 0.4,+ containers >= 0.6.0.1 && < 0.9,+ text >= 1.1.1.0 && < 2.2 + hs-source-dirs: xml-light+ exposed-modules: Text.Pandoc.XML.Light,+ Text.Pandoc.XML.Light.Types,+ Text.Pandoc.XML.Light.Proc,+ Text.Pandoc.XML.Light.Output+ library import: common-options- build-depends: Glob >= 0.7 && < 0.11,+ build-depends: xml-light,+ Glob >= 0.7 && < 0.11, JuicyPixels >= 3.1.6.1 && < 3.4,- SHA >= 1.6 && < 1.7,- aeson >= 0.7 && < 2.2,+ aeson >= 2.0.1.0 && < 2.4, aeson-pretty >= 0.8.9 && < 0.9, array >= 0.5 && < 0.6, attoparsec >= 0.12 && < 0.15,+ base64-bytestring >= 0.1 && < 1.3, binary >= 0.7 && < 0.11, blaze-html >= 0.9 && < 0.10, blaze-markup >= 0.8 && < 0.9,- bytestring >= 0.9 && < 0.12,+ bytestring >= 0.9 && < 0.13, case-insensitive >= 1.2 && < 1.3,- citeproc >= 0.8.0.1 && < 0.9,- commonmark >= 0.2.2 && < 0.3,- commonmark-extensions >= 0.2.3.1 && < 0.3,- commonmark-pandoc >= 0.2.1.2 && < 0.3,- connection >= 0.3.1,- containers >= 0.6.0.1 && < 0.7,- data-default >= 0.4 && < 0.8,- deepseq >= 1.3 && < 1.5,+ citeproc >= 0.13.0.1 && < 0.14,+ commonmark >= 0.3 && < 0.4,+ commonmark-extensions >= 0.2.7 && < 0.3,+ commonmark-pandoc >= 0.3 && < 0.4,+ containers >= 0.6.0.1 && < 0.9,+ crypton >= 0.30 && < 1.2,+ data-default >= 0.4 && < 0.9,+ deepseq >= 1.3 && < 1.6, directory >= 1.2.3 && < 1.4,- doclayout >= 0.4 && < 0.5,- doctemplates >= 0.10 && < 0.11,- base64 >= 0.4 && < 0.5,- emojis >= 0.1 && < 0.2,+ doclayout >= 0.5.0.1 && < 0.6,+ doctemplates >= 0.11 && < 0.12,+ emojis >= 0.1.4.1 && < 0.2, exceptions >= 0.8 && < 0.11, file-embed >= 0.0 && < 0.1,- filepath >= 1.1 && < 1.5,- gridtables >= 0.0.3 && < 0.1,+ filepath >= 1.1 && < 1.6,+ gridtables >= 0.1 && < 0.2, haddock-library >= 1.10 && < 1.12,- hslua-module-doclayout>= 1.0.4 && < 1.1,- hslua-module-path >= 1.0.3 && < 1.1,- hslua-module-system >= 1.0 && < 1.1,- hslua-module-text >= 1.0 && < 1.1,- hslua-module-version >= 1.0 && < 1.1,- http-client >= 0.4.30 && < 0.8,- http-client-tls >= 0.2.4 && < 0.4, http-types >= 0.8 && < 0.13, ipynb >= 0.2 && < 0.3,- jira-wiki-markup >= 1.4 && < 1.5,- lpeg >= 1.0.1 && < 1.1,- mtl >= 2.2 && < 2.3,- network >= 2.6,+ jira-wiki-markup >= 1.5.1 && < 1.6,+ mime-types >= 0.1.1 && < 0.2,+ mtl >= 2.2 && < 2.4, network-uri >= 2.6 && < 2.8,- pandoc-lua-marshal >= 0.1.7 && < 0.2,- pandoc-types >= 1.22.2 && < 1.23,+ pandoc-types >= 1.23.1 && < 1.24, parsec >= 3.1 && < 3.2, pretty >= 1.1 && < 1.2, pretty-show >= 1.10 && < 1.11, process >= 1.2.3 && < 1.7,- random >= 1 && < 1.3,+ random >= 1.2 && < 1.4, safe >= 0.3.18 && < 0.4, scientific >= 0.3 && < 0.4,- skylighting >= 0.13 && < 0.14,- skylighting-core >= 0.13 && < 0.14,+ 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.5.1 && < 0.12.6,- text >= 1.1.1.0 && < 2.1,+ texmath >= 0.13.1.2 && < 0.14,+ text >= 1.1.1.0 && < 2.2, text-conversions >= 0.3 && < 0.4,- time >= 1.5 && < 1.14,+ time >= 1.5 && < 1.17, unicode-collation >= 0.1.1 && < 0.2,+ unicode-data >= 0.6 && < 0.9, unicode-transforms >= 0.3 && < 0.5,- xml >= 1.3.12 && < 1.4,- xml-conduit >= 1.9.1.1 && < 1.10,- xml-types >= 0.3 && < 0.4, yaml >= 0.11 && < 0.12,- zip-archive >= 0.2.3.4 && < 0.5,- zlib >= 0.5 && < 0.7,- servant-server,- wai >= 0.3+ 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.10 && < 0.11,+ vector >= 0.12 && < 0.14,+ djot >= 0.1.4 && < 0.2,+ asciidoc >= 0.1.0.3 && < 0.2 if !os(windows) build-depends: unix >= 2.4 && < 2.9- if flag(nightly)- cpp-options: -DNIGHTLY- build-depends: template-haskell- if flag(lua53)- build-depends: hslua >= 2.1 && < 2.2,- hslua-aeson >= 2.2.1 && < 2.3- else- build-depends: hslua >= 2.2.1 && < 2.3- , hslua-aeson >= 2.2.1 && < 2.3 if flag(embed_data_files) cpp-options: -DEMBED_DATA_FILES- other-modules: Text.Pandoc.Data+ other-modules: Text.Pandoc.Data.BakedIn+ if flag(http)+ cpp-options: -DPANDOC_HTTP_SUPPORT+ build-depends:+ crypton-connection >= 0.3.1 && < 0.5,+ crypton-x509-system >= 1.6.7 && < 1.10,+ http-client >= 0.4.30 && < 0.8,+ http-client-tls >= 0.2.4 && < 0.5,+ network >= 2.6 && < 3.3,+ tls >= 2.0.1 && < 2.5 hs-source-dirs: src exposed-modules: Text.Pandoc, Text.Pandoc.App,+ Text.Pandoc.Data, Text.Pandoc.Options, Text.Pandoc.Extensions,+ Text.Pandoc.Format, Text.Pandoc.Shared, Text.Pandoc.Sources, Text.Pandoc.MediaBag, Text.Pandoc.Error, Text.Pandoc.Filter,- Text.Pandoc.Server,+ Text.Pandoc.Translations,+ Text.Pandoc.Translations.Types, Text.Pandoc.Readers,+ Text.Pandoc.Readers.AsciiDoc, Text.Pandoc.Readers.HTML, Text.Pandoc.Readers.LaTeX, Text.Pandoc.Readers.Markdown,@@ -589,27 +630,36 @@ Text.Pandoc.Readers.TikiWiki, Text.Pandoc.Readers.Txt2Tags, Text.Pandoc.Readers.Docx,- Text.Pandoc.Readers.Odt,+ Text.Pandoc.Readers.Pptx,+ Text.Pandoc.Readers.Xlsx,+ Text.Pandoc.Readers.ODT, Text.Pandoc.Readers.EPUB, Text.Pandoc.Readers.Muse, Text.Pandoc.Readers.Man,+ Text.Pandoc.Readers.Mdoc, Text.Pandoc.Readers.FB2, Text.Pandoc.Readers.DokuWiki, Text.Pandoc.Readers.Ipynb, Text.Pandoc.Readers.CSV, Text.Pandoc.Readers.RTF,- Text.Pandoc.Readers.Custom,+ Text.Pandoc.Readers.Typst,+ Text.Pandoc.Readers.Djot,+ Text.Pandoc.Readers.Pod, Text.Pandoc.Writers, Text.Pandoc.Writers.Native,- Text.Pandoc.Writers.Docbook,+ Text.Pandoc.Writers.XML,+ Text.Pandoc.Writers.DocBook, Text.Pandoc.Writers.JATS, Text.Pandoc.Writers.OPML, Text.Pandoc.Writers.HTML,+ Text.Pandoc.Writers.ChunkedHTML, Text.Pandoc.Writers.Ipynb, Text.Pandoc.Writers.ICML, Text.Pandoc.Writers.Jira, Text.Pandoc.Writers.LaTeX, Text.Pandoc.Writers.ConTeXt,+ Text.Pandoc.Writers.Djot,+ Text.Pandoc.Writers.Typst, Text.Pandoc.Writers.OpenDocument, Text.Pandoc.Writers.Texinfo, Text.Pandoc.Writers.Man,@@ -620,7 +670,6 @@ Text.Pandoc.Writers.RST, Text.Pandoc.Writers.Org, Text.Pandoc.Writers.AsciiDoc,- Text.Pandoc.Writers.Custom, Text.Pandoc.Writers.Textile, Text.Pandoc.Writers.MediaWiki, Text.Pandoc.Writers.DokuWiki,@@ -640,9 +689,13 @@ Text.Pandoc.Writers.OOXML, Text.Pandoc.Writers.AnnotatedTable, Text.Pandoc.Writers.BibTeX,- Text.Pandoc.Lua,+ Text.Pandoc.Writers.ANSI,+ Text.Pandoc.Writers.Vimdoc,+ Text.Pandoc.Writers.BBCode, Text.Pandoc.PDF, Text.Pandoc.UTF8,+ Text.Pandoc.Scripting,+ Text.Pandoc.Slides, Text.Pandoc.Templates, Text.Pandoc.XML, Text.Pandoc.SelfContained,@@ -655,20 +708,22 @@ Text.Pandoc.Emoji, Text.Pandoc.ImageSize, Text.Pandoc.Class,- Text.Pandoc.Citeproc+ Text.Pandoc.Class.IO,+ Text.Pandoc.Citeproc,+ Text.Pandoc.Chunks,+ Text.Pandoc.Transforms,+ Text.Pandoc.Version other-modules: Text.Pandoc.App.CommandLineOptions,- Text.Pandoc.App.FormatHeuristics,+ Text.Pandoc.App.Input, Text.Pandoc.App.Opt, Text.Pandoc.App.OutputSettings, Text.Pandoc.Class.CommonState,- Text.Pandoc.Class.IO, Text.Pandoc.Class.PandocMonad, Text.Pandoc.Class.PandocIO, Text.Pandoc.Class.PandocPure, Text.Pandoc.Class.Sandbox, Text.Pandoc.Filter.Environment, Text.Pandoc.Filter.JSON,- Text.Pandoc.Filter.Lua, Text.Pandoc.Parsing.Capabilities, Text.Pandoc.Parsing.Citations, Text.Pandoc.Parsing.General,@@ -677,13 +732,22 @@ Text.Pandoc.Parsing.Math, Text.Pandoc.Parsing.Smart, Text.Pandoc.Parsing.State,- Text.Pandoc.Parsing.Types,+ Text.Pandoc.Parsing.Future, Text.Pandoc.Readers.Docx.Lists, Text.Pandoc.Readers.Docx.Combine, Text.Pandoc.Readers.Docx.Parse, Text.Pandoc.Readers.Docx.Parse.Styles, Text.Pandoc.Readers.Docx.Util,+ Text.Pandoc.Readers.Docx.Symbols, Text.Pandoc.Readers.Docx.Fields,+ Text.Pandoc.Readers.OOXML.Shared,+ Text.Pandoc.Readers.Pptx.Parse,+ Text.Pandoc.Readers.Pptx.Shapes,+ Text.Pandoc.Readers.Pptx.Slides,+ Text.Pandoc.Readers.Pptx.SmartArt,+ Text.Pandoc.Readers.Xlsx.Parse,+ Text.Pandoc.Readers.Xlsx.Cells,+ Text.Pandoc.Readers.Xlsx.Sheets, Text.Pandoc.Readers.HTML.Parsing, Text.Pandoc.Readers.HTML.Table, Text.Pandoc.Readers.HTML.TagCategories,@@ -696,18 +760,22 @@ Text.Pandoc.Readers.LaTeX.Parsing, Text.Pandoc.Readers.LaTeX.SIunitx, Text.Pandoc.Readers.LaTeX.Table,- Text.Pandoc.Readers.LaTeX.Types,- Text.Pandoc.Readers.Odt.Base,- Text.Pandoc.Readers.Odt.Namespaces,- Text.Pandoc.Readers.Odt.StyleReader,- Text.Pandoc.Readers.Odt.ContentReader,- Text.Pandoc.Readers.Odt.Generic.Fallible,- Text.Pandoc.Readers.Odt.Generic.SetMap,- Text.Pandoc.Readers.Odt.Generic.Utils,- Text.Pandoc.Readers.Odt.Generic.Namespaces,- Text.Pandoc.Readers.Odt.Generic.XMLConverter,- Text.Pandoc.Readers.Odt.Arrows.State,- Text.Pandoc.Readers.Odt.Arrows.Utils,+ Text.Pandoc.Readers.Mdoc.Lex,+ Text.Pandoc.Readers.Mdoc.Macros,+ Text.Pandoc.Readers.Mdoc.Standards,+ Text.Pandoc.Readers.Typst.Parsing,+ Text.Pandoc.Readers.Typst.Math,+ Text.Pandoc.Readers.ODT.Base,+ Text.Pandoc.Readers.ODT.Namespaces,+ Text.Pandoc.Readers.ODT.StyleReader,+ Text.Pandoc.Readers.ODT.ContentReader,+ Text.Pandoc.Readers.ODT.Generic.Fallible,+ Text.Pandoc.Readers.ODT.Generic.SetMap,+ Text.Pandoc.Readers.ODT.Generic.Utils,+ Text.Pandoc.Readers.ODT.Generic.Namespaces,+ Text.Pandoc.Readers.ODT.Generic.XMLConverter,+ Text.Pandoc.Readers.ODT.Arrows.State,+ Text.Pandoc.Readers.ODT.Arrows.Utils, Text.Pandoc.Readers.Org.BlockStarts, Text.Pandoc.Readers.Org.Blocks, Text.Pandoc.Readers.Org.DocumentTree,@@ -719,6 +787,9 @@ Text.Pandoc.Readers.Org.Shared, 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, Text.Pandoc.Writers.Docx.Types,@@ -740,40 +811,17 @@ Text.Pandoc.Writers.Blaze, Text.Pandoc.Writers.Powerpoint.Presentation, Text.Pandoc.Writers.Powerpoint.Output,- Text.Pandoc.Lua.ErrorConversion,- Text.Pandoc.Lua.Filter,- Text.Pandoc.Lua.Global,- Text.Pandoc.Lua.Init,- Text.Pandoc.Lua.Marshal.CommonState,- Text.Pandoc.Lua.Marshal.Context,- Text.Pandoc.Lua.Marshal.PandocError,- Text.Pandoc.Lua.Marshal.ReaderOptions,- Text.Pandoc.Lua.Marshal.Reference,- Text.Pandoc.Lua.Marshal.Sources,- Text.Pandoc.Lua.Marshal.Template,- Text.Pandoc.Lua.Marshal.WriterOptions,- Text.Pandoc.Lua.Module.MediaBag,- Text.Pandoc.Lua.Module.Pandoc,- Text.Pandoc.Lua.Module.System,- Text.Pandoc.Lua.Module.Template,- Text.Pandoc.Lua.Module.Types,- Text.Pandoc.Lua.Module.Utils,- Text.Pandoc.Lua.Orphans,- Text.Pandoc.Lua.PandocLua,- Text.Pandoc.Lua.Writer.Classic,- Text.Pandoc.XML.Light,- Text.Pandoc.XML.Light.Types,- Text.Pandoc.XML.Light.Proc,- Text.Pandoc.XML.Light.Output,- Text.Pandoc.Network.HTTP,+ Text.Pandoc.Char,+ Text.Pandoc.TeX,+ Text.Pandoc.URI,+ Text.Pandoc.XMLFormat, Text.Pandoc.CSS, Text.Pandoc.CSV, Text.Pandoc.RoffChar, Text.Pandoc.UUID,- Text.Pandoc.Translations,- Text.Pandoc.Slides, Text.Pandoc.Image, Text.Pandoc.Citeproc.BibTeX,+ Text.Pandoc.Citeproc.Name, Text.Pandoc.Citeproc.CslJson, Text.Pandoc.Citeproc.Data, Text.Pandoc.Citeproc.Locator,@@ -783,49 +831,37 @@ autogen-modules: Paths_pandoc buildable: True -executable pandoc- import: common-executable- hs-source-dirs: app- main-is: pandoc.hs- buildable: True- other-modules: Paths_pandoc- build-depends: wai-extra >= 3.0.24,- warp,- safe- test-suite test-pandoc import: common-executable type: exitcode-stdio-1.0 main-is: test-pandoc.hs hs-source-dirs: test build-depends: pandoc,- Diff >= 0.2 && < 0.5,+ Diff >= 0.2 && < 1.1, Glob >= 0.7 && < 0.11,- bytestring >= 0.9 && < 0.12,- containers >= 0.4.2.1 && < 0.7,+ bytestring >= 0.9 && < 0.13,+ containers >= 0.4.2.1 && < 0.9, directory >= 1.2.3 && < 1.4,- doctemplates >= 0.10 && < 0.11,- exceptions >= 0.8 && < 0.11,- filepath >= 1.1 && < 1.5,- hslua >= 2.1 && < 2.3,- mtl >= 2.2 && < 2.3,- pandoc-types >= 1.22.2 && < 1.23,+ doctemplates >= 0.11 && < 0.12,+ filepath >= 1.1 && < 1.6,+ mtl >= 2.2 && < 2.4,+ pandoc-types >= 1.23.1 && < 1.24, process >= 1.2.3 && < 1.7,- tasty >= 0.11 && < 1.5,+ tasty >= 0.11 && < 1.6, tasty-golden >= 2.3 && < 2.4, tasty-hunit >= 0.9 && < 0.11,- tasty-lua >= 1.0 && < 1.1,- tasty-quickcheck >= 0.8 && < 0.11,- text >= 1.1.1.0 && < 2.1,- time >= 1.5 && < 1.14,+ tasty-quickcheck >= 0.8 && < 0.12,+ text >= 1.1.1.0 && < 2.2,+ temporary >= 1.1 && < 1.4,+ time >= 1.5 && < 1.17, xml >= 1.3.12 && < 1.4,- zip-archive >= 0.2.3.4 && < 0.5+ zip-archive >= 0.4.3 && < 0.5 other-modules: Tests.Old Tests.Command Tests.Helpers- Tests.Lua- Tests.Lua.Module Tests.Shared+ Tests.MediaBag+ Tests.XML Tests.Readers.LaTeX Tests.Readers.HTML Tests.Readers.JATS@@ -848,17 +884,21 @@ Tests.Readers.RST Tests.Readers.RTF Tests.Readers.Docx- Tests.Readers.Odt+ Tests.Readers.Pptx+ Tests.Readers.Xlsx+ Tests.Readers.ODT Tests.Readers.Txt2Tags Tests.Readers.EPUB Tests.Readers.Muse Tests.Readers.Creole Tests.Readers.Man+ Tests.Readers.Mdoc Tests.Readers.FB2+ Tests.Readers.Pod Tests.Readers.DokuWiki Tests.Writers.Native Tests.Writers.ConTeXt- Tests.Writers.Docbook+ Tests.Writers.DocBook Tests.Writers.HTML Tests.Writers.JATS Tests.Writers.Jira@@ -877,6 +917,7 @@ Tests.Writers.OOXML Tests.Writers.Ms Tests.Writers.AnnotatedTable+ Tests.Writers.BBCode benchmark benchmark-pandoc import: common-executable@@ -884,9 +925,9 @@ main-is: benchmark-pandoc.hs hs-source-dirs: benchmark build-depends: bytestring,- tasty-bench >= 0.2 && <= 0.4,- mtl >= 2.2 && < 2.3,- text >= 1.1.1.0 && < 2.1,+ tasty-bench >= 0.4 && <= 0.5,+ mtl >= 2.2 && < 2.4,+ text >= 1.1.1.0 && < 2.2, deepseq -- we increase heap size to avoid benchmarking garbage collection: ghc-options: -rtsopts -with-rtsopts=-A8m -threaded
@@ -3,7 +3,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Text.Pandoc- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -47,6 +47,8 @@ , module Text.Pandoc.Logging -- * Typeclass , module Text.Pandoc.Class+ -- * Internal data files+ , module Text.Pandoc.Data -- * Error handling , module Text.Pandoc.Error -- * Readers: converting /to/ Pandoc format@@ -55,17 +57,23 @@ , module Text.Pandoc.Writers -- * Rendering templates and default templates , module Text.Pandoc.Templates- -- * Miscellaneous+ -- * Localization+ , setTranslations+ , translateTerm+ -- * Version information , pandocVersion+ , pandocVersionText ) where import Text.Pandoc.Class import Text.Pandoc.Definition+import Text.Pandoc.Data import Text.Pandoc.Error import Text.Pandoc.Generic import Text.Pandoc.Logging import Text.Pandoc.Options import Text.Pandoc.Readers-import Text.Pandoc.Shared (pandocVersion)+import Text.Pandoc.Version (pandocVersion, pandocVersionText) import Text.Pandoc.Templates+import Text.Pandoc.Translations (setTranslations, translateTerm) import Text.Pandoc.Writers
@@ -1,11 +1,10 @@-{-# LANGUAGE TupleSections #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE CPP #-} {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Text.Pandoc.App- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu>@@ -16,22 +15,24 @@ -} module Text.Pandoc.App ( convertWithOpts+ , handleOptInfo , Opt(..)+ , OptInfo(..) , LineEnding(..)+ , IpynbOutput (..) , Filter(..) , defaultOpts , parseOptions , parseOptionsFromArgs , options , applyFilters+ , versionInfo ) where import qualified Control.Exception as E-import Control.Monad ( (>=>), when, forM_ )+import Control.Monad ( (>=>), when, forM, forM_ ) import Control.Monad.Trans ( MonadIO(..) ) import Control.Monad.Catch ( MonadMask )-import Control.Monad.Except (throwError, catchError)-import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as B8+import Control.Monad.Except (throwError) import qualified Data.ByteString.Lazy as BL import Data.Maybe (fromMaybe, isJust, isNothing) import qualified Data.Set as Set@@ -39,45 +40,48 @@ import qualified Data.Text as T import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Encoding as TE-import qualified Data.Text.Encoding as TSE import qualified Data.Text.Encoding.Error as TE-import qualified Data.Text.Encoding.Error as TSE-import Network.URI (URI (..), parseURI)-import System.Directory (doesDirectoryExist)+import Data.Char (toLower)+import System.Directory (doesDirectoryExist, createDirectory,+ createDirectoryIfMissing)+import Codec.Archive.Zip (toArchiveOrFail,+ extractFilesFromArchive, ZipOption(..)) import System.Exit (exitSuccess)-import System.FilePath ( takeBaseName, takeExtension)+import System.FilePath ( takeBaseName, takeExtension, takeDirectory) import System.IO (nativeNewline, stdout) import qualified System.IO as IO (Newline (..))+import Data.Version (showVersion) import Text.Pandoc import Text.Pandoc.Builder (setMeta) import Text.Pandoc.MediaBag (mediaItems)-import Text.Pandoc.MIME (getCharset, MimeType) import Text.Pandoc.Image (svgToPng)-import Text.Pandoc.App.FormatHeuristics (formatFromFilePaths) import Text.Pandoc.App.Opt (Opt (..), LineEnding (..), defaultOpts,- IpynbOutput (..))+ IpynbOutput (..), OptInfo(..)) import Text.Pandoc.App.CommandLineOptions (parseOptions, parseOptionsFromArgs,- options)-import Text.Pandoc.App.OutputSettings (OutputSettings (..), optToOutputSettings)+ options, handleOptInfo, versionInfo)+import Text.Pandoc.App.Input (InputParameters (..), readInput)+import Text.Pandoc.App.OutputSettings (OutputSettings (..), optToOutputSettings,+ sandbox')+import Text.Pandoc.Transforms (applyTransforms, filterIpynbOutput,+ headerShift, eastAsianLineBreakFilter) import Text.Collate.Lang (Lang (..), parseLang) import Text.Pandoc.Filter (Filter (JSONFilter, LuaFilter), Environment (..), applyFilters)+import qualified Text.Pandoc.Format as Format import Text.Pandoc.PDF (makePDF)+import Text.Pandoc.Scripting (ScriptingEngine (..), CustomComponents(..)) import Text.Pandoc.SelfContained (makeSelfContained)-import Text.Pandoc.Shared (eastAsianLineBreakFilter, stripEmptyParagraphs,- headerShift, isURI, tabFilter, uriPathToPath, filterIpynbOutput,- defaultUserDataDir, tshow)+import Text.Pandoc.Shared (tshow) import Text.Pandoc.Writers.Shared (lookupMetaString) import Text.Pandoc.Readers.Markdown (yamlToMeta)-import Text.Pandoc.Readers.Custom (readCustom) import qualified Text.Pandoc.UTF8 as UTF8 #ifndef _WINDOWS import System.Posix.IO (stdOutput) import System.Posix.Terminal (queryTerminal) #endif -convertWithOpts :: Opt -> IO ()-convertWithOpts opts = do+convertWithOpts :: ScriptingEngine -> Opt -> IO ()+convertWithOpts scriptingEngine opts = do let outputFile = fromMaybe "-" (optOutputFile opts) datadir <- case optDataDir opts of Nothing -> do@@ -86,7 +90,7 @@ return $ if exists then Just d else Nothing- Just _ -> return $ optDataDir opts+ mdatadir -> return mdatadir when (optDumpArgs opts) $ do UTF8.hPutStrLn stdout (T.pack outputFile)@@ -100,7 +104,7 @@ istty <- liftIO $ queryTerminal stdOutput #endif - res <- runIO $ convertWithOpts' istty datadir opts+ res <- runIO $ convertWithOpts' scriptingEngine istty datadir opts case res of Left e -> E.throwIO e Right (output, reports) -> do@@ -114,85 +118,90 @@ 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)+ , outputFile /= "-" -> do+ -- create directory and unzip+ createDirectory outputFile -- will fail if directory exists+ let zipopts = [OptRecursive, OptDestination outputFile] +++ [OptVerbose | optVerbosity opts == INFO]+ case toArchiveOrFail bs of+ Right archive -> extractFilesFromArchive zipopts archive+ Left e -> E.throwIO $ PandocShouldNeverHappenError $ T.pack e+ | otherwise -> writeFnBinary outputFile bs convertWithOpts' :: (PandocMonad m, MonadIO m, MonadMask m)- => Bool+ => ScriptingEngine+ -> Bool -> Maybe FilePath -> Opt -> m (PandocOutput, [LogMessage])-convertWithOpts' istty datadir opts = do+convertWithOpts' scriptingEngine istty datadir opts = do+ configureCommonState datadir opts let outputFile = fromMaybe "-" (optOutputFile opts) let filters = optFilters opts- let verbosity = optVerbosity opts- let sources = case optInputFiles opts of Just xs | not (optIgnoreArgs opts) -> xs _ -> ["-"]- setTrace (optTrace opts)- setVerbosity verbosity- setUserDataDir datadir- setResourcePath (optResourcePath opts) - setInputFiles (fromMaybe ["-"] (optInputFiles opts))- setOutputFile (optOutputFile opts)-+ let defFlavor fmt = Format.FlavoredFormat fmt mempty -- assign reader and writer based on options and filenames- readerName <- case optFrom opts of- Just f -> return f- Nothing -> case formatFromFilePaths sources of- Just f' -> return f'- Nothing | sources == ["-"] -> return "markdown"- | any (isURI . T.pack) sources -> return "html"- | otherwise -> do- report $ CouldNotDeduceFormat- (map (T.pack . takeExtension) sources) "markdown"- return "markdown"-- let readerNameBase = T.takeWhile (\c -> c /= '+' && c /= '-') readerName+ flvrd@(Format.FlavoredFormat readerNameBase _extsDiff) <-+ case optFrom opts of+ Just f -> Format.parseFlavoredFormat f+ Nothing -> case Format.formatFromFilePaths sources of+ Just f' -> return f'+ Nothing | sources == ["-"] -> return $ defFlavor "markdown"+ | otherwise -> do+ report $ CouldNotDeduceFormat+ (map (T.pack . takeExtension) sources) "markdown"+ return $ defFlavor "markdown" let makeSandboxed pureReader =- let files = maybe id (:) (optReferenceDoc opts) .- maybe id (:) (optEpubMetadata opts) .- maybe id (:) (optEpubCoverImage opts) .- maybe id (:) (optCSL opts) .- maybe id (:) (optCitationAbbreviations opts) $- optEpubFonts opts ++- optBibliography opts- in case pureReader of- TextReader r -> TextReader $ \o t -> sandbox files (r o t)- ByteStringReader r- -> ByteStringReader $ \o t -> sandbox files (r o t)+ case pureReader of+ TextReader r+ -> TextReader $ \o t -> sandbox' opts (r o t)+ ByteStringReader r+ -> ByteStringReader $ \o t -> sandbox' opts (r o t) (reader, readerExts) <-- if ".lua" `T.isSuffixOf` readerName- then return (TextReader (readCustom (T.unpack readerName)), mempty)+ if ".lua" `T.isSuffixOf` readerNameBase+ then do+ let scriptPath = T.unpack readerNameBase+ components <- engineLoadCustom scriptingEngine scriptPath+ r <- case customReader components of+ Nothing -> throwError $ PandocAppError $+ readerNameBase <> " does not contain a custom reader"+ Just r -> return r+ let extsConf = fromMaybe mempty (customExtensions components)+ rexts <- Format.applyExtensionsDiff extsConf flvrd+ return (r, rexts) else if optSandbox opts- then case runPure (getReader readerName) of+ then case runPure (getReader flvrd) of Left e -> throwError e Right (r, rexts) -> return (makeSandboxed r, rexts)- else getReader readerName+ else getReader flvrd - outputSettings <- optToOutputSettings opts+ outputSettings <- optToOutputSettings scriptingEngine opts let format = outputFormat outputSettings let writer = outputWriter outputSettings- let writerName = outputWriterName outputSettings- let writerNameBase = T.takeWhile (\c -> c /= '+' && c /= '-') writerName let writerOptions = outputWriterOptions outputSettings - let pdfOutput = isJust $ outputPdfProgram outputSettings-- let bibOutput = writerNameBase == "bibtex" ||- writerNameBase == "biblatex" ||- writerNameBase == "csljson"-- let standalone = optStandalone opts ||- not (isTextFormat format) ||- pdfOutput ||- bibOutput+ -- whether we are targeting PDF.+ let pdfOutput = map toLower (takeExtension outputFile) == ".pdf" ||+ optTo opts == Just "pdf"+ -- whether standalone output should be produced.+ let bibOutput = format `elem` ["bibtex", "biblatex", "csljson"]+ let standalone = isJust (writerTemplate writerOptions) || bibOutput + --+ -- Sanity checks+ -- when (pdfOutput && readerNameBase == "latex") $ case optInputFiles opts of Just (inputFile:_) -> report $ UnusualConversion $ T.pack $@@ -214,51 +223,30 @@ "Specify an output file using the -o option, or " <> "use '-o -' to force output to stdout." -- abbrevs <- Set.fromList . filter (not . T.null) . T.lines . UTF8.toText <$>- case optAbbreviations opts of- Nothing -> readDataFile "abbreviations"- Just f -> readFileStrict f-- case lookupMetaString "lang" (optMetadata opts) of- "" -> setTranslations $ Lang "en" Nothing (Just "US") [] [] []- l -> case parseLang l of- Left _ -> report $ InvalidLang l- Right l' -> setTranslations l'+ when (readerNameBase == "markdown_github" ||+ format == "markdown_github") $+ report $ Deprecated "markdown_github" "Use gfm instead." + abbrevs <- readAbbreviations (optAbbreviations opts) let readerOpts = def{ readerStandalone = standalone , readerColumns = optColumns opts , readerTabStop = optTabStop opts , readerIndentedCodeClasses = optIndentedCodeClasses opts- , readerDefaultImageExtension =- optDefaultImageExtension opts+ , readerDefaultImageExtension = optDefaultImageExtension opts , readerTrackChanges = optTrackChanges opts , readerAbbreviations = abbrevs , readerExtensions = readerExts , readerStripComments = optStripComments opts+ , readerTypstInputs = optTypstInputs opts } - metadataFromFile <-- case optMetadataFiles opts of- [] -> return mempty- paths -> do- -- If format is markdown or commonmark, use the enabled extensions,- -- otherwise treat metadata as pandoc markdown (see #7926, #6832)- let readerOptsMeta =- if readerNameBase == "markdown" || readerNameBase == "commonmark"- then readerOpts- else readerOpts{ readerExtensions = pandocExtensions }- mconcat <$> mapM- (\path -> do raw <- readMetadataFile path- yamlToMeta readerOptsMeta (Just path) raw) paths+ metadataFromFile <- getMetadataFromFiles readerNameBase readerOpts+ (optMetadataFiles opts) let transforms = (case optShiftHeadingLevelBy opts of 0 -> id x -> (headerShift x :)) .- (if optStripEmptyParagraphs opts- then (stripEmptyParagraphs :)- else id) . (if extensionEnabled Ext_east_asian_line_breaks readerExts && not (extensionEnabled Ext_east_asian_line_breaks@@ -280,22 +268,6 @@ _ -> Format format) :)) $ [] - let convertTabs = tabFilter (if optPreserveTabs opts ||- readerNameBase == "t2t" ||- readerNameBase == "man" ||- readerNameBase == "tsv"- then 0- else optTabStop opts)--- when (readerNameBase == "markdown_github" ||- writerNameBase == "markdown_github") $- report $ Deprecated "markdown_github" "Use gfm instead."-- mapM_ (uncurry setRequestHeader) (optRequestHeaders opts)-- setNoCheckCertificate (optNoCheckCertificate opts)- let isPandocCiteproc (JSONFilter f) = takeBaseName f == "pandoc-citeproc" isPandocCiteproc _ = False @@ -313,54 +285,40 @@ let filterEnv = Environment readerOpts writerOptions - inputs <- readSources sources+ let inputParams = InputParameters+ { inputReader = reader+ , inputReaderName = readerNameBase+ , inputReaderOptions = readerOpts+ , inputSources = sources+ , inputFileScope = optFileScope opts+ , inputSpacesPerTab = if optPreserveTabs opts+ then Nothing+ else Just (optTabStop opts)+ } - doc <- (case reader of- TextReader r- | readerNameBase == "json" ->- mconcat <$>- mapM (inputToText convertTabs- >=> r readerOpts . (:[])) inputs- | optFileScope opts ->- mconcat <$> mapM- (inputToText convertTabs- >=> r readerOpts . (:[]))- inputs- | otherwise -> mapM (inputToText convertTabs) inputs- >>= r readerOpts- ByteStringReader r ->- mconcat <$> mapM (r readerOpts . inputToLazyByteString) inputs)+ doc <- readInput inputParams >>= ( return . adjustMetadata (metadataFromFile <>) >=> return . adjustMetadata (<> optMetadata opts) >=> return . adjustMetadata (<> cslMetadata)+ >=> applyFilters scriptingEngine filterEnv filters [T.unpack format] >=> applyTransforms transforms- >=> applyFilters filterEnv filters [T.unpack format] >=> (if not (optSandbox opts) && (isJust (optExtractMedia opts)- || writerNameBase == "docx") -- for fallback pngs+ || format == "docx") -- for fallback pngs then fillMediaBag else return) >=> maybe return extractMedia (optExtractMedia opts) ) - when (writerNameBase == "docx" && not (optSandbox opts)) $ do- -- create fallback pngs for svgs- items <- mediaItems <$> getMediaBag- forM_ items $ \(fp, mt, bs) ->- case T.takeWhile (/=';') mt of- "image/svg+xml" -> do- res <- svgToPng (writerDpi writerOptions) bs- case res of- Right bs' -> do- let fp' = fp <> ".png"- insertMedia fp' (Just "image/png") bs'- Left e -> report $ CouldNotConvertImage (T.pack fp) (tshow e)- _ -> return ()+ when (format == "docx" && not (optSandbox opts)) $ do+ createPngFallbacks (writerDpi writerOptions) output <- case writer of- ByteStringWriter f -> BinaryOutput <$> f writerOptions doc+ ByteStringWriter f+ | format == "chunkedhtml" -> ZipOutput <$> f writerOptions doc+ | otherwise -> BinaryOutput <$> f writerOptions doc TextWriter f -> case outputPdfProgram outputSettings of- Just pdfProg -> do+ Just pdfProg | pdfOutput -> do res <- makePDF pdfProg (optPdfEngineOpts opts) f writerOptions doc case res of@@ -368,23 +326,88 @@ Left err' -> throwError $ PandocPDFError $ TL.toStrict (TE.decodeUtf8With TE.lenientDecode err') - Nothing -> do+ _ -> do let ensureNl t | standalone = t | T.null t || T.last t /= '\n' = t <> T.singleton '\n' | otherwise = t textOutput <- ensureNl <$> f writerOptions doc- if (optSelfContained opts || optEmbedResources opts) && htmlFormat format- then TextOutput <$> makeSelfContained textOutput+ if htmlFormat format &&+ (optSelfContained opts || optEmbedResources opts)+ then if optSandbox opts+ then sandbox' opts $+ TextOutput <$> makeSelfContained textOutput+ else TextOutput <$> makeSelfContained textOutput else return $ TextOutput textOutput reports <- getLog return (output, reports) -data PandocOutput = TextOutput Text | BinaryOutput BL.ByteString+data PandocOutput =+ TextOutput Text+ | BinaryOutput BL.ByteString+ | ZipOutput BL.ByteString deriving (Show) -type Transform = Pandoc -> Pandoc+-- | Configure the common state+configureCommonState :: PandocMonad m => Maybe FilePath -> Opt -> m ()+configureCommonState datadir opts = do+ setUserDataDir datadir+ setTrace (optTrace opts)+ setVerbosity (optVerbosity opts)+ setResourcePath (optResourcePath opts)+ setInputFiles (fromMaybe ["-"] (optInputFiles opts))+ setOutputFile (optOutputFile opts)+ setNoCheckCertificate (optNoCheckCertificate opts) + setRequestHeader "User-Agent" ("pandoc/" <> T.pack (showVersion pandocVersion))+ mapM_ (uncurry setRequestHeader) (optRequestHeaders opts)++ case lookupMetaString "lang" (optMetadata opts) of+ "" -> setTranslations $ Lang "en" Nothing (Just "US") [] [] []+ l -> case parseLang l of+ Left _ -> report $ InvalidLang l+ Right l' -> setTranslations l'++-- | Retrieves the set of abbreviations to be used by pandoc. These currently+-- only affect the Markdown reader.+readAbbreviations :: PandocMonad m => Maybe FilePath -> m (Set.Set Text)+readAbbreviations mbfilepath =+ (case mbfilepath of+ Nothing -> readDataFile "abbreviations"+ Just f -> readFileStrict f)+ >>= fmap (Set.fromList . filter (not . T.null) . T.lines) .+ toTextM (fromMaybe mempty mbfilepath)++createPngFallbacks :: (PandocMonad m, MonadIO m) => Int -> m ()+createPngFallbacks dpi = do+ -- create fallback pngs for svgs+ items <- mediaItems <$> getMediaBag+ forM_ items $ \(fp, mt, bs) ->+ case T.takeWhile (/=';') mt of+ "image/svg+xml" -> do+ res <- svgToPng dpi bs+ case res of+ Right bs' -> do+ let fp' = fp <> ".png"+ insertMedia fp' (Just "image/png") bs'+ Left e -> report $ CouldNotConvertImage (T.pack fp) (tshow e)+ _ -> return ()++getMetadataFromFiles :: PandocMonad m+ => Text -> ReaderOptions -> [FilePath] -> m Meta+getMetadataFromFiles readerFormat readerOpts = \case+ [] -> return mempty+ paths -> mconcat <$> do+ -- If format is markdown or commonmark, use the enabled extensions,+ -- otherwise treat metadata as pandoc markdown (see #7926, #6832)+ let readerOptsMeta =+ if readerFormat `elem` ["markdown", "commonmark"]+ then readerOpts+ else readerOpts{ readerExtensions = pandocExtensions }+ forM paths $ \path -> do+ raw <- readMetadataFile path+ yamlToMeta readerOptsMeta (Just path) raw+ htmlFormat :: Text -> Bool htmlFormat = (`elem` ["html","html4","html5","s5","slidy", "slideous","dzslides","revealjs"])@@ -394,69 +417,6 @@ adjustMetadata :: (Meta -> Meta) -> Pandoc -> Pandoc adjustMetadata f (Pandoc meta bs) = Pandoc (f meta) bs---- Transformations of a Pandoc document post-parsing:--applyTransforms :: Monad m => [Transform] -> Pandoc -> m Pandoc-applyTransforms transforms d = return $ foldr ($) d transforms--readSources :: PandocMonad m- => [FilePath] -> m [(FilePath, (BS.ByteString, Maybe MimeType))]-readSources srcs =- mapM (\fp -> do t <- readSource fp- return (if fp == "-" then "" else fp, t)) srcs--readSource :: PandocMonad m- => FilePath -> m (BS.ByteString, Maybe MimeType)-readSource "-" = (,Nothing) <$> readStdinStrict-readSource src =- case parseURI src of- Just u | uriScheme u `elem` ["http:","https:"] -> openURL (T.pack src)- | uriScheme u == "file:" ->- (,Nothing) <$>- readFileStrict (uriPathToPath $ T.pack $ uriPath u)- _ -> (,Nothing) <$> readFileStrict src--utf8ToText :: PandocMonad m => FilePath -> BS.ByteString -> m Text-utf8ToText fp bs =- case TSE.decodeUtf8' . dropBOM $ bs of- Left (TSE.DecodeError _ (Just w)) ->- case BS.elemIndex w bs of- Just offset -> throwError $ PandocUTF8DecodingError (T.pack fp) offset w- Nothing -> throwError $ PandocUTF8DecodingError (T.pack fp) 0 w- Left e -> throwError $ PandocAppError (tshow e)- Right t -> return t- where- dropBOM bs' =- if "\xEF\xBB\xBF" `BS.isPrefixOf` bs'- then BS.drop 3 bs'- else bs'---inputToText :: PandocMonad m- => (Text -> Text)- -> (FilePath, (BS.ByteString, Maybe MimeType))- -> m (FilePath, Text)-inputToText convTabs (fp, (bs,mt)) =- (fp,) . convTabs . T.filter (/='\r') <$>- case mt >>= getCharset of- Just "UTF-8" -> utf8ToText fp bs- Just "ISO-8859-1" -> return $ T.pack $ B8.unpack bs- Just charset -> throwError $ PandocUnsupportedCharsetError charset- Nothing -> catchError- (utf8ToText fp bs)- (\case- PandocUTF8DecodingError{} -> do- report $ NotUTF8Encoded- (if null fp- then "input"- else fp)- return $ T.pack $ B8.unpack bs- e -> throwError e)--inputToLazyByteString :: (FilePath, (BS.ByteString, Maybe MimeType))- -> BL.ByteString-inputToLazyByteString (_, (bs,_)) = BL.fromStrict bs writeFnBinary :: FilePath -> BL.ByteString -> IO () writeFnBinary "-" = BL.putStr
@@ -1,14 +1,11 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE LambdaCase #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeApplications #-} {- | Module : Text.Pandoc.App.CommandLineOptions- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu>@@ -20,24 +17,27 @@ module Text.Pandoc.App.CommandLineOptions ( parseOptions , parseOptionsFromArgs+ , handleOptInfo , options , engines , setVariable+ , versionInfo ) where-import Control.Monad import Control.Monad.Trans import Control.Monad.State.Strict+import Data.Containers.ListUtils (nubOrd)+import Data.Aeson (eitherDecode) import Data.Aeson.Encode.Pretty (encodePretty', Config(..), keyOrder, defConfig, Indent(..), NumberFormat(..)) import Data.Bifunctor (second) import Data.Char (toLower)-import Data.List (intercalate, sort, foldl')+import Data.List (intercalate, sort)+import qualified Data.List as L #ifdef _WINDOWS import Data.List (isPrefixOf) #endif import Data.Maybe (fromMaybe, isJust) import Data.Text (Text)-import HsLua (Exception, getglobal, openlibs, peek, run, top) import Safe (tailDef) import Skylighting (Syntax (..), defaultSyntaxMap) import System.Console.GetOpt@@ -48,70 +48,48 @@ 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)+ fullDefaultsPath, OptInfo(..)) import Text.Pandoc.Filter (Filter (..)) import Text.Pandoc.Highlighting (highlightingStyles, lookupHighlightingStyle)-import Text.Pandoc.Shared (ordNub, elemText, safeStrRead, defaultUserDataDir)+import Text.Pandoc.Scripting (ScriptingEngine (..), customTemplate)+import Text.Pandoc.Shared (safeStrRead) import Text.Printf--#ifdef EMBED_DATA_FILES-import Text.Pandoc.Data (dataFiles)-#else-import Paths_pandoc (getDataDir)-import System.Directory (getDirectoryContents)-#endif- import qualified Control.Exception as E+import Control.Monad.Except (ExceptT(..), runExceptT, throwError) import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as B import qualified Data.Map as M+import qualified Data.Set as Set import qualified Data.Text as T import qualified Text.Pandoc.UTF8 as UTF8 -#ifdef NIGHTLY-import qualified Language.Haskell.TH as TH-import Data.Time-#endif--#ifdef NIGHTLY-versionSuffix :: String-versionSuffix = "-nightly-" ++- $(TH.stringE =<<- TH.runIO (formatTime defaultTimeLocale "%F" <$> Data.Time.getCurrentTime))-#else-versionSuffix :: String-versionSuffix = ""-#endif--parseOptions :: [OptDescr (Opt -> IO Opt)] -> Opt -> IO Opt+parseOptions :: [OptDescr (Opt -> ExceptT OptInfo IO Opt)]+ -> Opt -> IO (Either OptInfo Opt) parseOptions options' defaults = do- rawArgs <- map UTF8.decodeArg <$> getArgs- prg <- getProgName+ rawArgs <- liftIO getArgs+ prg <- liftIO getProgName parseOptionsFromArgs options' defaults prg rawArgs parseOptionsFromArgs- :: [OptDescr (Opt -> IO Opt)] -> Opt -> String -> [String] -> IO Opt+ :: [OptDescr (Opt -> ExceptT OptInfo IO Opt)]+ -> Opt -> String -> [String] -> IO (Either OptInfo Opt) parseOptionsFromArgs options' defaults prg rawArgs = do let (actions, args, unrecognizedOpts, errors) =- getOpt' Permute options' (map UTF8.decodeArg rawArgs)+ getOpt' Permute options' (preprocessArgs rawArgs) let unknownOptionErrors = foldr (handleUnrecognizedOption . takeWhile (/= '=')) [] unrecognizedOpts - unless (null errors && null unknownOptionErrors) $- E.throwIO $ PandocOptionError $ T.pack $- concat errors ++ unlines unknownOptionErrors ++- ("Try " ++ prg ++ " --help for more information.")-- -- thread option data structure through all supplied option actions- opts <- foldl' (>>=) (return defaults) actions let mbArgs = case args of [] -> Nothing xs -> Just xs- return $ opts{ optInputFiles =++ let adjustOpts opts =+ opts{ optInputFiles = map normalizePath <$> (optInputFiles opts <> mbArgs) , optStandalone = -- certain other options imply standalone optStandalone opts ||@@ -121,36 +99,182 @@ not (null (optIncludeBeforeBody opts)) || not (null (optIncludeAfterBody opts)) } + if (null errors && null unknownOptionErrors)+ then -- thread option data structure through all supplied option actions+ runExceptT $ adjustOpts <$> (L.foldl' (>>=) (return defaults) actions)+ else return $ Left $ OptError $ PandocOptionError $ T.pack $+ concat errors ++ unlines unknownOptionErrors +++ ("Try " ++ prg ++ " --help for more information.")++-- | React to an 'OptInfo' by printing the requested information+-- and exiting or (if there was a parsing error) raising an error.+handleOptInfo :: ScriptingEngine -> OptInfo -> IO ()+handleOptInfo engine info = E.handle (handleError . Left) $ do+ case info of+ BashCompletion -> do+ datafiles <- getDataFileNames+ tpl <- runIOorExplode $+ UTF8.toString <$>+ readDefaultDataFile "bash_completion.tpl"+ let optnames (Option shorts longs _ _) =+ map (\c -> ['-',c]) shorts +++ map ("--" ++) longs+ let allopts = unwords (concatMap optnames options)+ UTF8.hPutStrLn stdout $ T.pack $ printf tpl allopts+ (T.unpack $ T.unwords readersNames)+ (T.unpack $ T.unwords writersNames)+ (T.unpack $ T.unwords $ map fst highlightingStyles)+ (unwords datafiles)+ ListInputFormats -> mapM_ (UTF8.hPutStrLn stdout) readersNames+ ListOutputFormats -> mapM_ (UTF8.hPutStrLn stdout) writersNames+ ListExtensions mbfmt -> do+ let formatName = fromMaybe "markdown" mbfmt+ let allExts = getAllExtensions formatName+ if formatName `notElem`+ (map fst (readers :: [(Text, Reader PandocPure)]) +++ map fst (writers :: [(Text, Writer PandocPure)]))+ then E.throwIO $ PandocOptionError $ formatName <>+ " is not a recognized reader or writer format"+ else do+ let defExts = getDefaultExtensions formatName+ let showExt x =+ (if extensionEnabled x defExts+ then '+'+ else if extensionEnabled x allExts+ then '-'+ else ' ') : drop 4 (show x)+ mapM_ (UTF8.hPutStrLn stdout . T.pack . showExt)+ (extensionsToList allExts)+ ListHighlightLanguages -> do+ let langs = [ T.unpack (T.toLower (sShortname s))+ | s <- M.elems defaultSyntaxMap+ , sShortname s `notElem`+ [T.pack "Alert", T.pack "Alert_indent"]+ ]+ mapM_ (UTF8.hPutStrLn stdout . T.pack) (sort langs)+ ListHighlightStyles -> do+ mapM_ (UTF8.hPutStrLn stdout . fst) highlightingStyles+ PrintDefaultTemplate mbout fmt -> do+ let write = maybe (UTF8.hPutStr stdout) (UTF8.writeFile) mbout++ templ <- runIO $+ case splitExtension (T.unpack fmt) of+ (_, "") -> do+ -- built-in format+ setUserDataDir Nothing+ getDefaultTemplate fmt+ _ -> do+ -- format looks like a filepath => custom writer+ components <- engineLoadCustom engine (T.unpack fmt)+ case customTemplate components of+ Just t -> pure t+ Nothing -> E.throw $ PandocNoTemplateError fmt+ case templ of+ Right t+ | T.null t -> -- e.g. for docx, odt, json:+ E.throwIO $ PandocCouldNotFindDataFileError $ T.pack+ ("templates/default." ++ T.unpack fmt)+ | otherwise -> write t+ Left e -> E.throwIO e+ PrintDefaultDataFile mbout f -> do+ let write = maybe BS.putStr BS.writeFile mbout+ runIOorExplode $ readDefaultDataFile (T.unpack f) >>= liftIO . write+ PrintHighlightStyle mbout styleName -> do+ let write = maybe B.putStr B.writeFile mbout+ sty <- runIOorExplode $ lookupHighlightingStyle (T.unpack styleName)+ write $ encodePretty'+ defConfig{confIndent = Spaces 4+ ,confCompare = keyOrder+ (map T.pack+ ["text-color"+ ,"background-color"+ ,"line-number-color"+ ,"line-number-background-color"+ ,"bold"+ ,"italic"+ ,"underline"+ ,"text-styles"])+ ,confNumFormat = Generic+ ,confTrailingNewline = True} sty+ VersionInfo -> versionInfo [] Nothing ""+ Help -> do+ prg <- getProgName+ mapM_ (UTF8.hPutStrLn stdout . T.stripEnd . T.pack) $+ lines $ usageMessage prg options+ OptError e -> E.throwIO e+ exitSuccess+ -- | Supported LaTeX engines; the first item is used as default engine -- when going through LaTeX. latexEngines :: [String]-latexEngines = ["pdflatex", "lualatex", "xelatex", "latexmk", "tectonic"]+latexEngines = [ "pdflatex", "lualatex", "xelatex", "latexmk", "tectonic"+ , "pdflatex-dev", "lualatex-dev" ] -- | Supported HTML PDF engines; the first item is used as default -- engine when going through HTML. htmlEngines :: [String]-htmlEngines = ["wkhtmltopdf", "weasyprint", "pagedjs-cli", "prince"]+htmlEngines = ["weasyprint", "wkhtmltopdf", "pagedjs-cli", "prince"] engines :: [(Text, String)] engines = map ("html",) htmlEngines ++ map ("html5",) htmlEngines ++ map ("latex",) latexEngines ++ map ("beamer",) latexEngines ++- [ ("ms", "pdfroff")+ [ ("ms", "groff")+ , ("ms", "pdfroff")+ , ("typst", "typst") , ("context", "context") ] pdfEngines :: [String]-pdfEngines = ordNub $ map snd engines+pdfEngines = nubOrd $ map snd engines +-- For motivation see #8956. We want to allow things like `-si` without+-- causing the `i` to be parsed as an optional boolean argument of `-s`.+-- This is for backwards compatibility given the addition of optional+-- boolean arguments in #8879.+preprocessArgs :: [String] -> [String]+preprocessArgs [] = []+preprocessArgs ("--":xs) = "--" : xs -- a bare '--' ends option parsing+-- note that -strue is interpreted as -strue while+-- -stmarkdown is interpreted as -s -tmarkdown+preprocessArgs (('-':c:d:cs):xs)+ | isShortBooleanOpt c+ , case toLower <$> (d:cs) of+ "true" -> True+ "false" -> True+ _ -> False+ = ('-':c:d:cs) : preprocessArgs xs+ | isShortBooleanOpt c+ , isShortOpt d = splitArg (c:d:cs) ++ preprocessArgs xs+preprocessArgs (x:xs) = x : preprocessArgs xs++isShortBooleanOpt :: Char -> Bool+isShortBooleanOpt = (`Set.member` shortBooleanOpts)+ where+ shortBooleanOpts =+ Set.fromList [c | Option [c] _ (OptArg _ "true|false") _ <- options]++isShortOpt :: Char -> Bool+isShortOpt = (`Set.member` shortOpts)+ where+ shortOpts = Set.fromList $ concat [cs | Option cs _ _ _ <- options]++splitArg :: String -> [String]+splitArg (c:d:cs)+ | isShortBooleanOpt c+ , isShortOpt d+ = ['-',c] : splitArg (d:cs)+splitArg (c:cs) = ['-':c:cs]+splitArg [] = []+ -- | A list of functions, each transforming the options data structure -- in response to a command-line option.-options :: [OptDescr (Opt -> IO Opt)]+options :: [OptDescr (Opt -> ExceptT OptInfo IO Opt)] options = [ Option "fr" ["from","read"] (ReqArg- (\arg opt -> return opt { optFrom =- Just (T.toLower $ T.pack arg) })+ (\arg opt -> return opt { optFrom = Just $ T.pack arg }) "FORMAT") "" @@ -180,7 +304,7 @@ let (key, val) = splitField arg return opt{ optMetadata = addMeta key val $ optMetadata opt })- "KEY[:VALUE]")+ "KEY[=VALUE]") "" , Option "" ["metadata-file"]@@ -192,28 +316,42 @@ , Option "d" ["defaults"] (ReqArg- (\arg opt -> runIOorExplode $ do- let defsState = DefaultsState { curDefaults = Nothing,- inheritanceGraph = [] }- fp <- fullDefaultsPath (optDataDir opt) arg- evalStateT (applyDefaults opt fp) defsState+ (\arg opt -> do+ res <- liftIO $ runIO $ do+ let defsState =+ DefaultsState { curDefaults = Nothing,+ inheritanceGraph = [] }+ fp <- fullDefaultsPath (optDataDir opt) arg+ evalStateT (applyDefaults opt fp) defsState+ case res of+ Left e -> optError e+ Right x -> return x ) "FILE") "" , Option "" ["file-scope"]- (NoArg- (\opt -> return opt { optFileScope = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--file-scope" arg+ return opt { optFileScope = boolValue })+ "true|false") "" -- "Parse input files before combining" , Option "" ["sandbox"]- (NoArg- (\opt -> return opt { optSandbox = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--sandbox" arg+ return opt { optSandbox = boolValue })+ "true|false") "" - , Option "s" ["standalone"]- (NoArg- (\opt -> return opt { optStandalone = True }))+ , Option "s" ["standalone"]+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--standalone/-s" arg+ return opt { optStandalone = boolValue })+ "true|false") "" -- "Include needed header and footer on output" , Option "" ["template"]@@ -230,9 +368,26 @@ return opt{ optVariables = setVariable (T.pack key) (T.pack val) $ optVariables opt })- "KEY[:VALUE]")+ "KEY[=VALUE]") "" + , Option "" ["variable-json"]+ (ReqArg+ (\arg opt -> do+ let (key, json) = splitField arg+ case eitherDecode (B.fromStrict . UTF8.fromString $ json) of+ Right (val :: Val Text) ->+ return opt{ optVariables =+ let Context m = optVariables opt+ in Context $ M.insert (T.pack key) val m }+ -- note that this replaces any existing value, which+ -- is different from what --variable does+ Left err' -> optError $ PandocOptionError $+ "Could not parse '" <> T.pack json <> "' as JSON:\n" <>+ T.pack err')+ "KEY[:JSON]")+ ""+ , Option "" ["wrap"] (ReqArg (\arg opt ->@@ -240,19 +395,25 @@ "auto" -> return opt{ optWrap = WrapAuto } "none" -> return opt{ optWrap = WrapNone } "preserve" -> return opt{ optWrap = WrapPreserve }- _ -> E.throwIO $ PandocOptionError+ _ -> optError $ PandocOptionError "--wrap must be auto, none, or preserve") "auto|none|preserve") "" -- "Option for wrapping text in output" , Option "" ["ascii"]- (NoArg- (\opt -> return opt { optAscii = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--ascii" arg+ return opt { optAscii = boolValue })+ "true|false") "" -- "Prefer ASCII output" , Option "" ["toc", "table-of-contents"]- (NoArg- (\opt -> return opt { optTableOfContents = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--toc/--table-of-contents" arg+ return opt { optTableOfContents = boolValue })+ "true|false") "" -- "Include table of contents" , Option "" ["toc-depth"]@@ -261,14 +422,33 @@ case safeStrRead arg of Just t | t >= 1 && t <= 6 -> return opt { optTOCDepth = t }- _ -> E.throwIO $ PandocOptionError- "TOC level must be a number 1-6")+ _ -> optError $ PandocOptionError+ "Argument of --toc-depth must be a number 1-6") "NUMBER") "" -- "Number of levels to include in TOC" + , Option "" ["lof", "list-of-figures"]+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--lof/--list-of-figures" arg+ return opt { optListOfFigures = boolValue })+ "true|false")+ "" -- "Include list of figures"++ , Option "" ["lot", "list-of-tables"]+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--lot/--list-of-tables" arg+ return opt { optListOfTables = boolValue })+ "true|false")+ "" -- "Include list of tables"+ , Option "N" ["number-sections"]- (NoArg- (\opt -> return opt { optNumberSections = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--number-sections/-N" arg+ return opt { optNumberSections = boolValue })+ "true|false") "" -- "Number sections" , Option "" ["number-offset"]@@ -277,8 +457,8 @@ case safeStrRead ("[" <> arg <> "]") of Just ns -> return opt { optNumberOffset = ns, optNumberSections = True }- _ -> E.throwIO $ PandocOptionError- "could not parse number-offset")+ _ -> optError $ PandocOptionError+ "could not parse argument of --number-offset") "NUMBERS") "" -- "Starting number for sections, subsections, etc." @@ -294,8 +474,8 @@ TopLevelPart } "default" -> return opt{ optTopLevelDivision = TopLevelDefault }- _ -> E.throwIO $ PandocOptionError $- "Top-level division must be " <>+ _ -> optError $ PandocOptionError $+ "Argument of --top-level division must be " <> "section, chapter, part, or default" ) "section|chapter|part") "" -- "Use top-level division type in LaTeX, ConTeXt, DocBook"@@ -342,13 +522,18 @@ , Option "" ["no-highlight"] (NoArg- (\opt -> return opt { optHighlightStyle = Nothing }))+ (\opt -> do+ deprecatedOption "--no-highlight"+ "Use --syntax-highlighting=none instead."+ return opt { optSyntaxHighlighting = NoHighlightingString })) "" -- "Don't highlight source code" , Option "" ["highlight-style"] (ReqArg- (\arg opt ->- return opt{ optHighlightStyle = Just $+ (\arg opt -> do+ deprecatedOption "--highlight-style"+ "Use --syntax-highlighting instead."+ return opt{ optSyntaxHighlighting = T.pack $ normalizePath arg }) "STYLE|FILE") "" -- "Style for highlighted code"@@ -361,13 +546,21 @@ "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 -> case safeStrRead arg of Just t | t > 0 -> return opt { optDpi = t }- _ -> E.throwIO $ PandocOptionError- "dpi must be a number greater than 0")+ _ -> optError $ PandocOptionError+ "Argument of --dpi must be a number greater than 0") "NUMBER") "" -- "Dpi (default 96)" @@ -379,8 +572,8 @@ "lf" -> return opt { optEol = LF } "native" -> return opt { optEol = Native } -- mac-syntax (cr) is not supported in ghc-base.- _ -> E.throwIO $ PandocOptionError- "--eol must be crlf, lf, or native")+ _ -> optError $ PandocOptionError+ "Argument of --eol must be crlf, lf, or native") "crlf|lf|native") "" -- "EOL (default OS-dependent)" @@ -389,14 +582,17 @@ (\arg opt -> case safeStrRead arg of Just t | t > 0 -> return opt { optColumns = t }- _ -> E.throwIO $ PandocOptionError- "columns must be a number greater than 0")+ _ -> optError $ PandocOptionError+ "Argument of --columns must be a number greater than 0") "NUMBER") "" -- "Length of line in characters" , Option "p" ["preserve-tabs"]- (NoArg- (\opt -> return opt { optPreserveTabs = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--preserve-tabs/-p" arg+ return opt { optPreserveTabs = boolValue })+ "true|false") "" -- "Preserve tabs instead of converting to spaces" , Option "" ["tab-stop"]@@ -404,8 +600,8 @@ (\arg opt -> case safeStrRead arg of Just t | t > 0 -> return opt { optTabStop = t }- _ -> E.throwIO $ PandocOptionError- "tab-stop must be a number greater than 0")+ _ -> optError $ PandocOptionError+ "Argument of --tab-stop must be a number greater than 0") "NUMBER") "" -- "Tab stop (default 4)" @@ -415,8 +611,10 @@ let b = takeBaseName arg if b `elem` pdfEngines then return opt { optPdfEngine = Just arg }- else E.throwIO $ PandocOptionError $ T.pack $ "pdf-engine must be one of "- ++ intercalate ", " pdfEngines)+ else optError $+ PandocOptionError $ T.pack $+ "Argument of --pdf-engine must be one of\n"+ ++ concatMap (\e -> "\t" <> e <> "\n") pdfEngines) "PROGRAM") "" -- "Name of program to use in generating PDF" @@ -436,29 +634,45 @@ "" -- "Path of custom reference doc" , Option "" ["self-contained"]- (NoArg- (\opt -> do- deprecatedOption "--self-contained" "use --embed-resources --standalone"- return opt { optSelfContained = True }))+ (OptArg+ (\arg opt -> do+ deprecatedOption "--self-contained" "use --embed-resources --standalone"+ boolValue <- readBoolFromOptArg "--self-contained" arg+ return opt { optSelfContained = boolValue })+ "true|false") "" -- "Make slide shows include all the needed js and css (deprecated)" - , Option "" ["embed-resources"]- (NoArg- (\opt -> return opt { optEmbedResources = True }))+ , Option "" ["embed-resources"] -- maybe True (\argStr -> argStr == "true") arg+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--embed-resources" arg+ return opt { optEmbedResources = boolValue })+ "true|false") "" -- "Make slide shows include all the needed js and css" + , Option "" ["link-images"] -- maybe True (\argStr -> argStr == "true") arg+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--link-images" arg+ return opt { optLinkImages = boolValue })+ "true|false")+ "" -- "Link images in ODT rather than embedding them"+ , Option "" ["request-header"] (ReqArg (\arg opt -> do let (key, val) = splitField arg return opt{ optRequestHeaders = (T.pack key, T.pack val) : optRequestHeaders opt })- "NAME:VALUE")+ "NAME=VALUE") "" , Option "" ["no-check-certificate"]- (NoArg- (\opt -> return opt { optNoCheckCertificate = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--no-check-certificate" arg+ return opt { optNoCheckCertificate = boolValue })+ "true|false") "" -- "Disable certificate validation" , Option "" ["abbreviations"]@@ -468,6 +682,14 @@ "FILE") "" -- "Specify file for custom abbreviations" + , Option "" ["typst-input"]+ (ReqArg+ (\arg opt -> do+ let (key, val) = splitField arg+ return opt{ optTypstInputs = (T.pack key, T.pack val) : optTypstInputs opt })+ "KEY=VALUE")+ ""+ , Option "" ["indented-code-classes"] (ReqArg (\arg opt -> return opt { optIndentedCodeClasses = T.words $@@ -502,8 +724,8 @@ case safeStrRead arg of Just t -> return opt{ optShiftHeadingLevelBy = t }- _ -> E.throwIO $ PandocOptionError- "shift-heading-level-by takes an integer argument")+ _ -> optError $ PandocOptionError+ "Argument of --shift-heading-level-by must be an integer") "NUMBER") "" -- "Shift heading level" @@ -515,19 +737,11 @@ case safeStrRead arg of Just t | t > 0 && t < 6 -> return opt{ optShiftHeadingLevelBy = t - 1 }- _ -> E.throwIO $ PandocOptionError- "base-header-level must be 1-5")+ _ -> optError $ PandocOptionError+ "Argument of --base-header-level must be 1-5") "NUMBER") "" -- "Headers base level" - , Option "" ["strip-empty-paragraphs"]- (NoArg- (\opt -> do- deprecatedOption "--strip-empty-paragraphs"- "Use +empty_paragraphs extension."- return opt{ optStripEmptyParagraphs = True }))- "" -- "Strip empty paragraphs"- , Option "" ["track-changes"] (ReqArg (\arg opt -> do@@ -535,20 +749,26 @@ "accept" -> return AcceptChanges "reject" -> return RejectChanges "all" -> return AllChanges- _ -> E.throwIO $ PandocOptionError $ T.pack- ("Unknown option for track-changes: " ++ arg)+ _ -> optError $ PandocOptionError $ T.pack+ "Argument of --track-changes must be accept, reject, or all" return opt { optTrackChanges = action }) "accept|reject|all") "" -- "Accepting or reject MS Word track-changes."" , Option "" ["strip-comments"]- (NoArg- (\opt -> return opt { optStripComments = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--strip-comments" arg+ return opt { optStripComments = boolValue })+ "true|false") "" -- "Strip HTML comments" , Option "" ["reference-links"]- (NoArg- (\opt -> return opt { optReferenceLinks = True } ))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--reference-links" arg+ return opt { optReferenceLinks = boolValue })+ "true|false") "" -- "Use reference links in parsing HTML" , Option "" ["reference-location"]@@ -558,42 +778,77 @@ "block" -> return EndOfBlock "section" -> return EndOfSection "document" -> return EndOfDocument- _ -> E.throwIO $ PandocOptionError $ T.pack- ("Unknown option for reference-location: " ++ arg)+ _ -> optError $ PandocOptionError $ T.pack+ "Argument of --reference-location must be block, section, or document" return opt { optReferenceLocation = action }) "block|section|document")- "" -- "Accepting or reject MS Word track-changes.""+ "" -- "Specify where reference links and footnotes go" - , Option "" ["atx-headers"]- (NoArg- (\opt -> do- deprecatedOption "--atx-headers"- "Use --markdown-headings=atx instead."- return opt { optSetextHeaders = False } ))- "" -- "Use atx-style headers for markdown"+ , Option "" ["figure-caption-position"]+ (ReqArg+ (\arg opt -> do+ pos <- case arg of+ "above" -> return CaptionAbove+ "below" -> return CaptionBelow+ _ -> optError $ PandocOptionError $ T.pack+ "Argument of --figure-caption-position must be above or below"+ return opt { optFigureCaptionPosition = pos })+ "above|below")+ "" -- "Specify where figure captions go" + , Option "" ["table-caption-position"]+ (ReqArg+ (\arg opt -> do+ pos <- case arg of+ "above" -> return CaptionAbove+ "below" -> return CaptionBelow+ _ -> optError $ PandocOptionError $ T.pack+ "Argument of --table-caption-position must be above or below"+ return opt { optTableCaptionPosition = pos })+ "above|below")+ "" -- "Specify where table captions go"+ , Option "" ["markdown-headings"] (ReqArg (\arg opt -> do headingFormat <- case arg of "setext" -> pure True "atx" -> pure False- _ -> E.throwIO $ PandocOptionError $ T.pack- ("Unknown markdown heading format: " ++ arg ++- ". Expecting atx or setext")+ _ -> optError $ PandocOptionError $ T.pack+ "Argument of --markdown-headings must be setext or atx" pure opt { optSetextHeaders = headingFormat } ) "setext|atx") "" + , Option "" ["list-tables"]+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--list-tables" arg+ return opt { optListTables = boolValue })+ "true|false")+ "" -- "Use list tables for RST"+ , Option "" ["listings"]- (NoArg- (\opt -> return opt { optListings = True }))+ (OptArg+ (\arg opt -> do+ 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" , Option "i" ["incremental"]- (NoArg- (\opt -> return opt { optIncremental = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--incremental/-i" arg+ return opt { optIncremental = boolValue })+ "true|false") "" -- "Make list items display incrementally in Slidy/Slideous/S5" , Option "" ["slide-level"]@@ -602,20 +857,25 @@ case safeStrRead arg of Just t | t >= 0 && t <= 6 -> return opt { optSlideLevel = Just t }- _ -> E.throwIO $ PandocOptionError- "slide level must be a number between 0 and 6")+ _ -> optError $ PandocOptionError+ "Argument of --slide-level must be a number between 0 and 6") "NUMBER") "" -- "Force header level for slides" , Option "" ["section-divs"]- (NoArg- (\opt -> return opt { optSectionDivs = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--section-divs" arg+ return opt { optSectionDivs = boolValue })+ "true|false") "" -- "Put sections in div tags in HTML" , Option "" ["html-q-tags"]- (NoArg- (\opt ->- return opt { optHtmlQTags = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--html-q-tags" arg+ return opt { optHtmlQTags = boolValue })+ "true|false") "" -- "Use <q> tags for quotes in HTML" , Option "" ["email-obfuscation"]@@ -625,8 +885,8 @@ "references" -> return ReferenceObfuscation "javascript" -> return JavascriptObfuscation "none" -> return NoObfuscation- _ -> E.throwIO $ PandocOptionError $ T.pack- ("Unknown obfuscation method: " ++ arg)+ _ -> optError $ PandocOptionError $ T.pack+ "Argument of --email-obfuscation must be references, javascript, or none" return opt { optEmailObfuscation = method }) "none|javascript|references") "" -- "Method for obfuscating email in HTML"@@ -672,6 +932,14 @@ "FILE") "" -- "Path of epub cover image" + , Option "" ["epub-title-page"]+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--epub-title-page" arg+ return opt{ optEpubTitlePage = boolValue })+ "true|false")+ ""+ , Option "" ["epub-metadata"] (ReqArg (\arg opt -> return opt { optEpubMetadata = Just $@@ -687,17 +955,37 @@ "FILE") "" -- "Directory of fonts to embed" - , Option "" ["epub-chapter-level"]+ , Option "" ["split-level"] (ReqArg (\arg opt -> case safeStrRead arg of Just t | t >= 1 && t <= 6 ->- return opt { optEpubChapterLevel = t }- _ -> E.throwIO $ PandocOptionError- "chapter level must be a number between 1 and 6")+ return opt { optSplitLevel = t }+ _ -> optError $ PandocOptionError+ "Argument of --split-level must be a number between 1 and 6") "NUMBER")- "" -- "Header level at which to split chapters in EPUB"+ "" -- "Header level at which to split documents in chunked HTML or EPUB" + , Option "" ["chunk-template"]+ (ReqArg+ (\arg opt ->+ return opt{ optChunkTemplate = Just (T.pack arg) })+ "PATHTEMPLATE")+ "" -- "Template for file paths in chunkedhtml"++ , Option "" ["epub-chapter-level"]+ (ReqArg+ (\arg opt -> do+ deprecatedOption "--epub-chapter-level"+ "use --split-level"+ case safeStrRead arg of+ Just t | t >= 1 && t <= 6 ->+ return opt { optSplitLevel = t }+ _ -> optError $ PandocOptionError+ "Argument of --epub-chapter-level must be a number between 1 and 6")+ "NUMBER")+ "" -- "Header level at which to split documents in chunked HTML or EPUB"+ , Option "" ["ipynb-output"] (ReqArg (\arg opt ->@@ -705,8 +993,8 @@ "all" -> return opt{ optIpynbOutput = IpynbOutputAll } "best" -> return opt{ optIpynbOutput = IpynbOutputBest } "none" -> return opt{ optIpynbOutput = IpynbOutputNone }- _ -> E.throwIO $ PandocOptionError- "ipynb-output must be all, none, or best")+ _ -> optError $ PandocOptionError+ "Argument of --ipynb-output must be all, none, or best") "all|none|best") "" -- "Starting number for sections, subsections, etc." @@ -727,10 +1015,12 @@ , Option "" ["csl"] (ReqArg- (\arg opt ->- return opt{ optMetadata =- addMeta "csl" (normalizePath arg) $- optMetadata opt })+ (\arg opt -> do+ case lookupMeta (T.pack "csl") $ optMetadata opt of+ Just _ -> optError $ PandocOptionError+ "--csl option can only be used once"+ Nothing -> return opt{ optMetadata = addMeta "csl" (normalizePath arg) $+ optMetadata opt }) "FILE") "" @@ -762,8 +1052,8 @@ , Option "" ["webtex"] (OptArg (\arg opt -> do- let url' = fromMaybe "https://latex.codecogs.com/png.latex?" arg- return opt { optHTMLMathMethod = WebTeX $ T.pack url' })+ let url' = maybe defaultWebTeXURL T.pack arg+ return opt { optHTMLMathMethod = WebTeX url' }) "URL") "" -- "Use web service for HTML math" @@ -791,18 +1081,27 @@ "" -- "Use gladtex for HTML math" , Option "" ["trace"]- (NoArg- (\opt -> return opt { optTrace = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--trace" arg+ return opt { optTrace = boolValue })+ "true|false") "" -- "Turn on diagnostic tracing in readers." , Option "" ["dump-args"]- (NoArg- (\opt -> return opt { optDumpArgs = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--dump-args" arg+ return opt { optDumpArgs = boolValue })+ "true|false") "" -- "Print output filename and arguments to stdout." , Option "" ["ignore-args"]- (NoArg- (\opt -> return opt { optIgnoreArgs = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--ignore-args" arg+ return opt { optIgnoreArgs = boolValue })+ "true|false") "" -- "Ignore command-line arguments." , Option "" ["verbose"]@@ -816,8 +1115,11 @@ "" -- "Suppress warnings." , Option "" ["fail-if-warnings"]- (NoArg- (\opt -> return opt { optFailIfWarnings = True }))+ (OptArg+ (\arg opt -> do+ boolValue <- readBoolFromOptArg "--fail-if-warnings" arg+ return opt { optFailIfWarnings = boolValue })+ "true|false") "" -- "Exit with error status if there were warnings." , Option "" ["log"]@@ -828,196 +1130,77 @@ "" -- "Log messages in JSON format to this file." , Option "" ["bash-completion"]- (NoArg- (\_ -> do- datafiles <- getDataFileNames- tpl <- runIOorExplode $- UTF8.toString <$>- readDefaultDataFile "bash_completion.tpl"- let optnames (Option shorts longs _ _) =- map (\c -> ['-',c]) shorts ++- map ("--" ++) longs- let allopts = unwords (concatMap optnames options)- UTF8.hPutStrLn stdout $ T.pack $ printf tpl allopts- (T.unpack $ T.unwords readersNames)- (T.unpack $ T.unwords writersNames)- (T.unpack $ T.unwords $ map fst highlightingStyles)- (unwords datafiles)- exitSuccess ))+ (NoArg (\_ -> optInfo BashCompletion)) "" -- "Print bash completion script" , Option "" ["list-input-formats"]- (NoArg- (\_ -> do- mapM_ (UTF8.hPutStrLn stdout) readersNames- exitSuccess ))+ (NoArg (\_ -> optInfo ListInputFormats)) "" , Option "" ["list-output-formats"]- (NoArg- (\_ -> do- mapM_ (UTF8.hPutStrLn stdout) writersNames- exitSuccess ))+ (NoArg (\_ -> optInfo ListOutputFormats)) "" , Option "" ["list-extensions"]- (OptArg- (\arg _ -> do- let extList :: [Extension]- extList = [minBound..maxBound]- let allExts =- case arg of- Nothing -> extensionsFromList extList- Just fmt -> getAllExtensions $ T.pack fmt- let formatName = maybe "markdown" T.pack arg- if formatName `notElem`- (map fst (readers :: [(Text, Reader PandocPure)]) ++- map fst (writers :: [(Text, Writer PandocPure)]))- then E.throwIO $ PandocOptionError $ formatName <>- " is not a recognized reader or writer format"- else do- let defExts = getDefaultExtensions formatName- let showExt x =- (if extensionEnabled x defExts- then '+'- else if extensionEnabled x allExts- then '-'- else ' ') : drop 4 (show x)- mapM_ (UTF8.hPutStrLn stdout . T.pack . showExt)- [ex | ex <- extList, extensionEnabled ex allExts]- exitSuccess )- "FORMAT")+ (OptArg (\arg _ -> optInfo $ ListExtensions $ T.pack <$> arg)+ "FORMAT") "" , Option "" ["list-highlight-languages"]- (NoArg- (\_ -> do- let langs = [ T.unpack (T.toLower (sShortname s))- | s <- M.elems defaultSyntaxMap- , sShortname s `notElem`- [T.pack "Alert", T.pack "Alert_indent"]- ]- mapM_ (UTF8.hPutStrLn stdout . T.pack) (sort langs)- exitSuccess ))+ (NoArg (\_ -> optInfo ListHighlightLanguages)) "" , Option "" ["list-highlight-styles"]- (NoArg- (\_ -> do- mapM_ (UTF8.hPutStrLn stdout . fst) highlightingStyles- exitSuccess ))+ (NoArg (\_ -> optInfo ListHighlightStyles)) "" , Option "D" ["print-default-template"] (ReqArg- (\arg opt -> do- let write = case optOutputFile opt of- Just f -> UTF8.writeFile f- Nothing -> UTF8.hPutStr stdout- templ <- runIO $ do- setUserDataDir Nothing- getDefaultTemplate (T.pack arg)- case templ of- Right t- | T.null t -> -- e.g. for docx, odt, json:- E.throwIO $ PandocCouldNotFindDataFileError $ T.pack- ("templates/default." ++ arg)- | otherwise -> write t- Left e -> E.throwIO e- exitSuccess)- "FORMAT")+ (\arg opts -> optInfo $+ PrintDefaultTemplate (optOutputFile opts) (T.pack arg))+ "FORMAT") "" -- "Print default template for FORMAT" , Option "" ["print-default-data-file"] (ReqArg- (\arg opt -> do- let write = case optOutputFile opt of- Just f -> BS.writeFile f- Nothing -> BS.hPutStr stdout- runIOorExplode $- readDefaultDataFile arg >>= liftIO . write- exitSuccess)- "FILE")+ (\arg opts -> optInfo $+ PrintDefaultDataFile (optOutputFile opts) (T.pack arg))+ "FILE") "" -- "Print default data file" , Option "" ["print-highlight-style"] (ReqArg- (\arg opt -> do- let write = maybe B.putStr B.writeFile $ optOutputFile opt- sty <- runIOorExplode $ lookupHighlightingStyle arg- write $ encodePretty'- defConfig{confIndent = Spaces 4- ,confCompare = keyOrder- (map T.pack- ["text-color"- ,"background-color"- ,"line-number-color"- ,"line-number-background-color"- ,"bold"- ,"italic"- ,"underline"- ,"text-styles"])- ,confNumFormat = Generic- ,confTrailingNewline = True} sty- exitSuccess)+ (\arg opts ->+ optInfo $ PrintHighlightStyle (optOutputFile opts)+ (T.pack arg)) "STYLE|FILE") "" -- "Print default template for FORMAT" - , Option "v" ["version"]- (NoArg- (\_ -> do- prg <- getProgName- defaultDatadir <- defaultUserDataDir- luaVersion <- HsLua.run @HsLua.Exception $ do- openlibs- getglobal "_VERSION"- peek top- UTF8.hPutStrLn stdout- $ T.pack- $ prg ++ " " ++ T.unpack pandocVersion ++ versionSuffix ++- compileInfo ++ "\nScripting engine: " ++ luaVersion ++- "\nUser data directory: " ++ defaultDatadir ++- ('\n':copyrightMessage)- exitSuccess ))+ (NoArg (\_ -> optInfo VersionInfo)) "" -- "Print version" , Option "h" ["help"]- (NoArg- (\_ -> do- prg <- getProgName- UTF8.hPutStr stdout (T.pack $ usageMessage prg options)- exitSuccess ))+ (NoArg (\_ -> optInfo Help)) "" -- "Show help" ] -getDataFileNames :: IO [FilePath]-getDataFileNames = do-#ifdef EMBED_DATA_FILES- let allDataFiles = map fst dataFiles-#else- allDataFiles <- filter (\x -> x /= "." && x /= "..") <$>- (getDataDir >>= getDirectoryContents)-#endif- return $ "reference.docx" : "reference.odt" : "reference.pptx" : allDataFiles+optError :: PandocError -> ExceptT OptInfo IO a+optError = throwError . OptError +optInfo :: OptInfo -> ExceptT OptInfo IO a+optInfo = throwError+ -- Returns usage message-usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String+usageMessage :: String -> [OptDescr (Opt -> ExceptT OptInfo IO Opt)] -> String usageMessage programName = usageInfo (programName ++ " [OPTIONS] [FILES]") copyrightMessage :: String copyrightMessage = intercalate "\n" [- "Copyright (C) 2006-2022 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." ] -compileInfo :: String-compileInfo =- "\nCompiled with pandoc-types " ++ VERSION_pandoc_types ++- ", texmath " ++ VERSION_texmath ++ ", skylighting " ++- VERSION_skylighting ++ ",\nciteproc " ++ VERSION_citeproc ++- ", ipynb " ++ VERSION_ipynb ++ ", hslua " ++ VERSION_hslua- handleUnrecognizedOption :: String -> [String] -> [String] handleUnrecognizedOption "--smart" = (("--smart/-S has been removed. Use +smart or -smart extension instead.\n" ++@@ -1055,16 +1238,17 @@ ("pdf" : map fst (writers :: [(Text, Writer PandocIO)])) splitField :: String -> (String, String)-splitField = second (tailDef "true") . break (`elemText` ":=")+splitField = second (tailDef "true") . break (\c -> c == ':' || c == '=') -deprecatedOption :: String -> String -> IO ()-deprecatedOption o msg =- runIO (report $ Deprecated (T.pack o) (T.pack msg)) >>=- \case+deprecatedOption :: String -> String -> ExceptT OptInfo IO ()+deprecatedOption o msg = do+ res <- liftIO $ runIO (report $ Deprecated (T.pack o) (T.pack msg))+ case res of Right () -> return ()- Left e -> E.throwIO e+ Left e -> optError e --- | Set text value in text context.+-- | Set text value in text context. Create list if it has a value already,+-- or add to a list value. setVariable :: Text -> Text -> Context Text -> Context Text setVariable key val (Context ctx) = Context $ M.alter go key ctx where go Nothing = Just $ toVal val@@ -1092,6 +1276,14 @@ | s == "FALSE" = MetaBool False | otherwise = MetaString $ T.pack s +readBoolFromOptArg :: Text -> Maybe String -> ExceptT OptInfo IO Bool+readBoolFromOptArg opt = maybe (return True) readBoolFromArg+ where readBoolFromArg arg = case toLower <$> arg of+ "true" -> return True+ "false" -> return False+ _ -> optError $ PandocOptionError $+ "Argument of " <> opt <> " must be either true or false"+ -- On Windows with ghc 8.6+, we need to rewrite paths -- beginning with \\ to \\?\UNC\. -- See #5127. normalizePath :: FilePath -> FilePath@@ -1103,3 +1295,21 @@ #else normalizePath = id #endif++-- | Print version information with customizable features and scripting engine+versionInfo :: [String] -> Maybe String -> String -> IO ()+versionInfo features mbScriptingEngineName suffix = do+ defaultDatadir <- defaultUserDataDir+ let featuresLine = if null features+ then []+ else ["Features: " ++ unwords features]+ let scriptingLine = case mbScriptingEngineName of+ Nothing -> []+ Just name -> ["Scripting engine: " ++ name]+ UTF8.putStr $ T.unlines $ map T.pack $+ ["pandoc " ++ showVersion pandocVersion ++ suffix] +++ featuresLine +++ scriptingLine +++ ["User data directory: " ++ defaultDatadir,+ copyrightMessage]+ exitSuccess
@@ -1,92 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.App.FormatHeuristics- Copyright : Copyright (C) 2006-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley@edu>- Stability : alpha- Portability : portable--Guess the format of a file from its name.--}-module Text.Pandoc.App.FormatHeuristics- ( formatFromFilePaths- ) where--import Data.Char (toLower)-import Data.Foldable (asum)-import Data.Text (Text)-import System.FilePath (takeExtension)---- | Determines default format based on file extensions; uses the format--- of the first extension that's associated with a format.------ Examples:------ > formatFromFilePaths ["text.unknown", "no-extension"]--- Nothing------ > formatFromFilePaths ["my.md", "other.rst"]--- Just "markdown"-formatFromFilePaths :: [FilePath] -> Maybe Text-formatFromFilePaths = asum . map formatFromFilePath---- | Determines format based on file extension.-formatFromFilePath :: FilePath -> Maybe Text-formatFromFilePath x =- case takeExtension (map toLower x) of- ".adoc" -> Just "asciidoc"- ".asciidoc" -> Just "asciidoc"- ".context" -> Just "context"- ".ctx" -> Just "context"- ".db" -> Just "docbook"- ".doc" -> Just "doc" -- so we get an "unknown reader" error- ".docx" -> Just "docx"- ".dokuwiki" -> Just "dokuwiki"- ".epub" -> Just "epub"- ".fb2" -> Just "fb2"- ".htm" -> Just "html"- ".html" -> Just "html"- ".icml" -> Just "icml"- ".json" -> Just "json"- ".latex" -> Just "latex"- ".lhs" -> Just "markdown+lhs"- ".ltx" -> Just "latex"- ".markdown" -> Just "markdown"- ".markua" -> Just "markua"- ".mkdn" -> Just "markdown"- ".mkd" -> Just "markdown"- ".mdwn" -> Just "markdown"- ".mdown" -> Just "markdown"- ".Rmd" -> Just "markdown"- ".md" -> Just "markdown"- ".ms" -> Just "ms"- ".muse" -> Just "muse"- ".native" -> Just "native"- ".odt" -> Just "odt"- ".opml" -> Just "opml"- ".org" -> Just "org"- ".pdf" -> Just "pdf" -- so we get an "unknown reader" error- ".pptx" -> Just "pptx"- ".ris" -> Just "ris"- ".roff" -> Just "ms"- ".rst" -> Just "rst"- ".rtf" -> Just "rtf"- ".s5" -> Just "s5"- ".t2t" -> Just "t2t"- ".tei" -> Just "tei"- ".tex" -> Just "latex"- ".texi" -> Just "texinfo"- ".texinfo" -> Just "texinfo"- ".text" -> Just "markdown"- ".textile" -> Just "textile"- ".txt" -> Just "markdown"- ".wiki" -> Just "mediawiki"- ".xhtml" -> Just "html"- ".ipynb" -> Just "ipynb"- ".csv" -> Just "csv"- ".tsv" -> Just "tsv"- ".bib" -> Just "biblatex"- ['.',y] | y `elem` ['1'..'9'] -> Just "man"- _ -> Nothing
@@ -0,0 +1,138 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-}+{- |+ Module : Text.Pandoc.App.Input+ Copyright : © 2006-2024 John MacFarlane+ License : GPL-2.0-or-later+ Maintainer : John MacFarlane <jgm@berkeley@edu>++Read from the file system into a pandoc document.+-}+module Text.Pandoc.App.Input+ ( InputParameters (..)+ , readInput+ ) where++import Control.Monad ((>=>), when)+import Control.Monad.Except (throwError, catchError)+import Data.Text (Text)+import Network.URI (URI (..), parseURI)+import Text.Pandoc.Transforms (adjustLinksAndIds)+import Text.Pandoc.Class ( PandocMonad, openURL, toTextM+ , readFileStrict, readStdinStrict, report)+import Text.Pandoc.Definition (Pandoc)+import Text.Pandoc.Error (PandocError (..))+import Text.Pandoc.Logging (LogMessage (..))+import Text.Pandoc.MIME (getCharset, MimeType)+import Text.Pandoc.Options (ReaderOptions (..))+import Text.Pandoc.Readers (Reader (..))+import Text.Pandoc.Shared (tabFilter)+import Text.Pandoc.URI (uriPathToPath)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy as BL+import qualified Data.Text as T++-- | Settings specifying how and which input should be processed.+data InputParameters m = InputParameters+ { inputReader :: Reader m+ , inputReaderName :: Text+ , inputReaderOptions :: ReaderOptions+ , inputSources :: [FilePath]+ , inputSpacesPerTab :: Maybe Int+ , inputFileScope :: Bool+ }++-- | Read all input into a pandoc document.+readInput :: PandocMonad m => InputParameters m -> m Pandoc+readInput params = do+ let sources = inputSources params+ let readerName = inputReaderName params+ let readerOpts = inputReaderOptions params+ let convertTabs :: Text -> Text+ convertTabs = tabFilter $ case inputSpacesPerTab params of+ Nothing -> 0+ Just ts -> if readerName `elem` ["t2t", "man", "tsv"]+ then 0+ else ts++ inputs <- readSources sources++ case inputReader params of+ TextReader r+ | readerName == "json" ->+ mconcat <$> mapM (inputToText convertTabs >=> r readerOpts . (:[]))+ inputs+ | inputFileScope params ->+ mconcat <$> mapM+ (\source -> do+ (fp, txt) <- inputToText convertTabs source+ adjustLinksAndIds (readerExtensions readerOpts)+ (T.pack fp) (map (T.pack . fst) inputs)+ <$> r readerOpts [(fp, txt)])+ inputs+ | otherwise -> mapM (inputToText convertTabs) inputs >>= r readerOpts+ ByteStringReader r ->+ mconcat <$> mapM (r readerOpts . inputToLazyByteString) inputs++readSources :: PandocMonad m+ => [FilePath] -> m [(FilePath, (BS.ByteString, Maybe MimeType))]+readSources srcs =+ mapM (\fp -> do t <- readSource fp+ return (if fp == "-" then "" else fp, t)) srcs++-- | Read input from a resource, i.e., either a file, a URL, or stdin+-- (@-@).+readSource :: PandocMonad m+ => FilePath -> m (BS.ByteString, Maybe MimeType)+readSource "-" = (,Nothing) <$> readStdinStrict+readSource src =+ case parseURI src of+ Just u | uriScheme u `elem` ["http:","https:"] -> openURL (T.pack src)+ | uriScheme u == "file:" ->+ (,Nothing) <$>+ readFileStrict (uriPathToPath $ T.pack $ uriPath u)+ _ -> (,Nothing) <$> readFileStrict src++inputToText :: PandocMonad m+ => (Text -> Text)+ -> (FilePath, (BS.ByteString, Maybe MimeType))+ -> m (FilePath, Text)+inputToText convTabs (fp, (bs,mt)) =+ (fp,) . convTabs . T.filter (/='\r') <$>+ case mt >>= getCharset of+ Just "UTF-8" -> toTextM fp bs+ Just "ISO-8859-1" -> return $ T.pack $ B8.unpack bs+ Just charset -> throwError $ PandocUnsupportedCharsetError charset+ Nothing -> catchError+ (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+inputToLazyByteString (_, (bs,_)) = BL.fromStrict bs
@@ -2,12 +2,13 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {- | Module : Text.Pandoc.App.Opt- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu>@@ -18,6 +19,7 @@ -} module Text.Pandoc.App.Opt ( Opt(..)+ , OptInfo(..) , LineEnding (..) , IpynbOutput (..) , DefaultsState (..)@@ -25,11 +27,13 @@ , applyDefaults , fullDefaultsPath ) where-import Control.Monad.Except (MonadIO, liftIO, throwError, (>=>), foldM)+import Control.Monad.Except (throwError)+import Control.Monad.Trans (MonadIO, liftIO, lift)+import Control.Monad ((>=>), foldM) import Control.Monad.State.Strict (StateT, modify, gets) import System.FilePath ( addExtension, (</>), takeExtension, takeDirectory ) import System.Directory ( canonicalizePath )-import Data.Char (toLower)+import Data.Char (toLower, isSpace) import Data.Maybe (fromMaybe) import GHC.Generics hiding (Meta) import Text.Pandoc.Filter (Filter (..))@@ -38,12 +42,15 @@ TrackChanges (AcceptChanges), WrapOption (WrapAuto), HTMLMathMethod (PlainMath), 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))-import Text.Pandoc.Shared (defaultUserDataDir, findM, ordNub)+import Data.Containers.ListUtils (nubOrd)+import Text.Pandoc.Data (defaultUserDataDir) import qualified Text.Pandoc.Parsing as P import Text.Pandoc.Readers.Metadata (yamlMap) import Text.Pandoc.Class.PandocPure@@ -54,8 +61,8 @@ import qualified Data.Map as M import qualified Data.ByteString.Char8 as B8 import Text.Pandoc.Definition (Meta(..), MetaValue(..))-import Data.Aeson (defaultOptions, Options(..), Result(..), camelTo2,- genericToJSON, fromJSON)+import Data.Aeson (defaultOptions, Options(..), Result(..),+ genericToJSON, fromJSON, camelTo2, eitherDecodeStrict) import Data.Aeson.TH (deriveJSON) import Control.Applicative ((<|>)) import Data.Yaml@@ -78,6 +85,22 @@ $(deriveJSON defaultOptions{ fieldLabelModifier = map toLower . drop 11 } ''IpynbOutput) +-- | Option parser results requesting informational output.+data OptInfo =+ BashCompletion+ | ListInputFormats+ | ListOutputFormats+ | ListExtensions (Maybe Text)+ | ListHighlightLanguages+ | ListHighlightStyles+ | PrintDefaultTemplate (Maybe FilePath) Text+ | PrintDefaultDataFile (Maybe FilePath) Text+ | PrintHighlightStyle (Maybe FilePath) Text+ | VersionInfo+ | Help+ | OptError PandocError+ deriving (Show, Generic)+ -- | Data structure for command line options. data Opt = Opt { optTabStop :: Int -- ^ Number of spaces per tab@@ -86,6 +109,8 @@ , optFrom :: Maybe Text -- ^ Reader format , optTo :: Maybe Text -- ^ Writer format , optTableOfContents :: Bool -- ^ Include table of contents+ , optListOfFigures :: Bool -- ^ Include list of figures+ , optListOfTables :: Bool -- ^ Include list of tables , optShiftHeadingLevelBy :: Int -- ^ Shift heading level by , optTemplate :: Maybe FilePath -- ^ Custom template , optVariables :: Context Text -- ^ Template variables to set@@ -99,18 +124,21 @@ , optIncremental :: Bool -- ^ Use incremental lists in Slidy/Slideous/S5 , optSelfContained :: Bool -- ^ Make HTML accessible offline (deprecated) , 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 , optReferenceDoc :: Maybe FilePath -- ^ Path of reference doc+ , optSplitLevel :: Int -- ^ Header level at which to split documents in epub and chunkedhtml+ , optChunkTemplate :: Maybe Text -- ^ Template to use for chunk filenames , optEpubSubdirectory :: String -- ^ EPUB subdir in OCF container , optEpubMetadata :: Maybe FilePath -- ^ EPUB metadata , optEpubFonts :: [FilePath] -- ^ EPUB fonts to embed- , optEpubChapterLevel :: Int -- ^ Header level at which to split chapters , optEpubCoverImage :: Maybe FilePath -- ^ Cover image for epub+ , optEpubTitlePage :: Bool -- ^ INclude title page in EPUB , optTOCDepth :: Int -- ^ Number of levels to include in TOC , optDumpArgs :: Bool -- ^ Output command-line arguments , optIgnoreArgs :: Bool -- ^ Ignore command-line arguments@@ -120,21 +148,22 @@ , optFailIfWarnings :: Bool -- ^ Fail on warnings , optReferenceLinks :: Bool -- ^ Use reference links in writing markdown, rst , optReferenceLocation :: ReferenceLocation -- ^ location for footnotes and link references in markdown output+ , optFigureCaptionPosition :: CaptionPosition -- ^ position for figure caption+ , optTableCaptionPosition :: CaptionPosition -- ^ position for table caption , optDpi :: Int -- ^ Dpi , optWrap :: WrapOption -- ^ Options for wrapping text , optColumns :: Int -- ^ Line length in characters , optFilters :: [Filter] -- ^ Filters to apply , optEmailObfuscation :: ObfuscationMethod , optIdentifierPrefix :: Text- , optStripEmptyParagraphs :: Bool -- ^ Strip empty paragraphs , 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 , optSetextHeaders :: Bool -- ^ Use atx headers for markdown level 1-2+ , optListTables :: Bool -- ^ Use list tables for RST , optAscii :: Bool -- ^ Prefer ascii output , optDefaultImageExtension :: Text -- ^ Default image extension , optExtractMedia :: Maybe FilePath -- ^ Path to extract embedded media@@ -155,6 +184,7 @@ , optBibliography :: [FilePath] -- ^ Bibliography files , optCitationAbbreviations :: Maybe FilePath -- ^ Citation abbreviations , optSandbox :: Bool+ , optTypstInputs :: [(Text, Text)] -- ^ List of parameter values for typst } deriving (Generic, Show) instance FromJSON Opt where@@ -166,6 +196,8 @@ <*> o .:? "from" <*> o .:? "to" <*> o .:? "table-of-contents" .!= optTableOfContents defaultOpts+ <*> o .:? "list-of-figures" .!= optListOfFigures defaultOpts+ <*> o .:? "list-of-tables" .!= optListOfTables defaultOpts <*> o .:? "shift-heading-level-by" .!= optShiftHeadingLevelBy defaultOpts <*> o .:? "template" <*> o .:? "variables" .!= optVariables defaultOpts@@ -179,18 +211,22 @@ <*> o .:? "incremental" .!= optIncremental defaultOpts <*> o .:? "self-contained" .!= optSelfContained defaultOpts <*> 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" <*> o .:? "reference-doc"+ <*> ((o .:? "split-level") <|> (o .:? "epub-chapter-level"))+ .!= optSplitLevel defaultOpts+ <*> o .:? "chunk-template" <*> o .:? "epub-subdirectory" .!= optEpubSubdirectory defaultOpts <*> o .:? "epub-metadata" <*> o .:? "epub-fonts" .!= optEpubFonts defaultOpts- <*> o .:? "epub-chapter-level" .!= optEpubChapterLevel defaultOpts <*> o .:? "epub-cover-image"+ <*> o .:? "epub-title-page" .!= optEpubTitlePage defaultOpts <*> o .:? "toc-depth" .!= optTOCDepth defaultOpts <*> o .:? "dump-args" .!= optDumpArgs defaultOpts <*> o .:? "ignore-args" .!= optIgnoreArgs defaultOpts@@ -200,21 +236,22 @@ <*> o .:? "fail-if-warnings" .!= optFailIfWarnings defaultOpts <*> o .:? "reference-links" .!= optReferenceLinks defaultOpts <*> o .:? "reference-location" .!= optReferenceLocation defaultOpts+ <*> o .:? "figure-caption-position" .!= optFigureCaptionPosition defaultOpts+ <*> o .:? "table-caption-position" .!= optTableCaptionPosition defaultOpts <*> o .:? "dpi" .!= optDpi defaultOpts <*> o .:? "wrap" .!= optWrap defaultOpts <*> o .:? "columns" .!= optColumns defaultOpts <*> o .:? "filters" .!= optFilters defaultOpts <*> o .:? "email-obfuscation" .!= optEmailObfuscation defaultOpts <*> o .:? "identifier-prefix" .!= optIdentifierPrefix defaultOpts- <*> o .:? "strip-empty-paragraphs" .!= optStripEmptyParagraphs defaultOpts <*> 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" <*> o .:? "setext-headers" .!= optSetextHeaders defaultOpts+ <*> o .:? "list-tables" .!= optListTables defaultOpts <*> o .:? "ascii" .!= optAscii defaultOpts <*> o .:? "default-image-extension" .!= optDefaultImageExtension defaultOpts <*> o .:? "extract-media"@@ -235,6 +272,7 @@ <*> o .:? "bibliography" .!= optBibliography defaultOpts <*> o .:? "citation-abbreviations" <*> o .:? "sandbox" .!= optSandbox defaultOpts+ <*> o .:? "typst-inputs" .!= optTypstInputs defaultOpts instance ToJSON Opt where toJSON = genericToJSON defaultOptions{@@ -276,11 +314,14 @@ => Opt -> StateT DefaultsState m Opt resolveVarsInOpt opt@Opt- { optTemplate = oTemplate+ { optTo = oTo+ , optFrom = oFrom+ , optTemplate = oTemplate , optMetadataFiles = oMetadataFiles , optOutputFile = oOutputFile , optInputFiles = oInputFiles , optSyntaxDefinitions = oSyntaxDefinitions+ , optSyntaxHighlighting = oSyntaxHighlighting , optAbbreviations = oAbbreviations , optReferenceDoc = oReferenceDoc , optEpubMetadata = oEpubMetadata@@ -299,9 +340,10 @@ , optBibliography = oBibliography , optCitationAbbreviations = oCitationAbbreviations , optPdfEngine = oPdfEngine- , optHighlightStyle = oHighlightStyle } = do+ oTo' <- mapM (fmap T.pack . resolveVars . T.unpack) oTo+ oFrom' <- mapM (fmap T.pack . resolveVars . T.unpack) oFrom oTemplate' <- mapM resolveVars oTemplate oMetadataFiles' <- mapM resolveVars oMetadataFiles oOutputFile' <- mapM resolveVars oOutputFile@@ -325,12 +367,15 @@ oBibliography' <- mapM resolveVars oBibliography oCitationAbbreviations' <- mapM resolveVars oCitationAbbreviations oPdfEngine' <- mapM resolveVars oPdfEngine- oHighlightStyle' <- mapM (fmap T.pack . resolveVars . T.unpack) oHighlightStyle- return opt{ optTemplate = oTemplate'+ oSyntaxHighlighting' <- T.pack <$> resolveVars (T.unpack oSyntaxHighlighting)+ return opt{ optTo = oTo'+ , optFrom = oFrom'+ , optTemplate = oTemplate' , optMetadataFiles = oMetadataFiles' , optOutputFile = oOutputFile' , optInputFiles = oInputFiles' , optSyntaxDefinitions = oSyntaxDefinitions'+ , optSyntaxHighlighting = oSyntaxHighlighting' , optAbbreviations = oAbbreviations' , optReferenceDoc = oReferenceDoc' , optEpubMetadata = oEpubMetadata'@@ -349,43 +394,52 @@ , optBibliography = oBibliography' , optCitationAbbreviations = oCitationAbbreviations' , optPdfEngine = oPdfEngine'- , optHighlightStyle = oHighlightStyle' } where- resolveVars :: FilePath -> StateT DefaultsState m FilePath- resolveVars [] = return []- resolveVars ('$':'{':xs) =+ resolveVars = expandVars (optDataDir opt)+ resolveVarsInFilter (JSONFilter fp) =+ JSONFilter <$> resolveVars fp+ resolveVarsInFilter (LuaFilter fp) =+ LuaFilter <$> resolveVars fp+ resolveVarsInFilter CiteprocFilter = return CiteprocFilter+++expandVars :: (PandocMonad m, MonadIO m)+ => Maybe FilePath+ -> FilePath+ -> StateT DefaultsState m FilePath+expandVars _ [] = return []+expandVars mbDataDir ('$':'{':xs) = let (ys, zs) = break (=='}') xs in if null zs then return $ '$':'{':xs else do- val <- lookupEnv' ys- (val ++) <$> resolveVars (drop 1 zs)- resolveVars (c:cs) = (c:) <$> resolveVars cs- lookupEnv' :: String -> StateT DefaultsState m String- lookupEnv' "." = do+ val <- expandEnv mbDataDir ys+ (val ++) <$> expandVars mbDataDir (drop 1 zs)+expandVars mbDataDir (c:cs) = (c:) <$> expandVars mbDataDir cs++expandEnv :: (PandocMonad m, MonadIO m)+ => Maybe FilePath+ -> String+ -> StateT DefaultsState m String+expandEnv _ "." = do mbCurDefaults <- gets curDefaults maybe (return "") (fmap takeDirectory . liftIO . canonicalizePath) mbCurDefaults- lookupEnv' "USERDATA" = do- mbodatadir <- mapM resolveVars oDataDir- mbdatadir <- getUserDataDir+expandEnv mbDataDir "USERDATA" = do+ mbodatadir <- mapM (expandVars mbDataDir) mbDataDir+ mbdatadir' <- getUserDataDir defdatadir <- liftIO defaultUserDataDir- return $ fromMaybe defdatadir (mbodatadir <|> mbdatadir)- lookupEnv' v = do+ return $ fromMaybe defdatadir (mbodatadir <|> mbdatadir')+expandEnv _ v = do mbval <- fmap T.unpack <$> lookupEnv (T.pack v) case mbval of Nothing -> do report $ EnvironmentVariableUndefined (T.pack v) return mempty Just x -> return x- resolveVarsInFilter (JSONFilter fp) =- JSONFilter <$> resolveVars fp- resolveVarsInFilter (LuaFilter fp) =- LuaFilter <$> resolveVars fp- resolveVarsInFilter CiteprocFilter = return CiteprocFilter @@ -396,8 +450,9 @@ parseDefaults n dataDir = parseDefsNames n >>= \ds -> return $ \o -> do -- get parent defaults: defsParent <- gets $ fromMaybe "" . curDefaults+ expandedDataDir <- mapM (expandVars dataDir) dataDir -- get child defaults:- defsChildren <- mapM (fullDefaultsPath dataDir) ds+ defsChildren <- mapM (\d -> expandVars expandedDataDir d >>= lift . fullDefaultsPath expandedDataDir) ds -- expand parent in defaults inheritance graph by children: defsGraph <- gets inheritanceGraph let defsGraphExp = expand defsGraph defsChildren defsParent@@ -442,6 +497,14 @@ parseJSON v >>= \x -> return (\o -> o{ optTableOfContents = x }) "toc" -> parseJSON v >>= \x -> return (\o -> o{ optTableOfContents = x })+ "list-of-figures" ->+ parseJSON v >>= \x -> return (\o -> o{ optListOfFigures = x })+ "lof" ->+ parseJSON v >>= \x -> return (\o -> o{ optListOfFigures = x })+ "list-of-tables" ->+ parseJSON v >>= \x -> return (\o -> o{ optListOfTables = x })+ "lot" ->+ parseJSON v >>= \x -> return (\o -> o{ optListOfTables = x }) "from" -> parseJSON v >>= \x -> return (\o -> o{ optFrom = x }) "reader" ->@@ -501,10 +564,13 @@ parseJSON v >>= \x -> return (\o -> o{ optSelfContained = x }) "embed-resources" -> parseJSON v >>= \x -> return (\o -> o{ optEmbedResources = x })+ "link-images" ->+ 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 =@@ -517,6 +583,8 @@ parseJSON v >>= \x -> return (\o -> o{ optSyntaxDefinitions = optSyntaxDefinitions o <> map unpack x })+ "syntax-highlighting" ->+ parseJSON v >>= \x -> return (\o -> o{ optSyntaxHighlighting = x }) "top-level-division" -> parseJSON v >>= \x -> return (\o -> o{ optTopLevelDivision = x }) "html-math-method" ->@@ -537,10 +605,16 @@ parseJSON v >>= \x -> return (\o -> o{ optEpubFonts = optEpubFonts o <> map unpack x }) "epub-chapter-level" ->- parseJSON v >>= \x -> return (\o -> o{ optEpubChapterLevel = x })+ parseJSON v >>= \x -> return (\o -> o{ optSplitLevel = x })+ "split-level" ->+ parseJSON v >>= \x -> return (\o -> o{ optSplitLevel = x })+ "chunk-template" ->+ parseJSON v >>= \x -> return (\o -> o{ optChunkTemplate = Just x }) "epub-cover-image" -> parseJSON v >>= \x -> return (\o -> o{ optEpubCoverImage = unpack <$> x })+ "epub-title-page" ->+ parseJSON v >>= \x -> return (\o -> o{ optEpubTitlePage = x }) "toc-depth" -> parseJSON v >>= \x -> return (\o -> o{ optTOCDepth = x }) "dump-args" ->@@ -559,6 +633,10 @@ parseJSON v >>= \x -> return (\o -> o{ optReferenceLinks = x }) "reference-location" -> parseJSON v >>= \x -> return (\o -> o{ optReferenceLocation = x })+ "figure-caption-position" ->+ parseJSON v >>= \x -> return (\o -> o{ optFigureCaptionPosition = x })+ "table-caption-position" ->+ parseJSON v >>= \x -> return (\o -> o{ optTableCaptionPosition = x }) "dpi" -> parseJSON v >>= \x -> return (\o -> o{ optDpi = x }) "wrap" ->@@ -577,8 +655,6 @@ "identifier-prefix" -> parseJSON v >>= \x -> return (\o -> o{ optIdentifierPrefix = x })- "strip-empty-paragraphs" ->- parseJSON v >>= \x -> return (\o -> o{ optStripEmptyParagraphs = x }) "indented-code-classes" -> parseJSON v >>= \x -> return (\o -> o{ optIndentedCodeClasses = x })@@ -587,7 +663,10 @@ "cite-method" -> parseJSON v >>= \x -> return (\o -> o{ optCiteMethod = x }) "listings" ->- parseJSON v >>= \x -> return (\o -> o{ optListings = x })+ parseJSON v >>= \x ->+ if x+ then return (\o -> o{ optSyntaxHighlighting = "idiomatic" })+ else return id "pdf-engine" -> parseJSON v >>= \x -> return (\o -> o{ optPdfEngine = unpack <$> x }) "pdf-engine-opts" ->@@ -601,14 +680,14 @@ return (\o -> o{ optPdfEngineOpts = [unpack x] })) "slide-level" -> parseJSON v >>= \x -> return (\o -> o{ optSlideLevel = x })- "atx-headers" ->- parseJSON v >>= \x -> return (\o -> o{ optSetextHeaders = not x }) "markdown-headings" -> parseJSON v >>= \x -> return (\o -> case T.toLower x of "atx" -> o{ optSetextHeaders = False } "setext" -> o{ optSetextHeaders = True } _ -> o)+ "list-tables" ->+ parseJSON v >>= \x -> return (\o -> o{ optListTables = x }) "ascii" -> parseJSON v >>= \x -> return (\o -> o{ optAscii = x }) "default-image-extension" ->@@ -696,6 +775,8 @@ , optFrom = Nothing , optTo = Nothing , optTableOfContents = False+ , optListOfFigures = False+ , optListOfTables = False , optShiftHeadingLevelBy = 0 , optTemplate = Nothing , optVariables = mempty@@ -704,23 +785,26 @@ , optOutputFile = Nothing , optInputFiles = Nothing , optNumberSections = False- , optNumberOffset = [0,0,0,0,0,0]+ , optNumberOffset = [] , optSectionDivs = False , optIncremental = False , optSelfContained = False , optEmbedResources = False+ , optLinkImages = False , optHtmlQTags = False- , optHighlightStyle = Just "pygments" , optSyntaxDefinitions = []+ , optSyntaxHighlighting = DefaultHighlightingString , optTopLevelDivision = TopLevelDefault , optHTMLMathMethod = PlainMath , optAbbreviations = Nothing , optReferenceDoc = Nothing+ , optSplitLevel = 1+ , optChunkTemplate = Nothing , optEpubSubdirectory = "EPUB" , optEpubMetadata = Nothing , optEpubFonts = []- , optEpubChapterLevel = 1 , optEpubCoverImage = Nothing+ , optEpubTitlePage = True , optTOCDepth = 3 , optDumpArgs = False , optIgnoreArgs = False@@ -730,21 +814,22 @@ , optFailIfWarnings = False , optReferenceLinks = False , optReferenceLocation = EndOfDocument+ , optFigureCaptionPosition = CaptionBelow+ , optTableCaptionPosition = CaptionAbove , optDpi = 96 , optWrap = WrapAuto , optColumns = 72 , optFilters = [] , optEmailObfuscation = NoObfuscation , optIdentifierPrefix = ""- , optStripEmptyParagraphs = False , optIndentedCodeClasses = [] , optDataDir = Nothing , optCiteMethod = Citeproc- , optListings = False , optPdfEngine = Nothing , optPdfEngineOpts = [] , optSlideLevel = Nothing , optSetextHeaders = False+ , optListTables = False , optAscii = False , optDefaultImageExtension = "" , optExtractMedia = Nothing@@ -765,6 +850,7 @@ , optBibliography = [] , optCitationAbbreviations = Nothing , optSandbox = False+ , optTypstInputs = [] } yamlToMeta :: Value -> Parser Meta@@ -786,11 +872,19 @@ setVerbosity $ optVerbosity opt modify $ \defsState -> defsState{ curDefaults = Just file } inp <- readFileStrict file- case decodeEither' (B8.unlines . takeWhile (/= "...") . B8.lines $ inp) of- Right f -> f opt- Left err' -> throwError $- PandocParseError- $ T.pack $ Data.Yaml.prettyPrintParseException err'+ let isJSON = B8.take 1 (B8.dropWhile isSpace inp) == "{"+ if isJSON+ then+ case eitherDecodeStrict inp of+ Right f -> f opt+ Left err' -> throwError $ PandocParseError $ T.pack $+ "Error parsing " <> file <> ":\n" <> err'+ else+ case decodeEither' (B8.unlines . takeWhile (/= "...") . B8.lines $ inp) of+ Right f -> f opt+ Left err' -> throwError $ PandocParseError $ T.pack $+ "Error parsing " <> file <> ":\n" <>+ Data.Yaml.prettyPrintParseException err' fullDefaultsPath :: (PandocMonad m, MonadIO m) => Maybe FilePath@@ -802,7 +896,14 @@ else file defaultDataDir <- liftIO defaultUserDataDir let defaultFp = fromMaybe defaultDataDir dataDir </> "defaults" </> fp- fromMaybe fp <$> findM fileExists [fp, defaultFp]+ fpExists <- fileExists fp+ if fpExists+ then return fp+ else do+ defaultFpExists <- fileExists defaultFp+ if defaultFpExists+ then return defaultFp+ else return fp -- | In a list of lists, append another list in front of every list which -- starts with specific element.@@ -817,4 +918,4 @@ cyclic :: Ord a => [[a]] -> Bool cyclic = any hasDuplicate where- hasDuplicate xs = length (ordNub xs) /= length xs+ hasDuplicate xs = length (nubOrd xs) /= length xs
@@ -1,11 +1,13 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} {- | Module : Text.Pandoc.App- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu>@@ -17,46 +19,51 @@ module Text.Pandoc.App.OutputSettings ( OutputSettings (..) , optToOutputSettings+ , sandbox' ) where import qualified Data.Map as M import qualified Data.Text as T import Text.DocTemplates (toVal, Context(..), Val(..)) import qualified Control.Exception as E import Control.Monad-import Control.Monad.Except (throwError)+import Control.Monad.Except (throwError, catchError) import Control.Monad.Trans import Data.Char (toLower) import Data.List (find)-import Data.Maybe (fromMaybe)+import Data.Maybe (catMaybes, fromMaybe) import Skylighting (defaultSyntaxMap) import Skylighting.Parser (addSyntaxDefinition, parseSyntaxDefinition) import System.Directory (getCurrentDirectory) import System.Exit (exitSuccess) import System.FilePath import System.IO (stdout)+import Text.Pandoc.Chunks (PathTemplate(..)) import Text.Pandoc-import Text.Pandoc.App.FormatHeuristics (formatFromFilePaths)+import Text.Pandoc.Filter (Filter(CiteprocFilter)) import Text.Pandoc.App.Opt (Opt (..))-import Text.Pandoc.App.CommandLineOptions (engines, setVariable)+import Text.Pandoc.App.CommandLineOptions (engines)+import Text.Pandoc.Format (FlavoredFormat (..), applyExtensionsDiff,+ parseFlavoredFormat, formatFromFilePaths) import Text.Pandoc.Highlighting (lookupHighlightingStyle)-import Text.Pandoc.Writers.Custom (writeCustom)+import Text.Pandoc.Scripting (ScriptingEngine (engineLoadCustom),+ CustomComponents(..)) import qualified Text.Pandoc.UTF8 as UTF8 readUtf8File :: PandocMonad m => FilePath -> m T.Text-readUtf8File = fmap UTF8.toText . readFileStrict+readUtf8File fp = readFileStrict fp >>= toTextM fp -- | Settings specifying how document output should be produced. data OutputSettings m = OutputSettings { outputFormat :: T.Text , outputWriter :: Writer m- , outputWriterName :: T.Text , outputWriterOptions :: WriterOptions , outputPdfProgram :: Maybe String } -- | Get output settings from command line options.-optToOutputSettings :: (PandocMonad m, MonadIO m) => Opt -> m (OutputSettings m)-optToOutputSettings opts = do+optToOutputSettings :: (PandocMonad m, MonadIO m)+ => ScriptingEngine -> Opt -> m (OutputSettings m)+optToOutputSettings scriptingEngine opts = do let outputFile = fromMaybe "-" (optOutputFile opts) when (optDumpArgs opts) . liftIO $ do@@ -68,56 +75,87 @@ let pdfOutput = map toLower (takeExtension outputFile) == ".pdf" || optTo opts == Just "pdf"- (writerName, maybePdfProg) <-+ let defaultOutput = "html"+ defaultOutputFlavor <- parseFlavoredFormat defaultOutput+ (flvrd@(FlavoredFormat format _extsDiff), maybePdfProg) <- if pdfOutput- then liftIO $ pdfWriterAndProg- (case optTo opts of- Just "pdf" -> Nothing- x -> x)- (optPdfEngine opts)+ then do+ outflavor <- case optTo opts of+ Just x | x /= "pdf" -> Just <$> parseFlavoredFormat x+ _ -> pure Nothing+ liftIO $ pdfWriterAndProg outflavor (optPdfEngine opts) else case optTo opts of- Just f -> return (f, Nothing)+ Just f -> (, optPdfEngine opts) <$> parseFlavoredFormat f Nothing- | outputFile == "-" -> return ("html", Nothing)- | otherwise ->- case formatFromFilePaths [outputFile] of- Nothing -> do- report $ CouldNotDeduceFormat- [T.pack $ takeExtension outputFile] "html"- return ("html", Nothing)- Just f -> return (f, Nothing)+ | outputFile == "-" ->+ return (defaultOutputFlavor, optPdfEngine opts)+ | otherwise -> case formatFromFilePaths [outputFile] of+ Nothing -> do+ report $ CouldNotDeduceFormat+ [T.pack $ takeExtension outputFile] defaultOutput+ return (defaultOutputFlavor, optPdfEngine opts)+ Just f -> return (f, optPdfEngine opts) - let format = if ".lua" `T.isSuffixOf` writerName- then writerName- else T.toLower $ baseWriterName writerName+ when (format == "asciidoctor") $ do+ report $ Deprecated "asciidoctor" "use asciidoc instead" let makeSandboxed pureWriter =- let files = maybe id (:) (optReferenceDoc opts) .- maybe id (:) (optEpubMetadata opts) .- maybe id (:) (optEpubCoverImage opts) .- maybe id (:) (optCSL opts) .- maybe id (:) (optCitationAbbreviations opts) $- optEpubFonts opts ++- optBibliography opts- in case pureWriter of- TextWriter w -> TextWriter $ \o d -> sandbox files (w o d)- ByteStringWriter w- -> ByteStringWriter $ \o d -> sandbox files (w o d)+ case pureWriter of+ TextWriter w -> TextWriter $ \o d -> sandbox' opts (w o d)+ ByteStringWriter w -> ByteStringWriter $ \o d -> sandbox' opts (w o d) + let standalone = optStandalone opts || isBinaryFormat format || pdfOutput+ let templateOrThrow = \case+ Left e -> throwError $ PandocTemplateError (T.pack e)+ Right t -> pure t+ let processCustomTemplate getDefault =+ case optTemplate opts of+ _ | not standalone -> return Nothing+ Nothing -> Just <$> getDefault+ Just tp -> do+ let getAndCompile fp =+ getTemplate fp >>= runWithPartials . compileTemplate fp >>=+ fmap Just . templateOrThrow+ catchError+ (getAndCompile tp)+ (\e ->+ if null (takeExtension tp)+ then getAndCompile (tp <.> T.unpack format)+ else throwError e) - (writer, writerExts) <-- if ".lua" `T.isSuffixOf` format- then return (TextWriter- (\o d -> writeCustom (T.unpack writerName) o d), mempty)- else if optSandbox opts- then- case runPure (getWriter writerName) of- Left e -> throwError e- Right (w, wexts) ->- return (makeSandboxed w, wexts)- else getWriter (T.toLower writerName)+ (writer, writerExts', mtemplate) <-+ if "lua" `T.isSuffixOf` format+ then do+ let path = T.unpack format+ components <- engineLoadCustom scriptingEngine path+ w <- case customWriter components of+ Nothing -> throwError $ PandocAppError $+ format <> " does not contain a custom writer"+ Just w -> return w+ let extsConf = fromMaybe mempty $ customExtensions components+ wexts <- applyExtensionsDiff extsConf flvrd+ templ <- processCustomTemplate $+ case customTemplate components of+ Nothing -> throwError $ PandocNoTemplateError format+ Just t -> runWithDefaultPartials (compileTemplate path t) >>=+ templateOrThrow+ return (w, wexts, templ)+ else+ if optSandbox opts+ then do+ tmpl <- processCustomTemplate (compileDefaultTemplate format)+ case runPure (getWriter flvrd) of+ Right (w, wexts) -> return (makeSandboxed w, wexts, tmpl)+ Left e -> throwError e+ else do+ (w, wexts) <- getWriter flvrd+ tmpl <- processCustomTemplate (compileDefaultTemplate format)+ return (w, wexts, tmpl) - let standalone = optStandalone opts || not (isTextFormat format) || pdfOutput+ -- see #10662:+ let writerExts = if CiteprocFilter `elem` optFilters opts+ then disableExtension Ext_citations writerExts'+ else writerExts' let addSyntaxMap existingmap f = do res <- liftIO (parseSyntaxDefinition f)@@ -128,10 +166,11 @@ syntaxMap <- foldM addSyntaxMap defaultSyntaxMap (optSyntaxDefinitions opts) - hlStyle <- traverse (lookupHighlightingStyle . T.unpack) $- optHighlightStyle opts-- let setVariableM k v = return . setVariable k v+ 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@@ -144,7 +183,7 @@ (ListVal $ v : map toVal vs) ctxMap Nothing -> M.insert k (toVal vs) ctxMap - let getTextContents fp = UTF8.toText . fst <$> fetchItem (T.pack fp)+ let getTextContents fp = (fst <$> fetchItem (T.pack fp)) >>= toTextM fp let setFilesVariableM k fps ctx = do xs <- mapM getTextContents fps@@ -160,6 +199,10 @@ >>= setVariableM "outputfile" (T.pack outputFile) >>=+ setVariableM "pandoc-version" pandocVersionText+ >>=+ maybe return (setVariableM "pdf-engine" . T.pack) maybePdfProg+ >>= setFilesVariableM "include-before" (optIncludeBeforeBody opts) >>= setFilesVariableM "include-after" (optIncludeAfterBody opts)@@ -170,15 +213,16 @@ >>= maybe return (setVariableM "title-prefix") (optTitlePrefix opts) >>=- maybe return (setVariableM "epub-cover-image")- (T.pack <$> optEpubCoverImage opts)+ maybe return (setVariableM "epub-cover-image" . T.pack)+ (optEpubCoverImage opts) >>= setVariableM "curdir" (T.pack curdir) >>= (\vars -> if format == "dzslides" then do- dztempl <- UTF8.toText <$> readDataFile- ("dzslides" </> "template.html")+ dztempl <-+ let fp = "dzslides" </> "template.html"+ in readDataFile fp >>= toTextM fp let dzline = "<!-- {{{{ dzslides core" let dzcore = T.unlines $ dropWhile (not . (dzline `T.isPrefixOf`))@@ -186,24 +230,13 @@ setVariableM "dzslides-core" dzcore vars else return vars) - templ <- case optTemplate opts of- _ | not standalone -> return Nothing- Nothing -> Just <$> compileDefaultTemplate format- Just tp -> do- -- strip off extensions- let tp' = case takeExtension tp of- "" -> tp <.> T.unpack format- _ -> tp- res <- getTemplate tp' >>= runWithPartials . compileTemplate tp'- case res of- Left e -> throwError $ PandocTemplateError $ T.pack e- Right t -> return $ Just t-- let writerOpts = def {- writerTemplate = templ+ let writerOpts = WriterOptions+ { writerTemplate = mtemplate , writerVariables = variables , writerTabStop = optTabStop opts , writerTableOfContents = optTableOfContents opts+ , writerListOfFigures = optListOfFigures opts+ , writerListOfTables = optListOfTables opts , writerHTMLMathMethod = optHTMLMathMethod opts , writerIncremental = optIncremental opts , writerCiteMethod = optCiteMethod opts@@ -213,6 +246,8 @@ , writerExtensions = writerExts , writerReferenceLinks = optReferenceLinks opts , writerReferenceLocation = optReferenceLocation opts+ , writerFigureCaptionPosition = optFigureCaptionPosition opts+ , writerTableCaptionPosition = optTableCaptionPosition opts , writerDpi = optDpi opts , writerWrapText = optWrap opts , writerColumns = optColumns opts@@ -220,39 +255,48 @@ , 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 , writerEpubMetadata = epubMetadata , writerEpubFonts = optEpubFonts opts- , writerEpubChapterLevel = optEpubChapterLevel opts+ , writerEpubTitlePage = optEpubTitlePage opts+ , writerSplitLevel = optSplitLevel opts+ , writerChunkTemplate = maybe (PathTemplate "%s-%i.html")+ PathTemplate+ (optChunkTemplate opts) , writerTOCDepth = optTOCDepth opts , writerReferenceDoc = optReferenceDoc opts , writerSyntaxMap = syntaxMap , writerPreferAscii = optAscii opts+ , writerLinkImages = optLinkImages opts } return $ OutputSettings { outputFormat = format , outputWriter = writer- , outputWriterName = writerName , outputWriterOptions = writerOpts , outputPdfProgram = maybePdfProg } -baseWriterName :: T.Text -> T.Text-baseWriterName = T.takeWhile (\c -> c /= '+' && c /= '-')+-- | Set text value in text context unless it is already set.+setVariableM :: Monad m+ => T.Text -> T.Text -> Context T.Text -> m (Context T.Text)+setVariableM key val (Context ctx) = return $ Context $ M.alter go key ctx+ where go Nothing = Just $ toVal val+ go (Just x) = Just x -pdfWriterAndProg :: Maybe T.Text -- ^ user-specified writer name+pdfWriterAndProg :: Maybe FlavoredFormat -- ^ user-specified format -> Maybe String -- ^ user-specified pdf-engine- -> IO (T.Text, Maybe String) -- ^ IO (writerName, maybePdfEngineProg)+ -> IO (FlavoredFormat, Maybe String) -- ^ format, pdf-engine pdfWriterAndProg mWriter mEngine = case go mWriter mEngine of Right (writ, prog) -> return (writ, Just prog) Left err -> liftIO $ E.throwIO $ PandocAppError err where- go Nothing Nothing = Right ("latex", "pdflatex")+ go Nothing Nothing = Right+ (FlavoredFormat "latex" mempty, "pdflatex") go (Just writer) Nothing = (writer,) <$> engineForWriter writer go Nothing (Just engine) = (,engine) <$> writerForEngine (takeBaseName engine) go (Just writer) (Just engine) | isCustomWriter writer =@@ -260,24 +304,40 @@ -- what they are doing. Right (writer, engine) go (Just writer) (Just engine) =- case find (== (baseWriterName writer, takeBaseName engine)) engines of+ case find (== (formatName writer, takeBaseName engine)) engines of Just _ -> Right (writer, engine) Nothing -> Left $ "pdf-engine " <> T.pack engine <>- " is not compatible with output format " <> writer+ " is not compatible with output format " <>+ formatName writer writerForEngine eng = case [f | (f,e) <- engines, e == eng] of- fmt : _ -> Right fmt+ fmt : _ -> Right (FlavoredFormat fmt mempty) [] -> Left $ "pdf-engine " <> T.pack eng <> " not known" - engineForWriter "pdf" = Left "pdf writer"- engineForWriter w = case [e | (f,e) <- engines, f == baseWriterName w] of+ engineForWriter (FlavoredFormat "pdf" _) = Left "pdf writer"+ engineForWriter w = case [e | (f,e) <- engines, f == formatName w] of eng : _ -> Right eng [] -> Left $- "cannot produce pdf output from " <> w+ "cannot produce pdf output from " <>+ formatName w - isCustomWriter w = ".lua" `T.isSuffixOf` w+ isCustomWriter w = ".lua" `T.isSuffixOf` formatName w -isTextFormat :: T.Text -> Bool-isTextFormat s =- s `notElem` ["odt","docx","epub2","epub3","epub","pptx","pdf"]+isBinaryFormat :: T.Text -> Bool+isBinaryFormat s =+ s `elem` ["odt","docx","epub2","epub3","epub","pptx","pdf","chunkedhtml"]++-- Like 'sandbox', but computes the list of files to preserve from+-- 'Opt'.+sandbox' :: (PandocMonad m, MonadIO m) => Opt -> PandocPure a -> m a+sandbox' opts = sandbox sandboxedFiles+ where+ sandboxedFiles = catMaybes [ optReferenceDoc opts+ , optEpubMetadata opts+ , optEpubCoverImage opts+ , optCSL opts+ , optCitationAbbreviations opts+ ] +++ optEpubFonts opts +++ optBibliography opts
@@ -1,6 +1,6 @@ {- | Module : Text.Pandoc.Asciify- Copyright : Copyright (C) 2013-2022 John MacFarlane+ Copyright : Copyright (C) 2013-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -1,6 +1,6 @@ {- | Module : Text.Pandoc.CSS-Copyright : © 2006-2022 John MacFarlane <jgm@berkeley.edu>,+Copyright : © 2006-2024 John MacFarlane <jgm@berkeley.edu>, 2015-2016 Mauro Bieg, 2015 Ophir Lifshitz <hangfromthefloor@gmail.com> License : GNU GPL, version 2 or above@@ -22,8 +22,9 @@ import Data.Maybe (mapMaybe, listToMaybe) import Data.Text (Text, pack) import Text.Pandoc.Shared (trim)-import Text.Parsec-import Text.Parsec.Text+import Text.Pandoc.Parsing++type Parser = Parsec Text () ruleParser :: Parser (Text, Text) ruleParser = do
@@ -1,6 +1,6 @@ {- | Module : Text.Pandoc.CSV- Copyright : Copyright (C) 2017-2022 John MacFarlane <jgm@berkeley.edu>+ Copyright : Copyright (C) 2017-2024 John MacFarlane <jgm@berkeley.edu> License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha@@ -19,9 +19,10 @@ import Control.Monad (unless, void, mzero) import Data.Text (Text) import qualified Data.Text as T-import Text.Parsec-import Text.Parsec.Text (Parser)+import Text.Pandoc.Parsing hiding (escaped) +type Parser = Parsec Text ()+ data CSVOptions = CSVOptions{ csvDelim :: Char , csvQuote :: Maybe Char@@ -79,7 +80,10 @@ pCSVDelim :: CSVOptions -> Parser () pCSVDelim opts = do char (csvDelim opts)- unless (csvKeepSpace opts) $ skipMany (oneOf " \t")+ let sp = case csvDelim opts of+ '\t' -> char ' '+ _ -> oneOf " \t"+ unless (csvKeepSpace opts) $ skipMany sp endline :: Parser () endline = do
@@ -0,0 +1,59 @@+{- |+ Module : Text.Pandoc.Char+ Copyright : Copyright (C) 2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Character functions not defined in Data.Char.+-}+module Text.Pandoc.Char ( isCJK )+where++-- | Returns True if character is CJK. Matches anything in:+--+-- * CJK Unified Ideographs Basic Block: U+4E00 - U+9FFF+-- * CJK Unified Ideographs Extension A: U+3400 - U+4DBF+-- * CJK Unified Ideographs Extension B: U+20000 - U+2A6DF+-- * CJK Unified Ideographs Extension C: U+2A700 - U+2B73F+-- * CJK Unified Ideographs Extension D: U+2B740 - U+2B81F+-- * CJK Compatibility Ideographs: U+F900 - U+FAFF+-- * CJK Compatibility Ideographs Supplement: U+2F800 - U+2FA1F+isCJK :: Char -> Bool+isCJK c =+ c >= '\x4e00' &&+ ( (c >= '\x2e80' && c <= '\x2eff') -- CJK Radicals Supplement+ || (c >= '\x2f00' && c <= '\x2fdf') -- Kangxi Radicals+ || (c >= '\x2ff0' && c <= '\x2fff') -- Ideographic Description Characters+ || (c >= '\x3000' && c <= '\x303f') -- JK Symbols and Punctuation+ || (c >= '\x3040' && c <= '\x309f') -- Hiragana+ || (c >= '\x30a0' && c <= '\x30ff') -- Katakana+ || (c >= '\x3100' && c <= '\x312f') -- Bopomofo+ || (c >= '\x3130' && c <= '\x318f') -- Kanbun+ || (c >= '\x3190' && c <= '\x319f') -- Kanbun+ || (c >= '\x31c0' && c <= '\x31ef') -- CJK Strokes+ || (c >= '\x31f0' && c <= '\x31ff') -- Katakana Phonetic Extensions+ || (c >= '\x3200' && c <= '\x32ff') -- Enclosed CJK Letters & Months+ || (c >= '\x3300' && c <= '\x33ff') -- CJK Compatibility+ || (c >= '\x3400' && c <= '\x4dbf') -- CJK Unified Ideographs Extension A+ || (c >= '\x4e00' && c <= '\x9fff') -- CJK Unified Ideographs+ || (c >= '\xa000' && c <= '\xa48f') -- Yi Syllables+ || (c >= '\xa490' && c <= '\xa4cf') -- Yi Radicals+ || (c >= '\xf900' && c <= '\xfaff') -- CJK Compatibility Ideographs+ || (c >= '\xfe10' && c <= '\xfe1f') -- Vertical forms+ || (c >= '\xfe30' && c <= '\xfe4f') -- CJK Compatibility Forms+ || (c >= '\xFE50' && c <= '\xFE6F') -- Small Form Variants+ || (c >= '\xFF00' && c <= '\xFFEE') -- Halfwidth and Fullwidth Forms+ || (c >= '\x1B000' && c <= '\x1B0FF') -- Kana Supplement+ || (c >= '\x1B100' && c <= '\x1B12F') -- Kana Extended-A+ || (c >= '\x1B130' && c <= '\x1B16F') -- Small Kana Extension+ || (c >= '\x20000' && c <= '\x2A6DF') -- CJK Unified Ideographs Extension B+ || (c >= '\x2A700' && c <= '\x2B73F') -- CJK Unified Ideographs Extension C+ || (c >= '\x2B740' && c <= '\x2B81F') -- CJK Unified Ideographs Extension D+ || (c >= '\x2B820' && c <= '\x2CEAF') -- CJK Unified Ideographs Extension E+ || (c >= '\x2CEB0' && c <= '\x2EBEF') -- CJK Unified Ideographs Extension F+ || (c >= '\x2F800' && c <= '\x2FA1F') -- CJK Compatibility Ideographs Supp+ || (c >= '\x30000' && c <= '\x3134F') -- CJK Unified Ideographs Exten+ )
@@ -0,0 +1,444 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{- |+ Module : Text.Pandoc.Chunks+ Copyright : Copyright (C) 2022-2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Functions and types for splitting a Pandoc into subdocuments,+e.g. for conversion into a set of HTML pages.+-}+module Text.Pandoc.Chunks+ ( Chunk(..)+ , ChunkedDoc(..)+ , PathTemplate(..)+ , splitIntoChunks+ , toTOCTree+ , tocToList+ , SecInfo(..)+ ) where++import Text.Pandoc.Definition+import Text.Pandoc.Shared (makeSections, stringify, inlineListToIdentifier,+ tshow, uniqueIdent)+import Text.Pandoc.Walk (Walkable(..), query)+import Data.Aeson (FromJSON, ToJSON)+import Data.Text (Text)+import Text.Printf (printf)+import Data.Maybe (fromMaybe, isNothing)+import qualified Data.Map as M+import qualified Data.Text as T+import Data.String (IsString)+import GHC.Generics (Generic)+import Text.HTML.TagSoup (Tag (TagOpen), fromAttrib, parseTags)+import Data.Tree (Tree(..))+import Data.Data (Data)+import Data.Typeable (Typeable)+import qualified Data.Set as Set+import Control.Monad.State++-- | Split 'Pandoc' into 'Chunk's, e.g. for conversion into+-- a set of HTML pages or EPUB chapters.+splitIntoChunks :: PathTemplate -- ^ Template for filepath+ -> Bool -- ^ Number sections+ -> Maybe Int -- ^ Base heading level+ -> Int -- ^ Chunk level -- level of section to split at+ -> Pandoc+ -> ChunkedDoc+splitIntoChunks pathTemplate numberSections mbBaseLevel+ chunklev (Pandoc meta blocks) =+ addNav .+ fixInternalReferences .+ walk rmNavAttrs $+ ChunkedDoc{ chunkedMeta = meta+ , chunkedChunks = chunks+ , chunkedTOC = tocTree }+ where+ tocTree = fixTOCTreePaths chunks $ toTOCTree sections+ chunks = makeChunks chunklev pathTemplate meta $ sections+ sections = ensureIds $ makeSections numberSections mbBaseLevel blocks++-- The TOC won't work if we don't have unique identifiers for all sections.+ensureIds :: [Block] -> [Block]+ensureIds bs = evalState (walkM go bs) mempty+ where+ go :: Block -> State (Set.Set Text) Block+ go b@(Div (ident,"section":cls,kvs) bs'@(Header _ _ ils : _))+ | T.null ident+ = do ids <- get+ let newid = uniqueIdent mempty ils ids+ modify $ Set.insert newid+ pure $ Div (newid,"section":cls,kvs) bs'+ | otherwise+ = do modify $ Set.insert ident+ pure b+ go b = pure b++-- | Add chunkNext, chunkPrev, chunkUp+addNav :: ChunkedDoc -> ChunkedDoc+addNav chunkedDoc =+ chunkedDoc{ chunkedChunks =+ addNext . addPrev . addUp $ chunkedChunks chunkedDoc }++addUp :: [Chunk] -> [Chunk]+addUp (c : d : ds)+ | chunkLevel c < chunkLevel d+ = c : addUp (d{ chunkUp = Just c } : ds)+ | chunkLevel c == chunkLevel d+ = c : addUp (d{ chunkUp = chunkUp c} : ds)+addUp (c:cs) = c : addUp cs+addUp [] = []++addNext :: [Chunk] -> [Chunk]+addNext cs = zipWith go cs (map Just (drop 1 cs) ++ [Nothing])+ where+ go c nxt = c{ chunkNext = nxt }++addPrev :: [Chunk] -> [Chunk]+addPrev cs = zipWith go cs (Nothing : map Just cs)+ where+ go c prev = c{ chunkPrev = prev }++-- | Fix internal references so they point to the path of the chunk.+fixInternalReferences :: ChunkedDoc -> ChunkedDoc+fixInternalReferences chunkedDoc = walk fixInternalRefs chunkedDoc+ where+ fixInternalRefs :: Inline -> Inline+ fixInternalRefs il@(Link attr ils (src,tit))+ = case T.uncons src of+ Just ('#', ident) -> Link attr ils (src', tit)+ where src' = case M.lookup ident refMap of+ Just chunk -> T.pack (chunkPath chunk) <> src+ Nothing -> src+ _ -> il+ fixInternalRefs il = il++ refMap = foldr chunkToRefs mempty (chunkedChunks chunkedDoc)++ chunkToRefs chunk m =+ let idents = chunkId chunk : getIdents (chunkContents chunk)+ in foldr (\ident -> M.insert ident chunk) m idents++ getIdents bs = query getBlockIdent bs ++ query getInlineIdent bs++ getBlockIdent :: Block -> [Text]+ getBlockIdent (Div (ident, _, _) _)+ | not (T.null ident) = [ident]+ getBlockIdent (Header _ (ident, _, _) _)+ | not (T.null ident) = [ident]+ getBlockIdent (Table (ident,_,_) _ _ _ _ _)+ | not (T.null ident) = [ident]+ getBlockIdent (RawBlock fmt raw)+ | isHtmlFormat fmt+ = foldr (\tag ->+ case tag of+ TagOpen{} ->+ case fromAttrib "id" tag of+ "" -> id+ x -> (x:)+ _ -> id)+ [] (parseTags raw)+ getBlockIdent _ = []++ getInlineIdent :: Inline -> [Text]+ getInlineIdent (Span (ident, _, _) _)+ | not (T.null ident) = [ident]+ getInlineIdent (Link (ident, _, _) _ _)+ | not (T.null ident) = [ident]+ getInlineIdent (Image (ident, _, _) _ _)+ | not (T.null ident) = [ident]+ getInlineIdent (RawInline fmt raw)+ | isHtmlFormat fmt+ = foldr (\tag ->+ case tag of+ TagOpen{} ->+ case fromAttrib "id" tag of+ "" -> id+ x -> (x:)+ _ -> id)+ [] (parseTags raw)+ getInlineIdent _ = []++ isHtmlFormat :: Format -> Bool+ isHtmlFormat (Format "html") = True+ isHtmlFormat (Format "html4") = True+ isHtmlFormat (Format "html5") = True+ isHtmlFormat _ = False+++makeChunks :: Int -> PathTemplate -> Meta -> [Block] -> [Chunk]+makeChunks chunklev pathTemplate meta = secsToChunks 1+ where+ isChunkHeader :: Block -> Bool+ isChunkHeader (Div (_,"section":_,_) (Header n _ _:_)) = n <= chunklev+ isChunkHeader _ = False++ secsToChunks :: Int -> [Block] -> [Chunk]+ secsToChunks chunknum bs =+ case break isChunkHeader bs of+ ([], []) -> []+ ([], (d@(Div attr@(_,"section":_,_) (h@(Header lvl _ _) : bs')) : rest))+ | chunklev == lvl ->+ -- If the header is of the same level as chunks, create a chunk+ toChunk chunknum d :+ secsToChunks (chunknum + 1) rest+ | chunklev > lvl ->+ case break isChunkHeader bs' of+ (xs, ys) -> toChunk chunknum (Div attr (h:xs)) :+ secsToChunks (chunknum + 1) (ys ++ rest)+ (xs, ys) -> toChunk chunknum+ (Div ("",["preamble"],[]) xs) :+ secsToChunks (chunknum + 1) ys++ toChunk :: Int -> Block -> Chunk+ toChunk chunknum+ (Div (divid,"section":classes,kvs) (h@(Header lvl _ ils) : bs)) =+ Chunk+ { chunkHeading = ils+ , chunkId = divid+ , chunkLevel = lvl+ , chunkNumber = chunknum+ , chunkSectionNumber = secnum+ , chunkPath = chunkpath+ , chunkUp = Nothing+ , chunkNext = Nothing+ , chunkPrev = Nothing+ , chunkUnlisted = "unlisted" `elem` classes+ , chunkContents =+ [Div (divid,"section":classes,kvs') (h : bs)]+ }+ where kvs' = kvs ++ [("nav-path", T.pack chunkpath)]+ secnum = lookup "number" kvs+ chunkpath = resolvePathTemplate pathTemplate chunknum+ (stringify ils)+ divid+ (fromMaybe "" secnum)+ toChunk chunknum (Div ("",["preamble"],[]) bs) =+ Chunk+ { chunkHeading = docTitle meta+ , chunkId = chunkid+ , chunkLevel = 0+ , chunkNumber = chunknum+ , chunkSectionNumber = Nothing+ , chunkPath = chunkpath+ , chunkUp = Nothing+ , chunkPrev = Nothing+ , chunkNext = Nothing+ , chunkUnlisted = False+ , chunkContents = bs+ }+ where+ chunkpath = resolvePathTemplate pathTemplate chunknum+ (stringify (docTitle meta))+ chunkid+ "0"+ chunkid = inlineListToIdentifier mempty (docTitle meta) <>+ "-" <> tshow chunknum+ toChunk _ b = error $ "toChunk called on inappropriate block " <> show b+ -- should not happen+++-- Remove some attributes we added just to construct chunkNext etc.+rmNavAttrs :: Block -> Block+rmNavAttrs (Div (ident,classes,kvs) bs) =+ Div (ident,classes,filter (not . isNavAttr) kvs) bs+ where+ isNavAttr (k,_) = "nav-" `T.isPrefixOf` k+rmNavAttrs b = b++resolvePathTemplate :: PathTemplate+ -> Int -- ^ Chunk number+ -> Text -- ^ Stringified heading text+ -> Text -- ^ Section identifier+ -> Text -- ^ Section number+ -> FilePath+resolvePathTemplate (PathTemplate templ) chunknum headingText ident secnum =+ T.unpack .+ T.filter (\c -> c /= '/' && c /= '\\') .+ T.replace "%n" (T.pack $ printf "%03d" chunknum) .+ T.replace "%s" secnum .+ T.replace "%h" headingText .+ T.replace "%i" ident $+ templ++-- | A 'PathTemplate' is a FilePath in which certain codes+-- will be substituted with information from a 'Chunk'.+-- @%n@ will be replaced with the chunk number+-- (padded with leading 0s to 3 digits),+-- @%s@ with the section number of the heading,+-- @%h@ with the (stringified) heading text,+-- @%i@ with the section identifier.+-- For example, @"section-%s-%i.html"@ might be resolved to+-- @"section-1.2-introduction.html"@.+newtype PathTemplate =+ PathTemplate { unPathTemplate :: Text }+ deriving (Show, IsString, Data, Typeable, Generic, ToJSON, FromJSON)++-- | A part of a document (typically a chapter or section, or+-- the part of a section before its subsections).+data Chunk =+ Chunk+ { chunkHeading :: [Inline]+ , chunkId :: Text+ , chunkLevel :: Int+ , chunkNumber :: Int+ , chunkSectionNumber :: Maybe Text+ , chunkPath :: FilePath+ , chunkUp :: Maybe Chunk+ , chunkPrev :: Maybe Chunk+ , chunkNext :: Maybe Chunk+ , chunkUnlisted :: Bool+ , chunkContents :: [Block]+ }+ deriving (Show, Eq, Generic)++instance Walkable Inline Chunk where+ query f chunk = query f (chunkContents chunk)+ walk f chunk = chunk{ chunkContents = walk f (chunkContents chunk) }+ walkM f chunk = do+ contents <- walkM f (chunkContents chunk)+ return chunk{ chunkContents = contents }++instance Walkable Block Chunk where+ query f chunk = query f (chunkContents chunk)+ walk f chunk = chunk{ chunkContents = walk f (chunkContents chunk) }+ walkM f chunk = do+ contents <- walkM f (chunkContents chunk)+ return chunk{ chunkContents = contents }++-- | A 'Pandoc' broken into 'Chunk's for writing to separate files.+data ChunkedDoc =+ ChunkedDoc+ { chunkedMeta :: Meta+ , chunkedTOC :: Tree SecInfo+ , chunkedChunks :: [Chunk]+ } deriving (Show, Eq, Generic)++instance Walkable Inline ChunkedDoc where+ query f doc = query f (chunkedChunks doc) <> query f (chunkedMeta doc)+ walk f doc = doc{ chunkedMeta = walk f (chunkedMeta doc)+ , chunkedChunks = walk f (chunkedChunks doc)+ }+ walkM f doc = do+ meta' <- walkM f (chunkedMeta doc)+ chunks' <- walkM f (chunkedChunks doc)+ return $ doc{ chunkedMeta = meta'+ , chunkedChunks = chunks' }++instance Walkable Block ChunkedDoc where+ query f doc = query f (chunkedChunks doc) <> query f (chunkedMeta doc)+ walk f doc = doc{ chunkedMeta = walk f (chunkedMeta doc)+ , chunkedChunks = walk f (chunkedChunks doc)+ }+ walkM f doc = do+ meta' <- walkM f (chunkedMeta doc)+ chunks' <- walkM f (chunkedChunks doc)+ return $ doc{ chunkedMeta = meta'+ , chunkedChunks = chunks' }++-- | Data for a section in a hierarchical document.+data SecInfo =+ SecInfo+ { secTitle :: [Inline]+ , secNumber :: Maybe Text+ , secId :: Text+ , secPath :: Text -- including fragment, e.g. chunk001.html#section-one+ , secLevel :: Int+ } deriving (Show, Eq, Generic)++instance Walkable Inline SecInfo where+ query f sec = query f (secTitle sec)+ walk f sec = sec{ secTitle = walk f (secTitle sec) }+ walkM f sec = do+ st <- walkM f (secTitle sec)+ return sec{ secTitle = st }++-- | Create tree of sections with titles, links, and numbers,+-- in a form that can be turned into a table of contents.+-- Presupposes that the '[Block]' is the output of 'makeSections'.+toTOCTree :: [Block] -> Tree SecInfo+toTOCTree =+ Node SecInfo{ secTitle = []+ , secNumber = Nothing+ , secId = ""+ , secPath = ""+ , secLevel = 0 } . foldr go []+ where+ go :: Block -> [Tree SecInfo] -> [Tree SecInfo]+ go (Div (ident,_,_) (Header lev (_,classes,kvs) ils : subsecs))+ | not (isNothing (lookup "number" kvs) && "unlisted" `elem` classes)+ = ((Node SecInfo{ secTitle = ils+ , secNumber = lookup "number" kvs+ , secId = ident+ , secPath = ""+ , secLevel = lev } (foldr go [] subsecs)) :)+ go (Div _ [d@Div{}]) = go d -- #8402+ go _ = id++-- | Adjusts paths in the TOC tree generated by 'toTOCTree'+-- to reflect division into Chunks.+fixTOCTreePaths :: [Chunk] -> Tree SecInfo -> Tree SecInfo+fixTOCTreePaths chunks = go ""+ where+ idMap = foldr (\chunk m ->+ let ids = filter (not . T.null)+ (chunkId chunk :+ query getIds (chunkContents chunk))+ in foldr (\i -> M.insert i (chunkPath chunk)) m ids)+ mempty chunks+ getIds :: Block -> [Text]+ getIds (Div (i,"section":_,_) _) = [i]+ getIds _ = []+ go :: FilePath -> Tree SecInfo -> Tree SecInfo+ go fp (Node secinfo subtrees) =+ let newpath = M.lookup (secId secinfo) idMap+ fp' = fromMaybe fp newpath+ fragment = "#" <> secId secinfo+ in Node secinfo{ secPath = T.pack fp' <> fragment }+ (map (go fp') subtrees)++-- | Creates a TOC link to the respective document section.+tocEntryToLink :: Bool -> SecInfo -> [Inline]+tocEntryToLink includeNumbers secinfo = headerLink+ where+ addNumber = case secNumber secinfo of+ Just num | includeNumbers+ -> (Span ("",["toc-section-number"],[])+ [Str num] :) . (Space :)+ _ -> id+ clean (Link _ xs _) = xs+ clean (Note _) = []+ clean x = [x]+ anchor = if T.null (secPath secinfo)+ then if T.null (secId secinfo)+ then ""+ else "#" <> secId secinfo+ else secPath secinfo+ headerText = addNumber $ walk (concatMap clean) (secTitle secinfo)+ headerLink = if T.null anchor+ then headerText+ else [Link ((if T.null (secId secinfo)+ then ""+ else "toc-" <> secId secinfo), [], [])+ headerText (anchor, "")]++-- | Generate a table of contents of the given depth.+tocToList :: Bool -> Int -> Tree SecInfo -> Block+tocToList includeNumbers tocDepth (Node _ subtrees) = BulletList (toItems subtrees)+ where+ toItems = map go . filter isBelowTocDepth+ isBelowTocDepth (Node sec _) = secLevel sec <= tocDepth+ go (Node secinfo xs) =+ Plain (tocEntryToLink includeNumbers secinfo) :+ case toItems xs of+ [] -> []+ ys -> [BulletList ys]
@@ -16,6 +16,7 @@ LocatorInfo(..)) import Text.Pandoc.Citeproc.CslJson (cslJsonToReferences) import Text.Pandoc.Citeproc.BibTeX (readBibtexString, Variant(..))+import Text.Pandoc.MIME (MimeType) import Text.Pandoc.Readers.RIS (readRIS) import Text.Pandoc.Citeproc.MetaValue (metaValueToReference, metaValueToText) import Text.Pandoc.Readers.Markdown (yamlToRefs)@@ -23,13 +24,14 @@ import qualified Text.Pandoc.Builder as B import Text.Pandoc.Definition as Pandoc import Text.Pandoc.Class (PandocMonad(..), getResourcePath, getUserDataDir,- fetchItem, readDataFile, report, setResourcePath)+ fetchItem, report, setResourcePath, toTextM)+import Text.Pandoc.Data (readDataFile) import Text.Pandoc.Error (PandocError(..)) import Text.Pandoc.Extensions (pandocExtensions) import Text.Pandoc.Logging (LogMessage(..)) import Text.Pandoc.Options (ReaderOptions(..))-import Text.Pandoc.Shared (stringify, ordNub, tshow)-import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Shared (stringify, tshow, makeSections)+import Data.Containers.ListUtils (nubOrd) import Text.Pandoc.Walk (query, walk, walkM) import Control.Applicative ((<|>)) import Control.Monad.Except (catchError, throwError)@@ -74,7 +76,9 @@ let citations = getCitations locale otherIdsMap $ Pandoc meta' bs - let linkCites = maybe False truish $ lookupMeta "link-citations" meta+ let linkCites = maybe False truish (lookupMeta "link-citations" meta) &&+ -- don't link citations if no bibliography to link to:+ not (maybe False truish (lookupMeta "suppress-bibliography" meta)) let linkBib = maybe True truish $ lookupMeta "link-bibliography" meta let opts = defaultCiteprocOptions{ linkCitations = linkCites , linkBibliography = linkBib }@@ -85,7 +89,7 @@ "csl-bib-body" : ["hanging-indent" | styleHangingIndent sopts] let refkvs = (case styleEntrySpacing sopts of- Just es | es > 0 -> (("entry-spacing",T.pack $ show es):)+ Just es -> (("entry-spacing",T.pack $ show es):) _ -> id) . (case styleLineSpacing sopts of Just ls | ls > 1 -> (("line-spacing",T.pack $ show ls):)@@ -140,7 +144,8 @@ let getCslDefault = readDataFile "default.csl" - cslContents <- UTF8.toText <$> maybe getCslDefault (getFile ".csl") cslfile+ cslContents <- maybe getCslDefault (getFile ".csl") cslfile >>=+ toTextM (maybe mempty T.unpack cslfile) let abbrevFile = lookupMeta "citation-abbreviations" meta >>= metaValueToText @@ -158,8 +163,8 @@ let getParentStyle url = do -- first, try to retrieve the style locally, then use HTTP. let basename = T.takeWhileEnd (/='/') url- UTF8.toText <$>- catchError (getFile ".csl" basename) (\_ -> fst <$> fetchItem url)+ catchError (getFile ".csl" basename) (\_ -> fst <$> fetchItem url)+ >>= toTextM (T.unpack url) styleRes <- Citeproc.parseStyle getParentStyle cslContents case styleRes of@@ -235,8 +240,8 @@ getRefsFromBib :: PandocMonad m => Locale -> (Text -> Bool) -> Text -> m [Reference Inlines] getRefsFromBib locale idpred fp = do- (raw, _) <- fetchItem fp- case formatFromExtension (T.unpack fp) of+ (raw, mt) <- fetchItem fp+ case getBibliographyFormat (T.unpack fp) mt of Just f -> getRefs locale f idpred (Just fp) raw Nothing -> throwError $ PandocAppError $ "Could not determine bibliography format for " <> fp@@ -251,13 +256,14 @@ getRefs locale format idpred mbfp raw = do let err' = throwError . PandocBibliographyError (fromMaybe mempty mbfp)+ let fp = maybe mempty T.unpack mbfp case format of Format_bibtex ->- either (err' . tshow) return .- readBibtexString Bibtex locale idpred . UTF8.toText $ raw+ toTextM fp raw >>=+ either (err' . tshow) return . readBibtexString Bibtex locale idpred Format_biblatex ->- either (err' . tshow) return .- readBibtexString Biblatex locale idpred . UTF8.toText $ raw+ toTextM fp raw >>=+ either (err' . tshow) return . readBibtexString Biblatex locale idpred Format_json -> either (err' . T.pack) (return . filter (idpred . unItemId . referenceId)) .@@ -269,7 +275,7 @@ raw return $ mapMaybe metaValueToReference rs Format_ris -> do- Pandoc meta _ <- readRIS def (UTF8.toText raw)+ Pandoc meta _ <- toTextM fp raw >>= readRIS def case lookupMeta "references" meta of Just (MetaList rs) -> return $ mapMaybe metaValueToReference rs _ -> return []@@ -289,10 +295,24 @@ -> M.Map Text ItemId -> Pandoc -> [Citeproc.Citation Inlines]-getCitations locale otherIdsMap = Foldable.toList . query getCitation+getCitations locale otherIdsMap (Pandoc meta blocks) =+ Foldable.toList (query getCitation meta <>+ foldMap handleBlock (makeSections False Nothing blocks)) where+ handleBlock :: Block -> Seq.Seq (Citeproc.Citation Inlines)+ handleBlock b@(Div (_,cls,_) _)+ | "section" `elem` cls+ , "reset-citation-positions" `elem` cls =+ case Seq.viewl (query getCitation b) of+ x Seq.:< xs -> addResetTo x Seq.<| xs+ Seq.EmptyL -> mempty+ handleBlock b = query getCitation b+ addResetTo citation = citation{ Citeproc.citationResetPosition = True } getCitation (Cite cs _fallback) = Seq.singleton $ Citeproc.Citation { Citeproc.citationId = Nothing+ , Citeproc.citationResetPosition = False+ , Citeproc.citationPrefix = Nothing+ , Citeproc.citationSuffix = Nothing , Citeproc.citationNoteNumber = case cs of [] -> Nothing@@ -312,7 +332,7 @@ where locmap = toLocatorMap locale go c =- let (mblocinfo, suffix) = parseLocator locmap (citationSuffix c)+ let (mblocinfo, suffix) = parseLocator locmap (Pandoc.citationSuffix c) cit = CitationItem { citationItemId = fromMaybe (ItemId $ Pandoc.citationId c)@@ -320,7 +340,7 @@ , citationItemLabel = locatorLabel <$> mblocinfo , citationItemLocator = locatorLoc <$> mblocinfo , citationItemType = NormalCite- , citationItemPrefix = case citationPrefix c of+ , citationItemPrefix = case Pandoc.citationPrefix c of [] -> Nothing ils -> Just $ B.fromList ils <> B.space@@ -352,25 +372,36 @@ | Format_ris deriving (Show, Eq, Ord) -formatFromExtension :: FilePath -> Maybe BibFormat-formatFromExtension fp = case dropWhile (== '.') $ takeExtension fp of- "biblatex" -> Just Format_biblatex- "bibtex" -> Just Format_bibtex- "bib" -> Just Format_biblatex- "json" -> Just Format_json- "yaml" -> Just Format_yaml- "yml" -> Just Format_yaml- "ris" -> Just Format_ris- _ -> Nothing-+getBibliographyFormat :: FilePath -> Maybe MimeType -> Maybe BibFormat+getBibliographyFormat fp mbmime = do+ let ext = takeExtension fp+ case ext of+ ".biblatex" -> pure Format_biblatex+ ".bibtex" -> pure Format_bibtex+ ".bib" -> pure Format_biblatex+ ".json" -> pure Format_json+ ".yaml" -> pure Format_yaml+ ".yml" -> pure Format_yaml+ ".ris" -> pure Format_ris+ _ -> do+ mime <- mbmime+ case T.takeWhile (/= ';') mime of+ "application/x-bibtex" -> pure Format_biblatex+ "application/x-reseach-info-systems" -> pure Format_ris+ "application/vnd.citationstyles.csl+json" -> pure Format_json+ "application/json" -> pure Format_json+ "application/x-yaml" -> pure Format_yaml+ "text/x-yaml" -> pure Format_yaml+ "text/yaml" -> pure Format_yaml+ _ -> Nothing isNote :: Inline -> Bool-isNote (Cite _ [Note _]) = True- -- the following allows citation styles that are "in-text" but use superscript- -- references to be treated as if they are "notes" for the purposes of moving- -- the citations after trailing punctuation (see <https://github.com/jgm/pandoc-citeproc/issues/382>):-isNote (Cite _ [Superscript _]) = True-isNote _ = False+isNote (Note _) = True+-- the following allows citation styles that are "in-text" but use superscript+-- references to be treated as if they are "notes" for the purposes of moving+-- the citations after trailing punctuation (see <https://github.com/jgm/pandoc-citeproc/issues/382>):+isNote (Superscript _) = True+isNote _ = False isSpacy :: Inline -> Bool isSpacy Space = True@@ -388,34 +419,35 @@ mvPunct moveNotes locale (x : xs) | isSpacy x = x : mvPunct moveNotes locale xs -- 'x [^1],' -> 'x,[^1]'-mvPunct moveNotes locale (q : s : x : ys)+mvPunct moveNotes locale (q : s : x@(Cite _ [il]) : ys) | isSpacy s- , isNote x- = let spunct = T.takeWhile isPunctuation $ stringify ys+ , isNote il+ = 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)- | not (null ils)- , isNote (last ils)+mvPunct moveNotes locale (Cite cs ils@(_:_) : ys)+ | isNote (last ils) , 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)))-mvPunct moveNotes locale (s : x : ys) | isSpacy s, isNote x =- x : mvPunct moveNotes locale ys+ (B.toList (dropTextWhile isPunct (B.fromList ys)))+mvPunct moveNotes locale (s : x@(Cite _ [il]) : ys)+ | isSpacy s+ , isNote il+ = x : mvPunct moveNotes locale ys mvPunct moveNotes locale (s : x@(Cite _ (Superscript _ : _)) : ys) | isSpacy s = x : mvPunct moveNotes locale ys mvPunct moveNotes locale (Cite cs ils : Str "." : ys)@@ -424,13 +456,18 @@ mvPunct moveNotes locale (x:xs) = x : mvPunct moveNotes locale xs mvPunct _ _ [] = [] +-- We don't treat an em-dash or en-dash as punctuation here, because we don't+-- want notes and quotes to move around them.+isPunct :: Char -> Bool+isPunct c = isPunctuation c && c /= '\x2014' && c /= '\x2013'+ endWithPunct :: Bool -> [Inline] -> Bool endWithPunct _ [] = False endWithPunct onlyFinal xs@(_:_) = case reverse (T.unpack $ stringify xs) of [] -> True -- covers .), .", etc.:- (d:c:_) | isPunctuation d+ (d:c:_) | isPunct d && not onlyFinal && isEndPunct c -> True (c:_) | isEndPunct c -> True@@ -460,13 +497,16 @@ -- 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) =- if isRefRemove meta- then Pandoc meta bs- else case runState (walkM go (Pandoc meta bs)) False of+ case lookupMeta "suppress-bibliography" meta of+ Just x | truish x -> Pandoc meta bs+ _ -> case runState (walkM go (Pandoc meta bs)) False of (d', True) -> d' (Pandoc meta' bs', False) -> Pandoc meta' $@@ -485,12 +525,13 @@ refDiv = Div ("refs", refclasses, refkvs) refs addUnNumbered cs = "unnumbered" : [c | c <- cs, c /= "unnumbered"] go :: Block -> State Bool Block- go (Div ("refs",cs,kvs) xs) = do- put True- -- refHeader isn't used if you have an explicit references div- let cs' = ordNub $ cs ++ refclasses- let kvs' = ordNub $ 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]@@ -502,10 +543,6 @@ Just (MetaBlocks [Para ils]) -> Just ils _ -> Nothing -isRefRemove :: Meta -> Bool-isRefRemove meta =- maybe False truish $ lookupMeta "suppress-bibliography" meta- legacyDateRanges :: Reference Inlines -> Reference Inlines legacyDateRanges ref = ref{ referenceVariables = M.map go $ referenceVariables ref }@@ -555,7 +592,8 @@ = Cite (c:cs) (addCommas (needsPeriod zs) ils) : addParens zs | otherwise- = Cite (c:cs) (concatMap noteInParens ils) : addParens zs+ = Cite (c:cs) (dropWhile (== Space) (concatMap noteInParens ils))+ : addParens zs addParens (x:xs) = x : addParens xs removeNotes (Span ("",["csl-note"],[]) ils) = Span ("",[],[]) ils
@@ -11,7 +11,8 @@ -- License : BSD-style (see LICENSE) -- -- Maintainer : John MacFarlane <fiddlosopher@gmail.com>--- Stability : unstable-- Portability : unportable+-- Stability : unstable+-- Portability : portable -- ----------------------------------------------------------------------------- @@ -19,7 +20,6 @@ ( Variant(..) , readBibtexString , writeBibtexString- , toName ) where @@ -35,8 +35,10 @@ import qualified Text.Pandoc.Walk as Walk import Citeproc.Types import Citeproc.Pandoc ()+import Data.List.Split (splitOn) import Text.Pandoc.Citeproc.Util (toIETF, splitStrWhen) import Text.Pandoc.Citeproc.Data (biblatexStringMap)+import Text.Pandoc.Citeproc.Name (toName, NameOpts(..), emptyName) import Data.Default import Data.Text (Text) import qualified Data.Text as T@@ -44,17 +46,19 @@ import Data.Maybe import Text.Pandoc.Parsing hiding ((<|>), many) import Control.Applicative-import Data.List.Split (splitOn, splitWhen, wordsBy)-import Control.Monad.RWS hiding ((<>))+import Control.Monad ( guard, MonadPlus(..), void )+import Control.Monad.RWS ( asks, RWST, gets, modify, evalRWST ) import qualified Data.Sequence as Seq import Data.Char (isAlphaNum, isDigit, isLetter, isUpper, toLower, toUpper, isLower, isPunctuation, isSpace)-import Data.List (foldl', intercalate, intersperse)+import Data.List (intercalate, intersperse)+import qualified Data.List as L import Safe (readMay) import Text.Printf (printf) import Text.DocLayout (literal, hsep, nest, hang, Doc(..), braces, ($$), cr)+ data Variant = Bibtex | Biblatex deriving (Show, Eq, Ord) @@ -114,12 +118,13 @@ "manuscript" -> "unpublished" "graphic" | variant == Biblatex -> "artwork" "song" | variant == Biblatex -> "music"- "legal_case" | variant == Biblatex -> "jurisdictionN"+ "legal_case" | variant == Biblatex -> "jurisdiction" "legislation" | variant == Biblatex -> "legislation" "treaty" | variant == Biblatex -> "legal" "personal_communication" | variant == Biblatex -> "letter" "motion_picture" | variant == Biblatex -> "movie"- "review" | variant == Biblatex -> "review"+ "review" | variant == Biblatex -> "review"+ "software" | variant == Biblatex -> "software" _ -> "misc" mbSubtype =@@ -144,6 +149,8 @@ , "volumes" , "number" , "pages"+ , "pagetotal"+ , "version" , "date" , "eventdate" , "urldate"@@ -179,6 +186,9 @@ , "type" , "note" , "annote"+ , "url" -- not officially supported, but supported by+ -- some styles (#8287)+ , "doi" ] valToInlines (TextVal t) = B.text t@@ -199,7 +209,7 @@ renderName name = case nameLiteral name of- Just t -> B.text t+ Just t -> B.spanWith ("",[],[]) $ B.text t Nothing -> spacedMaybes [ nameNonDroppingParticle name , nameFamily name@@ -321,6 +331,8 @@ getContentsFor "year" = getVariable "issued" >>= getYear getContentsFor "month" = getVariable "issued" >>= getMonth getContentsFor "pages" = getVariable "page" >>= toLaTeX . valToInlines+ getContentsFor "pagetotal" = getVariable "number-of-pages"+ >>= toLaTeX . valToInlines getContentsFor "langid" = getVariable "language" >>= toLaTeX . valToInlines getContentsFor "number" = (getVariable "number" <|> getVariable "collection-number"@@ -345,7 +357,7 @@ -- a map of bibtex "string" macros type StringMap = Map.Map Text Text -type BibParser = Parser Sources (Lang, StringMap)+type BibParser = Parsec Sources (Lang, StringMap) data Item = Item{ identifier :: Text , sourcePos :: SourcePos@@ -385,7 +397,8 @@ <|> return Nothing modify $ \s -> s{ untitlecase = untitlecase s && case hyphenation of- Just x -> "en-" `T.isPrefixOf` x+ Just x ->+ "en-" `T.isPrefixOf` x || x == "en" _ -> True } @@ -404,9 +417,7 @@ -- names let getNameList' f = Just <$>- getNameList (("bibtex", case variant of- Bibtex -> "true"- Biblatex -> "false") : opts) f+ getNameList opts f author' <- getNameList' "author" <|> return Nothing containerAuthor' <- getNameList' "bookauthor" <|> return Nothing@@ -466,12 +477,12 @@ subtitle' <- (guard isPeriodical >> getTitle "issuesubtitle") <|> (guard hasMaintitle >> guard (not isChapterlike) >>- getTitle "mainsubtitle")+ getTitle "mainsubtitle" <|> return mempty) <|> getTitle "subtitle" <|> return mempty titleaddon' <- (guard hasMaintitle >> guard (not isChapterlike) >>- getTitle "maintitleaddon")+ getTitle "maintitleaddon" <|> return mempty) <|> getTitle "titleaddon" <|> return mempty @@ -793,14 +804,6 @@ latex :: Text -> Bib Inlines latex = fmap blocksToInlines . latex' . T.strip -type Options = [(Text, Text)]--parseOptions :: Text -> Options-parseOptions = map breakOpt . T.splitOn ","- where breakOpt x = case T.break (=='=') x of- (w,v) -> (T.toLower $ T.strip w,- T.toLower $ T.strip $ T.drop 1 v)- bibEntries :: BibParser [Item] bibEntries = do skipMany nonEntry@@ -820,7 +823,7 @@ bibComment = do cistring "comment" spaces'- void inBraces <|> bibSkip <|> return ()+ void inBraces bibPreamble :: BibParser () bibPreamble = do@@ -839,7 +842,7 @@ updateState (\(l,m) -> (l, Map.insert k v m)) return () -take1WhileP :: Monad m => (Char -> Bool) -> ParserT Sources u m Text+take1WhileP :: Monad m => (Char -> Bool) -> ParsecT Sources u m Text take1WhileP f = T.pack <$> many1 (satisfy f) inBraces :: BibParser Text@@ -847,9 +850,7 @@ char '{' res <- manyTill ( take1WhileP (\c -> c /= '{' && c /= '}' && c /= '\\')- <|> (char '\\' >> (do c <- oneOf "{}"- return $ T.pack ['\\',c])- <|> return "\\")+ <|> (char '\\' >> T.cons '\\' . T.singleton <$> anyChar) <|> (braced <$> inBraces) ) (char '}') return $ T.concat res@@ -861,9 +862,8 @@ inQuotes = do char '"' T.concat <$> manyTill- ( take1WhileP (\c -> c /= '{' && c /= '"' && c /= '\\' && c /= '%')+ ( take1WhileP (\c -> c /= '{' && c /= '"' && c /= '\\') <|> (char '\\' >> T.cons '\\' . T.singleton <$> anyChar)- <|> ("" <$ (char '%' >> anyLine)) <|> braced <$> inBraces ) (char '"') @@ -970,7 +970,7 @@ getPeriodicalTitle :: Text -> Bib Inlines getPeriodicalTitle f = do ils <- getField f- return ils+ return $ protectCase id ils protectCase :: (Inlines -> Inlines) -> (Inlines -> Inlines) protectCase f = Walk.walk unprotect . f . Walk.walk protect@@ -1117,7 +1117,7 @@ toLiteralList _ = mzero concatWith :: Char -> [Inlines] -> Inlines-concatWith sep = foldl' go mempty+concatWith sep = L.foldl' go mempty where go :: Inlines -> Inlines -> Inlines go accum s | s == mempty = accum@@ -1132,21 +1132,37 @@ B.space <> s -getNameList :: Options -> Text -> Bib [Name]+parseOptions :: Text -> [(Text, Text)]+parseOptions = map breakOpt . T.splitOn ","+ where breakOpt x = case T.break (=='=') x of+ (w,v) -> (T.toLower $ T.strip w,+ T.toLower $ T.strip $ T.drop 1 v)++optionSet :: Text -> [(Text, Text)] -> Bool+optionSet key opts = case lookup key opts of+ Just "true" -> True+ Just s -> s == mempty+ _ -> False++getNameList :: [(Text, Text)] -> Text -> Bib [Name] getNameList opts f = do fs <- asks fields case Map.lookup f fs of- Just x -> latexNames opts x+ Just x -> latexNames nameopts x Nothing -> notFound f+ where+ nameopts = NameOpts{+ nameOptsPrefixIsNonDroppingParticle = optionSet "useprefix" opts,+ nameOptsUseJuniorComma = optionSet "juniorcomma" opts} -toNameList :: Options -> [Block] -> Bib [Name]+toNameList :: NameOpts -> [Block] -> Bib [Name] toNameList opts [Para xs] = filter (/= emptyName) <$> mapM (toName opts . addSpaceAfterPeriod) (splitByAnd xs) toNameList opts [Plain xs] = toNameList opts [Para xs] toNameList _ _ = mzero -latexNames :: Options -> Text -> Bib [Name]+latexNames :: NameOpts -> Text -> Bib [Name] latexNames opts t = latex' (T.strip t) >>= toNameList opts -- see issue 392 for motivation. We want to treat@@ -1163,109 +1179,6 @@ = Str (T.singleton c):Str ".":Space:go (Str (T.singleton d):xs) go (x:xs) = x:go xs -emptyName :: Name-emptyName =- Name { nameFamily = Nothing- , nameGiven = Nothing- , nameDroppingParticle = Nothing- , nameNonDroppingParticle = Nothing- , nameSuffix = Nothing- , nameLiteral = Nothing- , nameCommaSuffix = False- , nameStaticOrdering = False- }--toName :: MonadPlus m => Options -> [Inline] -> m Name-toName _ [Str "others"] =- return emptyName{ nameLiteral = Just "others" }-toName _ [Span ("",[],[]) ils] = -- corporate author- return emptyName{ nameLiteral = Just $ stringify ils }- -- extended BibLaTeX name format - see #266-toName _ ils@(Str ys:_) | T.any (== '=') ys = do- let commaParts = splitWhen (== Str ",")- . splitStrWhen (\c -> c == ',' || c == '=' || c == '\160')- $ ils- let addPart ag (Str "given" : Str "=" : xs) =- ag{ nameGiven = case nameGiven ag of- Nothing -> Just $ stringify xs- Just t -> Just $ t <> " " <> stringify xs }- addPart ag (Str "family" : Str "=" : xs) =- ag{ nameFamily = Just $ stringify xs }- addPart ag (Str "prefix" : Str "=" : xs) =- ag{ nameDroppingParticle = Just $ stringify xs }- addPart ag (Str "useprefix" : Str "=" : Str "true" : _) =- ag{ nameNonDroppingParticle = nameDroppingParticle ag- , nameDroppingParticle = Nothing }- addPart ag (Str "suffix" : Str "=" : xs) =- ag{ nameSuffix = Just $ stringify xs }- addPart ag (Space : xs) = addPart ag xs- addPart ag _ = ag- return $ foldl' addPart emptyName commaParts--- First von Last--- von Last, First--- von Last, Jr ,First--- NOTE: biblatex and bibtex differ on:--- Drummond de Andrade, Carlos--- bibtex takes "Drummond de" as the von;--- biblatex takes the whole as a last name.--- See https://github.com/plk/biblatex/issues/236--- Here we implement the more sensible biblatex behavior.-toName opts ils = do- let useprefix = optionSet "useprefix" opts- let usecomma = optionSet "juniorcomma" opts- let bibtex = optionSet "bibtex" opts- let words' = wordsBy (\x -> x == Space || x == Str "\160")- let commaParts = map words' $ splitWhen (== Str ",")- $ splitStrWhen- (\c -> c == ',' || c == '\160') ils- let (first, vonlast, jr) =- case commaParts of- --- First is the longest sequence of white-space separated- -- words starting with an uppercase and that is not the- -- whole string. von is the longest sequence of whitespace- -- separated words whose last word starts with lower case- -- and that is not the whole string.- [fvl] -> let (caps', rest') = span isCapitalized fvl- in if null rest' && not (null caps')- then (init caps', [last caps'], [])- else (caps', rest', [])- [vl,f] -> (f, vl, [])- (vl:j:f:_) -> (f, vl, j )- [] -> ([], [], [])-- let (von, lastname) =- if bibtex- then case span isCapitalized $ reverse vonlast of- ([],w:ws) -> (reverse ws, [w])- (vs, ws) -> (reverse ws, reverse vs)- else case break isCapitalized vonlast of- (vs@(_:_), []) -> (init vs, [last vs])- (vs, ws) -> (vs, ws)- let prefix = T.unwords $ map stringify von- let family = T.unwords $ map stringify lastname- let suffix = T.unwords $ map stringify jr- let given = T.unwords $ map stringify first- return- Name { nameFamily = if T.null family- then Nothing- else Just family- , nameGiven = if T.null given- then Nothing- else Just given- , nameDroppingParticle = if useprefix || T.null prefix- then Nothing- else Just prefix- , nameNonDroppingParticle = if useprefix && not (T.null prefix)- then Just prefix- else Nothing- , nameSuffix = if T.null suffix- then Nothing- else Just suffix- , nameLiteral = Nothing- , nameCommaSuffix = usecomma- , nameStaticOrdering = False- }- ordinalize :: Locale -> Text -> Text ordinalize locale n = let terms = localeTerms locale@@ -1279,20 +1192,6 @@ Just [] -> n Just (t:_) -> n <> snd t -isCapitalized :: [Inline] -> Bool-isCapitalized (Str (T.uncons -> Just (c,cs)) : rest)- | isUpper c = True- | isDigit c = isCapitalized (Str cs : rest)- | otherwise = False-isCapitalized (_:rest) = isCapitalized rest-isCapitalized [] = True--optionSet :: Text -> Options -> Bool-optionSet key opts = case lookup key opts of- Just "true" -> True- Just s -> s == mempty- _ -> False- getTypeAndGenre :: Bib (Text, Maybe Text) getTypeAndGenre = do lang <- gets localeLang@@ -1311,7 +1210,7 @@ | otherwise -> "article-journal" "book" -> "book" "booklet" -> "pamphlet"- "bookinbook" -> "chapter"+ "bookinbook" -> "book" "collection" -> "book" "dataset" -> "dataset" "electronic" -> "webpage"@@ -1336,7 +1235,7 @@ "proceedings" -> "book" "reference" -> "book" "report" -> "report"- "software" -> "book" -- no "software" type in CSL+ "software" -> "software" "suppbook" -> "chapter" "suppcollection" -> "chapter" "suppperiodical"
@@ -6,7 +6,8 @@ import Citeproc.CslJson import Citeproc.Types import Control.Monad.Identity (runIdentity)-import Data.Aeson (eitherDecodeStrict')+import Data.Aeson (eitherDecodeStrict', FromJSON(parseJSON), (.:), Value(..))+import Data.Aeson.Types (parseEither) import Data.ByteString (ByteString) import Text.Pandoc.Builder as B import Data.Text (Text)@@ -31,8 +32,11 @@ fromCslJson (CslLink u x) = B.link u "" (fromCslJson x) cslJsonToReferences :: ByteString -> Either String [Reference Inlines]-cslJsonToReferences raw =- case eitherDecodeStrict' raw of- Left e -> Left e- Right cslrefs -> Right $- map (runIdentity . traverse (return . fromCslJson)) cslrefs+cslJsonToReferences raw = do+ items <-+ case eitherDecodeStrict' raw of+ Left e -> Left e+ Right (Object o) -> parseEither (.: "items") o+ Right val@(Array _) -> parseEither parseJSON val+ Right _ -> Left "expecting Object or Array"+ pure $ map (runIdentity . traverse (return . fromCslJson)) items
@@ -11,10 +11,9 @@ import Text.Pandoc.Citeproc.Util (splitStrWhen) import Data.Text (Text) import qualified Data.Text as T-import Data.List (foldl')-import Text.Parsec+import qualified Data.List as L import Text.Pandoc.Definition-import Text.Pandoc.Parsing (romanNumeral)+import Text.Pandoc.Parsing import Text.Pandoc.Shared (stringify) import Control.Monad (mzero) import qualified Data.Map as M@@ -70,19 +69,53 @@ (rawlab, la, _) <- pLocatorLabelDelimited locMap -- we only care about balancing {} and [] (because of the outer [] scope); -- the rest can be anything- let inner = do { t <- anyToken; return (True, stringify t) }+ let inner = do { t <- anyToken; return (True, cslJsonify t) } gs <- many (pBalancedBraces [('{','}'), ('[',']')] inner) _ <- pMatchChar "}" (== '}')- let lo = T.concat $ map snd gs+ let lo = mconcat $ map snd gs return $ LocatorInfo{ locatorLoc = lo, locatorLabel = la, locatorRaw = rawlab <> "{" <> lo <> "}" } +-- a variant of stringify that preserves formatting using CSL JSON+-- conventions+cslJsonify :: Inline -> Text+cslJsonify = go+ where goMany :: [Inline] -> T.Text+ goMany = mconcat . map go+ go :: Inline -> T.Text+ go (Str t) = t+ go Space = " "+ go SoftBreak = " "+ go LineBreak = " "+ go (Emph ils) = "<i>" <> goMany ils <> "</i>"+ go (Underline ils) = "<u>" <> goMany ils <> "</u>"+ go (Strong ils) = "<b>" <> goMany ils <> "</b>"+ go (Strikeout ils) = goMany ils+ go (Superscript ils) = "<sup>" <> goMany ils <> "</sup>"+ go (Subscript ils) = "<sub>" <> goMany ils <> "</sub>"+ go (SmallCaps ils) = "<span style=\"font-variant:small-caps;\">" <>+ goMany ils <> "</span>"+ go (Quoted SingleQuote ils) = "'" <> goMany ils <> "'"+ go (Quoted DoubleQuote ils) = "\"" <> goMany ils <> "\""+ go (Cite _ ils) = goMany ils+ go (Code _ t) = t+ go (Math _ t) = t+ go (RawInline _ _) = ""+ go (Link _ ils _) = goMany ils+ go (Image _ ils _) = goMany ils+ go (Note _) = ""+ go (Span (_,cls@(_:_),_) ils) =+ "<span class=\"" <> T.unwords cls <> "\">" <> goMany ils <> "</span>"+ go (Span (_,[],[("style","baseline")]) ils) =+ "<span style=\"baseline\">" <> goMany ils <> "</span>"+ go (Span _ ils) = goMany ils+ pLocatorLabelDelimited :: LocatorMap -> LocatorParser (Text, Text, Bool) pLocatorLabelDelimited locMap- = pLocatorLabel' locMap lim <|> return ("", "page", True)- where- lim = stringify <$> anyToken+ = pLocatorLabel' locMap (stringify <$> anyToken)+ <|> (("", "page", True) <$ lookAhead (pMatchChar "digit" isDigit))+ <|> (pure ("", "", True)) pLocatorIntegrated :: LocatorMap -> LocatorParser LocatorInfo pLocatorIntegrated locMap = try $ do@@ -163,14 +196,14 @@ where except = notFollowedBy pBraces >> p -- outer and inner- surround = foldl' (\a (open, close) -> sur open close except <|> a)+ surround = L.foldl' (\a (open, close) -> sur open close except <|> a) except braces isc c = stringify <$> pMatchChar [c] (== c) sur c c' m = try $ do- (d, mid) <- between (isc c) (isc c') (option (False, "") m)+ (d, mid) <- isc c *> option (False, "") m <* isc c' return (d, T.cons c . flip T.snoc c' $ mid) flattened = concatMap (\(o, c) -> [o, c]) braces@@ -296,6 +329,6 @@ , "paragraph" , "part" , "section"- , "sub verbo"+ , "sub-verbo" , "verse" , "volume" ]
@@ -3,15 +3,13 @@ ( referenceToMetaValue , metaValueToReference , metaValueToText- , metaValueToPath ) where import Citeproc.Types import Text.Pandoc.Definition import Text.Pandoc.Builder as B-import Text.Pandoc.Walk (query)-import Text.Pandoc.Shared (stringify)+import Text.Pandoc.Shared (stringify, blocksToInlines') import Data.Maybe import Safe import qualified Data.Set as Set@@ -28,9 +26,6 @@ metaValueToText (MetaList xs) = T.unwords <$> mapM metaValueToText xs metaValueToText _ = Nothing -metaValueToPath :: MetaValue -> Maybe FilePath-metaValueToPath = fmap T.unpack . metaValueToText- metaValueToBool :: MetaValue -> Maybe Bool metaValueToBool (MetaBool b) = Just b metaValueToBool (MetaString "true") = Just True@@ -130,7 +125,7 @@ case v of MetaString t -> TextVal t MetaInlines ils -> FancyVal (B.fromList ils)- MetaBlocks bs -> FancyVal (B.fromList $ query id bs)+ MetaBlocks bs -> FancyVal (blocksToInlines' bs) MetaBool b -> TextVal (if b then "true" else "false") MetaList _ -> TextVal mempty MetaMap _ -> TextVal mempty
@@ -0,0 +1,153 @@+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.CSL.Input.Name+-- Copyright : (c) John MacFarlane+-- License : BSD-style (see LICENSE)+--+-- Maintainer : John MacFarlane <fiddlosopher@gmail.com>+-- Stability : unstable+-- Portability : portable+--+-----------------------------------------------------------------------------++module Text.Pandoc.Citeproc.Name+ ( toName+ , NameOpts(..)+ , emptyName+ )+ where++import Text.Pandoc.Definition+import Text.Pandoc.Shared (stringify)+import Citeproc.Types+import Citeproc.Pandoc ()+import Text.Pandoc.Citeproc.Util (splitStrWhen)+import qualified Data.Text as T+import Data.List.Split (splitWhen, wordsBy)+import Data.Char (isUpper, isDigit)+import qualified Data.List as L++emptyName :: Name+emptyName =+ Name { nameFamily = Nothing+ , nameGiven = Nothing+ , nameDroppingParticle = Nothing+ , nameNonDroppingParticle = Nothing+ , nameSuffix = Nothing+ , nameLiteral = Nothing+ , nameCommaSuffix = False+ , nameStaticOrdering = False+ }++-- | Options for 'toName'.+data NameOpts =+ NameOpts+ { nameOptsPrefixIsNonDroppingParticle :: Bool+ -- ^ Treat a prefix on the last name as a non-dropping particle+ -- (default is to treat it as a dropping particle). This corresponds+ -- to the biblatex option @useprefix@.+ , nameOptsUseJuniorComma :: Bool+ -- ^ Put a comma before a suffix like "Jr." This corresponds to the+ -- biblatex option @juniorcomma@.+ } deriving (Show)++-- | Parse a list of 'Inline's into a citeproc 'Name', identifying+-- first and last name, particles, suffixes.+toName :: Monad m => NameOpts -> [Inline] -> m Name+toName _ [Str "others"] =+ return emptyName{ nameLiteral = Just "others" }+toName _ [Span ("",[],[]) ils] = -- corporate author+ return emptyName{ nameLiteral = Just $ stringify ils }+-- extended BibLaTeX name format - see #266+toName _ ils@(Str ys:_) | T.any (== '=') ys = do+ let commaParts = splitWhen (== Str ",")+ . splitStrWhen (\c -> c == ',' || c == '=' || c == '\160')+ $ ils+ let addPart ag (Str "given" : Str "=" : xs) =+ ag{ nameGiven = case nameGiven ag of+ Nothing -> Just $ stringify xs+ Just t -> Just $ t <> " " <> stringify xs }+ addPart ag (Str "family" : Str "=" : xs) =+ ag{ nameFamily = Just $ stringify xs }+ addPart ag (Str "prefix" : Str "=" : xs) =+ ag{ nameDroppingParticle = Just $ stringify xs }+ addPart ag (Str "useprefix" : Str "=" : Str "true" : _) =+ ag{ nameNonDroppingParticle = nameDroppingParticle ag+ , nameDroppingParticle = Nothing }+ addPart ag (Str "suffix" : Str "=" : xs) =+ ag{ nameSuffix = Just $ stringify xs }+ addPart ag (Space : xs) = addPart ag xs+ addPart ag _ = ag+ return $ L.foldl' addPart emptyName commaParts+-- First von Last+-- von Last, First+-- von Last, Jr ,First+-- NOTE: biblatex and bibtex differ on:+-- Drummond de Andrade, Carlos+-- bibtex takes "Drummond de" as the von;+-- biblatex takes the whole as a last name.+-- See https://github.com/plk/biblatex/issues/236+-- Here we implement the more sensible biblatex behavior.+toName opts ils = do+ let words' = wordsBy (\x -> x == Space || x == Str "\160")+ let commaParts = map words' $ splitWhen (== Str ",")+ $ splitStrWhen+ (\c -> c == ',' || c == '\160') ils+ let (first, vonlast, jr) =+ case commaParts of+ --- First is the longest sequence of white-space separated+ -- words starting with an uppercase and that is not the+ -- whole string. von is the longest sequence of whitespace+ -- separated words whose last word starts with lower case+ -- and that is not the whole string.+ [fvl] -> let (caps', rest') = span isCapitalized fvl+ in if null rest' && not (null caps')+ then (init caps', [last caps'], [])+ else (caps', rest', [])+ [vl,f] -> (f, vl, [])+ (vl:j:f:_) -> (f, vl, j )+ [] -> ([], [], [])++ let (von, lastname) =+ case break isCapitalized vonlast of+ (vs@(_:_), []) -> (init vs, [last vs])+ (vs, ws) -> (vs, ws)+ let prefix = T.unwords $ map stringify von+ let family = T.unwords $ map stringify lastname+ let suffix = T.unwords $ map stringify jr+ let given = T.unwords $ map stringify first+ return+ Name { nameFamily = if T.null family+ then Nothing+ else Just family+ , nameGiven = if T.null given+ then Nothing+ else Just given+ , nameDroppingParticle = if nameOptsPrefixIsNonDroppingParticle opts ||+ T.null prefix+ then Nothing+ else Just prefix+ , nameNonDroppingParticle = if nameOptsPrefixIsNonDroppingParticle opts &&+ not (T.null prefix)+ then Just prefix+ else Nothing+ , nameSuffix = if T.null suffix+ then Nothing+ else Just suffix+ , nameLiteral = Nothing+ , nameCommaSuffix = nameOptsUseJuniorComma opts+ , nameStaticOrdering = False+ }++isCapitalized :: [Inline] -> Bool+isCapitalized (Str (T.uncons -> Just (c,cs)) : rest)+ | isUpper c = True+ | isDigit c = isCapitalized (Str cs : rest)+ | otherwise = False+isCapitalized (_:rest) = isCapitalized rest+isCapitalized [] = True
@@ -48,6 +48,7 @@ toIETF "ngerman" = "de-DE" toIETF "greek" = "el-GR" toIETF "polutonikogreek" = "el-GR"+toIETF "polytonicgreek" = "el-GR" toIETF "hebrew" = "he-IL" toIETF "hungarian" = "hu-HU" toIETF "icelandic" = "is-IS"@@ -79,4 +80,3 @@ toIETF "vietnamese" = "vi-VN" toIETF "latin" = "la" toIETF x = x-
@@ -23,9 +23,11 @@ , 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-import Text.Pandoc.Translations (Translations)+import Text.Pandoc.Translations.Types (Translations) import Text.Pandoc.Class.Sandbox
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {- | Module : Text.Pandoc.Class.CommonState Copyright : Copyright (C) 2016-2020 Jesse Rosenthal, John MacFarlane@@ -22,7 +23,10 @@ import Text.Collate.Lang (Lang) import Text.Pandoc.MediaBag (MediaBag) import Text.Pandoc.Logging (LogMessage, Verbosity (WARNING))-import Text.Pandoc.Translations (Translations)+import Text.Pandoc.Translations.Types (Translations)+#ifdef PANDOC_HTTP_SUPPORT+import Network.HTTP.Client (Manager)+#endif -- | 'CommonState' represents state that is used by all -- instances of 'PandocMonad'. Normally users should not@@ -50,6 +54,11 @@ , stResourcePath :: [FilePath] -- ^ Path to search for resources like -- included images+#ifdef PANDOC_HTTP_SUPPORT+ , stManager :: Maybe Manager+ -- ^ Manager for HTTP client; this needs to persist across many requests+ -- for efficiency.+#endif , stVerbosity :: Verbosity -- ^ Verbosity level , stTrace :: Bool@@ -75,6 +84,9 @@ , stInputFiles = [] , stOutputFile = Nothing , stResourcePath = ["."]+#ifdef PANDOC_HTTP_SUPPORT+ , stManager = Nothing+#endif , stVerbosity = WARNING , stTrace = False }
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Class.IO@@ -32,34 +33,43 @@ , readFileStrict , readStdinStrict , extractMedia+ , writeMedia ) where import Control.Monad.Except (throwError) import Control.Monad.IO.Class (MonadIO, liftIO)-import Data.ByteString.Base64 (decodeBase64Lenient)-import Data.ByteString.Lazy (toChunks) import Data.Text (Text, pack, unpack) import Data.Time (TimeZone, UTCTime) import Data.Unique (hashUnique)-import Network.Connection (TLSSettings (TLSSettingsSimple))+#ifdef PANDOC_HTTP_SUPPORT+import Data.ByteString.Lazy (toChunks)+import System.Environment (getEnv)+import Data.Default (def)+import Network.Connection (TLSSettings(..))+import qualified Network.TLS as TLS+import qualified Network.TLS.Extra as TLS+import System.X509 (getSystemCertificateStore) import Network.HTTP.Client- (httpLbs, responseBody, responseHeaders,- Request(port, host, requestHeaders), parseRequest, newManager)+ (httpLbs, Manager, responseBody, responseHeaders,+ Request(port, host, requestHeaders), parseUrlThrow, newManager, HttpException) import Network.HTTP.Client.Internal (addProxy) import Network.HTTP.Client.TLS (mkManagerSettings) import Network.HTTP.Types.Header ( hContentType ) import Network.Socket (withSocketsDo)-import Network.URI (unEscapeString)+import Text.Pandoc.Class.CommonState (CommonState (..))+import Text.Pandoc.Class.PandocMonad ( getsCommonState, modifyCommonState )+import qualified Data.CaseInsensitive as CI+#endif+import Network.URI (URI(..), parseURI, unEscapeString) import System.Directory (createDirectoryIfMissing)-import System.Environment (getEnv)-import System.FilePath ((</>), takeDirectory, normalise)+import System.FilePath ((</>), takeDirectory, takeFileName, normalise, takeExtension) import qualified System.FilePath.Posix as Posix import System.IO (stderr) import System.IO.Error import System.Random (StdGen)-import Text.Pandoc.Class.CommonState (CommonState (..)) import Text.Pandoc.Class.PandocMonad- (PandocMonad, getsCommonState, getMediaBag, report)+ (PandocMonad,+ getMediaBag, report, extractURIData) import Text.Pandoc.Definition (Pandoc, Inline (Image)) import Text.Pandoc.Error (PandocError (..)) import Text.Pandoc.Logging (LogMessage (..), messageVerbosity, showLogMessage)@@ -69,7 +79,6 @@ import qualified Control.Exception as E import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL-import qualified Data.CaseInsensitive as CI import qualified Data.Text as T import qualified Data.Time import qualified Data.Time.LocalTime@@ -79,6 +88,7 @@ import qualified System.FilePath.Glob import qualified System.Random import qualified Text.Pandoc.UTF8 as UTF8+import Codec.Archive.Zip #ifndef EMBED_DATA_FILES import qualified Paths_pandoc as Paths #endif@@ -119,36 +129,69 @@ newUniqueHash :: MonadIO m => m Int newUniqueHash = hashUnique <$> liftIO Data.Unique.newUnique +#ifdef PANDOC_HTTP_SUPPORT+getManager :: (PandocMonad m, MonadIO m) => m Manager+getManager = do+ mbManager <- getsCommonState stManager+ disableCertificateValidation <- getsCommonState stNoCheckCertificate+ case mbManager of+ Just manager -> pure manager+ Nothing -> do+ manager <- liftIO $ do+ certificateStore <- getSystemCertificateStore+ let tlsSettings = TLSSettings $+ (TLS.defaultParamsClient "localhost.localdomain" "80")+ { TLS.clientSupported = def{ TLS.supportedCiphers =+ TLS.ciphersuite_default+ , TLS.supportedExtendedMainSecret =+ TLS.AllowEMS }+ , TLS.clientShared = def+ { TLS.sharedCAStore = certificateStore+ , TLS.sharedValidationCache =+ if disableCertificateValidation+ then TLS.ValidationCache+ (\_ _ _ -> return TLS.ValidationCachePass)+ (\_ _ _ -> return ())+ else def+ }+ }+ let tlsManagerSettings = mkManagerSettings tlsSettings Nothing+ newManager tlsManagerSettings+ modifyCommonState $ \st -> st{ stManager = Just manager }+ pure manager+#endif+ openURL :: (PandocMonad m, MonadIO m) => Text -> m (B.ByteString, Maybe MimeType) openURL u- | Just u'' <- T.stripPrefix "data:" u = do- let mime = T.takeWhile (/=',') u''- let contents = UTF8.fromString $- unEscapeString $ T.unpack $ T.drop 1 $ T.dropWhile (/=',') u''- return (decodeBase64Lenient contents, Just mime)+ | Just (URI{ uriScheme = "data:",+ uriPath = upath }) <- parseURI (T.unpack u)+ = pure $ extractURIData upath+#ifdef PANDOC_HTTP_SUPPORT | otherwise = do let toReqHeader (n, v) = (CI.mk (UTF8.fromText n), UTF8.fromText v) customHeaders <- map toReqHeader <$> getsCommonState stRequestHeaders- disableCertificateValidation <- getsCommonState stNoCheckCertificate report $ Fetching u+ manager <- getManager res <- liftIO $ E.try $ withSocketsDo $ do- let parseReq = parseRequest proxy <- tryIOError (getEnv "http_proxy") let addProxy' x = case proxy of Left _ -> return x- Right pr -> parseReq pr >>= \r ->+ Right pr -> parseUrlThrow pr >>= \r -> return (addProxy (host r) (port r) x)- req <- parseReq (unpack u) >>= addProxy'+ req <- parseUrlThrow (unpack u) >>= addProxy' let req' = req{requestHeaders = customHeaders ++ requestHeaders req}- let tlsSimple = TLSSettingsSimple disableCertificateValidation False False- let tlsManagerSettings = mkManagerSettings tlsSimple Nothing- resp <- newManager tlsManagerSettings >>= httpLbs req'+ resp <- httpLbs req' manager return (B.concat $ toChunks $ responseBody resp, UTF8.toText `fmap` lookup hContentType (responseHeaders resp)) case res of Right r -> return r- Left e -> throwError $ PandocHttpError u e+ Left (e :: HttpException)+ -> throwError $ PandocHttpError u (T.pack (show e))+#else+ | otherwise =+ throwError $ PandocHttpError u "pandoc was compiled without HTTP support"+#endif -- | Read the lazy ByteString contents from a file path, raising an error on -- failure.@@ -203,16 +246,26 @@ where go l' = do UTF8.hPutStr stderr " " UTF8.hPutStrLn stderr l' --- | Extract media from the mediabag into a directory.+-- | Extract media from the mediabag into a directory (or a zip archive if the+-- path supplied ends in @.zip@. extractMedia :: (PandocMonad m, MonadIO m) => FilePath -> Pandoc -> m Pandoc-extractMedia dir d = do+extractMedia path d = do media <- getMediaBag let items = mediaItems media+ let (dir, mbZip) = case takeExtension path of+ ".zip" -> (takeDirectory path, Just (takeFileName path))+ _ -> (path, Nothing) if null items then return d else do- mapM_ (writeMedia dir) items+ let archive = foldr addEntry emptyArchive items+ case mbZip of+ Just fname -> writeMedia dir+ (fname, "application/zip", fromArchive archive)+ Nothing -> mapM_ (writeMedia dir) items return $ walk (adjustImagePath dir media) d+ where+ addEntry (fp, _mime, content) = addEntryToArchive (toEntry fp 0 content) -- | Write the contents of a media bag to a path. -- If the path contains URI escape sequences (percent-encoding),@@ -223,8 +276,11 @@ -> m () writeMedia dir (fp, _mt, bs) = do -- we normalize to get proper path separators for the platform+ -- we unescape URI encoding, but given how insertMedia+ -- is written, we shouldn't have any % in a canonical media name... let fullpath = normalise $ dir </> unEscapeString fp liftIOError (createDirectoryIfMissing True) (takeDirectory fullpath)+ report $ Extracting (T.pack fullpath) logIOError $ BL.writeFile fullpath bs -- | If the given Inline element is an image with a @src@ path equal to
@@ -23,44 +23,47 @@ module Text.Pandoc.Class.PandocMonad ( PandocMonad(..)+ , getTimestamp , getPOSIXTime , getZonedTime , readFileFromDirs , report- , setTrace+ , runSilently , setRequestHeader , setNoCheckCertificate , getLog , setVerbosity , getVerbosity+ , setTrace+ , getTrace , getMediaBag , setMediaBag , insertMedia , setUserDataDir , getUserDataDir , fetchItem+ , extractURIData , getInputFiles , setInputFiles , getOutputFile , setOutputFile , setResourcePath , getResourcePath- , readDefaultDataFile- , readDataFile+ , setRequestHeaders+ , getRequestHeaders+ , getSourceURL , readMetadataFile+ , toTextM , fillMediaBag , toLang- , setTranslations- , translateTerm , makeCanonical , findFileWithDataFallback- , getTimestamp+ , checkUserDataDir ) where -import Codec.Archive.Zip-import Control.Monad.Except (MonadError (catchError, throwError),- MonadTrans, lift, when)-import Data.List (foldl')+import Control.Monad.Except (MonadError (catchError, throwError))+import Control.Monad.Trans (MonadTrans, lift)+import Control.Monad (when) import Data.Time (UTCTime) import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds, posixSecondsToUTCTime)@@ -69,30 +72,29 @@ unEscapeString, parseURIReference, isAllowedInURI, parseURI, URI(..) ) import System.FilePath ((</>), takeExtension, dropExtension,- isRelative, splitDirectories, makeRelative)+ isRelative, makeRelative) import System.Random (StdGen)-import Text.Collate.Lang (Lang(..), parseLang, renderLang)+import Text.Collate.Lang (Lang(..), parseLang) import Text.Pandoc.Class.CommonState (CommonState (..)) import Text.Pandoc.Definition import Text.Pandoc.Error import Text.Pandoc.Logging import Text.Pandoc.MIME (MimeType, getMimeType) import Text.Pandoc.MediaBag (MediaBag, lookupMedia, MediaItem(..))-import Text.Pandoc.Shared (uriPathToPath, safeRead)-import Text.Pandoc.Translations (Term(..), Translations, lookupTerm,- readTranslations)+import Text.Pandoc.Shared (safeRead, makeCanonical, tshow)+import Text.Pandoc.URI (uriPathToPath, pBase64DataURI)+import qualified Data.Attoparsec.Text as A import Text.Pandoc.Walk (walkM)+import qualified Text.Pandoc.UTF8 as UTF8+import Data.ByteString.Base64 (decodeLenient) import Text.Parsec (ParsecT, getPosition, sourceLine, sourceName) import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL import qualified Data.Text as T import qualified Debug.Trace-import qualified System.FilePath.Posix as Posix import qualified Text.Pandoc.MediaBag as MB-import qualified Text.Pandoc.UTF8 as UTF8-#ifdef EMBED_DATA_FILES-import Text.Pandoc.Data (dataFiles)-#endif+import qualified Data.Text.Encoding as TSE+import qualified Data.Text.Encoding.Error as TSE -- | The PandocMonad typeclass contains all the potentially -- IO-related functions used in pandoc's readers and writers.@@ -167,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@@ -182,26 +193,22 @@ when (level <= verbosity) $ logOutput msg modifyCommonState $ \st -> st{ stLog = msg : stLog st } --- | Get the time from the @SOURCE_DATE_EPOCH@--- environment variable. The variable should contain a--- unix time stamp, the number of seconds since midnight Jan 01--- 1970 UTC. If the variable is not set or cannot be--- parsed as a unix time stamp, the current time is returned.--- This function is designed to make possible reproducible--- builds in formats that include a creation timestamp.-getTimestamp :: PandocMonad m => m UTCTime-getTimestamp = do- mbSourceDateEpoch <- lookupEnv "SOURCE_DATE_EPOCH"- case mbSourceDateEpoch >>= safeRead of- Just (epoch :: Integer) ->- return $ posixSecondsToUTCTime $ fromIntegral epoch- Nothing -> getCurrentTime+-- | 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}) --- | 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}+ return (result, newLog) -- | Set request header to use in HTTP requests. setRequestHeader :: PandocMonad m@@ -266,14 +273,40 @@ setResourcePath :: PandocMonad m => [FilePath] -> m () setResourcePath ps = modifyCommonState $ \st -> st{stResourcePath = ps} --- | Get the POSIX time.+-- | 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+-- reproducible builds.+getTimestamp :: PandocMonad m => m UTCTime+getTimestamp = do+ mbSourceDateEpoch <- lookupEnv "SOURCE_DATE_EPOCH"+ case mbSourceDateEpoch >>= safeRead of+ Just (epoch :: Integer) ->+ return $ posixSecondsToUTCTime $ fromIntegral epoch+ Nothing -> getCurrentTime++-- | Get the POSIX time. If @SOURCE_DATE_EPOCH@ is set to a unix time,+-- it is used instead of the current time. getPOSIXTime :: PandocMonad m => m POSIXTime-getPOSIXTime = utcTimeToPOSIXSeconds <$> getCurrentTime+getPOSIXTime = utcTimeToPOSIXSeconds <$> getTimestamp --- | Get the zoned time.+-- | Get the zoned time. If @SOURCE_DATE_EPOCH@ is set to a unix time,+-- value (POSIX time), it is used instead of the current time. getZonedTime :: PandocMonad m => m ZonedTime getZonedTime = do- t <- getCurrentTime+ t <- getTimestamp tz <- getCurrentTimeZone return $ utcToZonedTime tz t @@ -281,7 +314,7 @@ readFileFromDirs :: PandocMonad m => [FilePath] -> FilePath -> m (Maybe T.Text) readFileFromDirs [] _ = return Nothing readFileFromDirs (d:ds) f = catchError- (Just . T.pack . UTF8.toStringLazy <$> readFileLazy (d </> f))+ (Just <$> (readFileStrict (d </> f) >>= toTextM (d </> f))) (\_ -> readFileFromDirs ds f) -- | Convert BCP47 string to a Lang, issuing warning@@ -295,62 +328,6 @@ return Nothing Right l -> return (Just l) --- | Select the language to use with 'translateTerm'.--- Note that this does not read a translation file;--- that is only done the first time 'translateTerm' is--- used.-setTranslations :: PandocMonad m => Lang -> m ()-setTranslations lang =- modifyCommonState $ \st -> st{ stTranslations = Just (lang, Nothing) }---- | Load term map.-getTranslations :: PandocMonad m => m Translations-getTranslations = do- mbtrans <- getsCommonState stTranslations- case mbtrans of- Nothing -> return mempty -- no language defined- Just (_, Just t) -> return t- Just (lang, Nothing) -> do -- read from file- let translationFile = "translations/" <> renderLang lang <> ".yaml"- let fallbackFile = "translations/" <> langLanguage lang <> ".yaml"- let getTrans fp = do- bs <- readDataFile fp- case readTranslations (UTF8.toText bs) of- Left e -> do- report $ CouldNotLoadTranslations (renderLang lang)- (T.pack fp <> ": " <> e)- -- make sure we don't try again...- modifyCommonState $ \st ->- st{ stTranslations = Nothing }- return mempty- Right t -> do- modifyCommonState $ \st ->- st{ stTranslations = Just (lang, Just t) }- return t- catchError (getTrans $ T.unpack translationFile)- (\_ ->- catchError (getTrans $ T.unpack fallbackFile)- (\e -> do- report $ CouldNotLoadTranslations (renderLang lang)- $ case e of- PandocCouldNotFindDataFileError _ ->- "data file " <> fallbackFile <> " not found"- _ -> ""- -- make sure we don't try again...- modifyCommonState $ \st -> st{ stTranslations = Nothing }- return mempty))---- | Get a translation from the current term map.--- Issue a warning if the term is not defined.-translateTerm :: PandocMonad m => Term -> m T.Text-translateTerm term = do- translations <- getTranslations- case lookupTerm term translations of- Just s -> return s- Nothing -> do- report $ NoTranslation $ T.pack $ show term- return ""- -- | Specialized version of parseURIReference that disallows -- single-letter schemes. Reason: these are usually windows absolute -- paths.@@ -394,10 +371,13 @@ downloadOrRead :: PandocMonad m => T.Text -> m (B.ByteString, Maybe MimeType)-downloadOrRead s = do+downloadOrRead s+ | "data:" `T.isPrefixOf` s,+ Right (bs, mt) <- A.parseOnly (pBase64DataURI <* A.endOfInput) s+ = pure (bs, Just mt)+ | otherwise = do sourceURL <- getsCommonState stSourceURL- case (sourceURL >>= parseURIReference' .- ensureEscaped, ensureEscaped s) of+ case (sourceURL >>= parseURIReference' . ensureEscaped, ensureEscaped s) of (Just u, s') -> -- try fetching from relative path at source case parseURIReference' s' of Just u' -> openURL $ T.pack $ show $ u' `nonStrictRelativeTo` u@@ -409,8 +389,10 @@ Nothing -> openURL s' -- will throw error (Nothing, s') -> case parseURI (T.unpack s') of -- requires absolute URI- Just u' | uriScheme u' == "file:" ->- readLocalFile $ uriPathToPath (T.pack $ uriPath u')+ Just URI{ uriScheme = "file:", uriPath = upath}+ -> readLocalFile $ uriPathToPath (T.pack upath)+ Just URI{ uriScheme = "data:", uriPath = upath}+ -> pure $ extractURIData upath -- We don't want to treat C:/ as a scheme: Just u' | length (uriScheme u') > 2 -> openURL (T.pack $ show u') _ -> readLocalFile fp -- get from local file system@@ -426,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"@@ -436,145 +417,15 @@ convertSlash '\\' = '/' convertSlash x = x --- | Retrieve default reference.docx.-getDefaultReferenceDocx :: PandocMonad m => m Archive-getDefaultReferenceDocx = do- let paths = ["[Content_Types].xml",- "_rels/.rels",- "docProps/app.xml",- "docProps/core.xml",- "docProps/custom.xml",- "word/document.xml",- "word/fontTable.xml",- "word/footnotes.xml",- "word/comments.xml",- "word/numbering.xml",- "word/settings.xml",- "word/webSettings.xml",- "word/styles.xml",- "word/_rels/document.xml.rels",- "word/_rels/footnotes.xml.rels",- "word/theme/theme1.xml"]- let toLazy = BL.fromChunks . (:[])- let pathToEntry path = do- epochtime <- floor . utcTimeToPOSIXSeconds <$> getTimestamp- contents <- toLazy <$> readDataFile ("docx/" ++ path)- return $ toEntry path epochtime contents- datadir <- getUserDataDir- mbArchive <- case datadir of- Nothing -> return Nothing- Just d -> do- exists <- fileExists (d </> "reference.docx")- if exists- then return (Just (d </> "reference.docx"))- else return Nothing- case mbArchive of- Just arch -> toArchive <$> readFileLazy arch- Nothing -> foldr addEntryToArchive emptyArchive <$>- mapM pathToEntry paths---- | Retrieve default reference.odt.-getDefaultReferenceODT :: PandocMonad m => m Archive-getDefaultReferenceODT = do- let paths = ["mimetype",- "manifest.rdf",- "styles.xml",- "content.xml",- "meta.xml",- "settings.xml",- "Configurations2/accelerator/current.xml",- "Thumbnails/thumbnail.png",- "META-INF/manifest.xml"]- let pathToEntry path = do epochtime <- floor `fmap` getPOSIXTime- contents <- (BL.fromChunks . (:[])) `fmap`- readDataFile ("odt/" ++ path)- return $ toEntry path epochtime contents- datadir <- getUserDataDir- mbArchive <- case datadir of- Nothing -> return Nothing- Just d -> do- exists <- fileExists (d </> "reference.odt")- if exists- then return (Just (d </> "reference.odt"))- else return Nothing- case mbArchive of- Just arch -> toArchive <$> readFileLazy arch- Nothing -> foldr addEntryToArchive emptyArchive <$>- mapM pathToEntry paths---- | Retrieve default reference.pptx.-getDefaultReferencePptx :: PandocMonad m => m Archive-getDefaultReferencePptx = do- -- We're going to narrow this down substantially once we get it- -- working.- let paths = [ "[Content_Types].xml"- , "_rels/.rels"- , "docProps/app.xml"- , "docProps/core.xml"- , "ppt/_rels/presentation.xml.rels"- , "ppt/presProps.xml"- , "ppt/presentation.xml"- , "ppt/slideLayouts/_rels/slideLayout1.xml.rels"- , "ppt/slideLayouts/_rels/slideLayout2.xml.rels"- , "ppt/slideLayouts/_rels/slideLayout3.xml.rels"- , "ppt/slideLayouts/_rels/slideLayout4.xml.rels"- , "ppt/slideLayouts/_rels/slideLayout5.xml.rels"- , "ppt/slideLayouts/_rels/slideLayout6.xml.rels"- , "ppt/slideLayouts/_rels/slideLayout7.xml.rels"- , "ppt/slideLayouts/_rels/slideLayout8.xml.rels"- , "ppt/slideLayouts/_rels/slideLayout9.xml.rels"- , "ppt/slideLayouts/_rels/slideLayout10.xml.rels"- , "ppt/slideLayouts/_rels/slideLayout11.xml.rels"- , "ppt/slideLayouts/slideLayout1.xml"- , "ppt/slideLayouts/slideLayout10.xml"- , "ppt/slideLayouts/slideLayout11.xml"- , "ppt/slideLayouts/slideLayout2.xml"- , "ppt/slideLayouts/slideLayout3.xml"- , "ppt/slideLayouts/slideLayout4.xml"- , "ppt/slideLayouts/slideLayout5.xml"- , "ppt/slideLayouts/slideLayout6.xml"- , "ppt/slideLayouts/slideLayout7.xml"- , "ppt/slideLayouts/slideLayout8.xml"- , "ppt/slideLayouts/slideLayout9.xml"- , "ppt/slideMasters/_rels/slideMaster1.xml.rels"- , "ppt/slideMasters/slideMaster1.xml"- , "ppt/slides/_rels/slide1.xml.rels"- , "ppt/slides/slide1.xml"- , "ppt/slides/_rels/slide2.xml.rels"- , "ppt/slides/slide2.xml"- , "ppt/slides/_rels/slide3.xml.rels"- , "ppt/slides/slide3.xml"- , "ppt/slides/_rels/slide4.xml.rels"- , "ppt/slides/slide4.xml"- , "ppt/tableStyles.xml"- , "ppt/theme/theme1.xml"- , "ppt/viewProps.xml"- -- These relate to notes slides.- , "ppt/notesMasters/notesMaster1.xml"- , "ppt/notesMasters/_rels/notesMaster1.xml.rels"- , "ppt/notesSlides/notesSlide1.xml"- , "ppt/notesSlides/_rels/notesSlide1.xml.rels"- , "ppt/notesSlides/notesSlide2.xml"- , "ppt/notesSlides/_rels/notesSlide2.xml.rels"- , "ppt/theme/theme2.xml"- ]- let toLazy = BL.fromChunks . (:[])- let pathToEntry path = do- epochtime <- floor . utcTimeToPOSIXSeconds <$> getCurrentTime- contents <- toLazy <$> readDataFile ("pptx/" ++ path)- return $ toEntry path epochtime contents- datadir <- getUserDataDir- mbArchive <- case datadir of- Nothing -> return Nothing- Just d -> do- exists <- fileExists (d </> "reference.pptx")- if exists- then return (Just (d </> "reference.pptx"))- else return Nothing- case mbArchive of- Just arch -> toArchive <$> readFileLazy arch- Nothing -> foldr addEntryToArchive emptyArchive <$>- mapM pathToEntry paths+-- Extract data from a data URI's path component.+extractURIData :: String -> (B.ByteString, Maybe MimeType)+extractURIData upath =+ case break (== ';') (filter (/= ' ') mimespec) of+ (mime', ";base64") -> (decodeLenient contents, Just (T.pack mime'))+ (mime', _) -> (contents, Just (T.pack mime'))+ where+ (mimespec, rest) = break (== ',') $ unEscapeString upath+ contents = UTF8.fromString $ drop 1 rest -- | Checks if the file path is relative to a parent directory. isRelativeToParentDir :: FilePath -> Bool@@ -590,19 +441,6 @@ then getUserDataDir else return Nothing ---- | Read file from user data directory or,---- if not found there, from the default data files.-readDataFile :: PandocMonad m => FilePath -> m B.ByteString-readDataFile fname = do- datadir <- checkUserDataDir fname- case datadir of- Nothing -> readDefaultDataFile fname- Just userDir -> do- exists <- fileExists (userDir </> fname)- if exists- then readFileStrict (userDir </> fname)- else readDefaultDataFile fname- -- | Read metadata file from the working directory or, if not found there, from -- the metadata subdirectory of the user data directory. readMetadataFile :: PandocMonad m => FilePath -> m B.ByteString@@ -610,42 +448,6 @@ Nothing -> throwError $ PandocCouldNotFindMetadataFileError (T.pack fname) Just metadataFile -> readFileStrict metadataFile --- | Read file from from the default data files.-readDefaultDataFile :: PandocMonad m => FilePath -> m B.ByteString-readDefaultDataFile "reference.docx" =- B.concat . BL.toChunks . fromArchive <$> getDefaultReferenceDocx-readDefaultDataFile "reference.pptx" =- B.concat . BL.toChunks . fromArchive <$> getDefaultReferencePptx-readDefaultDataFile "reference.odt" =- B.concat . BL.toChunks . fromArchive <$> getDefaultReferenceODT-readDefaultDataFile fname =-#ifdef EMBED_DATA_FILES- case lookup (makeCanonical fname) dataFiles of- Nothing -> throwError $ PandocCouldNotFindDataFileError $ T.pack fname- Just contents -> return contents-#else- getDataFileName fname' >>= checkExistence >>= readFileStrict- where fname' = if fname == "MANUAL.txt" then fname else "data" </> fname---- | Returns the input filename unchanged if the file exits, and throws--- a `PandocCouldNotFindDataFileError` if it doesn't.-checkExistence :: PandocMonad m => FilePath -> m FilePath-checkExistence fn = do- exists <- fileExists fn- if exists- then return fn- else throwError $ PandocCouldNotFindDataFileError $ T.pack fn-#endif---- | Canonicalizes a file path by removing redundant @.@ and @..@.-makeCanonical :: FilePath -> FilePath-makeCanonical = Posix.joinPath . transformPathParts . splitDirectories- where transformPathParts = reverse . foldl' go []- go as "." = as- go ("..":as) ".." = ["..", ".."] <> as- go (_:as) ".." = as- go as x = x : as- -- | Tries to run an action on a file: for each directory given, a -- filepath is created from the given filename, and the action is run on -- that filepath. Returns the result of the first successful execution@@ -658,6 +460,27 @@ catchError ((p </> fp,) <$> action (p </> fp)) (\_ -> withPaths ps action fp) +-- | A variant of Text.Pandoc.UTF8.toText that takes a FilePath+-- as well as the file's contents as parameter, and traps UTF8+-- decoding errors so it can issue a more informative PandocUTF8DecodingError+-- with source position.+toTextM :: PandocMonad m => FilePath -> B.ByteString -> m T.Text+toTextM fp bs =+ case TSE.decodeUtf8' . filterCRs . dropBOM $ bs of+ Left (TSE.DecodeError _ (Just w)) ->+ case B.elemIndex w bs of+ Just offset ->+ throwError $ PandocUTF8DecodingError (T.pack fp) offset w+ Nothing -> throwError $ PandocUTF8DecodingError (T.pack fp) 0 w+ Left e -> throwError $ PandocAppError (tshow e)+ Right t -> return t+ where+ dropBOM bs' =+ if "\xEF\xBB\xBF" `B.isPrefixOf` bs'+ then B.drop 3 bs'+ else bs'+ filterCRs = B.filter (/=13)+ -- | Returns @fp@ if the file exists in the current directory; otherwise -- searches for the data file relative to @/subdir/@. Returns @Nothing@ -- if neither file exists.@@ -699,6 +522,11 @@ return $ Image attr lab (src, tit)) (\e -> case e of+ PandocIOError text err -> do+ report $ CouldNotFetchResource text . T.pack $+ (show err ++ "\nReplacing image with description.")+ -- emit alt text+ return $ replacementSpan attr src tit lab PandocResourceNotFound _ -> do report $ CouldNotFetchResource src "replacing image with description"@@ -706,7 +534,7 @@ return $ replacementSpan attr src tit lab PandocHttpError u er -> do report $ CouldNotFetchResource u- (T.pack $ show er ++ "\rReplacing image with description.")+ (er <> "\nReplacing image with description.") -- emit alt text return $ replacementSpan attr src tit lab _ -> throwError e)
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-}@@ -29,8 +30,17 @@ ) where import Codec.Archive.Zip+import Control.Monad.Trans ( MonadTrans(lift) ) import Control.Monad.Except+ ( ExceptT(..), MonadError(throwError), runExceptT ) import Control.Monad.State.Strict+ ( StateT(StateT),+ State,+ MonadState(put, get),+ modify,+ evalState,+ evalStateT )+import Control.Monad (foldM) import Data.Default import Data.Text (Text) import Data.Time (UTCTime)@@ -40,7 +50,7 @@ import System.Directory (doesDirectoryExist, getDirectoryContents) import System.FilePath ((</>)) import System.FilePath.Glob (match, compile)-import System.Random (StdGen, split, mkStdGen)+import System.Random (StdGen, mkStdGen) import Text.Pandoc.Class.CommonState (CommonState (..)) import Text.Pandoc.Class.PandocMonad import Text.Pandoc.Error@@ -49,6 +59,15 @@ import qualified Data.Map as M import qualified Data.Text as T import qualified System.Directory as Directory (getModificationTime)++#if MIN_VERSION_random(1,3,0)+import System.Random (splitGen, SplitGen)++split :: SplitGen g => g -> (g, g)+split = splitGen+#else+import System.Random (split)+#endif -- | The 'PureState' contains ersatz representations -- of things that would normally be obtained through IO.
@@ -1,6 +1,6 @@ {- | Module : Text.Pandoc.Class.Sandbox-Copyright : Copyright (C) 2021-2022 John MacFarlane+Copyright : Copyright (C) 2021-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane (<jgm@berkeley.edu>)@@ -12,7 +12,9 @@ -} module Text.Pandoc.Class.Sandbox- ( sandbox )+ ( sandbox+ , sandboxWithFileTree+ ) where import Control.Monad (foldM)@@ -30,8 +32,18 @@ -- ersatz file system and be available for reading. sandbox :: (PandocMonad m, MonadIO m) => [FilePath] -> PandocPure a -> m a sandbox files action = do- oldState <- getCommonState tree <- liftIO $ foldM addToFileTree mempty files+ sandboxWithFileTree tree action++-- | Lift a PandocPure action into any instance of PandocMonad.+-- The main computation is done purely, but CommonState is preserved+-- continuously, and warnings are emitted after the action completes.+-- The parameter is an ersatz file system which will be available for+-- reading.+sandboxWithFileTree :: (PandocMonad m, MonadIO m)+ => FileTree -> PandocPure a -> m a+sandboxWithFileTree tree action = do+ oldState <- getCommonState case runPure (do putCommonState oldState modifyPureState $ \ps -> ps{ stFiles = tree } result <- action@@ -47,4 +59,3 @@ mapM_ logOutput (filter ((<= verbosity) . messageVerbosity) newMessages) return result-
@@ -1,32 +1,245 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}+#ifdef EMBED_DATA_FILES {-# LANGUAGE TemplateHaskell #-}+#endif {- | Module : Text.Pandoc.Data-Copyright : Copyright (C) 2013-2022 John MacFarlane+Copyright : Copyright (C) 2013-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu> Stability : alpha Portability : portable -Provide contents data files as Haskell values.+Access to pandoc's data files. -}-module Text.Pandoc.Data (dataFiles) where-+module Text.Pandoc.Data ( readDefaultDataFile+ , readDataFile+ , getDataFileNames+ , defaultUserDataDir+ ) where+import Text.Pandoc.Class (PandocMonad(..), checkUserDataDir, getTimestamp,+ getUserDataDir, getPOSIXTime)+import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)+import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString as B-import Data.FileEmbed-import System.FilePath (splitDirectories)-import qualified System.FilePath.Posix as Posix+import Codec.Archive.Zip+import qualified Data.Text as T+import Control.Monad.Except (throwError)+import Text.Pandoc.Error (PandocError(..))+import System.FilePath+import System.Directory+import qualified Control.Exception as E+#ifdef EMBED_DATA_FILES+import Text.Pandoc.Data.BakedIn (dataFiles)+import Text.Pandoc.Shared (makeCanonical)+#else+import Paths_pandoc (getDataDir)+#endif --- We ensure that the data files are stored using Posix--- path separators (/), even on Windows.-dataFiles :: [(FilePath, B.ByteString)]-dataFiles = map (\(fp, contents) ->- (Posix.joinPath (splitDirectories fp), contents)) dataFiles'+-- | Read file from the default data files.+readDefaultDataFile :: PandocMonad m => FilePath -> m B.ByteString+readDefaultDataFile "reference.docx" =+ B.concat . BL.toChunks . fromArchive <$> getDefaultReferenceDocx+readDefaultDataFile "reference.pptx" =+ B.concat . BL.toChunks . fromArchive <$> getDefaultReferencePptx+readDefaultDataFile "reference.odt" =+ B.concat . BL.toChunks . fromArchive <$> getDefaultReferenceODT+readDefaultDataFile fname =+#ifdef EMBED_DATA_FILES+ case lookup (makeCanonical fname) dataFiles of+ Nothing -> throwError $ PandocCouldNotFindDataFileError $ T.pack fname+ Just contents -> return contents+#else+ getDataFileName fname' >>= checkExistence >>= readFileStrict+ where fname' = if fname == "MANUAL.txt" then fname else "data" </> fname -dataFiles' :: [(FilePath, B.ByteString)]-dataFiles' = ("MANUAL.txt", $(embedFile "MANUAL.txt")) :- -- handle the hidden file separately, since embedDir doesn't- -- include it:- ("docx/_rels/.rels", $(embedFile "data/docx/_rels/.rels")) :- ("pptx/_rels/.rels", $(embedFile "data/pptx/_rels/.rels")) :- $(embedDir "data")+-- | Returns the input filename unchanged if the file exits, and throws+-- a `PandocCouldNotFindDataFileError` if it doesn't.+checkExistence :: PandocMonad m => FilePath -> m FilePath+checkExistence fn = do+ exists <- fileExists fn+ if exists+ then return fn+ else throwError $ PandocCouldNotFindDataFileError $ T.pack fn+#endif++--- | Read file from user data directory or,+--- if not found there, from the default data files.+readDataFile :: PandocMonad m => FilePath -> m B.ByteString+readDataFile fname = do+ datadir <- checkUserDataDir fname+ case datadir of+ Nothing -> readDefaultDataFile fname+ Just userDir -> do+ exists <- fileExists (userDir </> fname)+ if exists+ then readFileStrict (userDir </> fname)+ else readDefaultDataFile fname++-- | Retrieve default reference.docx.+getDefaultReferenceDocx :: PandocMonad m => m Archive+getDefaultReferenceDocx = do+ let paths = ["[Content_Types].xml",+ "_rels/.rels",+ "docProps/app.xml",+ "docProps/core.xml",+ "docProps/custom.xml",+ "word/document.xml",+ "word/fontTable.xml",+ "word/footnotes.xml",+ "word/comments.xml",+ "word/numbering.xml",+ "word/settings.xml",+ "word/webSettings.xml",+ "word/styles.xml",+ "word/_rels/document.xml.rels",+ "word/_rels/footnotes.xml.rels",+ "word/theme/theme1.xml"]+ let toLazy = BL.fromChunks . (:[])+ let pathToEntry path = do+ epochtime <- floor . utcTimeToPOSIXSeconds <$> getTimestamp+ contents <- toLazy <$> readDataFile ("docx/" ++ path)+ return $ toEntry path epochtime contents+ datadir <- getUserDataDir+ mbArchive <- case datadir of+ Nothing -> return Nothing+ Just d -> do+ exists <- fileExists (d </> "reference.docx")+ if exists+ then return (Just (d </> "reference.docx"))+ else return Nothing+ case mbArchive of+ Just arch -> toArchive <$> readFileLazy arch+ Nothing -> foldr addEntryToArchive emptyArchive <$>+ mapM pathToEntry paths++-- | Retrieve default reference.odt.+getDefaultReferenceODT :: PandocMonad m => m Archive+getDefaultReferenceODT = do+ let paths = ["mimetype",+ "manifest.rdf",+ "styles.xml",+ "content.xml",+ "meta.xml",+ "META-INF/manifest.xml"]+ let pathToEntry path = do epochtime <- floor `fmap` getPOSIXTime+ contents <- (BL.fromChunks . (:[])) `fmap`+ readDataFile ("odt/" ++ path)+ return $ toEntry path epochtime contents+ datadir <- getUserDataDir+ mbArchive <- case datadir of+ Nothing -> return Nothing+ Just d -> do+ exists <- fileExists (d </> "reference.odt")+ if exists+ then return (Just (d </> "reference.odt"))+ else return Nothing+ case mbArchive of+ Just arch -> toArchive <$> readFileLazy arch+ Nothing -> foldr addEntryToArchive emptyArchive <$>+ mapM pathToEntry paths++-- | Retrieve default reference.pptx.+getDefaultReferencePptx :: PandocMonad m => m Archive+getDefaultReferencePptx = do+ -- We're going to narrow this down substantially once we get it+ -- working.+ let paths = [ "[Content_Types].xml"+ , "_rels/.rels"+ , "docProps/app.xml"+ , "docProps/core.xml"+ , "ppt/_rels/presentation.xml.rels"+ , "ppt/presProps.xml"+ , "ppt/presentation.xml"+ , "ppt/slideLayouts/_rels/slideLayout1.xml.rels"+ , "ppt/slideLayouts/_rels/slideLayout2.xml.rels"+ , "ppt/slideLayouts/_rels/slideLayout3.xml.rels"+ , "ppt/slideLayouts/_rels/slideLayout4.xml.rels"+ , "ppt/slideLayouts/_rels/slideLayout5.xml.rels"+ , "ppt/slideLayouts/_rels/slideLayout6.xml.rels"+ , "ppt/slideLayouts/_rels/slideLayout7.xml.rels"+ , "ppt/slideLayouts/_rels/slideLayout8.xml.rels"+ , "ppt/slideLayouts/_rels/slideLayout9.xml.rels"+ , "ppt/slideLayouts/_rels/slideLayout10.xml.rels"+ , "ppt/slideLayouts/_rels/slideLayout11.xml.rels"+ , "ppt/slideLayouts/slideLayout1.xml"+ , "ppt/slideLayouts/slideLayout10.xml"+ , "ppt/slideLayouts/slideLayout11.xml"+ , "ppt/slideLayouts/slideLayout2.xml"+ , "ppt/slideLayouts/slideLayout3.xml"+ , "ppt/slideLayouts/slideLayout4.xml"+ , "ppt/slideLayouts/slideLayout5.xml"+ , "ppt/slideLayouts/slideLayout6.xml"+ , "ppt/slideLayouts/slideLayout7.xml"+ , "ppt/slideLayouts/slideLayout8.xml"+ , "ppt/slideLayouts/slideLayout9.xml"+ , "ppt/slideMasters/_rels/slideMaster1.xml.rels"+ , "ppt/slideMasters/slideMaster1.xml"+ , "ppt/slides/_rels/slide1.xml.rels"+ , "ppt/slides/slide1.xml"+ , "ppt/slides/_rels/slide2.xml.rels"+ , "ppt/slides/slide2.xml"+ , "ppt/slides/_rels/slide3.xml.rels"+ , "ppt/slides/slide3.xml"+ , "ppt/slides/_rels/slide4.xml.rels"+ , "ppt/slides/slide4.xml"+ , "ppt/tableStyles.xml"+ , "ppt/theme/theme1.xml"+ , "ppt/viewProps.xml"+ -- These relate to notes slides.+ , "ppt/notesMasters/notesMaster1.xml"+ , "ppt/notesMasters/_rels/notesMaster1.xml.rels"+ , "ppt/notesSlides/notesSlide1.xml"+ , "ppt/notesSlides/_rels/notesSlide1.xml.rels"+ , "ppt/notesSlides/notesSlide2.xml"+ , "ppt/notesSlides/_rels/notesSlide2.xml.rels"+ , "ppt/theme/theme2.xml"+ ]+ let toLazy = BL.fromChunks . (:[])+ let pathToEntry path = do+ epochtime <- floor <$> getPOSIXTime+ contents <- toLazy <$> readDataFile ("pptx/" ++ path)+ return $ toEntry path epochtime contents+ datadir <- getUserDataDir+ mbArchive <- case datadir of+ Nothing -> return Nothing+ Just d -> do+ exists <- fileExists (d </> "reference.pptx")+ if exists+ then return (Just (d </> "reference.pptx"))+ else return Nothing+ case mbArchive of+ Just arch -> toArchive <$> readFileLazy arch+ Nothing -> foldr addEntryToArchive emptyArchive <$>+ mapM pathToEntry paths++getDataFileNames :: IO [FilePath]+getDataFileNames = do+#ifdef EMBED_DATA_FILES+ let allDataFiles = map fst dataFiles+#else+ allDataFiles <- filter (\x -> x /= "." && x /= "..") <$>+ (getDataDir >>= getDirectoryContents)+#endif+ return $ "reference.docx" : "reference.odt" : "reference.pptx" : allDataFiles++-- | Return appropriate user data directory for platform. We use+-- XDG_DATA_HOME (or its default value), but for backwards compatibility,+-- we fall back to the legacy user data directory ($HOME/.pandoc on *nix)+-- if the XDG_DATA_HOME is missing and this exists. If neither directory+-- is present, we return the XDG data directory. If the XDG data directory+-- is not defined (e.g. because we are in an environment where $HOME is+-- not defined), we return the empty string.+defaultUserDataDir :: IO FilePath+defaultUserDataDir = do+ xdgDir <- E.catch (getXdgDirectory XdgData "pandoc")+ (\(_ :: E.SomeException) -> return mempty)+ xdgExists <- doesDirectoryExist xdgDir+ legacyDir <- E.catch (getAppUserDataDirectory "pandoc")+ (\(_ :: E.SomeException) -> return mempty)+ legacyDirExists <- doesDirectoryExist legacyDir+ if not xdgExists && legacyDirExists+ then return legacyDir+ else return xdgDir
@@ -0,0 +1,32 @@+{-# LANGUAGE TemplateHaskell #-}+{- |+Module : Text.Pandoc.Data.BakedIn+Copyright : Copyright (C) 2013-2024 John MacFarlane+License : GNU GPL, version 2 or above++Maintainer : John MacFarlane <jgm@berkeley@edu>+Stability : alpha+Portability : portable++Provide contents data files as Haskell values.+-}+module Text.Pandoc.Data.BakedIn (dataFiles) where++import qualified Data.ByteString as B+import Data.FileEmbed+import System.FilePath (splitDirectories)+import qualified System.FilePath.Posix as Posix++-- We ensure that the data files are stored using Posix+-- path separators (/), even on Windows.+dataFiles :: [(FilePath, B.ByteString)]+dataFiles = map (\(fp, contents) ->+ (Posix.joinPath (splitDirectories fp), contents)) dataFiles'++dataFiles' :: [(FilePath, B.ByteString)]+dataFiles' = ("MANUAL.txt", $(embedFile "MANUAL.txt")) :+ -- handle the hidden file separately, since embedDir doesn't+ -- include it:+ ("docx/_rels/.rels", $(embedFile "data/docx/_rels/.rels")) :+ ("pptx/_rels/.rels", $(embedFile "data/pptx/_rels/.rels")) :+ $(embedDir "data")
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Error- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -23,27 +23,20 @@ import Data.Typeable (Typeable) import Data.Word (Word8) import Data.Text (Text)-import Data.List (sortOn) import qualified Data.Text as T-import Data.Ord (Down(..)) import GHC.Generics (Generic)-import Network.HTTP.Client (HttpException) import System.Exit (ExitCode (..), exitWith) import System.IO (stderr) import qualified Text.Pandoc.UTF8 as UTF8-import Text.Pandoc.Sources (Sources(..)) import Text.Printf (printf)-import Text.Parsec.Error-import Text.Parsec.Pos hiding (Line) import Text.Pandoc.Shared (tshow) import Citeproc (CiteprocError, prettyCiteprocError) data PandocError = PandocIOError Text IOError- | PandocHttpError Text HttpException+ | PandocHttpError Text Text | PandocShouldNeverHappenError Text | PandocSomeError Text | PandocParseError Text- | PandocParsecError Sources ParseError | PandocMakePDFError Text | PandocOptionError Text | PandocSyntaxMapError Text@@ -53,92 +46,81 @@ | PandocXMLError Text Text | PandocFilterError Text Text | PandocLuaError Text+ | PandocNoScriptingEngine | PandocCouldNotFindDataFileError Text | PandocCouldNotFindMetadataFileError Text | PandocResourceNotFound Text | PandocTemplateError Text+ | PandocNoTemplateError Text | PandocAppError Text | PandocEpubSubdirectoryError Text | PandocMacroLoop Text | PandocUTF8DecodingError Text Int Word8 | PandocIpynbDecodingError Text | PandocUnsupportedCharsetError Text+ | PandocFormatError Text Text | PandocUnknownReaderError Text | PandocUnknownWriterError Text | PandocUnsupportedExtensionError Text Text | PandocCiteprocError CiteprocError | PandocBibliographyError Text Text+ | PandocInputNotTextError Text deriving (Show, Typeable, Generic) instance Exception PandocError+ where+ displayException = T.unpack . renderError renderError :: PandocError -> Text renderError e = case e of PandocIOError _ err' -> T.pack $ displayException err'- PandocHttpError u err' ->- "Could not fetch " <> u <> "\n" <> tshow err'+ PandocHttpError u err' -> "Could not fetch " <> u <> "\n" <> err' PandocShouldNeverHappenError s -> "Something we thought was impossible happened!\n" <> "Please report this to pandoc's developers: " <> s PandocSomeError s -> s PandocParseError s -> s- PandocParsecError (Sources inputs) err' ->- let errPos = errorPos err'- errLine = sourceLine errPos- errColumn = sourceColumn errPos- errFile = sourceName errPos- errorInFile =- case sortOn (Down . sourceLine . fst)- [ (pos,t)- | (pos,t) <- inputs- , sourceName pos == errFile- , sourceLine pos <= errLine- ] of- [] -> ""- ((pos,txt):_) ->- let ls = T.lines txt <> [""]- ln = (errLine - sourceLine pos) + 1- in if length ls > ln && ln >= 1- then T.concat ["\n", ls !! (ln - 1)- ,"\n", T.replicate (errColumn - 1) " "- ,"^"]- else ""- in "Error at " <> tshow err' <> errorInFile PandocMakePDFError s -> s PandocOptionError s -> s PandocSyntaxMapError s -> s PandocFailOnWarningError -> "Failing because there were warnings." PandocPDFProgramNotFoundError pdfprog ->- pdfprog <> " not found. Please select a different --pdf-engine or install " <> pdfprog+ quote pdfprog <> " not found. Please select a different --pdf-engine or install "+ <> quote pdfprog PandocPDFError logmsg -> "Error producing PDF.\n" <> logmsg PandocXMLError fp logmsg -> "Invalid XML" <>- (if T.null fp then "" else " in " <> fp) <> ":\n" <> logmsg+ (if T.null fp then "" else " in " <> quote fp) <> ":\n" <> logmsg PandocFilterError filtername msg -> "Error running filter " <>- filtername <> ":\n" <> msg+ quote filtername <> ":\n" <> msg PandocLuaError msg -> "Error running Lua:\n" <> msg+ PandocNoScriptingEngine -> "This version of pandoc has been compiled " <>+ "without Lua support." PandocCouldNotFindDataFileError fn ->- "Could not find data file " <> fn+ "Could not find data file " <> quote fn PandocCouldNotFindMetadataFileError fn ->- "Could not find metadata file " <> fn+ "Could not find metadata file " <> quote fn PandocResourceNotFound fn ->- "File " <> fn <> " not found in resource path"- PandocTemplateError s -> "Error compiling template " <> s+ "File " <> quote fn <> " not found in resource path"+ PandocTemplateError s -> "Error compiling template " <> quote s+ PandocNoTemplateError fp -> "No template defined in " <> quote fp PandocAppError s -> s PandocEpubSubdirectoryError s ->- "EPUB subdirectory name '" <> s <> "' contains illegal characters"+ "EPUB subdirectory name " <> quote s <> " contains illegal characters" PandocMacroLoop s -> "Loop encountered in expanding macro " <> s PandocUTF8DecodingError f offset w ->- "UTF-8 decoding error in " <> f <> " at byte offset " <> tshow offset <>- " (" <> T.pack (printf "%2x" w) <> ").\n" <>- "The input must be a UTF-8 encoded text."+ "UTF-8 decoding error in " <> quote f <> " at byte offset "+ <> tshow offset <> " (" <> T.pack (printf "%2x" w) <> ").\n"+ <> "The input must be a UTF-8 encoded text." PandocIpynbDecodingError w -> "ipynb decoding error: " <> w PandocUnsupportedCharsetError charset ->- "Unsupported charset " <> charset+ "Unsupported charset " <> quote charset+ PandocFormatError format s ->+ "Error parsing format " <> quote format <> ": " <> s PandocUnknownReaderError r ->- "Unknown input format " <> r <>+ "Unknown input format " <> quote r <> case r of "doc" -> "\nPandoc can convert from DOCX, but not from DOC." <> "\nTry using Word to save your DOC file as DOCX," <>@@ -146,29 +128,41 @@ "pdf" -> "\nPandoc can convert to PDF, but not from PDF." _ -> "" PandocUnknownWriterError w ->- "Unknown output format " <> w <>+ "Unknown output format " <> quote w <> case w of "pdf" -> "To create a pdf using pandoc, use" <>- " -t latex|beamer|context|ms|html5" <>+ " -t latex|beamer|context|ms|html5|typst" <> "\nand specify an output file with " <> ".pdf extension (-o filename.pdf)." "doc" -> "\nPandoc can convert to DOCX, but not to DOC." _ -> "" PandocUnsupportedExtensionError ext f ->- "The extension " <> ext <> " is not supported " <>- "for " <> f+ "The extension " <> quote ext <> " is not supported " <>+ "for " <> f <> ".\nUse --list-extensions=" <> f <> " to " <>+ "list supported extensions." PandocCiteprocError e' -> prettyCiteprocError e' PandocBibliographyError fp msg ->- "Error reading bibliography file " <> fp <> ":\n" <> msg+ "Error reading bibliography file " <> quote fp <> ":\n" <> msg+ PandocInputNotTextError fp ->+ "Expected text as an input, but received binary data from " <>+ (if T.null fp+ then "stdin"+ else "file " <> quote fp) <>+ ".\nIf you intended to convert from binary format, verify that it's " <>+ "supported and use\nexplicit -f FORMAT." +quote :: Text -> Text+quote s = "'" <> s <> "'" -- | Handle PandocError by exiting with an error message. handleError :: Either PandocError a -> IO a handleError (Right r) = return r handleError (Left e) = case e of- PandocIOError _ err' -> ioError err'+ PandocIOError _ err' -> do+ putStrLn $ displayException err'+ exitWith (ExitFailure 1) _ -> err exitCode (renderError e) where exitCode =@@ -178,6 +172,7 @@ PandocAppError{} -> 4 PandocTemplateError{} -> 5 PandocOptionError{} -> 6+ PandocFormatError{} -> 20 PandocUnknownReaderError{} -> 21 PandocUnknownWriterError{} -> 22 PandocUnsupportedExtensionError{} -> 23@@ -191,15 +186,17 @@ PandocShouldNeverHappenError{} -> 62 PandocSomeError{} -> 63 PandocParseError{} -> 64- PandocParsecError{} -> 65 PandocMakePDFError{} -> 66 PandocSyntaxMapError{} -> 67 PandocFilterError{} -> 83 PandocLuaError{} -> 84+ PandocNoTemplateError{} -> 87+ PandocNoScriptingEngine -> 89 PandocMacroLoop{} -> 91 PandocUTF8DecodingError{} -> 92 PandocIpynbDecodingError{} -> 93 PandocUnsupportedCharsetError{} -> 94+ PandocInputNotTextError{} -> 95 PandocCouldNotFindDataFileError{} -> 97 PandocCouldNotFindMetadataFileError{} -> 98 PandocResourceNotFound{} -> 99
@@ -1,12 +1,10 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Extensions- Copyright : Copyright (C) 2012-2022 John MacFarlane+ Copyright : Copyright (C) 2012-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -16,13 +14,16 @@ Data structures and functions for representing markup extensions. -} module Text.Pandoc.Extensions ( Extension(..)+ , readExtension+ , showExtension , Extensions , emptyExtensions , extensionsFromList- , parseFormatSpec+ , extensionsToList , extensionEnabled , enableExtension , disableExtension+ , disableExtensions , getDefaultExtensions , getAllExtensions , pandocExtensions@@ -32,20 +33,19 @@ , githubMarkdownExtensions , multimarkdownExtensions ) where-import Data.Bits (clearBit, setBit, testBit, (.|.)) import Data.Data (Data)-import Data.List (foldl') import qualified Data.Text as T import Data.Typeable (Typeable) import GHC.Generics (Generic)-import Safe (readMay)-import Text.Parsec-import Data.Aeson.TH (deriveJSON)+import Text.Read (readMaybe) import Data.Aeson+import Data.List (sort)+import qualified Data.Set as Set -- | Individually selectable syntax extensions. data Extension = Ext_abbreviations -- ^ PHP markdown extra abbreviation definitions+ | Ext_alerts -- ^ Special block quotes become alerts | Ext_all_symbols_escapable -- ^ Make all non-alphanumerics escapable | Ext_amuse -- ^ Enable Text::Amuse extensions to Emacs Muse markup | Ext_angle_brackets_escapable -- ^ Make < and > escapable@@ -59,8 +59,6 @@ | Ext_blank_before_header -- ^ Require blank line before a header | Ext_bracketed_spans -- ^ Bracketed spans with attributes | Ext_citations -- ^ Pandoc/citeproc citations- | Ext_compact_definition_lists -- ^ Definition lists without space between items,- -- and disallow laziness | Ext_definition_lists -- ^ Definition lists as in pandoc, mmd, php | Ext_east_asian_line_breaks -- ^ Newlines in paragraphs are ignored between -- East Asian wide characters. Note: this extension@@ -86,6 +84,7 @@ | Ext_gutenberg -- ^ Use Project Gutenberg conventions for plain | Ext_hard_line_breaks -- ^ All newlines become hard line breaks | Ext_header_attributes -- ^ Explicit header attributes {#id .class k=v}+ | Ext_table_attributes -- ^ Explicit table attributes after caption | Ext_ignore_line_breaks -- ^ Newlines in paragraphs are ignored | Ext_implicit_figures -- ^ A paragraph with just an image is a figure | Ext_implicit_header_references -- ^ Implicit reference links for headers@@ -97,6 +96,7 @@ | Ext_link_attributes -- ^ link and image attributes | Ext_lists_without_preceding_blankline -- ^ Allow lists without preceding blank | Ext_literate_haskell -- ^ Enable literate Haskell conventions+ | Ext_mark -- ^ Enable ==mark== syntax to highlight text | Ext_markdown_attribute -- ^ Interpret text inside HTML as markdown iff -- container has attribute 'markdown' | Ext_markdown_in_html_blocks -- ^ Interpret as markdown inside HTML blocks@@ -121,6 +121,8 @@ | Ext_shortcut_reference_links -- ^ Shortcut reference links | Ext_simple_tables -- ^ Pandoc-style simple tables | Ext_smart -- ^ "Smart" quotes, apostrophes, ellipses, dashes+ | Ext_smart_quotes -- ^ "Smart" quotes+ | Ext_special_strings -- ^ Treat certain strings like special characters | Ext_sourcepos -- ^ Include source position attributes | Ext_space_in_atx_header -- ^ Require space between # and header text | Ext_spaced_reference_links -- ^ Allow space between two parts of ref link@@ -129,50 +131,85 @@ | Ext_subscript -- ^ Subscript using ~this~ syntax | Ext_superscript -- ^ Superscript using ^this^ syntax | Ext_styles -- ^ Read styles that pandoc doesn't know+ | Ext_tagging -- ^ Output optimized for PDF tagging | Ext_task_lists -- ^ Parse certain list items as task list items | Ext_table_captions -- ^ Pandoc-style table captions | Ext_tex_math_dollars -- ^ TeX math between $..$ or $$..$$+ | Ext_tex_math_gfm -- ^ Additional TeX math style used in GFM | Ext_tex_math_double_backslash -- ^ TeX math btw \\(..\\) \\[..\\] | Ext_tex_math_single_backslash -- ^ TeX math btw \(..\) \[..\]+ | Ext_wikilinks_title_after_pipe -- ^ Support wikilinks of style+ -- [[target|title]]+ | Ext_wikilinks_title_before_pipe -- ^ Support wikilinks of style+ -- [[title|target]] | Ext_xrefs_name -- ^ Use xrefs with names | Ext_xrefs_number -- ^ Use xrefs with numbers | Ext_yaml_metadata_block -- ^ YAML metadata block- deriving (Show, Read, Enum, Eq, Ord, Bounded, Data, Typeable, Generic)+ | CustomExtension T.Text -- ^ Custom extension+ deriving (Show, Read, Eq, Ord, Data, Typeable, Generic) -$(deriveJSON defaultOptions{ constructorTagModifier = drop 4 } ''Extension)+instance FromJSON Extension where+ parseJSON = withText "Extension" (pure . readExtension . T.unpack) -newtype Extensions = Extensions Integer+instance ToJSON Extension where+ toJSON = String . showExtension++newtype Extensions = Extensions (Set.Set Extension) deriving (Show, Read, Eq, Ord, Data, Typeable, Generic) instance Semigroup Extensions where- (Extensions a) <> (Extensions b) = Extensions (a .|. b)+ (Extensions a) <> (Extensions b) = Extensions (a <> b) instance Monoid Extensions where- mempty = Extensions 0+ mempty = Extensions mempty mappend = (<>) instance FromJSON Extensions where- parseJSON =- return . foldr enableExtension emptyExtensions . fromJSON+ parseJSON = fmap extensionsFromList . parseJSON instance ToJSON Extensions where- toJSON exts = toJSON $- [ext | ext <- [minBound..maxBound], extensionEnabled ext exts]+ toJSON (Extensions exts) = toJSON exts +-- | Reads a single extension from a string.+readExtension :: String -> Extension+readExtension "lhs" = Ext_literate_haskell+readExtension name =+ case readMaybe ("Ext_" ++ name) of+ Just ext -> ext+ Nothing -> CustomExtension (T.pack name)++-- | Show an extension in human-readable form.+showExtension :: Extension -> T.Text+showExtension ext =+ case ext of+ CustomExtension t -> t+ _ -> T.drop 4 $ T.pack $ show ext+ extensionsFromList :: [Extension] -> Extensions-extensionsFromList = foldr enableExtension emptyExtensions+extensionsFromList = Extensions . Set.fromList +extensionsToList :: Extensions -> [Extension]+extensionsToList (Extensions extset) = sort $ Set.toList extset+ emptyExtensions :: Extensions-emptyExtensions = Extensions 0+emptyExtensions = Extensions mempty extensionEnabled :: Extension -> Extensions -> Bool-extensionEnabled x (Extensions exts) = testBit exts (fromEnum x)+extensionEnabled x (Extensions exts) = x `Set.member` exts enableExtension :: Extension -> Extensions -> Extensions-enableExtension x (Extensions exts) = Extensions (setBit exts (fromEnum x))+enableExtension x (Extensions exts) = Extensions (Set.insert x exts) disableExtension :: Extension -> Extensions -> Extensions-disableExtension x (Extensions exts) = Extensions (clearBit exts (fromEnum x))+disableExtension x (Extensions exts) = Extensions (Set.delete x exts) +-- | Removes the extensions in the second set from those in the first.+disableExtensions :: Extensions -- ^ base set+ -> Extensions -- ^ extensions to remove+ -> Extensions+disableExtensions (Extensions base) (Extensions remove) = Extensions $+ -- keep only those extensions that are in `base` but not in `remove`.+ base `Set.difference` remove+ -- | Extensions to be used with pandoc-flavored markdown. pandocExtensions :: Extensions pandocExtensions = extensionsFromList@@ -217,6 +254,7 @@ , Ext_task_lists , Ext_auto_identifiers , Ext_header_attributes+ , Ext_table_attributes , Ext_link_attributes , Ext_implicit_header_references , Ext_line_blocks@@ -273,6 +311,8 @@ , Ext_emoji , Ext_fenced_code_blocks , Ext_backtick_code_blocks+ , Ext_footnotes+ , Ext_alerts ] -- | Extensions to be used with multimarkdown.@@ -364,6 +404,8 @@ , Ext_yaml_metadata_block , Ext_footnotes , Ext_tex_math_dollars+ , Ext_tex_math_gfm+ , Ext_alerts ] getDefaultExtensions "commonmark" = extensionsFromList [Ext_raw_html]@@ -374,8 +416,6 @@ , Ext_strikeout , Ext_task_lists , Ext_emoji- , Ext_pipe_tables- , Ext_raw_html , Ext_smart , Ext_tex_math_dollars , Ext_superscript@@ -388,10 +428,12 @@ , Ext_raw_attribute , Ext_implicit_header_references , Ext_attributes+ , Ext_alerts , Ext_yaml_metadata_block ] getDefaultExtensions "org" = extensionsFromList [Ext_citations,+ Ext_special_strings, Ext_task_lists, Ext_auto_identifiers] getDefaultExtensions "html" = extensionsFromList@@ -432,6 +474,9 @@ getDefaultExtensions "opml" = pandocExtensions -- affects notes getDefaultExtensions "markua" = extensionsFromList []+getDefaultExtensions "typst" = extensionsFromList [Ext_citations,+ Ext_smart]+getDefaultExtensions "dokuwiki" = extensionsFromList [Ext_smart] getDefaultExtensions _ = extensionsFromList [Ext_auto_identifiers] @@ -466,14 +511,17 @@ , Ext_mmd_title_block , Ext_abbreviations , Ext_autolink_bare_uris+ , Ext_mark , Ext_mmd_link_attributes , Ext_mmd_header_identifiers- , Ext_compact_definition_lists , Ext_gutenberg , Ext_smart , Ext_literate_haskell , Ext_short_subsuperscripts , Ext_rebase_relative_paths+ , Ext_wikilinks_title_after_pipe+ , Ext_wikilinks_title_before_pipe+ , Ext_alerts ] getAll "markdown_strict" = allMarkdownExtensions getAll "markdown_phpextra" = allMarkdownExtensions@@ -511,10 +559,12 @@ , Ext_task_lists , Ext_emoji , Ext_raw_html+ , Ext_alerts , Ext_implicit_figures , Ext_hard_line_breaks , Ext_smart , Ext_tex_math_dollars+ , Ext_tex_math_gfm , Ext_superscript , Ext_subscript , Ext_definition_lists@@ -526,6 +576,8 @@ , Ext_implicit_header_references , Ext_attributes , Ext_sourcepos+ , Ext_wikilinks_title_after_pipe+ , Ext_wikilinks_title_before_pipe , Ext_yaml_metadata_block , Ext_rebase_relative_paths ]@@ -534,6 +586,8 @@ extensionsFromList [ Ext_citations , Ext_smart+ , Ext_smart_quotes+ , Ext_special_strings , Ext_fancy_lists , Ext_task_lists ]@@ -565,6 +619,7 @@ , Ext_raw_tex , Ext_task_lists , Ext_literate_haskell+ , Ext_empty_paragraphs ] getAll "beamer" = getAll "latex" getAll "context" = autoIdExtensions <>@@ -572,6 +627,7 @@ [ Ext_smart , Ext_raw_tex , Ext_ntb+ , Ext_tagging ] getAll "textile" = autoIdExtensions <> extensionsFromList@@ -594,7 +650,9 @@ getAll "vimwiki" = autoIdExtensions getAll "dokuwiki" = autoIdExtensions <> extensionsFromList- [ Ext_tex_math_dollars ]+ [ Ext_tex_math_dollars+ , Ext_raw_html+ , Ext_smart ] getAll "tikiwiki" = autoIdExtensions getAll "rst" = autoIdExtensions <> extensionsFromList@@ -604,31 +662,7 @@ getAll "mediawiki" = autoIdExtensions <> extensionsFromList [ Ext_smart ]+ getAll "typst" = extensionsFromList [Ext_citations, Ext_smart]+ getAll "djot" = extensionsFromList [Ext_sourcepos]+ getAll "man" = autoIdExtensions getAll _ = mempty----- | Parse a format-specifying string into a markup format,--- a set of extensions to enable, and a set of extensions to disable.-parseFormatSpec :: T.Text- -> Either ParseError (T.Text, [Extension], [Extension])-parseFormatSpec = parse formatSpec ""- where formatSpec = do- name <- formatName- (extsToEnable, extsToDisable) <- foldl' (flip ($)) ([],[]) <$>- many extMod- return (T.pack name, reverse extsToEnable, reverse extsToDisable)- formatName = many1 $ noneOf "-+"- extMod = do- polarity <- oneOf "-+"- name <- many $ noneOf "-+"- ext <- case readMay ("Ext_" ++ name) of- Just n -> return n- Nothing- | name == "lhs" -> return Ext_literate_haskell- | otherwise -> unexpected $- "unknown extension: " ++ name- return $ \(extsToEnable, extsToDisable) ->- case polarity of- '+' -> (ext : extsToEnable, extsToDisable)- _ -> (extsToEnable, ext : extsToDisable)-
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Filter- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu>@@ -16,6 +16,7 @@ ( Filter (..) , Environment (..) , applyFilters+ , applyJSONFilter ) where import System.CPUTime (getCPUTime)@@ -28,8 +29,8 @@ import Text.Pandoc.Filter.Environment (Environment (..)) import Text.Pandoc.Logging import Text.Pandoc.Citeproc (processCitations)+import Text.Pandoc.Scripting (ScriptingEngine (engineApplyFilter)) import qualified Text.Pandoc.Filter.JSON as JSONFilter-import qualified Text.Pandoc.Filter.Lua as LuaFilter import qualified Data.Text as T import System.FilePath (takeExtension) import Control.Applicative ((<|>))@@ -40,7 +41,7 @@ data Filter = LuaFilter FilePath | JSONFilter FilePath | CiteprocFilter -- built-in citeproc- deriving (Show, Generic)+ deriving (Show, Generic, Eq) instance FromJSON Filter where parseJSON node =@@ -73,21 +74,22 @@ -- | Modify the given document using a filter. applyFilters :: (PandocMonad m, MonadIO m)- => Environment+ => ScriptingEngine+ -> Environment -> [Filter] -> [String] -> Pandoc -> m Pandoc-applyFilters fenv filters args d = do+applyFilters scrngin fenv filters args d = do expandedFilters <- mapM expandFilterPath filters foldM applyFilter d expandedFilters where applyFilter doc (JSONFilter f) = withMessages f $ JSONFilter.apply fenv args f doc applyFilter doc (LuaFilter f) =- withMessages f $ LuaFilter.apply fenv args f doc+ withMessages f $ engineApplyFilter scrngin fenv args f doc applyFilter doc CiteprocFilter =- processCitations doc+ withMessages "citeproc" $ processCitations doc withMessages f action = do verbosity <- getVerbosity when (verbosity == INFO) $ report $ RunningFilter f@@ -106,3 +108,11 @@ filterPath :: PandocMonad m => FilePath -> m FilePath filterPath fp = fromMaybe fp <$> findFileWithDataFallback "filters" fp++applyJSONFilter :: MonadIO m+ => Environment+ -> [String]+ -> FilePath+ -> Pandoc+ -> m Pandoc+applyJSONFilter = JSONFilter.apply
@@ -3,7 +3,7 @@ Copyright : ©2020-2021 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Filter- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu>@@ -27,7 +27,8 @@ import Text.Pandoc.Error (PandocError (PandocFilterError)) import Text.Pandoc.Filter.Environment (Environment (..)) import Text.Pandoc.Process (pipeProcess)-import Text.Pandoc.Shared (pandocVersion, tshow)+import Text.Pandoc.Version (pandocVersionText)+import Text.Pandoc.Shared (tshow) import qualified Control.Exception as E import qualified Text.Pandoc.UTF8 as UTF8 @@ -65,7 +66,7 @@ let ropts = envReaderOptions fenv env <- getEnvironment let env' = Just- ( ("PANDOC_VERSION", T.unpack pandocVersion)+ ( ("PANDOC_VERSION", T.unpack pandocVersionText) : ("PANDOC_READER_OPTIONS", UTF8.toStringLazy (encode ropts)) : env ) (exitcode, outbs) <- E.handle filterException $
@@ -1,51 +0,0 @@-{- |- Module : Text.Pandoc.Filter.Lua- Copyright : Copyright (C) 2006-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley@edu>- Stability : alpha- Portability : portable--Apply Lua filters to modify a pandoc documents programmatically.--}-module Text.Pandoc.Filter.Lua (apply) where--import Control.Exception (throw)-import Control.Monad ((>=>))-import qualified Data.Text as T-import Text.Pandoc.Class (PandocMonad)-import Control.Monad.Trans (MonadIO)-import Text.Pandoc.Definition (Pandoc)-import Text.Pandoc.Error (PandocError (PandocFilterError, PandocLuaError))-import Text.Pandoc.Filter.Environment (Environment (..))-import Text.Pandoc.Lua (Global (..), runLua, runFilterFile, setGlobals)---- | Run the Lua filter in @filterPath@ for a transformation to the--- target format (first element in args). Pandoc uses Lua init files to--- setup the Lua interpreter.-apply :: (PandocMonad m, MonadIO m)- => Environment- -> [String]- -> FilePath- -> Pandoc- -> m Pandoc-apply fenv args fp doc = do- let format = case args of- (x:_) -> x- _ -> error "Format not supplied for Lua filter"- runLua >=> forceResult fp $ do- setGlobals [ FORMAT $ T.pack format- , PANDOC_READER_OPTIONS (envReaderOptions fenv)- , PANDOC_WRITER_OPTIONS (envWriterOptions fenv)- , PANDOC_SCRIPT_FILE fp- ]- runFilterFile fp doc--forceResult :: (PandocMonad m, MonadIO m)- => FilePath -> Either PandocError Pandoc -> m Pandoc-forceResult fp eitherResult = case eitherResult of- Right x -> return x- Left err -> throw . PandocFilterError (T.pack fp) $ case err of- PandocLuaError msg -> msg- _ -> T.pack $ show err
@@ -0,0 +1,251 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Format+ Copyright : © 2022-2024 Albert Krewinkel+ License : GPL-2.0-or-later+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com>++Handling of format specifiers for input and output.+-}+module Text.Pandoc.Format+ ( FlavoredFormat (..)+ , ExtensionsConfig (..)+ , ExtensionsDiff (..)+ , diffExtensions+ , parseFlavoredFormat+ , applyExtensionsDiff+ , getExtensionsConfig+ , formatFromFilePaths+ ) where++import Control.Monad.Except (throwError)+import Data.Char (toLower)+import Data.Foldable (asum)+import qualified Data.List as L+import System.FilePath (splitExtension, takeExtension)+import Text.Pandoc.Class (PandocMonad)+import Text.Pandoc.Error (PandocError (..))+import Text.Pandoc.Extensions+ ( Extension (Ext_literate_haskell)+ , Extensions+ , disableExtensions+ , enableExtension+ , extensionsFromList+ , extensionsToList+ , getAllExtensions+ , getDefaultExtensions+ , showExtension+ , readExtension+ )+import Network.URI (URI (..), parseURI)+import Text.Pandoc.Parsing+import qualified Data.Text as T++-- | Format specifier with the format's name and the lists of extensions+-- to be enabled or disabled.+data FlavoredFormat = FlavoredFormat+ { formatName :: T.Text+ , formatExtsDiff :: ExtensionsDiff+ } deriving (Show)++-- | Changes to a set of extensions, i.e., list of extensions to be+-- enabled or disabled.+data ExtensionsDiff = ExtensionsDiff+ { extsToEnable :: Extensions+ , extsToDisable :: Extensions+ } deriving (Show)++instance Semigroup ExtensionsDiff where+ ExtensionsDiff enA disA <> ExtensionsDiff enB disB =+ ExtensionsDiff+ ((enA `disableExtensions` disB) <> enB)+ ((disA `disableExtensions` enB) <> disB)++instance Monoid ExtensionsDiff where+ mempty = ExtensionsDiff mempty mempty+ mappend = (<>)++-- | Calculate the change set to get from one set of extensions to+-- another.+diffExtensions :: Extensions -> Extensions -> ExtensionsDiff+diffExtensions def actual = ExtensionsDiff+ { extsToEnable = actual `disableExtensions` def+ , extsToDisable = def `disableExtensions` actual+ }++-- | Describes the properties of a format.+data ExtensionsConfig = ExtensionsConfig+ { extsDefault :: Extensions -- ^ Extensions enabled by default+ , extsSupported :: Extensions -- ^ Extensions that can be enabled or disabled.+ } deriving (Show)++-- | Returns the extensions configuration of a format.+getExtensionsConfig :: T.Text -> ExtensionsConfig+getExtensionsConfig fmt = ExtensionsConfig+ { extsDefault = getDefaultExtensions fmt+ , extsSupported = getAllExtensions fmt+ }++instance Semigroup ExtensionsConfig where+ ExtensionsConfig x1 y1 <> ExtensionsConfig x2 y2 =+ ExtensionsConfig (x1 <> x2) (y1 <> y2)++instance Monoid ExtensionsConfig where+ mappend = (<>)+ mempty = ExtensionsConfig mempty mempty++-- | Apply the extension changes in the format spec to the extensions+-- given in the format's extensions configuration. Throws an error in+-- case of an unknown or unsupported extension.+applyExtensionsDiff :: PandocMonad m+ => ExtensionsConfig+ -> FlavoredFormat+ -> m Extensions+applyExtensionsDiff extConf (FlavoredFormat fname extsDiff) = do+ let extsInDiff = extsToEnable extsDiff <> extsToDisable extsDiff+ let unsupported = extsInDiff `disableExtensions` (extsSupported extConf)+ case extensionsToList unsupported of+ ext:_ -> throwError $ PandocUnsupportedExtensionError+ (showExtension ext) fname+ [] -> pure ((extsDefault extConf `disableExtensions`+ extsToDisable extsDiff) <> extsToEnable extsDiff)++-- | Parse a format-specifying string into a markup format and the+-- change set to the format's extensions. Throws an error if the spec+-- cannot be parsed or contains an unknown extension.+parseFlavoredFormat :: PandocMonad m+ => T.Text+ -> m FlavoredFormat+parseFlavoredFormat spec =+ -- Paths like `latex-foo-bar.lua` or `latex-smart-citations.lua`+ -- should be parsed as the format name. The `-` (or `+`) in the+ -- filename would confuse the extensions parser, so, if `spec` looks+ -- like a filename, the file's basename is split off into the prefix.+ -- Only the remaining part is parsed, and the prefix is appended back+ -- to the format after parsing.+ case parse (fixSourcePos *> formatSpec) "" spec' of+ Right (fname, extsDiff) -> pure (FlavoredFormat (prefix <> fname) extsDiff)+ Left err -> throwError $ PandocFormatError spec (T.pack $ show err)+ where+ fixSourcePos = do+ pos <- getPosition+ setPosition (incSourceColumn pos (T.length prefix))+ formatSpec = do+ name <- parseFormatName+ extsDiff <- pExtensionsDiff+ return ( T.pack name, extsDiff )+ parseFormatName = many1 $ noneOf "-+"+ (prefix, spec') = case splitExtension (T.unpack spec) of+ (_, "") -> ("", T.toLower spec) -- no extension+ (p,s) -> (T.pack p, T.pack s)++pExtensionsDiff :: (UpdateSourcePos s Char, Stream s m Char)+ => ParsecT s u m ExtensionsDiff+pExtensionsDiff = L.foldl' (flip ($)) mempty <$> many extMod+ where+ extMod = do+ polarity <- oneOf "-+"+ name <- many $ noneOf "-+"+ let ext = readExtension name+ return $ \extsDiff ->+ case polarity of+ '+' -> extsDiff{extsToEnable = enableExtension ext $+ extsToEnable extsDiff}+ _ -> extsDiff{extsToDisable = enableExtension ext $+ extsToDisable extsDiff}++-- | Determines default format based on file extensions; uses the format+-- of the first extension that's associated with a format.+--+-- Examples:+--+-- > formatFromFilePaths ["text.unknown", "no-extension"]+-- Nothing+--+-- > formatFromFilePaths ["my.md", "other.rst"]+-- Just "markdown"+formatFromFilePaths :: [FilePath] -> (Maybe FlavoredFormat)+formatFromFilePaths = asum . map formatFromFilePath++-- | Determines format based on file extension.+formatFromFilePath :: FilePath -> Maybe FlavoredFormat+formatFromFilePath x =+ case takeExtension (map toLower fpath) of+ ".Rmd" -> defFlavor "markdown"+ ".adoc" -> defFlavor "asciidoc"+ ".asciidoc" -> defFlavor "asciidoc"+ ".bib" -> defFlavor "biblatex"+ ".context" -> defFlavor "context"+ ".csv" -> defFlavor "csv"+ ".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"+ ".epub" -> defFlavor "epub"+ ".fb2" -> defFlavor "fb2"+ ".htm" -> defFlavor "html"+ ".html" -> defFlavor "html"+ ".icml" -> defFlavor "icml"+ ".ipynb" -> defFlavor "ipynb"+ ".json" -> defFlavor "json"+ ".latex" -> defFlavor "latex"+ ".lhs" -> defFlavor "markdown" `withExtension` Ext_literate_haskell+ ".ltx" -> defFlavor "latex"+ ".markdown" -> defFlavor "markdown"+ ".markua" -> defFlavor "markua"+ ".md" -> defFlavor "markdown"+ ".mdown" -> defFlavor "markdown"+ ".mdwn" -> defFlavor "markdown"+ ".mkd" -> defFlavor "markdown"+ ".mkdn" -> defFlavor "markdown"+ ".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"+ ".pdf" -> defFlavor "pdf" -- so we get an "unknown reader" error+ ".pl" -> defFlavor "pod"+ ".pm" -> defFlavor "pod"+ ".pod" -> defFlavor "pod"+ ".pptx" -> defFlavor "pptx"+ ".ris" -> defFlavor "ris"+ ".roff" -> defFlavor "ms"+ ".rst" -> defFlavor "rst"+ ".rtf" -> defFlavor "rtf"+ ".s5" -> defFlavor "s5"+ ".t2t" -> defFlavor "t2t"+ ".tei" -> defFlavor "tei"+ ".tex" -> defFlavor "latex"+ ".texi" -> defFlavor "texinfo"+ ".texinfo" -> defFlavor "texinfo"+ ".text" -> defFlavor "markdown"+ ".textile" -> defFlavor "textile"+ ".tsv" -> defFlavor "tsv"+ ".txt" -> defFlavor "markdown"+ ".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+ defFlavor f = Just (FlavoredFormat f mempty)+ withExtension Nothing _ = Nothing+ withExtension (Just (FlavoredFormat f ed)) ext = Just $+ FlavoredFormat f (ed <> ExtensionsDiff (extensionsFromList [ext]) mempty)+ fpath = case parseURI x of+ Nothing -> x+ Just URI{ uriPath = "" } -> "index.html"+ Just URI{ uriPath = "/" } -> "index.html"+ Just URI{ uriPath = up } -> up
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Highlighting- Copyright : Copyright (C) 2008-2022 John MacFarlane+ Copyright : Copyright (C) 2008-2025 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -15,12 +15,27 @@ , languages , languagesByExtension , highlight+ -- * Formats+ -- ** LaTeX , formatLaTeXInline , formatLaTeXBlock , styleToLaTeX+ -- ** HTML , formatHtmlInline , formatHtmlBlock+ , formatHtml4Block , styleToCss+ -- ** ConTeXt+ , formatConTeXtInline+ , formatConTeXtBlock+ , styleToConTeXt+ , formatANSI+ -- ** Typst+ , formatTypstBlock+ , formatTypstInline+ , styleToTypst+ -- * Styles+ , defaultStyle , pygments , espresso , zenburn@@ -34,18 +49,57 @@ , fromListingsLanguage , toListingsLanguage ) where-import Control.Monad+import Control.Monad ( msum ) import qualified Data.Map as M import Data.Maybe (fromMaybe) import qualified Data.Text as T import Skylighting-import Text.Pandoc.Definition+ ( SyntaxMap,+ breezeDark,+ espresso,+ haddock,+ kate,+ monochrome,+ pygments,+ tango,+ zenburn,+ formatHtml4Block,+ formatHtmlBlock,+ formatHtmlInline,+ styleToCss,+ formatConTeXtBlock,+ formatConTeXtInline,+ styleToConTeXt,+ formatLaTeXBlock,+ formatLaTeXInline,+ styleToLaTeX,+ formatTypstBlock,+ formatTypstInline,+ styleToTypst,+ formatANSI,+ Style,+ FormatOptions(containerClasses, startNumber, lineAnchors,+ numberLines, lineIdPrefix, codeClasses),+ SourceLine,+ lookupSyntax,+ syntaxesByExtension,+ parseTheme,+ tokenize,+ defaultFormatOpts,+ TokenizerConfig(traceOutput, TokenizerConfig, syntaxMap),+ Syntax(sShortname, sName),+ TokenType(NormalTok) )+import Text.Pandoc.Definition ( Attr ) import Text.Pandoc.Class (PandocMonad, readFileLazy) import Text.Pandoc.Error (PandocError(..)) import Control.Monad.Except (throwError) import System.FilePath (takeExtension) import Text.Pandoc.Shared (safeRead) +-- | The default highlighting style used by pandoc (pygments).+defaultStyle :: Style+defaultStyle = pygments+ highlightingStyles :: [(T.Text, Style)] highlightingStyles = [("pygments", pygments),@@ -236,4 +290,3 @@ Just sty -> return sty Nothing -> throwError $ PandocOptionError $ T.pack $ "Unknown highlight-style " ++ s-
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings, ScopedTypeVariables, CPP #-} {- | Module : Text.Pandoc.Image-Copyright : Copyright (C) 2020-2022 John MacFarlane+Copyright : Copyright (C) 2020-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -3,7 +3,7 @@ {-# OPTIONS_GHC -fno-warn-type-defaults #-} {- | Module : Text.Pandoc.ImageSize-Copyright : Copyright (C) 2011-2022 John MacFarlane+Copyright : Copyright (C) 2011-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -13,6 +13,7 @@ Functions for determining the size of a PNG, JPEG, or GIF image. -} module Text.Pandoc.ImageSize ( ImageType(..)+ , ImageSize(..) , imageType , imageSize , sizeInPixels@@ -36,6 +37,9 @@ import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy as BL import Data.Binary.Get+import Data.Bits ((.&.), shiftR, shiftL)+import Data.Word (bitReverse32, Word32)+import Data.Maybe (isJust, fromJust) import Data.Char (isDigit) import Control.Monad import Text.Pandoc.Shared (safeRead)@@ -49,15 +53,16 @@ import qualified Data.Text.Lazy as TL import qualified Data.Text.Encoding as TE import Control.Applicative+import qualified Data.Attoparsec.ByteString as AW import qualified Data.Attoparsec.ByteString.Char8 as A import qualified Codec.Picture.Metadata as Metadata-import qualified Codec.Picture.Metadata.Exif as Exif 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+data ImageType = Png | Gif | Jpeg | Svg | Pdf | Eps | Emf | Tiff | Webp | Avif deriving Show data Direction = Width | Height instance Show Direction where@@ -68,6 +73,8 @@ | Centimeter Double | Millimeter Double | Inch Double+ | Point Double+ | Pica Double | Percent Double | Em Double deriving Eq@@ -77,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" @@ -97,14 +106,23 @@ (T.unsnoc -> Just (xs, '.')) -> xs xs -> xs +dropBOM :: ByteString -> ByteString+dropBOM bs =+ if "\xEF\xBB\xBF" `B.isPrefixOf` bs+ then B.drop 3 bs+ else bs+ imageType :: ByteString -> Maybe ImageType imageType img = case B.take 4 img of "\x89\x50\x4e\x47" -> return Png "\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"@@ -116,7 +134,13 @@ "\x01\x00\x00\x00" | B.take 4 (B.drop 40 img) == " EMF" -> return Emf- _ -> mzero+ "\xEF\xBB\xBF<" -- BOM before svg+ -> imageType (B.drop 3 img)+ "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 findSvgTag img = "<svg" `B.isInfixOf` img || "<SVG" `B.isInfixOf` img@@ -132,6 +156,8 @@ Just Eps -> mbToEither "could not determine EPS size" $ epsSize img 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@@ -185,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) @@ -192,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 @@ -226,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) @@ -249,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 @@ -278,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@@ -298,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 =@@ -306,17 +352,9 @@ Left e -> Left (T.pack e) Right (_, meta) -> do pxx <- maybe (Left "Could not determine width") Right $- -- first look for exif image width, then width- (Metadata.lookup- (Metadata.Exif (Exif.TagUnknown 0xA002)) meta >>=- exifDataToWord) <|> Metadata.lookup Metadata.Width meta pxy <- maybe (Left "Could not determine height") Right $- -- first look for exif image height, then height- (Metadata.lookup- (Metadata.Exif (Exif.TagUnknown 0xA003)) meta >>=- exifDataToWord) <|>- Metadata.lookup Metadata.Height meta+ Metadata.lookup Metadata.Height meta dpix <- maybe (Right 72) Right $ Metadata.lookup Metadata.DpiX meta dpiy <- maybe (Right 72) Right $ Metadata.lookup Metadata.DpiY meta return $ ImageSize@@ -324,16 +362,11 @@ , pxY = fromIntegral pxy , dpiX = fromIntegral dpix , dpiY = fromIntegral dpiy }- where- exifDataToWord (Exif.ExifLong x) = Just $ fromIntegral x- exifDataToWord (Exif.ExifShort x) = Just $ fromIntegral x- exifDataToWord _ = Nothing - svgSize :: WriterOptions -> ByteString -> Maybe ImageSize svgSize opts img = do doc <- either (const mzero) return $ parseXMLElement- $ TL.fromStrict $ UTF8.toText img+ $ TL.fromStrict $ UTF8.toText $ dropBOM img let viewboxSize = do vb <- findAttrBy (== QName "viewBox" Nothing Nothing) doc [_,_,w,h] <- mapM safeRead (T.words vb)@@ -341,7 +374,9 @@ let dpi = fromIntegral $ writerDpi opts let dirToInt dir = do dim <- findAttrBy (== QName dir Nothing Nothing) doc >>= lengthToDim- return $ inPixel opts dim+ case dim of+ Percent _ -> mzero+ _ -> pure $ inPixel opts dim w <- dirToInt "width" <|> (fst <$> viewboxSize) h <- dirToInt "height" <|> (snd <$> viewboxSize) return ImageSize {@@ -381,3 +416,240 @@ case parseheader . BL.fromStrict $ img of Left _ -> Nothing Right (_, _, size) -> Just size++-- See https://developers.google.com/speed/webp/docs/riff_container+-- and RFC 6386+pWebpSize :: AW.Parser ImageSize+pWebpSize = do+ AW.string "RIFF"+ AW.take 4+ AW.string "WEBP"+ (w, h) <- lossy <|> lossless <|> extended+ return $ def+ { pxX = w+ , pxY = h+ }+ where+ bitsToMaybe = either (const Nothing) (\((_, _, s)) -> Just s)+ decode d = bitsToMaybe . d . BL.fromStrict+ lossySize = runGetOrFail $ do+ word <- getWord16le+ return $ word .&. 0x3FFF+ lossy = do+ AW.string "VP8 "+ AW.take 4 -- length in bytes of VP8 Lossy stream size+ keyFrame <- AW.anyWord8+ guard $ keyFrame .&. 1 == 0+ AW.take 2 -- remaining bytes of frame header+ AW.word8 0x9d -- VP8 keyframe magic+ AW.word8 0x01+ AW.word8 0x2a+ width16 <- AW.take 2+ height16 <- AW.take 2+ let w = toInteger <$> decode lossySize width16+ h = toInteger <$> decode lossySize height16+ guard $ isJust w && isJust h+ return (fromJust w, fromJust h)+ losslessSizes = runGetOrFail $ do+ bitReverse32 <$> getWord32le+ losslessSize word = 1 + (word .&. 0x3FFF)+ lossless = do+ AW.string "VP8L"+ AW.take 4 -- length in bytes of VP8 Lossless chunk size+ AW.word8 0x2f -- webp lossless stream magic+ sizes <- AW.take 4+ let mbword = decode losslessSizes sizes+ guard $ isJust mbword+ let word = fromJust mbword+ let w = toInteger $ losslessSize word+ h = toInteger $ losslessSize (word `shiftR` 14)+ return (w, h)+ extendedSize = runGetOrFail $ do+ low <- toInteger <$> getWord16le+ high <- toInteger <$> getWord8+ return $ 1 + (high `shiftL` 16) + (low)+ extended = do+ AW.string "VP8X"+ AW.take 8 -- VP8X chunk length, flags and reserved area+ width24 <- AW.take 3+ height24 <- AW.take 3+ let w = decode extendedSize width24+ h = decode extendedSize height24+ guard $ isJust w && isJust h+ return (fromJust w, fromJust h)++webpSize :: WriterOptions -> ByteString -> Maybe ImageSize+webpSize opts img =+ 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,7 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Logging- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -79,6 +79,8 @@ | Fetching Text | Extracting Text | LoadedResource FilePath FilePath+ | ScriptingInfo Text (Maybe SourcePos)+ | ScriptingWarning Text (Maybe SourcePos) | NoTitleElement Text | NoLangSpecified | InvalidLang Text@@ -98,12 +100,19 @@ | EnvironmentVariableUndefined Text | DuplicateAttribute Text Text | NotUTF8Encoded FilePath+ | MakePDFInfo Text Text+ | MakePDFWarning Text+ | UnclosedDiv SourcePos SourcePos+ | UnsupportedCodePage Int+ | YamlWarning SourcePos Text+ | UnsupportedPdfStandard Text deriving (Show, Eq, Data, Ord, Typeable, Generic) instance ToJSON LogMessage where toJSON x = object $ "verbosity" .= toJSON (messageVerbosity x) : "type" .= toJSON (show $ toConstr x) :+ "pretty" .= toJSON (showLogMessage x) : case x of SkippedContent s pos -> ["contents" .= s,@@ -200,6 +209,22 @@ LoadedResource orig found -> ["for" .= orig ,"from" .= found]+ ScriptingInfo msg mbpos ->+ ["message" .= msg] <>+ case mbpos of+ Nothing -> []+ Just pos -> ["source" .= sourceName pos+ ,"line" .= toJSON (sourceLine pos)+ ,"column" .= toJSON (sourceColumn pos)+ ]+ ScriptingWarning msg mbpos ->+ ["message" .= msg] <>+ case mbpos of+ Nothing -> []+ Just pos -> ["source" .= sourceName pos+ ,"line" .= toJSON (sourceLine pos)+ ,"column" .= toJSON (sourceColumn pos)+ ] NoTitleElement fallback -> ["fallback" .= fallback] NoLangSpecified -> []@@ -244,6 +269,31 @@ ,"value" .= val] NotUTF8Encoded src -> ["source" .= src]+ MakePDFInfo description contents ->+ ["description" .= description+ ,"contents" .= contents]+ MakePDFWarning message ->+ ["message" .= message]+ UnclosedDiv openpos closepos ->+ ["openpos" .= object+ [ "source" .= sourceName openpos,+ "line" .= toJSON (sourceLine openpos),+ "column" .= toJSON (sourceColumn openpos)]+ ,"closepos" .= object+ [ "source" .= sourceName closepos,+ "line" .= toJSON (sourceLine closepos),+ "column" .= toJSON (sourceColumn closepos)]+ ]+ UnsupportedCodePage cpg ->+ ["codepage" .= cpg]+ YamlWarning pos msg ->+ [ "source" .= sourceName pos+ , "line" .= toJSON (sourceLine pos)+ , "column" .= toJSON (sourceColumn pos)+ , "message" .= msg+ ]+ UnsupportedPdfStandard s ->+ ["contents" .= s] showPos :: SourcePos -> Text showPos pos = Text.pack $ sn ++ "line " ++@@ -322,11 +372,16 @@ "Extracting " <> fp <> "..." LoadedResource orig found -> "Loaded " <> Text.pack orig <> " from " <> Text.pack found+ ScriptingInfo s mbpos ->+ "Scripting info" <>+ maybe "" (\pos -> " at " <> showPos pos) mbpos <> ": " <> s+ ScriptingWarning s mbpos ->+ "Scripting warning" <>+ maybe "" (\pos -> " at " <> showPos pos) mbpos <> ": " <> s NoTitleElement fallback -> "This document format requires a nonempty <title> element.\n" <> "Defaulting to '" <> fallback <> "' as the title.\n" <>- "To specify a title, use 'title' in metadata or " <>- "--metadata title=\"...\"."+ "To specify a title, use --variable pagetitle=\"...\"." NoLangSpecified -> "No value for 'lang' was specified in the metadata.\n" <> "It is recommended that lang be specified for this format."@@ -375,6 +430,19 @@ NotUTF8Encoded src -> Text.pack src <> " is not UTF-8 encoded: falling back to latin1."+ MakePDFInfo description contents ->+ "[makePDF] " <> description <>+ if Text.null contents+ then mempty+ else "\n" <> contents+ MakePDFWarning message -> "[makePDF] " <> message+ UnclosedDiv openpos closepos -> "Div at " <> showPos openpos <>+ " unclosed at " <> showPos closepos <> ", closing implicitly."+ UnsupportedCodePage cpg -> "Unsupported code page " <> tshow cpg <>+ ". Text will likely be garbled."+ YamlWarning pos m -> "YAML warning (" <> showPos pos <> "): " <> m+ UnsupportedPdfStandard s ->+ "PDF standard '" <> s <> "' is not supported by LaTeX and will be ignored." messageVerbosity :: LogMessage -> Verbosity messageVerbosity msg =@@ -396,7 +464,7 @@ ParsingUnescaped{} -> INFO InlineNotRendered{} -> INFO BlockNotRendered{} -> INFO- DocxParserWarning{} -> INFO+ DocxParserWarning{} -> WARNING PowerpointTemplateWarning{} -> WARNING IgnoredIOError{} -> WARNING CouldNotFetchResource{} -> WARNING@@ -408,7 +476,9 @@ Fetching{} -> INFO Extracting{} -> INFO LoadedResource{} -> INFO- NoTitleElement{} -> WARNING+ ScriptingInfo{} -> INFO+ ScriptingWarning{} -> WARNING+ NoTitleElement{} -> INFO NoLangSpecified -> INFO InvalidLang{} -> WARNING CouldNotHighlight{} -> WARNING@@ -427,3 +497,9 @@ EnvironmentVariableUndefined{}-> WARNING DuplicateAttribute{} -> WARNING NotUTF8Encoded{} -> WARNING+ MakePDFInfo{} -> INFO+ MakePDFWarning{} -> WARNING+ UnclosedDiv{} -> WARNING+ UnsupportedCodePage{} -> WARNING+ YamlWarning{} -> WARNING+ UnsupportedPdfStandard{} -> WARNING
@@ -1,23 +0,0 @@-{- |- Module : Text.Pandoc.Lua- Copyright : Copyright © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Running pandoc Lua filters.--}-module Text.Pandoc.Lua- ( runLua- -- * Lua globals- , Global (..)- , setGlobals- -- * Filters- , runFilterFile- ) where--import Text.Pandoc.Lua.Filter (runFilterFile)-import Text.Pandoc.Lua.Global (Global (..), setGlobals)-import Text.Pandoc.Lua.Init (runLua)-import Text.Pandoc.Lua.Orphans ()
@@ -1,40 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{- |- Module : Text.Pandoc.Lua.ErrorConversion- Copyright : © 2020-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Define how Lua errors are converted into @'PandocError'@ Haskell-exceptions, and /vice versa/.--}-module Text.Pandoc.Lua.ErrorConversion- ( addContextToException- ) where--import HsLua (LuaError, LuaE, resultToEither, runPeek, top)-import Text.Pandoc.Error (PandocError (PandocLuaError))-import Text.Pandoc.Lua.Marshal.PandocError (pushPandocError, peekPandocError)--import qualified Data.Text as T-import qualified HsLua as Lua--addContextToException :: ()-addContextToException = undefined---- | Retrieve a @'PandocError'@ from the Lua stack.-popPandocError :: LuaE PandocError PandocError-popPandocError = do- errResult <- runPeek $ peekPandocError top- case resultToEither errResult of- Right x -> return x- Left err -> return $ PandocLuaError (T.pack err)---- Ensure conversions between Lua errors and 'PandocError' exceptions--- are possible.-instance LuaError PandocError where- popException = popPandocError- pushException = pushPandocError- luaException = PandocLuaError . T.pack
@@ -1,46 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE IncoherentInstances #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{- |-Module : Text.Pandoc.Lua.Filter-Copyright : © 2012-2022 John MacFarlane,- © 2017-2022 Albert Krewinkel-License : GNU GPL, version 2 or above-Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>-Stability : alpha--Types and functions for running Lua filters.--}-module Text.Pandoc.Lua.Filter- ( runFilterFile- ) where-import Control.Monad ((>=>), (<$!>))-import HsLua as Lua-import Text.Pandoc.Definition-import Text.Pandoc.Error (PandocError)-import Text.Pandoc.Lua.ErrorConversion ()-import Text.Pandoc.Lua.Marshal.AST-import Text.Pandoc.Lua.Marshal.Filter----- | Transform document using the filter defined in the given file.-runFilterFile :: FilePath -> Pandoc -> LuaE PandocError Pandoc-runFilterFile filterPath doc = do- oldtop <- gettop- stat <- dofileTrace filterPath- if stat /= Lua.OK- then throwErrorAsException- else do- newtop <- gettop- -- Use the returned filters, or the implicitly defined global- -- filter if nothing was returned.- luaFilters <- forcePeek $- if newtop - oldtop >= 1- then peekList peekFilter top- else (:[]) <$!> (liftLua pushglobaltable *> peekFilter top)- settop oldtop- runAll luaFilters doc--runAll :: [Filter] -> Pandoc -> LuaE PandocError Pandoc-runAll = foldr ((>=>) . applyFully) return
@@ -1,74 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Lua- Copyright : Copyright © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Pandoc's Lua globals.--}-module Text.Pandoc.Lua.Global- ( Global (..)- , setGlobals- ) where--import HsLua as Lua-import HsLua.Module.Version (pushVersion)-import Paths_pandoc (version)-import Text.Pandoc.Class.CommonState (CommonState)-import Text.Pandoc.Definition (Pandoc, pandocTypesVersion)-import Text.Pandoc.Error (PandocError)-import Text.Pandoc.Lua.Marshal.CommonState (pushCommonState)-import Text.Pandoc.Lua.Marshal.Pandoc (pushPandoc)-import Text.Pandoc.Lua.Marshal.ReaderOptions (pushReaderOptionsReadonly)-import Text.Pandoc.Lua.Marshal.WriterOptions (pushWriterOptions)-import Text.Pandoc.Lua.Orphans ()-import Text.Pandoc.Options (ReaderOptions, WriterOptions)--import qualified Data.Text as Text---- | Permissible global Lua variables.-data Global =- FORMAT Text.Text- | PANDOC_API_VERSION- | PANDOC_DOCUMENT Pandoc- | PANDOC_READER_OPTIONS ReaderOptions- | PANDOC_WRITER_OPTIONS WriterOptions- | PANDOC_SCRIPT_FILE FilePath- | PANDOC_STATE CommonState- | PANDOC_VERSION- -- Cannot derive instance of Data because of CommonState---- | Set all given globals.-setGlobals :: [Global] -> LuaE PandocError ()-setGlobals = mapM_ setGlobal--setGlobal :: Global -> LuaE PandocError ()-setGlobal global = case global of- -- This could be simplified if Global was an instance of Data.- FORMAT format -> do- Lua.pushText format- Lua.setglobal "FORMAT"- PANDOC_API_VERSION -> do- pushVersion pandocTypesVersion- Lua.setglobal "PANDOC_API_VERSION"- PANDOC_DOCUMENT doc -> do- pushPandoc doc- Lua.setglobal "PANDOC_DOCUMENT"- PANDOC_READER_OPTIONS ropts -> do- pushReaderOptionsReadonly ropts- Lua.setglobal "PANDOC_READER_OPTIONS"- PANDOC_WRITER_OPTIONS wopts -> do- pushWriterOptions wopts- Lua.setglobal "PANDOC_WRITER_OPTIONS"- PANDOC_SCRIPT_FILE filePath -> do- Lua.pushString filePath- Lua.setglobal "PANDOC_SCRIPT_FILE"- PANDOC_STATE commonState -> do- pushCommonState commonState- Lua.setglobal "PANDOC_STATE"- PANDOC_VERSION -> do- pushVersion version- Lua.setglobal "PANDOC_VERSION"
@@ -1,153 +0,0 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Lua- Copyright : Copyright © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Functions to initialize the Lua interpreter.--}-module Text.Pandoc.Lua.Init- ( runLua- ) where--import Control.Monad (forM, forM_, when)-import Control.Monad.Catch (throwM, try)-import Control.Monad.Trans (MonadIO (..))-import Data.Maybe (catMaybes)-import HsLua as Lua hiding (status, try)-import Text.Pandoc.Class.PandocMonad (PandocMonad, readDataFile)-import Text.Pandoc.Error (PandocError (PandocLuaError))-import Text.Pandoc.Lua.Marshal.List (newListMetatable, pushListModule)-import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua, runPandocLua)-import qualified Data.ByteString.Char8 as Char8-import qualified Data.Text as T-import qualified Lua.LPeg as LPeg-import qualified HsLua.Aeson-import qualified HsLua.Module.DocLayout as Module.Layout-import qualified HsLua.Module.Path as Module.Path-import qualified HsLua.Module.Text as Module.Text-import qualified Text.Pandoc.Lua.Module.Pandoc as Module.Pandoc-import qualified Text.Pandoc.Lua.Module.MediaBag as Pandoc.MediaBag-import qualified Text.Pandoc.Lua.Module.System as Pandoc.System-import qualified Text.Pandoc.Lua.Module.Template as Pandoc.Template-import qualified Text.Pandoc.Lua.Module.Types as Pandoc.Types-import qualified Text.Pandoc.Lua.Module.Utils as Pandoc.Utils---- | Run the lua interpreter, using pandoc's default way of environment--- initialization.-runLua :: (PandocMonad m, MonadIO m)- => LuaE PandocError a -> m (Either PandocError a)-runLua action =- runPandocLua . try $ do- initLuaState- liftPandocLua action---- | Modules that are loaded at startup and assigned to fields in the--- pandoc module.------ Note that @pandoc.List@ is not included here for technical reasons;--- it must be handled separately.-loadedModules :: [Module PandocError]-loadedModules =- [ Pandoc.MediaBag.documentedModule- , Pandoc.System.documentedModule- , Pandoc.Template.documentedModule- , Pandoc.Types.documentedModule- , Pandoc.Utils.documentedModule- , Module.Layout.documentedModule { moduleName = "pandoc.layout" }- , Module.Path.documentedModule { moduleName = "pandoc.path" }- , Module.Text.documentedModule- ]---- | Initialize the lua state with all required values-initLuaState :: PandocLua ()-initLuaState = do- liftPandocLua Lua.openlibs- initJsonMetatable- initPandocModule- installLpegSearcher- setGlobalModules- loadInitScript "init.lua"- where- initPandocModule :: PandocLua ()- initPandocModule = liftPandocLua $ do- -- Push module table- registerModule Module.Pandoc.documentedModule- -- load modules and add them to the `pandoc` module table.- forM_ loadedModules $ \mdl -> do- registerModule mdl- let fieldname (Name mdlname) = Name .- maybe mdlname snd . Char8.uncons . snd $- Char8.break (== '.') mdlname- Lua.setfield (nth 2) (fieldname $ moduleName mdl)- -- pandoc.List is low-level and must be opened differently.- requirehs "pandoc.List" (const pushListModule)- setfield (nth 2) "List"- -- assign module to global variable- Lua.setglobal "pandoc"-- loadInitScript :: FilePath -> PandocLua ()- loadInitScript scriptFile = do- script <- readDataFile scriptFile- status <- liftPandocLua $ Lua.dostring script- when (status /= Lua.OK) . liftPandocLua $ do- err <- popException- let prefix = "Couldn't load '" <> T.pack scriptFile <> "':\n"- throwM . PandocLuaError . (prefix <>) $ case err of- PandocLuaError msg -> msg- _ -> T.pack $ show err-- setGlobalModules :: PandocLua ()- setGlobalModules = liftPandocLua $ do- let globalModules =- [ ("lpeg", LPeg.luaopen_lpeg_ptr) -- must be loaded first- , ("re", LPeg.luaopen_re_ptr) -- re depends on lpeg- ]- loadedBuiltInModules <- fmap catMaybes . forM globalModules $- \(pkgname, luaopen) -> do- Lua.pushcfunction luaopen- usedBuiltIn <- Lua.pcall 0 1 Nothing >>= \case- OK -> do -- all good, loading succeeded- -- register as loaded module so later modules can rely on this- Lua.getfield Lua.registryindex Lua.loaded- Lua.pushvalue (Lua.nth 2)- Lua.setfield (Lua.nth 2) pkgname- Lua.pop 1 -- pop _LOADED- return True- _ -> do -- built-in library failed, load system lib- Lua.pop 1 -- ignore error message- -- Try loading via the normal package loading mechanism.- Lua.getglobal "require"- Lua.pushName pkgname- Lua.call 1 1 -- Throws an exception if loading failed again!- return False-- -- Module on top of stack. Register as global- Lua.setglobal pkgname- return $ if usedBuiltIn then Just pkgname else Nothing-- -- Remove module entry from _LOADED table in registry if we used a- -- built-in library. This ensures that later calls to @require@ will- -- prefer the shared library, if any.- forM_ loadedBuiltInModules $ \pkgname -> do- Lua.getfield Lua.registryindex Lua.loaded- Lua.pushnil- Lua.setfield (Lua.nth 2) pkgname- Lua.pop 1 -- registry-- installLpegSearcher :: PandocLua ()- installLpegSearcher = liftPandocLua $ do- Lua.getglobal' "package.searchers"- Lua.pushHaskellFunction $ Lua.state >>= liftIO . LPeg.lpeg_searcher- Lua.rawseti (Lua.nth 2) . (+1) . fromIntegral =<< Lua.rawlen (Lua.nth 2)- Lua.pop 1 -- remove 'package.searchers' from stack---- | Setup the metatable that's assigned to Lua tables that were created--- from/via JSON arrays.-initJsonMetatable :: PandocLua ()-initJsonMetatable = liftPandocLua $ do- newListMetatable HsLua.Aeson.jsonarray (pure ())
@@ -1,68 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Lua.Marshal.CommonState- Copyright : © 2012-2022 John MacFarlane- © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Instances to marshal (push) and unmarshal (peek) the common state.--}-module Text.Pandoc.Lua.Marshal.CommonState- ( typeCommonState- , peekCommonState- , pushCommonState- ) where--import HsLua-import Text.Pandoc.Class (CommonState (..))-import Text.Pandoc.Logging (LogMessage, showLogMessage)-import Text.Pandoc.Lua.Marshal.List (pushPandocList)---- | Lua type used for the @CommonState@ object.-typeCommonState :: LuaError e => DocumentedType e CommonState-typeCommonState = deftype "pandoc CommonState" []- [ readonly "input_files" "input files passed to pandoc"- (pushPandocList pushString, stInputFiles)-- , readonly "output_file" "the file to which pandoc will write"- (maybe pushnil pushString, stOutputFile)-- , readonly "log" "list of log messages"- (pushPandocList (pushUD typeLogMessage), stLog)-- , readonly "request_headers" "headers to add for HTTP requests"- (pushPandocList (pushPair pushText pushText), stRequestHeaders)-- , readonly "resource_path"- "path to search for resources like included images"- (pushPandocList pushString, stResourcePath)-- , readonly "source_url" "absolute URL + dir of 1st source file"- (maybe pushnil pushText, stSourceURL)-- , readonly "user_data_dir" "directory to search for data files"- (maybe pushnil pushString, stUserDataDir)-- , readonly "trace" "controls whether tracing messages are issued"- (pushBool, stTrace)-- , readonly "verbosity" "verbosity level"- (pushString . show, stVerbosity)- ]--peekCommonState :: LuaError e => Peeker e CommonState-peekCommonState = peekUD typeCommonState--pushCommonState :: LuaError e => Pusher e CommonState-pushCommonState = pushUD typeCommonState--typeLogMessage :: LuaError e => DocumentedType e LogMessage-typeLogMessage = deftype "pandoc LogMessage"- [ operation Index $ defun "__tostring"- ### liftPure showLogMessage- <#> udparam typeLogMessage "msg" "object"- =#> functionResult pushText "string" "stringified log message"- ]- mempty -- no members
@@ -1,28 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{- |- Module : Text.Pandoc.Lua.Marshaling.Context- Copyright : © 2012-2022 John MacFarlane- © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Marshaling instance for doctemplates Context and its components.--}-module Text.Pandoc.Lua.Marshal.Context () where--import qualified HsLua as Lua-import HsLua (Pushable)-import Text.DocTemplates (Context(..), Val(..), TemplateTarget)-import Text.DocLayout (render)--instance (TemplateTarget a, Pushable a) => Pushable (Context a) where- push (Context m) = Lua.push m--instance (TemplateTarget a, Pushable a) => Pushable (Val a) where- push NullVal = Lua.push ()- push (BoolVal b) = Lua.push b- push (MapVal ctx) = Lua.push ctx- push (ListVal xs) = Lua.push xs- push (SimpleVal d) = Lua.push $ render Nothing d
@@ -1,50 +0,0 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{- |- Module : Text.Pandoc.Lua.Marshal.PandocError- Copyright : © 2020-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Marshal of @'PandocError'@ values.--}-module Text.Pandoc.Lua.Marshal.PandocError- ( peekPandocError- , pushPandocError- , typePandocError- )- where--import HsLua (LuaError, Peeker, Pusher, liftLua, pushString)-import HsLua.Packaging-import Text.Pandoc.Error (PandocError (PandocLuaError))--import qualified HsLua as Lua-import qualified Text.Pandoc.UTF8 as UTF8---- | Lua userdata type definition for PandocError.-typePandocError :: LuaError e => DocumentedType e PandocError-typePandocError = deftype "PandocError"- [ operation Tostring $ defun "__tostring"- ### liftPure (show @PandocError)- <#> udparam typePandocError "obj" "PandocError object"- =#> functionResult pushString "string" "string representation of error."- ]- mempty -- no members---- | Peek a @'PandocError'@ element to the Lua stack.-pushPandocError :: LuaError e => Pusher e PandocError-pushPandocError = pushUD typePandocError---- | Retrieve a @'PandocError'@ from the Lua stack.-peekPandocError :: LuaError e => Peeker e PandocError-peekPandocError idx = Lua.retrieving "PandocError" $- liftLua (Lua.ltype idx) >>= \case- Lua.TypeUserdata -> peekUD typePandocError idx- _ -> do- msg <- liftLua $ Lua.state >>= \l -> Lua.liftIO (Lua.popErrorMessage l)- return $ PandocLuaError (UTF8.toText msg)
@@ -1,137 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{- |- Module : Text.Pandoc.Lua.Marshaling.ReaderOptions- Copyright : © 2012-2022 John MacFarlane- © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Marshaling instance for ReaderOptions and its components.--}-module Text.Pandoc.Lua.Marshal.ReaderOptions- ( peekReaderOptions- , pushReaderOptions- , pushReaderOptionsReadonly- ) where--import Data.Default (def)-import HsLua as Lua-#if !MIN_VERSION_hslua(2,2,0)-import HsLua.Aeson (peekViaJSON, pushViaJSON)-#endif-import Text.Pandoc.Lua.Marshal.List (pushPandocList)-import Text.Pandoc.Options (ReaderOptions (..))------- Reader Options------- | Retrieve a ReaderOptions value, either from a normal ReaderOptions--- value, from a read-only object, or from a table with the same--- keys as a ReaderOptions object.-peekReaderOptions :: LuaError e => Peeker e ReaderOptions-peekReaderOptions = retrieving "ReaderOptions" . \idx ->- liftLua (ltype idx) >>= \case- TypeUserdata -> choice [ peekUD typeReaderOptions- , peekUD typeReaderOptionsReadonly- ]- idx- TypeTable -> peekReaderOptionsTable idx- _ -> failPeek =<<- typeMismatchMessage "ReaderOptions userdata or table" idx---- | Pushes a ReaderOptions value as userdata object.-pushReaderOptions :: LuaError e => Pusher e ReaderOptions-pushReaderOptions = pushUD typeReaderOptions---- | Pushes a ReaderOptions object, but makes it read-only.-pushReaderOptionsReadonly :: LuaError e => Pusher e ReaderOptions-pushReaderOptionsReadonly = pushUD typeReaderOptionsReadonly---- | ReaderOptions object type for read-only values.-typeReaderOptionsReadonly :: LuaError e => DocumentedType e ReaderOptions-typeReaderOptionsReadonly = deftype "ReaderOptions (read-only)"- [ operation Tostring $ lambda- ### liftPure show- <#> udparam typeReaderOptions "opts" "options to print in native format"- =#> functionResult pushString "string" "Haskell representation"- , operation Newindex $ lambda- ### (failLua "This ReaderOptions value is read-only.")- =?> "Throws an error when called, i.e., an assignment is made."- ]- readerOptionsMembers---- | 'ReaderOptions' object type.-typeReaderOptions :: LuaError e => DocumentedType e ReaderOptions-typeReaderOptions = deftype "ReaderOptions"- [ operation Tostring $ lambda- ### liftPure show- <#> udparam typeReaderOptions "opts" "options to print in native format"- =#> functionResult pushString "string" "Haskell representation"- ]- readerOptionsMembers---- | Member properties of 'ReaderOptions' Lua values.-readerOptionsMembers :: LuaError e- => [Member e (DocumentedFunction e) ReaderOptions]-readerOptionsMembers =- [ property "abbreviations" ""- (pushSet pushText, readerAbbreviations)- (peekSet peekText, \opts x -> opts{ readerAbbreviations = x })- , property "columns" ""- (pushIntegral, readerColumns)- (peekIntegral, \opts x -> opts{ readerColumns = x })- , property "default_image_extension" ""- (pushText, readerDefaultImageExtension)- (peekText, \opts x -> opts{ readerDefaultImageExtension = x })- , property "extensions" ""- (pushViaJSON, readerExtensions)- (peekViaJSON, \opts x -> opts{ readerExtensions = x })- , property "indented_code_classes" ""- (pushPandocList pushText, readerIndentedCodeClasses)- (peekList peekText, \opts x -> opts{ readerIndentedCodeClasses = x })- , property "standalone" ""- (pushBool, readerStandalone)- (peekBool, \opts x -> opts{ readerStandalone = x })- , property "strip_comments" ""- (pushBool, readerStripComments)- (peekBool, \opts x -> opts{ readerStripComments = x })- , property "tab_stop" ""- (pushIntegral, readerTabStop)- (peekIntegral, \opts x -> opts{ readerTabStop = x })- , property "track_changes" ""- (pushViaJSON, readerTrackChanges)- (choice [peekRead, peekViaJSON], \opts x -> opts{ readerTrackChanges = x })- ]---- | Retrieves a 'ReaderOptions' object from a table on the stack, using--- the default values for all missing fields.------ Internally, this pushes the default reader options, sets each--- key/value pair of the table in the userdata value, then retrieves the--- object again. This will update all fields and complain about unknown--- keys.-peekReaderOptionsTable :: LuaError e => Peeker e ReaderOptions-peekReaderOptionsTable idx = retrieving "ReaderOptions (table)" $ do- liftLua $ do- absidx <- absindex idx- pushUD typeReaderOptions def- let setFields = do- next absidx >>= \case- False -> return () -- all fields were copied- True -> do- pushvalue (nth 2) *> insert (nth 2)- settable (nth 4) -- set in userdata object- setFields- pushnil -- first key- setFields- peekUD typeReaderOptions top `lastly` pop 1--instance Pushable ReaderOptions where- push = pushReaderOptions
@@ -1,96 +0,0 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{- |- Module : Text.Pandoc.Lua.Marshaling.ReaderOptions- Copyright : © 2012-2022 John MacFarlane- © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Marshal citeproc 'Reference' values.--}-module Text.Pandoc.Lua.Marshal.Reference- ( pushReference- ) where--import Citeproc.Types- ( Date (..), DateParts (..), ItemId (..), Name (..), Reference (..)- , Val (..), Variable, fromVariable- )-import Control.Monad (forM_)-import HsLua hiding (Name, Reference, pushName, peekName)-import Text.Pandoc.Builder (Inlines, toList)-import Text.Pandoc.Lua.Marshal.Inline (pushInlines)-import Text.Pandoc.Lua.Marshal.List (pushPandocList)--import qualified Data.Map as Map---- | Pushes a ReaderOptions value as userdata object.-pushReference :: LuaError e => Pusher e (Reference Inlines)-pushReference reference = do- pushAsTable [ ("id", pushItemId . referenceId)- , ("type", pushText . referenceType)- ]- reference- forM_ (Map.toList $ referenceVariables reference) $ \(var, val) -> do- pushVariable var- pushVal val- rawset (nth 3)---- | Pushes an 'ItemId' as a string.-pushItemId :: Pusher e ItemId-pushItemId = pushText . unItemId---- | Pushes a person's 'Name' as a table.-pushName :: LuaError e => Pusher e Name-pushName = pushAsTable- [ ("family" , pushTextOrNil . nameFamily)- , ("given" , pushTextOrNil . nameGiven)- , ("dropping-particle" , pushTextOrNil . nameDroppingParticle)- , ("non-dropping-particle" , pushTextOrNil . nameNonDroppingParticle)- , ("suffix" , pushTextOrNil . nameSuffix)- , ("literal" , pushTextOrNil . nameLiteral)- , ("comma-suffix" , pushBoolOrNil . nameCommaSuffix)- , ("static-ordering" , pushBoolOrNil . nameStaticOrdering)- ]- where- pushTextOrNil = \case- Nothing -> pushnil- Just xs -> pushText xs---- | Pushes a boolean, but uses @nil@ instead of @false@; table fields--- are not set unless the value is true.-pushBoolOrNil :: Pusher e Bool-pushBoolOrNil = \case- False -> pushnil- True -> pushBool True---- | Pushes a 'Variable' as string.-pushVariable :: Pusher e Variable-pushVariable = pushText . fromVariable---- | Pushes a 'Val', i.e., a variable value.-pushVal :: LuaError e => Pusher e (Val Inlines)-pushVal = \case- TextVal t -> pushText t- FancyVal inlns -> pushInlines $ toList inlns- NumVal i -> pushIntegral i- NamesVal names -> pushPandocList pushName names- DateVal date -> pushDate date- _ -> pushText mempty---- | Pushes a 'Date' as table.-pushDate :: LuaError e => Pusher e Date-pushDate = pushAsTable- [ ("date-parts", pushPandocList pushDateParts . dateParts)- , ("circa", pushBoolOrNil . dateCirca)- , ("season", maybe pushnil pushIntegral . dateSeason)- , ("literal", maybe pushnil pushText . dateLiteral)- ]- where- -- date parts are lists of Int values- pushDateParts (DateParts dp) = pushPandocList pushIntegral dp
@@ -1,56 +0,0 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{- |-Module : Text.Pandoc.Lua.Marshaling.Sources-Copyright : © 2021-2022 Albert Krewinkel-License : GNU GPL, version 2 or above-Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>--Marshal 'Sources'.--}-module Text.Pandoc.Lua.Marshal.Sources- ( peekSources- , pushSources- ) where--import Control.Monad ((<$!>))-import Data.Text (Text)-import HsLua as Lua-import Text.Pandoc.Lua.Marshal.List (newListMetatable)-import Text.Pandoc.Sources (Sources (..), toSources)-import Text.Parsec (SourcePos, sourceName)---- | Pushes the 'Sources' as a list of lazy Lua objects.-pushSources :: LuaError e => Pusher e Sources-pushSources (Sources srcs) = do- pushList (pushUD typeSource) srcs- newListMetatable "pandoc Sources" $ do- pushName "__tostring"- pushHaskellFunction $ do- sources <- forcePeek $ peekList (peekUD typeSource) (nthBottom 1)- pushText . mconcat $ map snd sources- return 1- rawset (nth 3)- setmetatable (nth 2)---- | Retrieves sources from the stack.-peekSources :: LuaError e => Peeker e Sources-peekSources idx = liftLua (ltype idx) >>= \case- TypeString -> toSources <$!> peekText idx- TypeTable -> Sources <$!> peekList (peekUD typeSource) idx- _ -> Sources . (:[]) <$!> peekUD typeSource idx---- | Source object type.-typeSource :: LuaError e => DocumentedType e (SourcePos, Text)-typeSource = deftype "pandoc input source"- [ operation Tostring $ lambda- ### liftPure snd- <#> udparam typeSource "srcs" "Source to print in native format"- =#> functionResult pushText "string" "Haskell representation"- ]- [ readonly "name" "source name"- (pushString, sourceName . fst)- , readonly "text" "source text"- (pushText, snd)- ]
@@ -1,31 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{- |-Module : Text.Pandoc.Lua.Marshal.Template-Copyright : © 2021-2022 Albert Krewinkel-License : GNU GPL, version 2 or above-Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>--Marshal 'Template' 'Text'.--}-module Text.Pandoc.Lua.Marshal.Template- ( pushTemplate- , peekTemplate- , typeTemplate- ) where--import Data.Text (Text)-import HsLua as Lua-import Text.DocTemplates (Template)---- | Pushes a 'Template' as a an opaque userdata value.-pushTemplate :: LuaError e => Pusher e (Template Text)-pushTemplate = pushUD typeTemplate---- | Retrieves a 'Template' 'Text' value from the stack.-peekTemplate :: LuaError e => Peeker e (Template Text)-peekTemplate = peekUD typeTemplate---- | Template object type.-typeTemplate :: LuaError e => DocumentedType e (Template Text)-typeTemplate = deftype "pandoc Template" [] []
@@ -1,244 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{- |- Module : Text.Pandoc.Lua.Marshaling.WriterOptions- Copyright : © 2021-2022 Albert Krewinkel, John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Marshaling instance for WriterOptions and its components.--}-module Text.Pandoc.Lua.Marshal.WriterOptions- ( peekWriterOptions- , pushWriterOptions- ) where--import Control.Applicative (optional)-import Data.Default (def)-import HsLua as Lua-#if !MIN_VERSION_hslua(2,2,0)-import HsLua.Aeson (peekViaJSON, pushViaJSON)-#endif-import Text.Pandoc.Lua.Marshal.List (pushPandocList)-import Text.Pandoc.Lua.Marshal.Template (peekTemplate, pushTemplate)-import Text.Pandoc.Options (WriterOptions (..))------- Writer Options------- | Retrieve a WriterOptions value, either from a normal WriterOptions--- value, from a read-only object, or from a table with the same--- keys as a WriterOptions object.-peekWriterOptions :: LuaError e => Peeker e WriterOptions-peekWriterOptions = retrieving "WriterOptions" . \idx ->- liftLua (ltype idx) >>= \case- TypeUserdata -> peekUD typeWriterOptions idx- TypeTable -> peekWriterOptionsTable idx- _ -> failPeek =<<- typeMismatchMessage "WriterOptions userdata or table" idx---- | Pushes a WriterOptions value as userdata object.-pushWriterOptions :: LuaError e => Pusher e WriterOptions-pushWriterOptions = pushUD typeWriterOptions---- | 'WriterOptions' object type.-typeWriterOptions :: LuaError e => DocumentedType e WriterOptions-typeWriterOptions = deftype "WriterOptions"- [ operation Tostring $ lambda- ### liftPure show- <#> udparam typeWriterOptions "opts" "options to print in native format"- =#> functionResult pushString "string" "Haskell representation"- ]- [ property "cite_method"- "How to print cites"- (pushViaJSON, writerCiteMethod)- (peekViaJSON, \opts x -> opts{ writerCiteMethod = x })-- , property "columns"- "Characters in a line (for text wrapping)"- (pushIntegral, writerColumns)- (peekIntegral, \opts x -> opts{ writerColumns = x })-- , property "dpi"- "DPI for pixel to/from inch/cm conversions"- (pushIntegral, writerDpi)- (peekIntegral, \opts x -> opts{ writerDpi = x })-- , property "email_obfuscation"- "How to obfuscate emails"- (pushViaJSON, writerEmailObfuscation)- (peekViaJSON, \opts x -> opts{ writerEmailObfuscation = x })-- , property "epub_chapter_level"- "Header level for chapters (separate files)"- (pushIntegral, writerEpubChapterLevel)- (peekIntegral, \opts x -> opts{ writerEpubChapterLevel = x })-- , property "epub_fonts"- "Paths to fonts to embed"- (pushPandocList pushString, writerEpubFonts)- (peekList peekString, \opts x -> opts{ writerEpubFonts = x })-- , property "epub_metadata"- "Metadata to include in EPUB"- (maybe pushnil pushText, writerEpubMetadata)- (optional . peekText, \opts x -> opts{ writerEpubMetadata = x })-- , property "epub_subdirectory"- "Subdir for epub in OCF"- (pushText, writerEpubSubdirectory)- (peekText, \opts x -> opts{ writerEpubSubdirectory = x })-- , property "extensions"- "Markdown extensions that can be used"- (pushViaJSON, writerExtensions)- (peekViaJSON, \opts x -> opts{ writerExtensions = x })-- , property "highlight_style"- "Style to use for highlighting (nil = no highlighting)"- (maybe pushnil pushViaJSON, writerHighlightStyle)- (optional . peekViaJSON, \opts x -> opts{ writerHighlightStyle = x })-- , property "html_math_method"- "How to print math in HTML"- (pushViaJSON, writerHTMLMathMethod)- (peekViaJSON, \opts x -> opts{ writerHTMLMathMethod = x })-- , property "html_q_tags"- "Use @<q>@ tags for quotes in HTML"- (pushBool, writerHtmlQTags)- (peekBool, \opts x -> opts{ writerHtmlQTags = x })-- , property "identifier_prefix"- "Prefix for section & note ids in HTML and for footnote marks in markdown"- (pushText, writerIdentifierPrefix)- (peekText, \opts x -> opts{ writerIdentifierPrefix = x })-- , property "incremental"- "True if lists should be incremental"- (pushBool, writerIncremental)- (peekBool, \opts x -> opts{ writerIncremental = x })-- , property "listings"- "Use listings package for code"- (pushBool, writerListings)- (peekBool, \opts x -> opts{ writerListings = x })-- , property "number_offset"- "Starting number for section, subsection, ..."- (pushPandocList pushIntegral, writerNumberOffset)- (peekList peekIntegral, \opts x -> opts{ writerNumberOffset = x })-- , property "number_sections"- "Number sections in LaTeX"- (pushBool, writerNumberSections)- (peekBool, \opts x -> opts{ writerNumberSections = x })-- , property "prefer_ascii"- "Prefer ASCII representations of characters when possible"- (pushBool, writerPreferAscii)- (peekBool, \opts x -> opts{ writerPreferAscii = x })-- , property "reference_doc"- "Path to reference document if specified"- (maybe pushnil pushString, writerReferenceDoc)- (optional . peekString, \opts x -> opts{ writerReferenceDoc = x })-- , property "reference_links"- "Use reference links in writing markdown, rst"- (pushBool, writerReferenceLinks)- (peekBool, \opts x -> opts{ writerReferenceLinks = x })-- , property "reference_location"- "Location of footnotes and references for writing markdown"- (pushViaJSON, writerReferenceLocation)- (peekViaJSON, \opts x -> opts{ writerReferenceLocation = x })-- , property "section_divs"- "Put sections in div tags in HTML"- (pushBool, writerSectionDivs)- (peekBool, \opts x -> opts{ writerSectionDivs = x })-- , property "setext_headers"- "Use setext headers for levels 1-2 in markdown"- (pushBool, writerSetextHeaders)- (peekBool, \opts x -> opts{ writerSetextHeaders = x })-- , property "slide_level"- "Force header level of slides"- (maybe pushnil pushIntegral, writerSlideLevel)- (optional . peekIntegral, \opts x -> opts{ writerSlideLevel = x })-- -- , property "syntax_map" "Syntax highlighting definition"- -- (pushViaJSON, writerSyntaxMap)- -- (peekViaJSON, \opts x -> opts{ writerSyntaxMap = x })- -- :: SyntaxMap-- , property "tab_stop"- "Tabstop for conversion btw spaces and tabs"- (pushIntegral, writerTabStop)- (peekIntegral, \opts x -> opts{ writerTabStop = x })-- , property "table_of_contents"- "Include table of contents"- (pushBool, writerTableOfContents)- (peekBool, \opts x -> opts{ writerTableOfContents = x })-- , property "template"- "Template to use"- (maybe pushnil pushTemplate, writerTemplate)- (optional . peekTemplate, \opts x -> opts{ writerTemplate = x })- -- :: Maybe (Template Text)-- , property "toc_depth"- "Number of levels to include in TOC"- (pushIntegral, writerTOCDepth)- (peekIntegral, \opts x -> opts{ writerTOCDepth = x })-- , property "top_level_division"- "Type of top-level divisions"- (pushViaJSON, writerTopLevelDivision)- (peekViaJSON, \opts x -> opts{ writerTopLevelDivision = x })-- , property "variables"- "Variables to set in template"- (pushViaJSON, writerVariables)- (peekViaJSON, \opts x -> opts{ writerVariables = x })-- , property "wrap_text"- "Option for wrapping text"- (pushViaJSON, writerWrapText)- (peekViaJSON, \opts x -> opts{ writerWrapText = x })- ]---- | Retrieves a 'WriterOptions' object from a table on the stack, using--- the default values for all missing fields.------ Internally, this pushes the default writer options, sets each--- key/value pair of the table in the userdata value, then retrieves the--- object again. This will update all fields and complain about unknown--- keys.-peekWriterOptionsTable :: LuaError e => Peeker e WriterOptions-peekWriterOptionsTable idx = retrieving "WriterOptions (table)" $ do- liftLua $ do- absidx <- absindex idx- pushUD typeWriterOptions def- let setFields = do- next absidx >>= \case- False -> return () -- all fields were copied- True -> do- pushvalue (nth 2) *> insert (nth 2)- settable (nth 4) -- set in userdata object- setFields- pushnil -- first key- setFields- peekUD typeWriterOptions top `lastly` pop 1--instance Pushable WriterOptions where- push = pushWriterOptions
@@ -1,143 +0,0 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Lua.Module.MediaBag- Copyright : Copyright © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>--The Lua module @pandoc.mediabag@.--}-module Text.Pandoc.Lua.Module.MediaBag- ( documentedModule- ) where--import Prelude hiding (lookup)-import Data.Maybe (fromMaybe)-import HsLua ( LuaE, DocumentedFunction, Module (..)- , (<#>), (###), (=#>), (=?>), (#?), defun, functionResult- , opt, parameter, stringParam, textParam)-import Text.Pandoc.Class.CommonState (CommonState (..))-import Text.Pandoc.Class.PandocMonad (fetchItem, fillMediaBag, getMediaBag,- modifyCommonState, setMediaBag)-import Text.Pandoc.Error (PandocError)-import Text.Pandoc.Lua.Marshal.Pandoc (peekPandoc, pushPandoc)-import Text.Pandoc.Lua.Marshal.List (pushPandocList)-import Text.Pandoc.Lua.Orphans ()-import Text.Pandoc.Lua.PandocLua (unPandocLua)-import Text.Pandoc.MIME (MimeType)--import qualified Data.ByteString.Lazy as BL-import qualified HsLua as Lua-import qualified Text.Pandoc.MediaBag as MB------- MediaBag submodule----documentedModule :: Module PandocError-documentedModule = Module- { moduleName = "pandoc.mediabag"- , moduleDescription = "mediabag access"- , moduleFields = []- , moduleFunctions =- [ delete- , empty- , fetch- , fill- , insert- , items- , list- , lookup- ]- , moduleOperations = []- }---- | Delete a single item from the media bag.-delete :: DocumentedFunction PandocError-delete = defun "delete"- ### (\fp -> unPandocLua $ modifyCommonState- (\st -> st { stMediaBag = MB.deleteMedia fp (stMediaBag st) }))- <#> stringParam "filepath" "filename of item to delete"- =#> []----- | Delete all items from the media bag.-empty :: DocumentedFunction PandocError-empty = defun "empty"- ### unPandocLua (modifyCommonState (\st -> st { stMediaBag = mempty }))- =#> []---- | Fill the mediabag with all images in the document that aren't--- present yet.-fill :: DocumentedFunction PandocError-fill = defun "fill"- ### unPandocLua . fillMediaBag- <#> parameter peekPandoc "Pandoc" "doc"- "document from which to fill the mediabag"- =#> functionResult pushPandoc "Pandoc" "modified document"- #? ("Fills the mediabag with the images in the given document.\n" <>- "An image that cannot be retrieved will be replaced with a Span\n" <>- "of class \"image\" that contains the image description.\n" <>- "" <>- "Images for which the mediabag already contains an item will\n" <>- "not be processed again.")---- | Insert a new item into the media bag.-insert :: DocumentedFunction PandocError-insert = defun "insert"- ### (\fp mmime contents -> unPandocLua $ do- mb <- getMediaBag- setMediaBag $ MB.insertMedia fp mmime contents mb- return (Lua.NumResults 0))- <#> stringParam "filepath" "item file path"- <#> opt (textParam "mimetype" "the item's MIME type")- <#> parameter Lua.peekLazyByteString "string" "contents" "binary contents"- =#> []---- | Returns iterator values to be used with a Lua @for@ loop.-items :: DocumentedFunction PandocError-items = defun "items"- ### (do- mb <-unPandocLua getMediaBag- let pushItem (fp, mimetype, contents) = do- Lua.pushString fp- Lua.pushText mimetype- Lua.pushByteString $ BL.toStrict contents- return (Lua.NumResults 3)- Lua.pushIterator pushItem (MB.mediaItems mb))- =?> "Iterator triple"---- | Function to lookup a value in the mediabag.-lookup :: DocumentedFunction PandocError-lookup = defun "lookup"- ### (\fp -> unPandocLua (MB.lookupMedia fp <$> getMediaBag) >>= \case- Nothing -> 1 <$ Lua.pushnil- Just item -> 2 <$ do- Lua.pushText $ MB.mediaMimeType item- Lua.pushLazyByteString $ MB.mediaContents item)- <#> stringParam "filepath" "path of item to lookup"- =?> "MIME type and contents"---- | Function listing all mediabag items.-list :: DocumentedFunction PandocError-list = defun "list"- ### (unPandocLua (MB.mediaDirectory <$> getMediaBag))- =#> functionResult (pushPandocList pushEntry) "table" "list of entry triples"- where- pushEntry :: (FilePath, MimeType, Int) -> LuaE PandocError ()- pushEntry (fp, mimeType, contentLength) = do- Lua.newtable- Lua.pushName "path" *> Lua.pushString fp *> Lua.rawset (-3)- Lua.pushName "type" *> Lua.pushText mimeType *> Lua.rawset (-3)- Lua.pushName "length" *> Lua.pushIntegral contentLength *> Lua.rawset (-3)---- | Lua function to retrieve a new item.-fetch :: DocumentedFunction PandocError-fetch = defun "fetch"- ### (\src -> do- (bs, mimeType) <- unPandocLua $ fetchItem src- Lua.pushText $ fromMaybe "" mimeType- Lua.pushByteString bs- return 2)- <#> textParam "src" "URI to fetch"- =?> "Returns two string values: the fetched contents and the mimetype."
@@ -1,320 +0,0 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{- |- Module : Text.Pandoc.Lua.Module.Pandoc- Copyright : Copyright © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Pandoc module for lua.--}-module Text.Pandoc.Lua.Module.Pandoc- ( pushModule- , documentedModule- ) where--import Prelude hiding (read)-import Control.Applicative ((<|>))-import Control.Monad (forM_, when)-import Control.Monad.Catch (catch, throwM)-import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr)-import Data.Default (Default (..))-import Data.Maybe (fromMaybe)-import Data.Proxy (Proxy (Proxy))-import HsLua hiding (pushModule)-import System.Exit (ExitCode (..))-import Text.Pandoc.Definition-import Text.Pandoc.Error (PandocError (..))-import Text.Pandoc.Lua.Orphans ()-import Text.Pandoc.Lua.Marshal.AST-import Text.Pandoc.Lua.Marshal.Filter (peekFilter)-import Text.Pandoc.Lua.Marshal.ReaderOptions ( peekReaderOptions- , pushReaderOptions)-import Text.Pandoc.Lua.Marshal.Sources (peekSources)-import Text.Pandoc.Lua.Marshal.WriterOptions ( peekWriterOptions- , pushWriterOptions)-import Text.Pandoc.Lua.Module.Utils (sha1)-import Text.Pandoc.Lua.PandocLua (PandocLua (unPandocLua), liftPandocLua)-import Text.Pandoc.Options ( ReaderOptions (readerExtensions)- , WriterOptions (writerExtensions) )-import Text.Pandoc.Process (pipeProcess)-import Text.Pandoc.Readers (Reader (..), getReader, readers)-import Text.Pandoc.Sources (toSources)-import Text.Pandoc.Writers (Writer (..), getWriter, writers)--import qualified HsLua as Lua-import qualified Data.ByteString.Lazy as BL-import qualified Data.ByteString.Lazy.Char8 as BSL-import qualified Data.Set as Set-import qualified Data.Text as T-import qualified Text.Pandoc.UTF8 as UTF8---- | Push the "pandoc" package to the Lua stack. Requires the `List`--- module to be loadable.-pushModule :: PandocLua NumResults-pushModule = do- liftPandocLua $ Lua.pushModule documentedModule- return 1--documentedModule :: Module PandocError-documentedModule = Module- { moduleName = "pandoc"- , moduleDescription = T.unlines- [ "Lua functions for pandoc scripts; includes constructors for"- , "document elements, functions to parse text in a given"- , "format, and functions to filter and modify a subtree."- ]- , moduleFields = readersField : writersField :- stringConstants ++ [inlineField, blockField]- , moduleOperations = []- , moduleFunctions = mconcat- [ functions- , otherConstructors- , blockConstructors- , inlineConstructors- , metaValueConstructors- ]- }---- | Set of input formats accepted by @read@.-readersField :: Field PandocError-readersField = Field- { fieldName = "readers"- , fieldDescription = T.unlines- [ "Set of formats that pandoc can parse. All keys in this table can"- , "be used as the `format` value in `pandoc.read`."- ]- , fieldPushValue = pushSet pushText $- Set.fromList (map fst (readers @PandocLua))- }---- | Set of input formats accepted by @write@.-writersField :: Field PandocError-writersField = Field- { fieldName = "writers"- , fieldDescription = T.unlines- [ "Set of formats that pandoc can generate. All keys in this table"- , "can be used as the `format` value in `pandoc.write`."- ]- , fieldPushValue = pushSet pushText $- Set.fromList (map fst (writers @PandocLua))- }---- | Inline table field-inlineField :: Field PandocError-inlineField = Field- { fieldName = "Inline"- , fieldDescription = "Inline constructors, nested under 'constructors'."- -- the nesting happens for historical reasons and should probably be- -- changed.- , fieldPushValue = pushWithConstructorsSubtable inlineConstructors- }---- | @Block@ module field-blockField :: Field PandocError-blockField = Field- { fieldName = "Block"- , fieldDescription = "Inline constructors, nested under 'constructors'."- -- the nesting happens for historical reasons and should probably be- -- changed.- , fieldPushValue = pushWithConstructorsSubtable blockConstructors- }--pushWithConstructorsSubtable :: [DocumentedFunction PandocError]- -> LuaE PandocError ()-pushWithConstructorsSubtable constructors = do- newtable -- Field table- newtable -- constructor table- pushName "constructor" *> pushvalue (nth 2) *> rawset (nth 4)- forM_ constructors $ \fn -> do- pushName (functionName fn)- pushDocumentedFunction fn- rawset (nth 3)- pop 1 -- pop constructor table--otherConstructors :: LuaError e => [DocumentedFunction e]-otherConstructors =- [ mkPandoc- , mkMeta- , mkAttr- , mkAttributeList- , mkBlocks- , mkCitation- , mkCell- , mkRow- , mkTableHead- , mkTableFoot- , mkInlines- , mkListAttributes- , mkSimpleTable-- , defun "ReaderOptions"- ### liftPure id- <#> parameter peekReaderOptions "ReaderOptions|table" "opts" "reader options"- =#> functionResult pushReaderOptions "ReaderOptions" "new object"- #? "Creates a new ReaderOptions value."-- , defun "WriterOptions"- ### liftPure id- <#> parameter peekWriterOptions "WriterOptions|table" "opts"- "writer options"- =#> functionResult pushWriterOptions "WriterOptions" "new object"- #? "Creates a new WriterOptions value."- ]--stringConstants :: [Field e]-stringConstants =- let constrs :: forall a. Data a => Proxy a -> [String]- constrs _ = map showConstr . dataTypeConstrs . dataTypeOf @a $ undefined- nullaryConstructors = mconcat- [ constrs (Proxy @ListNumberStyle)- , constrs (Proxy @ListNumberDelim)- , constrs (Proxy @QuoteType)- , constrs (Proxy @MathType)- , constrs (Proxy @Alignment)- , constrs (Proxy @CitationMode)- ]- toField s = Field- { fieldName = T.pack s- , fieldDescription = T.pack s- , fieldPushValue = pushString s- }- in map toField nullaryConstructors--functions :: [DocumentedFunction PandocError]-functions =- [ defun "pipe"- ### (\command args input -> do- (ec, output) <- Lua.liftIO $ pipeProcess Nothing command args input- `catch` (throwM . PandocIOError "pipe")- case ec of- ExitSuccess -> 1 <$ Lua.pushLazyByteString output- ExitFailure n -> do- pushPipeError (PipeError (T.pack command) n output)- Lua.error)- <#> parameter peekString "string" "command" "path to executable"- <#> parameter (peekList peekString) "{string,...}" "args"- "list of arguments"- <#> parameter peekLazyByteString "string" "input"- "input passed to process via stdin"- =?> "output string, or error triple"-- , defun "read"- ### (\content mformatspec mreaderOptions -> do- let formatSpec = fromMaybe "markdown" mformatspec- readerOpts = fromMaybe def mreaderOptions- readAction = getReader formatSpec >>= \case- (TextReader r, es) ->- r readerOpts{readerExtensions = es}- (case content of- Left bs -> toSources $ UTF8.toText bs- Right sources -> sources)- (ByteStringReader r, es) ->- case content of- Left bs -> r readerOpts{readerExtensions = es}- (BSL.fromStrict bs)- Right _ -> liftPandocLua $ Lua.failLua- "Cannot use bytestring reader with Sources"- try (unPandocLua readAction) >>= \case- Right pd ->- -- success, got a Pandoc document- return pd- Left (PandocUnknownReaderError f) ->- Lua.failLua . T.unpack $ "Unknown reader: " <> f- Left (PandocUnsupportedExtensionError e f) ->- Lua.failLua . T.unpack $- "Extension " <> e <> " not supported for " <> f- Left e ->- throwM e)- <#> parameter (\idx -> (Left <$> peekByteString idx)- <|> (Right <$> peekSources idx))- "string|Sources" "content" "text to parse"- <#> opt (textParam "formatspec" "format and extensions")- <#> opt (parameter peekReaderOptions "ReaderOptions" "reader_options"- "reader options")- =#> functionResult pushPandoc "Pandoc" "result document"-- , sha1-- , defun "walk_block"- ### walkElement- <#> parameter peekBlockFuzzy "Block" "block" "element to traverse"- <#> parameter peekFilter "Filter" "lua_filter" "filter functions"- =#> functionResult pushBlock "Block" "modified Block"-- , defun "walk_inline"- ### walkElement- <#> parameter peekInlineFuzzy "Inline" "inline" "element to traverse"- <#> parameter peekFilter "Filter" "lua_filter" "filter functions"- =#> functionResult pushInline "Inline" "modified Inline"-- , defun "write"- ### (\doc mformatspec mwriterOpts -> do- let formatSpec = fromMaybe "html" mformatspec- writerOpts = fromMaybe def mwriterOpts- unPandocLua $ getWriter formatSpec >>= \case- (TextWriter w, es) -> Right <$>- w writerOpts{ writerExtensions = es } doc- (ByteStringWriter w, es) -> Left <$>- w writerOpts{ writerExtensions = es } doc)- <#> parameter peekPandoc "Pandoc" "doc" "document to convert"- <#> opt (textParam "formatspec" "format and extensions")- <#> opt (parameter peekWriterOptions "WriterOptions" "writer_options"- "writer options")- =#> functionResult (either pushLazyByteString pushText) "string"- "result document"- ]- where- walkElement x f =- walkInlineSplicing f x- >>= walkInlinesStraight f- >>= walkBlockSplicing f- >>= walkBlocksStraight f--data PipeError = PipeError- { pipeErrorCommand :: T.Text- , pipeErrorCode :: Int- , pipeErrorOutput :: BL.ByteString- }--peekPipeError :: LuaError e => StackIndex -> LuaE e PipeError-peekPipeError idx =- PipeError- <$> (Lua.getfield idx "command" *> Lua.peek (-1) <* Lua.pop 1)- <*> (Lua.getfield idx "error_code" *> Lua.peek (-1) <* Lua.pop 1)- <*> (Lua.getfield idx "output" *> Lua.peek (-1) <* Lua.pop 1)--pushPipeError :: LuaError e => Pusher e PipeError-pushPipeError pipeErr = do- pushAsTable [ ("command" , pushText . pipeErrorCommand)- , ("error_code" , pushIntegral . pipeErrorCode)- , ("output" , pushLazyByteString . pipeErrorOutput)- ] pipeErr- pushPipeErrorMetaTable- Lua.setmetatable (nth 2)- where- pushPipeErrorMetaTable :: LuaError e => LuaE e ()- pushPipeErrorMetaTable = do- v <- Lua.newmetatable "pandoc pipe error"- when v $ do- pushName "__tostring"- pushHaskellFunction pipeErrorMessage- rawset (nth 3)-- pipeErrorMessage :: LuaError e => LuaE e NumResults- pipeErrorMessage = do- (PipeError cmd errorCode output) <- peekPipeError (nthBottom 1)- pushByteString . BSL.toStrict . BSL.concat $- [ BSL.pack "Error running "- , BSL.pack $ T.unpack cmd- , BSL.pack " (error code "- , BSL.pack $ show errorCode- , BSL.pack "): "- , if output == mempty then BSL.pack "<no output>" else output- ]- return (NumResults 1)
@@ -1,41 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{- |- Module : Text.Pandoc.Lua.Module.System- Copyright : © 2019-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Pandoc's system Lua module.--}-module Text.Pandoc.Lua.Module.System- ( documentedModule- ) where--import HsLua-import HsLua.Module.System- (arch, env, getwd, ls, mkdir, os, rmdir, with_env, with_tmpdir, with_wd)---- | Push the pandoc.system module on the Lua stack.-documentedModule :: LuaError e => Module e-documentedModule = Module- { moduleName = "pandoc.system"- , moduleDescription = "system functions"- , moduleFields =- [ arch- , os- ]- , moduleFunctions =- [ setName "environment" env- , setName "get_working_directory" getwd- , setName "list_directory" ls- , setName "make_directory" mkdir- , setName "remove_directory" rmdir- , setName "with_environment" with_env- , setName "with_temporary_directory" with_tmpdir- , setName "with_working_directory" with_wd- ]- , moduleOperations = []- }
@@ -1,61 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Lua.Module.Template- Copyright : Copyright © 2022 Albert Krewinkel, John MacFarlane- License : GNU GPL, version 2 or above- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>--Lua module to handle pandoc templates.--}-module Text.Pandoc.Lua.Module.Template- ( documentedModule- ) where--import HsLua-import Text.Pandoc.Error (PandocError)-import Text.Pandoc.Lua.Marshal.Template (pushTemplate)-import Text.Pandoc.Lua.PandocLua (PandocLua (unPandocLua), liftPandocLua)-import Text.Pandoc.Templates- (compileTemplate, getDefaultTemplate, runWithPartials, runWithDefaultPartials)--import qualified Data.Text as T---- | The "pandoc.template" module.-documentedModule :: Module PandocError-documentedModule = Module- { moduleName = "pandoc.template"- , moduleDescription = T.unlines- [ "Lua functions for pandoc templates."- ]- , moduleFields = []- , moduleOperations = []- , moduleFunctions = functions- }---- | Template module functions.-functions :: [DocumentedFunction PandocError]-functions =- [ defun "compile"- ### (\template mfilepath -> unPandocLua $- case mfilepath of- Just fp -> runWithPartials (compileTemplate fp template)- Nothing -> runWithDefaultPartials- (compileTemplate "templates/default" template))- <#> parameter peekText "string" "template" "template string"- <#> opt (stringParam "templ_path" "template path")- =#> functionResult (either failLua pushTemplate) "pandoc Template"- "compiled template"-- , defun "default"- ### (\mformat -> unPandocLua $ do- let getFORMAT = liftPandocLua $ do- getglobal "FORMAT"- forcePeek $ peekText top `lastly` pop 1- format <- maybe getFORMAT pure mformat- getDefaultTemplate format)- <#> opt (textParam "writer"- "writer for which the template should be returned.")- =#> functionResult pushText "string"- "string representation of the writer's default template"-- ]
@@ -1,42 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Lua.Module.Types- Copyright : © 2019-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Pandoc data type constructors.--}-module Text.Pandoc.Lua.Module.Types- ( documentedModule- ) where--import HsLua ( Module (..), (###), (<#>), (=#>)- , defun, functionResult, parameter)-import HsLua.Module.Version (peekVersionFuzzy, pushVersion)-import Text.Pandoc.Error (PandocError)-import Text.Pandoc.Lua.ErrorConversion ()---- | Push the pandoc.types module on the Lua stack.-documentedModule :: Module PandocError-documentedModule = Module- { moduleName = "pandoc.types"- , moduleDescription =- "Constructors for types that are not part of the pandoc AST."- , moduleFields = []- , moduleFunctions =- [ defun "Version"- ### return- <#> parameter peekVersionFuzzy "string|integer|{integer,...}|Version"- "version_specifier"- (mconcat [ "either a version string like `'2.7.3'`, "- , "a single integer like `2`, "- , "list of integers like `{2,7,3}`, "- , "or a Version object"- ])- =#> functionResult pushVersion "Version" "A new Version object."- ]- , moduleOperations = []- }
@@ -1,239 +0,0 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{- |- Module : Text.Pandoc.Lua.Module.Utils- Copyright : Copyright © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Utility module for Lua, exposing internal helper functions.--}-module Text.Pandoc.Lua.Module.Utils- ( documentedModule- , sha1- ) where--import Control.Applicative ((<|>))-import Control.Monad ((<$!>))-import Data.Data (showConstr, toConstr)-import Data.Default (def)-import Data.Maybe (fromMaybe)-import Data.Version (Version)-import HsLua as Lua-import HsLua.Module.Version (peekVersionFuzzy, pushVersion)-import Text.Pandoc.Citeproc (getReferences, processCitations)-import Text.Pandoc.Definition-import Text.Pandoc.Error (PandocError)-import Text.Pandoc.Lua.Marshal.AST-import Text.Pandoc.Lua.Marshal.Reference-import Text.Pandoc.Lua.PandocLua (PandocLua (unPandocLua))--import qualified Data.Digest.Pure.SHA as SHA-import qualified Data.ByteString.Lazy as BSL-import qualified Data.Map as Map-import qualified Data.Text as T-import qualified Text.Pandoc.Builder as B-import qualified Text.Pandoc.Filter.JSON as JSONFilter-import qualified Text.Pandoc.Shared as Shared-import qualified Text.Pandoc.UTF8 as UTF8-import qualified Text.Pandoc.Writers.Shared as Shared---- | Push the "pandoc.utils" module to the Lua stack.-documentedModule :: Module PandocError-documentedModule = Module- { moduleName = "pandoc.utils"- , moduleDescription = "pandoc utility functions"- , moduleFields = []- , moduleOperations = []- , moduleFunctions =- [ defun "blocks_to_inlines"- ### (\blks mSep -> do- let sep = maybe Shared.defaultBlocksSeparator B.fromList mSep- return $ B.toList (Shared.blocksToInlinesWithSep sep blks))- <#> parameter (peekList peekBlock) "list of blocks"- "blocks" ""- <#> opt (parameter (peekList peekInline) "list of inlines" "inline" "")- =#> functionResult pushInlines "list of inlines" ""-- , defun "citeproc"- ### unPandocLua . processCitations- <#> parameter peekPandoc "Pandoc" "doc" "document"- =#> functionResult pushPandoc "Pandoc" "processed document"- #? T.unwords- [ "Process the citations in the file, replacing them with "- , "rendered citations and adding a bibliography. "- , "See the manual section on citation rendering for details."- ]-- , defun "equals"- ### equal- <#> parameter pure "AST element" "elem1" ""- <#> parameter pure "AST element" "elem2" ""- =#> functionResult pushBool "boolean" "true iff elem1 == elem2"-- , defun "make_sections"- ### liftPure3 Shared.makeSections- <#> parameter peekBool "boolean" "numbering" "add header numbers"- <#> parameter (\i -> (Nothing <$ peekNil i) <|> (Just <$!> peekIntegral i))- "integer or nil" "baselevel" ""- <#> parameter (peekList peekBlock) "list of blocks"- "blocks" "document blocks to process"- =#> functionResult pushBlocks "list of Blocks"- "processes blocks"-- , defun "normalize_date"- ### liftPure Shared.normalizeDate- <#> parameter peekText "string" "date" "the date string"- =#> functionResult (maybe pushnil pushText) "string or nil"- "normalized date, or nil if normalization failed."- #? T.unwords- [ "Parse a date and convert (if possible) to \"YYYY-MM-DD\" format. We"- , "limit years to the range 1601-9999 (ISO 8601 accepts greater than"- , "or equal to 1583, but MS Word only accepts dates starting 1601)."- , "Returns nil instead of a string if the conversion failed."- ]-- , sha1-- , defun "Version"- ### liftPure (id @Version)- <#> parameter peekVersionFuzzy- "version string, list of integers, or integer"- "v" "version description"- =#> functionResult pushVersion "Version" "new Version object"- #? "Creates a Version object."-- , defun "references"- ### (unPandocLua . getReferences Nothing)- <#> parameter peekPandoc "Pandoc" "doc" "document"- =#> functionResult (pushPandocList pushReference) "table"- "lift of references"- #? mconcat- [ "Get references defined inline in the metadata and via an external "- , "bibliography. Only references that are actually cited in the "- , "document (either with a genuine citation or with `nocite`) are "- , "returned. URL variables are converted to links."- ]-- , defun "run_json_filter"- ### (\doc filterPath margs -> do- args <- case margs of- Just xs -> return xs- Nothing -> do- Lua.getglobal "FORMAT"- (forcePeek ((:[]) <$!> peekString top) <* pop 1)- JSONFilter.apply def args filterPath doc- )- <#> parameter peekPandoc "Pandoc" "doc" "input document"- <#> parameter peekString "filepath" "filter_path" "path to filter"- <#> opt (parameter (peekList peekString) "list of strings"- "args" "arguments to pass to the filter")- =#> functionResult pushPandoc "Pandoc" "filtered document"-- , defun "stringify"- ### stringify- <#> parameter pure "AST element" "elem" "some pandoc AST element"- =#> functionResult pushText "string" "stringified element"-- , defun "from_simple_table"- ### from_simple_table- <#> parameter peekSimpleTable "SimpleTable" "simple_tbl" ""- =?> "Simple table"-- , defun "to_roman_numeral"- ### liftPure Shared.toRomanNumeral- <#> parameter (peekIntegral @Int) "integer" "n" "number smaller than 4000"- =#> functionResult pushText "string" "roman numeral"- #? "Converts a number < 4000 to uppercase roman numeral."-- , defun "to_simple_table"- ### to_simple_table- <#> parameter peekTable "Block" "tbl" "a table"- =#> functionResult pushSimpleTable "SimpleTable" "SimpleTable object"- #? "Converts a table into an old/simple table."-- , defun "type"- ### (\idx -> getmetafield idx "__name" >>= \case- TypeString -> fromMaybe mempty <$> tostring top- _ -> ltype idx >>= typename)- <#> parameter pure "any" "object" ""- =#> functionResult pushByteString "string" "type of the given value"- #? ("Pandoc-friendly version of Lua's default `type` function, " <>- "returning the type of a value. If the argument has a " <>- "string-valued metafield `__name`, then it gives that string. " <>- "Otherwise it behaves just like the normal `type` function.")- ]- }---- | Documented Lua function to compute the hash of a string.-sha1 :: DocumentedFunction e-sha1 = defun "sha1"- ### liftPure (SHA.showDigest . SHA.sha1)- <#> parameter (fmap BSL.fromStrict . peekByteString) "string" "input" ""- =#> functionResult pushString "string" "hexadecimal hash value"- #? "Compute the hash of the given string value."----- | Convert pandoc structure to a string with formatting removed.--- Footnotes are skipped (since we don't want their contents in link--- labels).-stringify :: LuaError e => StackIndex -> LuaE e T.Text-stringify idx = forcePeek . retrieving "stringifyable element" $- choice- [ (fmap Shared.stringify . peekPandoc)- , (fmap Shared.stringify . peekInline)- , (fmap Shared.stringify . peekBlock)- , (fmap Shared.stringify . peekCitation)- , (fmap stringifyMetaValue . peekMetaValue)- , (fmap (const "") . peekAttr)- , (fmap (const "") . peekListAttributes)- ] idx- where- stringifyMetaValue :: MetaValue -> T.Text- stringifyMetaValue mv = case mv of- MetaBool b -> T.toLower $ T.pack (show b)- MetaString s -> s- MetaList xs -> mconcat $ map stringifyMetaValue xs- MetaMap m -> mconcat $ map (stringifyMetaValue . snd) (Map.toList m)- _ -> Shared.stringify mv---- | Converts an old/simple table into a normal table block element.-from_simple_table :: SimpleTable -> LuaE PandocError NumResults-from_simple_table (SimpleTable capt aligns widths head' body) = do- Lua.push $ Table- nullAttr- (Caption Nothing [Plain capt | not (null capt)])- (zipWith (\a w -> (a, toColWidth w)) aligns widths)- (TableHead nullAttr [blockListToRow head' | not (null head') ])- [TableBody nullAttr 0 [] $ map blockListToRow body | not (null body)]- (TableFoot nullAttr [])- return (NumResults 1)- where- blockListToRow :: [[Block]] -> Row- blockListToRow = Row nullAttr . map (B.simpleCell . B.fromList)-- toColWidth :: Double -> ColWidth- toColWidth 0 = ColWidthDefault- toColWidth w = ColWidth w---- | Converts a table into an old/simple table.-to_simple_table :: Block -> LuaE PandocError SimpleTable-to_simple_table = \case- Table _attr caption specs thead tbodies tfoot -> do- let (capt, aligns, widths, headers, rows) =- Shared.toLegacyTable caption specs thead tbodies tfoot- return $ SimpleTable capt aligns widths headers rows- blk -> Lua.failLua $ mconcat- [ "Expected Table, got ", showConstr (toConstr blk), "." ]--peekTable :: LuaError e => Peeker e Block-peekTable idx = peekBlock idx >>= \case- t@(Table {}) -> return t- b -> Lua.failPeek $ mconcat- [ "Expected Table, got "- , UTF8.fromString $ showConstr (toConstr b)- , "." ]
@@ -1,116 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE FlexibleInstances #-}-{- |- Module : Text.Pandoc.Lua.Orphans- Copyright : © 2012-2022 John MacFarlane- © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--Orphan instances for Lua's Pushable and Peekable type classes.--}-module Text.Pandoc.Lua.Orphans () where--import Data.Version (Version)-import HsLua-import HsLua.Module.Version (peekVersionFuzzy)-import Text.Pandoc.Definition-import Text.Pandoc.Lua.Marshal.AST-import Text.Pandoc.Lua.Marshal.CommonState ()-import Text.Pandoc.Lua.Marshal.Context ()-import Text.Pandoc.Lua.Marshal.PandocError()-import Text.Pandoc.Lua.Marshal.ReaderOptions ()-import Text.Pandoc.Lua.Marshal.Sources (pushSources)-import Text.Pandoc.Lua.ErrorConversion ()-import Text.Pandoc.Sources (Sources)--instance Pushable Pandoc where- push = pushPandoc--instance Pushable Meta where- push = pushMeta--instance Pushable MetaValue where- push = pushMetaValue--instance Pushable Block where- push = pushBlock--instance {-# OVERLAPPING #-} Pushable [Block] where- push = pushBlocks--instance Pushable Alignment where- push = pushString . show--instance Pushable CitationMode where- push = pushCitationMode--instance Pushable Format where- push = pushFormat--instance Pushable ListNumberDelim where- push = pushString . show--instance Pushable ListNumberStyle where- push = pushString . show--instance Pushable MathType where- push = pushMathType--instance Pushable QuoteType where- push = pushQuoteType--instance Pushable Cell where- push = pushCell--instance Pushable Inline where- push = pushInline--instance {-# OVERLAPPING #-} Pushable [Inline] where- push = pushInlines--instance Pushable Citation where- push = pushCitation--instance Pushable Row where- push = pushRow--instance Pushable TableBody where- push = pushTableBody--instance Pushable TableFoot where- push = pushTableFoot--instance Pushable TableHead where- push = pushTableHead---- These instances exist only for testing. It's a hack to avoid making--- the marshalling modules public.-instance Peekable Inline where- safepeek = peekInline--instance Peekable Block where- safepeek = peekBlock--instance Peekable Cell where- safepeek = peekCell--instance Peekable Meta where- safepeek = peekMeta--instance Peekable Pandoc where- safepeek = peekPandoc--instance Peekable Row where- safepeek = peekRow--instance Peekable Version where- safepeek = peekVersionFuzzy--instance {-# OVERLAPPING #-} Peekable Attr where- safepeek = peekAttr--instance Pushable Sources where- push = pushSources
@@ -1,113 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-{- |- Module : Text.Pandoc.Lua.PandocLua- Copyright : Copyright © 2020-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>- Stability : alpha--PandocMonad instance which allows execution of Lua operations and which-uses Lua to handle state.--}-module Text.Pandoc.Lua.PandocLua- ( PandocLua (..)- , runPandocLua- , liftPandocLua- ) where--import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)-import Control.Monad.Except (MonadError (catchError, throwError))-import Control.Monad.IO.Class (MonadIO)-import HsLua as Lua-import Text.Pandoc.Class.PandocMonad (PandocMonad (..))-import Text.Pandoc.Error (PandocError)-import Text.Pandoc.Lua.Global (Global (..), setGlobals)-import Text.Pandoc.Lua.Marshal.CommonState (peekCommonState)--import qualified Control.Monad.Catch as Catch-import qualified Text.Pandoc.Class.IO as IO---- | Type providing access to both, pandoc and Lua operations.-newtype PandocLua a = PandocLua { unPandocLua :: LuaE PandocError a }- deriving- ( Applicative- , Functor- , Monad- , MonadCatch- , MonadIO- , MonadMask- , MonadThrow- )---- | Lift a @'Lua'@ operation into the @'PandocLua'@ type.-liftPandocLua :: LuaE PandocError a -> PandocLua a-liftPandocLua = PandocLua---- | Evaluate a @'PandocLua'@ computation, running all contained Lua--- operations..-runPandocLua :: (PandocMonad m, MonadIO m) => PandocLua a -> m a-runPandocLua pLua = do- origState <- getCommonState- globals <- defaultGlobals- (result, newState) <- liftIO . Lua.run . unPandocLua $ do- putCommonState origState- liftPandocLua $ setGlobals globals- r <- pLua- c <- getCommonState- return (r, c)- putCommonState newState- return result--instance {-# OVERLAPPING #-} Exposable PandocError (PandocLua NumResults) where- partialApply _narg = liftLua . unPandocLua--instance Pushable a => Exposable PandocError (PandocLua a) where- partialApply _narg x = 1 <$ (liftLua (unPandocLua x >>= Lua.push))---- | Global variables which should always be set.-defaultGlobals :: PandocMonad m => m [Global]-defaultGlobals = do- commonState <- getCommonState- return- [ PANDOC_API_VERSION- , PANDOC_STATE commonState- , PANDOC_VERSION- ]--instance MonadError PandocError PandocLua where- catchError = Catch.catch- throwError = Catch.throwM--instance PandocMonad PandocLua where- lookupEnv = IO.lookupEnv- getCurrentTime = IO.getCurrentTime- getCurrentTimeZone = IO.getCurrentTimeZone- newStdGen = IO.newStdGen- newUniqueHash = IO.newUniqueHash-- openURL = IO.openURL-- readFileLazy = IO.readFileLazy- readFileStrict = IO.readFileStrict- readStdinStrict = IO.readStdinStrict-- glob = IO.glob- fileExists = IO.fileExists- getDataFileName = IO.getDataFileName- getModificationTime = IO.getModificationTime-- getCommonState = PandocLua $ do- Lua.getglobal "PANDOC_STATE"- forcePeek $ peekCommonState Lua.top- putCommonState = PandocLua . setGlobals . (:[]) . PANDOC_STATE-- logOutput = IO.logOutput
@@ -1,250 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{- |- Module : Text.Pandoc.Lua.Writer.Classic- Copyright : Copyright (C) 2012-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Conversion of Pandoc documents using a \"classic\" custom Lua writer.--}-module Text.Pandoc.Lua.Writer.Classic- ( runCustom- ) where-import Control.Applicative (optional)-import Control.Arrow ((***))-import Data.List (intersperse)-import Data.Maybe (fromMaybe)-import qualified Data.Text as T-import Data.Text (Text, pack)-import HsLua as Lua hiding (Operation (Div))-#if !MIN_VERSION_hslua(2,2,0)-import HsLua.Aeson (peekViaJSON)-#endif-import Text.DocLayout (literal, render)-import Text.DocTemplates (Context)-import Text.Pandoc.Definition-import Text.Pandoc.Lua.Marshal.Attr (pushAttributeList)-import Text.Pandoc.Lua.Orphans ()-import Text.Pandoc.Options-import Text.Pandoc.Templates (renderTemplate)-import Text.Pandoc.Writers.Shared---- | List of key-value pairs that is pushed to Lua as AttributeList--- userdata.-newtype AttributeList = AttributeList [(Text, Text)]-instance Pushable AttributeList where- push (AttributeList kvs) = pushAttributeList kvs--attrToMap :: Attr -> AttributeList-attrToMap (id',classes,keyvals) = AttributeList- $ ("id", id')- : ("class", T.unwords classes)- : keyvals--newtype Stringify a = Stringify a--instance Pushable (Stringify Format) where- push (Stringify (Format f)) = Lua.push (T.toLower f)--instance Pushable (Stringify [Inline]) where- push (Stringify ils) = Lua.push =<< inlineListToCustom ils--instance Pushable (Stringify [Block]) where- push (Stringify blks) = Lua.push =<< blockListToCustom blks--instance Pushable (Stringify MetaValue) where- push (Stringify (MetaMap m)) = Lua.push (fmap Stringify m)- push (Stringify (MetaList xs)) = Lua.push (map Stringify xs)- push (Stringify (MetaBool x)) = Lua.push x- push (Stringify (MetaString s)) = Lua.push s- push (Stringify (MetaInlines ils)) = Lua.push (Stringify ils)- push (Stringify (MetaBlocks bs)) = Lua.push (Stringify bs)--instance Pushable (Stringify Citation) where- push (Stringify cit) = flip pushAsTable cit- [ ("citationId", push . citationId)- , ("citationPrefix", push . Stringify . citationPrefix)- , ("citationSuffix", push . Stringify . citationSuffix)- , ("citationMode", push . citationMode)- , ("citationNoteNum", push . citationNoteNum)- , ("citationHash", push . citationHash)- ]---- | Key-value pair, pushed as a table with @a@ as the only key and @v@ as the--- associated value.-newtype KeyValue a b = KeyValue (a, b)--instance (Pushable a, Pushable b) => Pushable (KeyValue a b) where- push (KeyValue (k, v)) = do- Lua.newtable- Lua.push k- Lua.push v- Lua.rawset (Lua.nth 3)---- | Convert Pandoc to custom markup using a classic Lua writer.-runCustom :: LuaError e- => WriterOptions- -> Pandoc- -> LuaE e Text-runCustom opts doc@(Pandoc meta _) = do- (body, context) <- docToCustom opts doc- -- convert metavalues to a template context (variables)- metaContext <- metaToContext opts- (fmap (literal . pack) . blockListToCustom)- (fmap (literal . pack) . inlineListToCustom)- meta- -- merge contexts from metadata and variables- let renderContext = context <> metaContext- return $ case writerTemplate opts of- Nothing -> body- Just tpl -> render Nothing $- renderTemplate tpl $ setField "body" body renderContext---- | Converts a Pandoc value to custom markup using a classic Lua writer.-docToCustom :: forall e. LuaError e- => WriterOptions -> Pandoc -> LuaE e (Text, Context Text)-docToCustom opts (Pandoc (Meta metamap) blocks) = do- body <- blockListToCustom blocks- -- invoke doesn't work with multiple return values, so we have to call- -- `Doc` manually.- Lua.getglobal "Doc" -- function- push body -- argument 1- push (fmap Stringify metamap) -- argument 2- push (writerVariables opts) -- argument 3- call 3 2- rendered <- peek (nth 2) -- first return value- context <- forcePeek . optional $ peekViaJSON top -- snd return value- return (rendered, fromMaybe mempty context)----- | Convert Pandoc block element to Custom.-blockToCustom :: forall e. LuaError e- => Block -- ^ Block element- -> LuaE e String--blockToCustom Null = return ""--blockToCustom (Plain inlines) = invoke "Plain" (Stringify inlines)--blockToCustom (Para [Image attr txt (src,tit)]) =- invoke "CaptionedImage" src tit (Stringify txt) (attrToMap attr)--blockToCustom (Para inlines) = invoke "Para" (Stringify inlines)--blockToCustom (LineBlock linesList) =- invoke "LineBlock" (map (Stringify) linesList)--blockToCustom (RawBlock format str) =- invoke "RawBlock" (Stringify format) str--blockToCustom HorizontalRule = invoke "HorizontalRule"--blockToCustom (Header level attr inlines) =- invoke "Header" level (Stringify inlines) (attrToMap attr)--blockToCustom (CodeBlock attr str) =- invoke "CodeBlock" str (attrToMap attr)--blockToCustom (BlockQuote blocks) =- invoke "BlockQuote" (Stringify blocks)--blockToCustom (Table _ blkCapt specs thead tbody tfoot) =- let (capt, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot- aligns' = map show aligns- capt' = Stringify capt- headers' = map (Stringify) headers- rows' = map (map (Stringify)) rows- in invoke "Table" capt' aligns' widths headers' rows'--blockToCustom (BulletList items) =- invoke "BulletList" (map (Stringify) items)--blockToCustom (OrderedList (num,sty,delim) items) =- invoke "OrderedList" (map (Stringify) items) num (show sty) (show delim)--blockToCustom (DefinitionList items) =- invoke "DefinitionList"- (map (KeyValue . (Stringify *** map (Stringify))) items)--blockToCustom (Div attr items) =- invoke "Div" (Stringify items) (attrToMap attr)---- | Convert list of Pandoc block elements to Custom.-blockListToCustom :: forall e. LuaError e- => [Block] -- ^ List of block elements- -> LuaE e String-blockListToCustom xs = do- blocksep <- invoke "Blocksep"- bs <- mapM blockToCustom xs- return $ mconcat $ intersperse blocksep bs---- | Convert list of Pandoc inline elements to Custom.-inlineListToCustom :: forall e. LuaError e => [Inline] -> LuaE e String-inlineListToCustom lst = do- xs <- mapM (inlineToCustom @e) lst- return $ mconcat xs---- | Convert Pandoc inline element to Custom.-inlineToCustom :: forall e. LuaError e => Inline -> LuaE e String--inlineToCustom (Str str) = invoke "Str" str--inlineToCustom Space = invoke "Space"--inlineToCustom SoftBreak = invoke "SoftBreak"--inlineToCustom (Emph lst) = invoke "Emph" (Stringify lst)--inlineToCustom (Underline lst) = invoke "Underline" (Stringify lst)--inlineToCustom (Strong lst) = invoke "Strong" (Stringify lst)--inlineToCustom (Strikeout lst) = invoke "Strikeout" (Stringify lst)--inlineToCustom (Superscript lst) = invoke "Superscript" (Stringify lst)--inlineToCustom (Subscript lst) = invoke "Subscript" (Stringify lst)--inlineToCustom (SmallCaps lst) = invoke "SmallCaps" (Stringify lst)--inlineToCustom (Quoted SingleQuote lst) =- invoke "SingleQuoted" (Stringify lst)--inlineToCustom (Quoted DoubleQuote lst) =- invoke "DoubleQuoted" (Stringify lst)--inlineToCustom (Cite cs lst) =- invoke "Cite" (Stringify lst) (map (Stringify) cs)--inlineToCustom (Code attr str) =- invoke "Code" str (attrToMap attr)--inlineToCustom (Math DisplayMath str) =- invoke "DisplayMath" str--inlineToCustom (Math InlineMath str) =- invoke "InlineMath" str--inlineToCustom (RawInline format str) =- invoke "RawInline" (Stringify format) str--inlineToCustom LineBreak = invoke "LineBreak"--inlineToCustom (Link attr txt (src,tit)) =- invoke "Link" (Stringify txt) src tit (attrToMap attr)--inlineToCustom (Image attr alt (src,tit)) =- invoke "Image" (Stringify alt) src tit (attrToMap attr)--inlineToCustom (Note contents) = invoke "Note" (Stringify contents)--inlineToCustom (Span attr items) =- invoke "Span" (Stringify items) (attrToMap attr)
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.MIME- Copyright : Copyright (C) 2011-2022 John MacFarlane+ Copyright : Copyright (C) 2011-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -20,8 +20,10 @@ import Data.List (isPrefixOf, isSuffixOf) import qualified Data.Map as M import qualified Data.Text as T+import qualified Data.Text.Encoding as T import Data.Maybe (fromMaybe, listToMaybe) import Data.Tuple (swap)+import qualified Network.Mime import System.FilePath type MimeType = T.Text@@ -43,19 +45,21 @@ getMimeTypeDef = fromMaybe "application/octet-stream" . getMimeType extensionFromMimeType :: MimeType -> Maybe T.Text--- few special cases, where there are multiple options:-extensionFromMimeType "text/plain" = Just "txt"-extensionFromMimeType "video/quicktime" = Just "mov"-extensionFromMimeType "video/mpeg" = Just "mpeg"-extensionFromMimeType "video/dv" = Just "dv"-extensionFromMimeType "image/vnd.djvu" = Just "djvu"-extensionFromMimeType "image/tiff" = Just "tiff"-extensionFromMimeType "image/jpeg" = Just "jpg"-extensionFromMimeType "application/xml" = Just "xml"-extensionFromMimeType "application/ogg" = Just "ogg" extensionFromMimeType mimetype =- M.lookup (T.takeWhile (/=';') mimetype) reverseMimeTypes -- note: we just look up the basic mime type, dropping the content-encoding etc.+ case T.takeWhile (/=';') mimetype of+ -- handle a few special cases, where there are multiple options:+ "text/plain" -> Just "txt"+ "video/quicktime" -> Just "mov"+ "video/mpeg" -> Just "mpeg"+ "video/dv" -> Just "dv"+ "image/vnd.djvu" -> Just "djvu"+ "image/tiff" -> Just "tiff"+ "image/jpeg" -> Just "jpg"+ "application/xml" -> Just "xml"+ "application/ogg" -> Just "ogg"+ "image/svg+xml" -> Just "svg" -- avoid svgz+ mt -> M.lookup mt reverseMimeTypes -- | Determine general media category for file path, e.g. --@@ -81,37 +85,19 @@ -- Except for first entry, list borrowed from -- <https://github.com/Happstack/happstack-server/blob/master/src/Happstack/Server/FileServe/BuildingBlocks.hs happstack-server> mimeTypesList :: [(T.Text, MimeType)]-mimeTypesList =- [("cpt","image/x-corelphotopaint")- ,("gz","application/x-gzip")- ,("cabal","application/x-cabal")- ,("%","application/x-trash")+mimeTypesList = M.toList (M.map T.decodeUtf8 Network.Mime.defaultMimeMap) +++ [("%","application/x-trash") ,("323","text/h323")- ,("3gp","video/3gpp")- ,("7z","application/x-7z-compressed")- ,("abw","application/x-abiword")- ,("ai","application/postscript")- ,("aif","audio/x-aiff")- ,("aifc","audio/x-aiff")- ,("aiff","audio/x-aiff") ,("alc","chemical/x-alchemy")+ ,("apng","image/apng") ,("art","image/x-jg")- ,("asc","text/plain")- ,("asf","video/x-ms-asf") ,("asn","chemical/x-ncbi-asn1") ,("aso","chemical/x-ncbi-asn1-binary")- ,("asx","video/x-ms-asf")- ,("atom","application/atom")- ,("atomcat","application/atomcat+xml") ,("atomsrv","application/atomserv+xml")- ,("au","audio/basic")- ,("avi","video/x-msvideo")+ ,("avif", "image/avif") ,("b","chemical/x-molconn-Z") ,("bak","application/x-trash") ,("bat","application/x-msdos-program")- ,("bcpio","application/x-bcpio")- ,("bib","text/x-bibtex")- ,("bin","application/octet-stream") ,("bmp","image/x-ms-bmp") ,("boo","text/x-boo") ,("book","application/x-maker")@@ -119,89 +105,55 @@ ,("c","text/x-csrc") ,("c++","text/x-c++src") ,("c3d","chemical/x-chem3d")- ,("cab","application/x-cab")+ ,("cabal","application/x-cabal") ,("cac","chemical/x-cache") ,("cache","chemical/x-cache")- ,("cap","application/cap") ,("cascii","chemical/x-cactvs-binary")- ,("cat","application/vnd.ms-pki.seccat") ,("cbin","chemical/x-cactvs-binary")- ,("cbr","application/x-cbr") ,("cbz","application/x-cbz") ,("cc","text/x-c++src") ,("cdf","application/x-cdf") ,("cdr","image/x-coreldraw") ,("cdt","image/x-coreldrawtemplate")- ,("cdx","chemical/x-cdx")- ,("cdy","application/vnd.cinderella") ,("cef","chemical/x-cxf") ,("cer","chemical/x-cerius") ,("chm","chemical/x-chemdraw") ,("chrt","application/x-kchart")- ,("cif","chemical/x-cif")- ,("class","application/java-vm")- ,("cls","text/x-tex")- ,("cmdf","chemical/x-cmdf")- ,("cml","chemical/x-cml")- ,("cod","application/vnd.rim.cod") ,("com","application/x-msdos-program") ,("cpa","chemical/x-compass")- ,("cpio","application/x-cpio") ,("cpp","text/x-c++src")- ,("cpt","application/mac-compactpro")+ ,("cpt","image/x-corelphotopaint") ,("crl","application/x-pkcs7-crl")- ,("crt","application/x-x509-ca-cert") ,("csf","chemical/x-cache-csf")- ,("csh","application/x-csh") ,("csm","chemical/x-csml")- ,("csml","chemical/x-csml")- ,("css","text/css")- ,("csv","text/csv") ,("ctab","chemical/x-cactvs-binary") ,("ctx","chemical/x-ctx")- ,("cu","application/cu-seeme") ,("cub","chemical/x-gaussian-cube") ,("cxf","chemical/x-cxf") ,("cxx","text/x-c++src") ,("d","text/x-dsrc") ,("dat","chemical/x-mopac-input")- ,("dcr","application/x-director")- ,("deb","application/x-debian-package") ,("dif","video/dv") ,("diff","text/x-diff")- ,("dir","application/x-director")- ,("djv","image/vnd.djvu")- ,("djvu","image/vnd.djvu") ,("dl","video/dl") ,("dll","application/x-msdos-program")- ,("dmg","application/x-apple-diskimage") ,("dms","application/x-dms")- ,("doc","application/msword")- ,("dot","application/msword")- ,("dv","video/dv")- ,("dvi","application/x-dvi") ,("dx","chemical/x-jcamp-dx")- ,("dxr","application/x-director") ,("emb","chemical/x-embl-dl-nucleotide") ,("embl","chemical/x-embl-dl-nucleotide") ,("emf","image/x-emf")- ,("emz","application/x-msmetafile")- ,("eml","message/rfc822") ,("ent","chemical/x-ncbi-asn1-ascii")- ,("eot","application/vnd.ms-fontobject")++ -- The type used in mime-types is `application/postscript`,+ -- but code in Text.Pandoc.PDF relies on the type being+ -- `application/eps`. Do not remove without updating that+ -- module. ,("eps","application/eps")- ,("etx","text/x-setext")- ,("exe","application/x-msdos-program")- ,("ez","application/andrew-inset")+ ,("fb","application/x-maker") ,("fbdoc","application/x-maker") ,("fch","chemical/x-gaussian-checkpoint") ,("fchk","chemical/x-gaussian-checkpoint")- ,("fig","application/x-xfig")- ,("flac","application/x-flac")- ,("fli","video/fli")- ,("fm","application/x-maker")- ,("frame","application/x-maker") ,("frm","application/x-maker") ,("fs","text/plain") ,("gal","chemical/x-gaussian-log")@@ -212,164 +164,67 @@ ,("gcf","application/x-graphing-calculator") ,("gcg","chemical/x-gcg8-sequence") ,("gen","chemical/x-genbank")- ,("gf","application/x-tex-gf")- ,("gif","image/gif") ,("gjc","chemical/x-gaussian-input") ,("gjf","chemical/x-gaussian-input") ,("gl","video/gl") ,("glsl","text/plain")- ,("gnumeric","application/x-gnumeric") ,("gpt","chemical/x-mopac-graph")- ,("gsf","application/x-font") ,("gsm","audio/x-gsm")- ,("gtar","application/x-gtar") ,("h","text/x-chdr") ,("h++","text/x-c++hdr")- ,("hdf","application/x-hdf") ,("hh","text/x-c++hdr") ,("hin","chemical/x-hin") ,("hpp","text/x-c++hdr")- ,("hqx","application/mac-binhex40") ,("hs","text/x-haskell") ,("hta","application/hta")- ,("htc","text/x-component")- ,("htm","text/html")- ,("html","text/html") ,("hxx","text/x-c++hdr") ,("ica","application/x-ica")- ,("ice","x-conference/x-cooltalk")- ,("ico","image/x-icon")- ,("ics","text/calendar") ,("icz","text/calendar")- ,("ief","image/ief")- ,("iges","model/iges")- ,("igs","model/iges") ,("iii","application/x-iphone") ,("inp","chemical/x-gamess-input") ,("ins","application/x-internet-signup")- ,("iso","application/x-iso9660-image") ,("isp","application/x-internet-signup") ,("ist","chemical/x-isostar") ,("istr","chemical/x-isostar")- ,("jad","text/vnd.sun.j2me.app-descriptor")- ,("jar","application/java-archive")- ,("java","text/x-java") ,("jdx","chemical/x-jcamp-dx")- ,("jmz","application/x-jmol")- ,("jng","image/x-jng")- ,("jnlp","application/x-java-jnlp-file")- ,("jpe","image/jpeg")- ,("jpeg","image/jpeg") ,("jfif","image/jpeg")- ,("jpg","image/jpeg")- ,("js","application/javascript")- ,("kar","audio/midi")+ ,("jxl","image/jxl")+ ,("jmz","application/x-jmol") ,("key","application/pgp-keys") ,("kil","application/x-killustrator") ,("kin","chemical/x-kinemage")- ,("kml","application/vnd.google-earth.kml+xml")- ,("kmz","application/vnd.google-earth.kmz")- ,("kpr","application/x-kpresenter")- ,("kpt","application/x-kpresenter")- ,("ksp","application/x-kspread")- ,("kwd","application/x-kword")- ,("kwt","application/x-kword")- ,("latex","application/x-latex")- ,("lha","application/x-lha") ,("lhs","text/x-literate-haskell") ,("lsf","video/x-la-asf") ,("lsx","video/x-la-asf")- ,("ltx","text/x-tex") ,("lyx","application/x-lyx") ,("lzh","application/x-lzh") ,("lzx","application/x-lzx")- ,("m3u","audio/mpegurl")- ,("m4a","audio/mpeg")- ,("m4v","video/x-m4v")- ,("maker","application/x-maker") ,("man","application/x-troff-man") ,("mcif","chemical/x-mmcif") ,("mcm","chemical/x-macmolecule") ,("mdb","application/msaccess") ,("me","application/x-troff-me")- ,("mesh","model/mesh")- ,("mid","audio/midi")- ,("midi","audio/midi")- ,("mif","application/x-mif")- ,("mkv","video/x-matroska") ,("mm","application/x-freemind") ,("mmd","chemical/x-macromodel-input")- ,("mmf","application/vnd.smaf")- ,("mml","text/mathml") ,("mmod","chemical/x-macromodel-input")- ,("mng","video/x-mng") ,("moc","text/x-moc") ,("mol","chemical/x-mdl-molfile") ,("mol2","chemical/x-mol2") ,("moo","chemical/x-mopac-out") ,("mop","chemical/x-mopac-input") ,("mopcrt","chemical/x-mopac-input")- ,("mov","video/quicktime")- ,("movie","video/x-sgi-movie")- ,("mp2","audio/mpeg")- ,("mp3","audio/mpeg")- ,("mp4","video/mp4") ,("mpc","chemical/x-mopac-input")- ,("mpe","video/mpeg")- ,("mpeg","video/mpeg") ,("mpega","audio/mpeg")- ,("mpg","video/mpeg")- ,("mpga","audio/mpeg") ,("ms","application/x-troff-ms")- ,("msh","model/mesh") ,("msi","application/x-msi") ,("mvb","chemical/x-mopac-vib")- ,("mxu","video/vnd.mpegurl")- ,("nb","application/mathematica")- ,("nc","application/x-netcdf") ,("nwc","application/x-nwc") ,("o","application/x-object")- ,("oda","application/oda")- ,("odb","application/vnd.oasis.opendocument.database")- ,("odc","application/vnd.oasis.opendocument.chart")- ,("odf","application/vnd.oasis.opendocument.formula")- ,("odg","application/vnd.oasis.opendocument.graphics")- ,("odi","application/vnd.oasis.opendocument.image")- ,("odm","application/vnd.oasis.opendocument.text-master")- ,("odp","application/vnd.oasis.opendocument.presentation")- ,("ods","application/vnd.oasis.opendocument.spreadsheet")- ,("odt","application/vnd.oasis.opendocument.text")- ,("oga","audio/ogg")- ,("ogg","application/ogg")- ,("ogv","video/ogg")- ,("ogx","application/ogg") ,("old","application/x-trash")- ,("opus","audio/ogg")- ,("otg","application/vnd.oasis.opendocument.graphics-template")- ,("oth","application/vnd.oasis.opendocument.text-web")- ,("otp","application/vnd.oasis.opendocument.presentation-template")- ,("ots","application/vnd.oasis.opendocument.spreadsheet-template")- ,("otf","font/otf")- ,("ott","application/vnd.oasis.opendocument.text-template") ,("oza","application/x-oz-application")- ,("p","text/x-pascal")- ,("p7r","application/x-pkcs7-certreqresp")- ,("pac","application/x-ns-proxy-autoconfig")- ,("pas","text/x-pascal") ,("pat","image/x-coreldrawpattern") ,("patch","text/x-diff")- ,("pbm","image/x-portable-bitmap")- ,("pcap","application/cap")- ,("pcf","application/x-font")- ,("pcf.Z","application/x-font")- ,("pcx","image/pcx") ,("pdb","chemical/x-pdb")- ,("pdf","application/pdf")- ,("pfa","application/x-font")- ,("pfb","application/x-font")- ,("pgm","image/x-portable-graymap")- ,("pgn","application/x-chess-pgn")- ,("pgp","application/pgp-signature") ,("php","application/x-httpd-php") ,("php3","application/x-httpd-php3") ,("php3p","application/x-httpd-php3-preprocessed")@@ -378,171 +233,46 @@ ,("pht","application/x-httpd-php") ,("phtml","application/x-httpd-php") ,("pk","application/x-tex-pk")- ,("pl","text/x-perl") ,("pls","audio/x-scpls")- ,("pm","text/x-perl")- ,("png","image/png")- ,("pnm","image/x-portable-anymap") ,("pot","text/plain")- ,("ppm","image/x-portable-pixmap")- ,("pps","application/vnd.ms-powerpoint")- ,("ppt","application/vnd.ms-powerpoint")- ,("prf","application/pics-rules") ,("prt","chemical/x-ncbi-asn1-ascii")- ,("ps","application/postscript")- ,("psd","image/x-photoshop") ,("py","text/x-python") ,("pyc","application/x-python-code") ,("pyo","application/x-python-code")- ,("qt","video/quicktime") ,("qtl","application/x-quicktimeplayer")- ,("ra","audio/x-pn-realaudio")- ,("ram","audio/x-pn-realaudio")- ,("rar","application/rar")- ,("ras","image/x-cmu-raster") ,("rd","chemical/x-mdl-rdfile")- ,("rdf","application/rdf+xml")- ,("rgb","image/x-rgb") ,("rhtml","application/x-httpd-eruby") ,("rm","audio/x-pn-realaudio")- ,("roff","application/x-troff") ,("ros","chemical/x-rosdal")- ,("rpm","application/x-redhat-package-manager")- ,("rss","application/rss+xml")- ,("rtf","application/rtf")- ,("rtx","text/richtext") ,("rxn","chemical/x-mdl-rxnfile") ,("sct","text/scriptlet") ,("sd","chemical/x-mdl-sdfile") ,("sd2","audio/x-sd2")- ,("sda","application/vnd.stardivision.draw")- ,("sdc","application/vnd.stardivision.calc")- ,("sdd","application/vnd.stardivision.impress") ,("sdf","application/vnd.stardivision.math") ,("sds","application/vnd.stardivision.chart")- ,("sdw","application/vnd.stardivision.writer")- ,("ser","application/java-serialized-object") ,("sgf","application/x-go-sgf")- ,("sgl","application/vnd.stardivision.writer-global")- ,("sh","application/x-sh")- ,("shar","application/x-shar")- ,("shtml","text/html") ,("sid","audio/prs.sid") ,("sik","application/x-trash")- ,("silo","model/mesh")- ,("sis","application/vnd.symbian.install")- ,("sisx","x-epoc/x-sisx-app")- ,("sit","application/x-stuffit")- ,("sitx","application/x-stuffit")- ,("skd","application/x-koan")- ,("skm","application/x-koan")- ,("skp","application/x-koan")- ,("skt","application/x-koan")- ,("smi","application/smil")- ,("smil","application/smil")- ,("snd","audio/basic") ,("spc","chemical/x-galactic-spc")- ,("spl","application/futuresplash")- ,("spx","audio/ogg")- ,("src","application/x-wais-source")- ,("stc","application/vnd.sun.xml.calc.template")- ,("std","application/vnd.sun.xml.draw.template")- ,("sti","application/vnd.sun.xml.impress.template")- ,("stl","application/vnd.ms-pki.stl")- ,("stw","application/vnd.sun.xml.writer.template")- ,("sty","text/x-tex")- ,("sv4cpio","application/x-sv4cpio")- ,("sv4crc","application/x-sv4crc")- ,("svg","image/svg+xml")- -- removed for now, since it causes problems with- -- extensionFromMimeType: see #2183.- -- ,("svgz","image/svg+xml") ,("sw","chemical/x-swissprot")- ,("swf","application/x-shockwave-flash") ,("swfl","application/x-shockwave-flash")- ,("sxc","application/vnd.sun.xml.calc")- ,("sxd","application/vnd.sun.xml.draw")- ,("sxg","application/vnd.sun.xml.writer.global")- ,("sxi","application/vnd.sun.xml.impress")- ,("sxm","application/vnd.sun.xml.math")- ,("sxw","application/vnd.sun.xml.writer")- ,("t","application/x-troff")- ,("tar","application/x-tar") ,("taz","application/x-gtar")- ,("tcl","application/x-tcl")- ,("tex","text/x-tex")- ,("texi","application/x-texinfo")- ,("texinfo","application/x-texinfo")- ,("text","text/plain") ,("tgf","chemical/x-mdl-tgf")- ,("tgz","application/x-gtar")- ,("tif","image/tiff")- ,("tiff","image/tiff")- ,("tk","text/x-tcl") ,("tm","text/texmacs")- ,("torrent","application/x-bittorrent")- ,("tr","application/x-troff") ,("ts","text/texmacs") ,("tsp","application/dsptype")- ,("tsv","text/tab-separated-values")- ,("ttf","font/ttf")- ,("txt","text/plain")- ,("udeb","application/x-debian-package")- ,("uls","text/iuls")- ,("ustar","application/x-ustar") ,("val","chemical/x-ncbi-asn1-binary")- ,("vcd","application/x-cdlink")- ,("vcf","text/x-vcard")- ,("vcs","text/x-vcalendar") ,("vmd","chemical/x-vmd") ,("vms","chemical/x-vamas-iso14976") ,("vrm","x-world/x-vrml")- ,("vrml","model/vrml") ,("vs","text/plain")- ,("vsd","application/vnd.visio")- ,("vtt","text/vtt")- ,("wad","application/x-doom")- ,("wav","audio/x-wav")- ,("wax","audio/x-ms-wax")- ,("wbmp","image/vnd.wap.wbmp")- ,("wbxml","application/vnd.wap.wbxml")- ,("webm","video/webm")- ,("webp","image/webp") ,("wk","application/x-123")- ,("wm","video/x-ms-wm")- ,("wma","audio/x-ms-wma")- ,("wmd","application/x-ms-wmd") ,("wmf","image/x-wmf")- ,("wml","text/vnd.wap.wml")- ,("wmlc","application/vnd.wap.wmlc")- ,("wmls","text/vnd.wap.wmlscript")- ,("wmlsc","application/vnd.wap.wmlscriptc")- ,("wmv","video/x-ms-wmv")- ,("wmx","video/x-ms-wmx") ,("wmz","application/x-ms-wmz")- ,("woff","font/woff")- ,("woff2","font/woff2") ,("wp5","application/wordperfect5.1")- ,("wpd","application/wordperfect")- ,("wrl","model/vrml") ,("wsc","text/scriptlet")- ,("wvx","video/x-ms-wvx") ,("wz","application/x-wingz")- ,("xbm","image/x-xbitmap")- ,("xcf","image/x-xcf")- ,("xht","application/xhtml+xml")- ,("xhtml","application/xhtml+xml") ,("xlb","application/vnd.ms-excel")- ,("xls","application/vnd.ms-excel")- ,("xlt","application/vnd.ms-excel")- ,("xml","application/xml")- ,("xpi","application/x-xpinstall")- ,("xpm","image/x-xpixmap")- ,("xsl","application/xml") ,("xtel","chemical/x-xtel")- ,("xul","application/vnd.mozilla.xul+xml")- ,("xwd","image/x-xwindowdump")- ,("xyz","chemical/x-xyz")- ,("zip","application/zip") ,("zmt","chemical/x-mopac-input") ]
@@ -4,7 +4,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {- | Module : Text.Pandoc.MediaBag- Copyright : Copyright (C) 2014-2015, 2017-2022 John MacFarlane+ Copyright : Copyright (C) 2014-2015, 2017-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -23,6 +23,7 @@ mediaDirectory, mediaItems ) where+import Crypto.Hash (hashWith, SHA1(SHA1)) import qualified Data.ByteString.Lazy as BL import Data.Data (Data) import qualified Data.Map as M@@ -34,8 +35,8 @@ import Text.Pandoc.MIME (MimeType, getMimeTypeDef, extensionFromMimeType) import Data.Text (Text) import qualified Data.Text as T-import Data.Digest.Pure.SHA (sha1, showDigest)-import Network.URI (URI (..), parseURI)+import Network.URI (URI (..), isURI, parseURI, unEscapeString)+import Data.List (isInfixOf) data MediaItem = MediaItem@@ -54,9 +55,14 @@ instance Show MediaBag where show bag = "MediaBag " ++ show (mediaDirectory bag) --- | We represent paths with /, in normalized form.+-- | We represent paths with /, in normalized form. Percent-encoding+-- is not resolved. canonicalize :: FilePath -> Text-canonicalize = T.replace "\\" "/" . T.pack . normalise+-- avoid an expensive call to isURI for data URIs:+canonicalize fp@('d':'a':'t':'a':':':_) = T.pack fp+canonicalize fp+ | isURI fp = T.pack fp+ | otherwise = T.replace "\\" "/" . T.pack . normalise $ fp -- | Delete a media item from a 'MediaBag', or do nothing if no item corresponds -- to the given path.@@ -73,28 +79,39 @@ -> BL.ByteString -- ^ contents of resource -> MediaBag -> MediaBag-insertMedia fp mbMime contents (MediaBag mediamap) =- MediaBag (M.insert fp' mediaItem mediamap)- where mediaItem = MediaItem{ mediaPath = newpath- , mediaContents = contents- , mediaMimeType = mt }- fp' = canonicalize fp- uri = parseURI fp- newpath = if Posix.isRelative fp- && Windows.isRelative fp- && isNothing uri- && ".." `notElem` splitDirectories fp- then T.unpack fp'- else showDigest (sha1 contents) <> "." <> ext- fallback = case takeExtension fp of- ".gz" -> getMimeTypeDef $ dropExtension fp- _ -> getMimeTypeDef fp- mt = fromMaybe fallback mbMime- path = maybe fp uriPath uri- ext = case takeExtension path of- '.':e -> e- _ -> maybe "" T.unpack $ extensionFromMimeType mt-+insertMedia fp mbMime contents (MediaBag mediamap)+ | 'd':'a':'t':'a':':':_ <- fp+ , Just mt' <- mbMime+ = MediaBag (M.insert fp'+ MediaItem{ mediaPath = hashpath+ , mediaContents = contents+ , mediaMimeType = mt' } mediamap)+ | otherwise = MediaBag (M.insert fp' mediaItem mediamap)+ where+ mediaItem = MediaItem{ mediaPath = newpath+ , mediaContents = contents+ , mediaMimeType = mt }+ fp' = canonicalize fp+ fp'' = unEscapeString $ T.unpack fp'+ uri = parseURI fp+ hashpath = show (hashWith SHA1 (BL.toStrict contents)) <> ext+ newpath = if Posix.isRelative fp''+ && Windows.isRelative fp''+ && isNothing uri+ && not (".." `isInfixOf` fp'')+ && '%' `notElem` fp''+ then fp''+ else hashpath+ fallback = case takeExtension fp'' of+ ".gz" -> getMimeTypeDef $ dropExtension fp''+ _ -> getMimeTypeDef fp''+ mt = fromMaybe fallback mbMime+ path = maybe fp'' (unEscapeString . uriPath) uri+ ext = case extensionFromMimeType mt of+ Just e -> '.':T.unpack e+ Nothing -> case takeExtension path of+ '.':e | '%' `notElem` e -> '.':e+ _ -> "" -- | Lookup a media item in a 'MediaBag', returning mime type and contents. lookupMedia :: FilePath
@@ -1,18 +0,0 @@-{- |- Module : Text.Pandoc.Writers.Markdown.Inline- Copyright : Copyright (C) 2006-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--}-module Text.Pandoc.Network.HTTP (- urlEncode- ) where-import qualified Network.HTTP.Types as HTTP-import qualified Text.Pandoc.UTF8 as UTF8-import qualified Data.Text as T--urlEncode :: T.Text -> T.Text-urlEncode = UTF8.toText . HTTP.urlEncode True . UTF8.fromText
@@ -3,10 +3,11 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE TemplateHaskell #-} {- | Module : Text.Pandoc.Options- Copyright : Copyright (C) 2012-2022 John MacFarlane+ Copyright : Copyright (C) 2012-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -21,6 +22,10 @@ , HTMLMathMethod (..) , CiteMethod (..) , ObfuscationMethod (..)+ , HighlightMethod (..)+ , pattern NoHighlightingString+ , pattern DefaultHighlightingString+ , pattern IdiomaticHighlightingString , HTMLSlideVariant (..) , EPUBVersion (..) , WrapOption (..)@@ -28,9 +33,11 @@ , WriterOptions (..) , TrackChanges (..) , ReferenceLocation (..)+ , CaptionPosition (..) , def , isEnabled , defaultMathJaxURL+ , defaultWebTeXURL , defaultKaTeXURL ) where import Control.Applicative ((<|>))@@ -40,12 +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.Highlighting (Style, pygments)+import Text.Pandoc.Chunks (PathTemplate)+import Text.Pandoc.Highlighting (Style) import Text.Pandoc.UTF8 (toStringLazy) import Data.Aeson.TH (deriveJSON) import Data.Aeson@@ -65,6 +74,7 @@ , readerTrackChanges :: TrackChanges -- ^ Track changes setting for docx , readerStripComments :: Bool -- ^ Strip HTML comments instead of parsing as raw HTML -- (only implemented in commonmark)+ , readerTypstInputs :: [(Text, Text)] -- ^ parameters specified using --typst-input } deriving (Show, Read, Data, Typeable, Generic) instance HasSyntaxExtensions ReaderOptions where@@ -81,6 +91,7 @@ , readerDefaultImageExtension = "" , readerTrackChanges = AcceptChanges , readerStripComments = False+ , readerTypstInputs = [] } defaultAbbrevs :: Set.Set Text@@ -112,7 +123,8 @@ mburl <- m .:? "url" case method :: Text of "plain" -> return PlainMath- "webtex" -> return $ WebTeX $ fromMaybe "" mburl+ "webtex" -> return $ WebTeX $+ fromMaybe defaultWebTeXURL mburl "gladtex" -> return GladTeX "mathml" -> return MathML "mathjax" -> return $ MathJax $@@ -122,7 +134,7 @@ _ -> fail $ "Unknown HTML math method " ++ show method) node <|> (case node of String "plain" -> return PlainMath- String "webtex" -> return $ WebTeX ""+ String "webtex" -> return $ WebTeX defaultWebTeXURL String "gladtex" -> return GladTeX String "mathml" -> return MathML String "mathjax" -> return $ MathJax defaultMathJaxURL@@ -182,6 +194,43 @@ toJSON ReferenceObfuscation = String "references" toJSON JavascriptObfuscation = String "javascript" +-- | Method to provide code highlighting.+data HighlightMethod =+ Skylighting Style+ | IdiomaticHighlighting+ | DefaultHighlighting+ | NoHighlighting+ deriving (Show, Read, Eq, Data, Typeable, Generic)++-- | String representation of the idiomatic highlighting option.+pattern IdiomaticHighlightingString :: Text+pattern IdiomaticHighlightingString = "idiomatic"++-- | String representation of the default highlighting option.+pattern DefaultHighlightingString :: Text+pattern DefaultHighlightingString = "default"++-- | String representation of the no highlighting option+pattern NoHighlightingString :: Text+pattern NoHighlightingString = "none"++instance ToJSON HighlightMethod where+ toJSON NoHighlighting = String NoHighlightingString+ toJSON IdiomaticHighlighting = String IdiomaticHighlightingString+ toJSON DefaultHighlighting = String DefaultHighlightingString+ toJSON (Skylighting style) = toJSON style++instance FromJSON HighlightMethod where+ parseJSON = \case+ String NoHighlightingString -> pure NoHighlighting+ String IdiomaticHighlightingString -> pure IdiomaticHighlighting+ String DefaultHighlightingString -> pure DefaultHighlighting+ String x -> fail $ "Unknown highlighting method " <> T.unpack x+ Bool True -> pure DefaultHighlighting+ Bool False -> pure NoHighlighting+ Null -> pure NoHighlighting+ v -> Skylighting <$> parseJSON v+ -- | Varieties of HTML slide shows. data HTMLSlideVariant = S5Slides | SlidySlides@@ -285,12 +334,30 @@ toJSON EndOfSection = "end-of-section" toJSON EndOfDocument = "end-of-document" +-- | Positions for figure and table captions+data CaptionPosition = CaptionAbove -- ^ above figure or table+ | CaptionBelow -- ^ below figure or table+ deriving (Show, Read, Eq, Data, Typeable, Generic)++instance FromJSON CaptionPosition where+ parseJSON v =+ case v of+ String "above" -> return CaptionAbove+ String "below" -> return CaptionBelow+ _ -> fail $ "Unknown caption position " <> toStringLazy (encode v)++instance ToJSON CaptionPosition where+ toJSON CaptionAbove = "above"+ toJSON CaptionBelow = "below"+ -- | Options for writers data WriterOptions = WriterOptions { writerTemplate :: Maybe (Template Text) -- ^ Template to use , writerVariables :: Context Text -- ^ Variables to set in template , writerTabStop :: Int -- ^ Tabstop for conversion btw spaces and tabs , writerTableOfContents :: Bool -- ^ Include table of contents+ , writerListOfFigures :: Bool -- ^ Include list of figures+ , writerListOfTables :: Bool -- ^ Include list of tables , writerIncremental :: Bool -- ^ True if lists should be incremental , writerHTMLMathMethod :: HTMLMathMethod -- ^ How to print math in HTML , writerNumberSections :: Bool -- ^ Number sections in LaTeX@@ -308,19 +375,23 @@ , 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 , writerEpubMetadata :: Maybe Text -- ^ Metadata to include in EPUB , writerEpubFonts :: [FilePath] -- ^ Paths to fonts to embed- , writerEpubChapterLevel :: Int -- ^ Header level for chapters (separate files)+ , writerEpubTitlePage :: Bool -- ^ Include title page in epub+ , writerSplitLevel :: Int -- ^ Header level at which to split EPUB or chunked HTML into separate files+ , writerChunkTemplate :: PathTemplate -- ^ Template for filenames in chunked HTML , writerTOCDepth :: Int -- ^ Number of levels to include in TOC , writerReferenceDoc :: Maybe FilePath -- ^ Path to reference document if specified , writerReferenceLocation :: ReferenceLocation -- ^ Location of footnotes and references for writing markdown+ , writerFigureCaptionPosition :: CaptionPosition -- ^ Position of figure caption+ , writerTableCaptionPosition :: CaptionPosition -- ^ Position of table caption , writerSyntaxMap :: SyntaxMap , writerPreferAscii :: Bool -- ^ Prefer ASCII representations of characters when possible+ , writerLinkImages :: Bool -- ^ Use links rather than embedding ODT images } deriving (Show, Data, Typeable, Generic) instance Default WriterOptions where@@ -328,6 +399,8 @@ , writerVariables = mempty , writerTabStop = 4 , writerTableOfContents = False+ , writerListOfFigures = False+ , writerListOfTables = False , writerIncremental = False , writerHTMLMathMethod = PlainMath , writerNumberSections = False@@ -344,18 +417,23 @@ , writerHtmlQTags = False , writerSlideLevel = Nothing , writerTopLevelDivision = TopLevelDefault- , writerListings = False- , writerHighlightStyle = Just pygments+ , writerHighlightMethod = DefaultHighlighting , writerSetextHeaders = False+ , writerListTables = False , writerEpubSubdirectory = "EPUB" , writerEpubMetadata = Nothing , writerEpubFonts = []- , writerEpubChapterLevel = 1+ , writerEpubTitlePage = True+ , writerSplitLevel = 1+ , writerChunkTemplate = "%s-%i.html" , writerTOCDepth = 3 , writerReferenceDoc = Nothing , writerReferenceLocation = EndOfDocument+ , writerFigureCaptionPosition = CaptionBelow+ , writerTableCaptionPosition = CaptionAbove , writerSyntaxMap = defaultSyntaxMap , writerPreferAscii = False+ , writerLinkImages = False } instance HasSyntaxExtensions WriterOptions where@@ -366,10 +444,13 @@ isEnabled ext opts = ext `extensionEnabled` getExtensions opts defaultMathJaxURL :: Text-defaultMathJaxURL = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js"+defaultMathJaxURL = "https://cdn.jsdelivr.net/npm/mathjax@4/tex-chtml.js" +defaultWebTeXURL :: Text+defaultWebTeXURL = "https://latex.codecogs.com/png.latex?"+ defaultKaTeXURL :: Text-defaultKaTeXURL = "https://cdn.jsdelivr.net/npm/katex@0.15.1/dist/"+defaultKaTeXURL = "https://cdn.jsdelivr.net/npm/katex@latest/dist/" -- Update documentation in doc/filters.md if this is changed. $(deriveJSON defaultOptions{ fieldLabelModifier =
@@ -5,7 +5,7 @@ {-# LANGUAGE FlexibleContexts #-} {- | Module : Text.Pandoc.PDF- Copyright : Copyright (C) 2012-2022 John MacFarlane+ Copyright : Copyright (C) 2012-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -18,8 +18,9 @@ import qualified Codec.Picture as JP import qualified Control.Exception as E-import Control.Monad (when) import Control.Monad.Trans (MonadIO (..))+import Control.Monad (foldM_)+import Crypto.Hash (hashWith, SHA1(SHA1)) import qualified Data.ByteString as BS import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy as BL@@ -35,13 +36,14 @@ import System.Environment import System.Exit (ExitCode (..)) import System.FilePath-import System.IO (stderr, hClose)+import System.IO (hClose) import System.IO.Temp (withSystemTempDirectory, withTempDirectory, withTempFile) import qualified System.IO.Error as IE-import Text.DocLayout (literal)+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))@@ -52,15 +54,16 @@ import Text.Pandoc.Walk (walkM) import Text.Pandoc.Writers.Shared (getField, metaToContext) import Control.Monad.Catch (MonadMask)-import Data.Digest.Pure.SHA (sha1, showDigest) #ifdef _WINDOWS import Data.List (intercalate) #endif import Data.List (isPrefixOf, find)-import Text.Pandoc.Class (fillMediaBag, getVerbosity,- readFileLazy, readFileStrict, fileExists,- report, extractMedia, PandocMonad)+import Text.Pandoc.MediaBag (mediaItems)+import Text.Pandoc.Class (fillMediaBag, getMediaBag, getVerbosity, setVerbosity,+ readFileStrict, fileExists,+ report, extractMedia, PandocMonad, runIOorExplode) import Text.Pandoc.Logging+import Text.DocTemplates ( FromContext(lookupContext) ) #ifdef _WINDOWS changePathSeparators :: FilePath -> FilePath@@ -80,45 +83,93 @@ -> WriterOptions -- ^ options -> Pandoc -- ^ document -> m (Either ByteString ByteString)-makePDF program pdfargs writer opts doc =+makePDF program pdfargs writer opts doc = withTempDir (program == "typst") "media" $ \mediaDir -> do+#ifdef _WINDOWS+ -- note: we want / even on Windows, for TexLive+ let tmpdir = changePathSeparators mediaDir+#else+ let tmpdir = mediaDir+#endif+ let isTeXFormat "context" = True+ isTeXFormat "tectonic" = True+ isTeXFormat "latexmk" = True+ isTeXFormat "lualatex" = True+ isTeXFormat "lualatex-dev" = True+ isTeXFormat "pdflatex" = True+ isTeXFormat "pdflatex-dev" = True+ isTeXFormat "xelatex" = True+ isTeXFormat _ = False+ let opts' = if isTeXFormat program+ then -- disable quote ligatures to avoid bad ligatures like ?`+ opts{ writerExtensions = disableExtension Ext_smart+ (writerExtensions opts) }+ else opts+ source <- fillMediaBag doc+ >>= extractMedia tmpdir+ >>= (if isTeXFormat program+ then walkM (convertImages opts' tmpdir)+ else return)+ >>= writer opts'++ verbosity <- getVerbosity+ let compileHTML mkOutArgs = do+ -- check to see if there is anything in mediabag, and if so,+ -- make the HTML self contained+ mediabag <- getMediaBag+ source' <- case mediaItems mediabag of+ [] -> pure source+ _ -> makeSelfContained source+ liftIO $+ toPdfViaTempFile verbosity program pdfargs mkOutArgs ".html" source' case takeBaseName program of- "wkhtmltopdf" -> makeWithWkhtmltopdf program pdfargs writer opts doc- prog | prog `elem` ["pagedjs-cli" ,"weasyprint", "prince"] -> do- source <- writer opts doc- verbosity <- getVerbosity- liftIO $ html2pdf verbosity program pdfargs source+ "wkhtmltopdf" -> makeWithWkhtmltopdf program pdfargs writer opts' doc+ "pagedjs-cli" -> compileHTML (\f -> ["-o", f])+ "prince" -> compileHTML (\f -> ["-o", f])+ "weasyprint" -> compileHTML (:[])+ "typst" -> liftIO $+ toPdfViaTempFile verbosity program ("compile":pdfargs) (:[]) ".typ" source "pdfroff" -> do- source <- writer opts doc+ let paperargs =+ case lookupContext "papersize" (writerVariables opts') of+ Just s+ | T.takeEnd 1 s == "l" -> ["-P-p" <>+ T.unpack (T.dropEnd 1 s), "-P-l"]+ | otherwise -> ["-P-p" <> T.unpack s]+ Nothing -> [] let args = ["-ms", "-mpdfmark", "-mspdf",- "-e", "-t", "-k", "-KUTF-8", "-i"] ++ pdfargs+ "-e", "-t", "-k", "-KUTF-8", "-i"] +++ ["-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+ "groff" -> do+ let paperargs =+ case lookupContext "papersize" (writerVariables opts') of+ Just s+ | T.takeEnd 1 s == "l" -> ["-P-p" <>+ T.unpack (T.dropEnd 1 s), "-P-l"]+ | otherwise -> ["-P-p" <> T.unpack s]+ Nothing -> []+ let args = ["-ms", "-Tpdf",+ "-e", "-t", "-k", "-KUTF-8"] +++ ["-U" | ".PDFPIC" `T.isInfixOf` source] +++ paperargs ++ pdfargs+ generic2pdf program args source+ "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"] ""@@ -126,9 +177,9 @@ then return $ Just $ filter (not . isSpace) sout else return Nothing) (\(_ :: E.SomeException) -> return Nothing)- if '~' `elem` tmp || uname == Just "Cygwin" -- see #5451- then withTempDirectory "." templ action- else withSystemTempDirectory templ action+ if useWorkingDirectory || '~' `elem` tmp || uname == Just "Cygwin" -- see #5451+ then withTempDirectory "." templ action+ else withSystemTempDirectory templ action makeWithWkhtmltopdf :: (PandocMonad m, MonadIO m) => String -- ^ wkhtmltopdf or path@@ -165,18 +216,9 @@ -- see #6474 source <- writer opts doc verbosity <- getVerbosity- liftIO $ html2pdf verbosity program args source--handleImages :: (PandocMonad m, MonadIO m)- => WriterOptions- -> FilePath -- ^ temp dir to store images- -> Pandoc -- ^ document- -> m Pandoc-handleImages opts tmpdir doc =- fillMediaBag doc >>=- extractMedia tmpdir >>=- walkM (convertImages opts tmpdir)+ liftIO $ toPdfViaTempFile verbosity program args (:[]) ".html" source +-- convert SVG to PDF, and pixel formats to PNG or JPEG, for TeX formats convertImages :: (PandocMonad m, MonadIO m) => WriterOptions -> FilePath -> Inline -> m Inline convertImages opts tmpdir (Image attr ils (src, tit)) = do@@ -217,7 +259,7 @@ E.catch (Right pngOut <$ JP.savePngImage pngOut img) $ \(e :: E.SomeException) -> return (Left (tshow e)) where- sha = showDigest (sha1 (UTF8.fromStringLazy fname))+ sha = show (hashWith SHA1 (UTF8.fromString fname)) pngOut = normalise $ tmpdir </> sha <.> "png" pdfOut = normalise $ tmpdir </> sha <.> "pdf" svgIn = normalise fname@@ -246,10 +288,15 @@ -> Text -- ^ tex source -> m (Either ByteString ByteString) tex2pdf program args tmpDir source = do- let numruns | takeBaseName program == "latexmk" = 1- | "\\tableofcontents" `T.isInfixOf` source = 3 -- to get page numbers- | otherwise = 2 -- 1 run won't give you PDF bookmarks- (exit, log', mbPdf) <- runTeXProgram program args numruns tmpDir source+ let isOutdirArg x = "-outdir=" `isPrefixOf` x ||+ "-output-directory=" `isPrefixOf` x+ let outDir =+ case find isOutdirArg args of+ Just x -> drop 1 $ dropWhile (/='=') x+ Nothing -> tmpDir+ let file = tmpDir ++ "/input.tex" -- note: tmpDir has / path separators+ liftIO $ BS.writeFile file $ UTF8.fromText source+ (exit, log', mbPdf) <- runTeXProgram program args tmpDir outDir case (exit, mbPdf) of (ExitFailure _, _) -> do let logmsg = extractMsg log'@@ -262,13 +309,14 @@ return $ Left $ logmsg <> extramsg (ExitSuccess, Nothing) -> return $ Left "" (ExitSuccess, Just pdf) -> do+ latexWarnings log' missingCharacterWarnings log' return $ Right pdf missingCharacterWarnings :: PandocMonad m => ByteString -> m () missingCharacterWarnings log' = do let ls = BC.lines log'- let isMissingCharacterWarning = BC.isPrefixOf "Missing character: "+ let isMissingCharacterWarning = BC.isPrefixOf "Missing character:" let toCodePoint c | isAscii c = T.singleton c | otherwise = T.pack $ c : " (U+" ++ printf "%04X" (ord c) ++ ")"@@ -279,6 +327,20 @@ ] mapM_ (report . MissingCharacter) warnings +latexWarnings :: PandocMonad m => ByteString -> m ()+latexWarnings log' = foldM_ go Nothing (BC.lines log')+ where+ go Nothing ln+ | BC.isPrefixOf "LaTeX Warning:" ln =+ pure $ Just ln+ | otherwise = pure Nothing+ go (Just msg) ln+ | ln == "" = do -- emit report and reset accumulator+ report $ MakePDFWarning $ render (Just 60) $+ hsep $ map literal $ T.words $ utf8ToText msg+ pure Nothing+ | otherwise = pure $ Just (msg <> ln)+ -- parsing output extractMsg :: ByteString -> ByteString@@ -315,17 +377,11 @@ let sourceBL = BL.fromStrict $ UTF8.fromText source let programArgs = ["--outdir", tmpDir] ++ args ++ ["-"] env <- liftIO getEnvironment- verbosity <- getVerbosity- when (verbosity >= INFO) $ liftIO $- showVerboseInfo (Just tmpDir) program programArgs env- (utf8ToText sourceBL)+ showVerboseInfo (Just tmpDir) program programArgs env (utf8ToText sourceBL) (exit, out) <- liftIO $ E.catch (pipeProcess (Just env) program programArgs sourceBL) (handlePDFProgramNotFound program)- when (verbosity >= INFO) $ liftIO $ do- UTF8.hPutStrLn stderr "[makePDF] Running"- BL.hPutStr stderr out- UTF8.hPutStr stderr "\n"+ report $ MakePDFInfo "tectonic output" (utf8ToText out) let pdfFile = tmpDir ++ "/texput.pdf" (_, pdf) <- getResultingPDF Nothing pdfFile return (exit, out, pdf)@@ -350,61 +406,70 @@ Just logFile' -> do logExists <- fileExists logFile' if logExists- then Just <$> readFileLazy logFile'+ then Just . BL.fromStrict <$> readFileStrict logFile' else return Nothing Nothing -> return Nothing return (log', pdf) --- Run a TeX program on an input bytestring and return (exit code,--- contents of stdout, contents of produced PDF if any). Rerun--- a fixed number of times to resolve references.+-- Run a TeX program once in a temp directory (on input.tex) and return (exit code,+-- contents of stdout, contents of produced PDF if any). runTeXProgram :: (PandocMonad m, MonadIO m)- => String -> [String] -> Int -> FilePath- -> Text -> m (ExitCode, ByteString, Maybe ByteString)-runTeXProgram program args numRuns tmpDir' source = do- let isOutdirArg x = "-outdir=" `isPrefixOf` x ||- "-output-directory=" `isPrefixOf` x- let tmpDir =- case find isOutdirArg args of- Just x -> drop 1 $ dropWhile (/='=') x- Nothing -> tmpDir'- liftIO $ createDirectoryIfMissing True tmpDir- let file = tmpDir ++ "/input.tex" -- note: tmpDir has / path separators- liftIO $ BS.writeFile file $ UTF8.fromText source+ => String -> [String] -> FilePath -> FilePath+ -> m (ExitCode, ByteString, Maybe ByteString)+runTeXProgram program args tmpDir outDir = do let isLatexMk = takeBaseName program == "latexmk"- programArgs | isLatexMk = ["-interaction=batchmode", "-halt-on-error", "-pdf",- "-quiet", "-outdir=" ++ tmpDir] ++ args ++ [file]- | otherwise = ["-halt-on-error", "-interaction", "nonstopmode",- "-output-directory", tmpDir] ++ args ++ [file]+ programArgs | isLatexMk =+ ["-interaction=batchmode", "-halt-on-error", "-pdf",+ "-quiet", "-outdir=" ++ outDir] ++ args ++ [file]+ | otherwise =+ ["-halt-on-error", "-interaction", "nonstopmode",+ "-output-directory", outDir] ++ args ++ [file] env' <- liftIO getEnvironment let sep = [searchPathSeparator] let texinputs = maybe (tmpDir ++ sep) ((tmpDir ++ sep) ++) $ lookup "TEXINPUTS" env' let env'' = ("TEXINPUTS", texinputs) :- ("TEXMFOUTPUT", tmpDir) :+ ("TEXMFOUTPUT", outDir) : [(k,v) | (k,v) <- env' , k /= "TEXINPUTS" && k /= "TEXMFOUTPUT"]- verbosity <- getVerbosity- when (verbosity >= INFO) $ liftIO $- UTF8.readFile file >>=- showVerboseInfo (Just tmpDir) program programArgs env''- let runTeX runNumber = do- (exit, out) <- liftIO $ E.catch- (pipeProcess (Just env'') program programArgs BL.empty)- (handlePDFProgramNotFound program)- when (verbosity >= INFO) $ liftIO $ do- UTF8.hPutStrLn stderr $ "[makePDF] Run #" <> tshow runNumber- BL.hPutStr stderr out- UTF8.hPutStr stderr "\n"- if runNumber < numRuns- then runTeX (runNumber + 1)- else do- let logFile = replaceExtension file ".log"- let pdfFile = replaceExtension file ".pdf"- (log', pdf) <- getResultingPDF (Just logFile) pdfFile- return (exit, fromMaybe out log', pdf)- runTeX 1+ liftIO (UTF8.readFile file) >>=+ showVerboseInfo (Just tmpDir) program programArgs env''+ go env'' programArgs (1 :: Int)+ where+ file = tmpDir ++ "/input.tex"+ outfile = outDir ++ "/input.pdf"+ go env'' programArgs runNumber = do+ let maxruns = 4 -- stop if warnings present after 4 runs+ report $ MakePDFInfo ("LaTeX run number " <> tshow runNumber) mempty+ (exit, out) <- liftIO $ E.catch+ (pipeProcess (Just env'') program programArgs BL.empty)+ (handlePDFProgramNotFound program)+ report $ MakePDFInfo "LaTeX output" (utf8ToText out)+ -- parse log to see if we need to rerun LaTeX+ let logFile = replaceExtension outfile ".log"+ logExists <- fileExists logFile+ logContents <- if logExists+ then BL.fromStrict <$> readFileStrict logFile+ else return mempty+ let rerunWarnings = checkForRerun logContents+ tocFileExists <- fileExists (replaceExtension outfile ".toc")+ -- if we have a TOC we always need 3 runs, see #10308+ let rerunWarnings' = rerunWarnings ++ ["TOC is present" | tocFileExists]+ if not (null rerunWarnings') && runNumber < maxruns+ then do+ report $ MakePDFInfo "Rerun needed"+ (T.intercalate "\n" (map utf8ToText rerunWarnings'))+ go env'' programArgs (runNumber + 1)+ else do+ (log', pdf) <- getResultingPDF (Just logFile) outfile+ return (exit, fromMaybe out log', pdf) + checkForRerun log' = filter isRerunWarning $ BC.lines log'++ isRerunWarning ln =+ let ln' = BL.toStrict ln+ in BS.isInfixOf "Warning:" ln' && BS.isInfixOf "Rerun" ln'+ generic2pdf :: (PandocMonad m, MonadIO m) => String -> [String]@@ -412,9 +477,7 @@ -> m (Either ByteString ByteString) generic2pdf program args source = do env' <- liftIO getEnvironment- verbosity <- getVerbosity- when (verbosity >= INFO) $- liftIO $ showVerboseInfo Nothing program args env' source+ showVerboseInfo Nothing program args env' source (exit, out) <- liftIO $ E.catch (pipeProcess (Just env') program args (BL.fromStrict $ UTF8.fromText source))@@ -423,34 +486,32 @@ ExitFailure _ -> Left out ExitSuccess -> Right out --html2pdf :: Verbosity -- ^ Verbosity level- -> String -- ^ Program (wkhtmltopdf, weasyprint, prince, or path)+toPdfViaTempFile ::+ Verbosity -- ^ Verbosity level+ -> String -- ^ Program (program name or path) -> [String] -- ^ Args to program- -> Text -- ^ HTML5 source+ -> (String -> [String]) -- ^ Construct args for output file+ -> String -- ^ extension to use for input file (e.g. '.html')+ -> Text -- ^ Source -> IO (Either ByteString ByteString)-html2pdf verbosity program args source =- -- write HTML to temp file so we don't have to rewrite- -- all links in `a`, `img`, `style`, `script`, etc. tags,- -- and piping to weasyprint didn't work on Windows either.- withTempFile "." "html2pdf.html" $ \file h1 ->- withTempFile "." "html2pdf.pdf" $ \pdfFile h2 -> do+toPdfViaTempFile verbosity program args mkOutArgs extension source =+ withTempFile "." ("toPdfViaTempFile" <> extension) $ \file h1 ->+ withTempFile "." "toPdfViaTempFile.pdf" $ \pdfFile h2 -> do hClose h1 hClose h2 BS.writeFile file $ UTF8.fromText source- let pdfFileArgName = ["-o" | takeBaseName program `elem`- ["pagedjs-cli", "prince"]]- let programArgs = args ++ [file] ++ pdfFileArgName ++ [pdfFile]+ let programArgs = args ++ [file] ++ mkOutArgs pdfFile env' <- getEnvironment- when (verbosity >= INFO) $- UTF8.readFile file >>=- showVerboseInfo Nothing program programArgs env'+ fileContents <- UTF8.readFile file+ runIOorExplode $ do+ setVerbosity verbosity+ showVerboseInfo Nothing program programArgs env' fileContents (exit, out) <- E.catch (pipeProcess (Just env') program programArgs BL.empty) (handlePDFProgramNotFound program)- when (verbosity >= INFO) $ do- BL.hPutStr stderr out- UTF8.hPutStr stderr "\n"+ runIOorExplode $ do+ setVerbosity verbosity+ 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@@ -470,21 +531,20 @@ -> Text -- ^ ConTeXt source -> m (Either ByteString ByteString) context2pdf program pdfargs tmpDir source = do+ let file = "input.tex"+ let programArgs = "--batchmode" : pdfargs ++ [file]+ env' <- liftIO getEnvironment verbosity <- getVerbosity+ liftIO $ BS.writeFile (tmpDir </> file) $ UTF8.fromText source+ liftIO (UTF8.readFile (tmpDir </> file)) >>=+ showVerboseInfo (Just tmpDir) program programArgs env' liftIO $ inDirectory tmpDir $ do- let file = "input.tex"- BS.writeFile file $ UTF8.fromText source- let programArgs = "--batchmode" : pdfargs ++ [file]- env' <- getEnvironment- when (verbosity >= INFO) $ liftIO $- UTF8.readFile file >>=- showVerboseInfo (Just tmpDir) program programArgs env' (exit, out) <- E.catch (pipeProcess (Just env') program programArgs BL.empty) (handlePDFProgramNotFound program)- when (verbosity >= INFO) $ do- BL.hPutStr stderr out- UTF8.hPutStr stderr "\n"+ runIOorExplode $ do+ setVerbosity verbosity+ report $ MakePDFInfo "ConTeXt run output" (utf8ToText out) let pdfFile = replaceExtension file ".pdf" pdfExists <- doesFileExist pdfFile mbPdf <- if pdfExists@@ -501,39 +561,111 @@ (ExitSuccess, Just pdf) -> return $ Right pdf -showVerboseInfo :: Maybe FilePath+showVerboseInfo :: PandocMonad m+ => Maybe FilePath -> String -> [String] -> [(String, String)] -> Text- -> IO ()+ -> m () showVerboseInfo mbTmpDir program programArgs env source = do case mbTmpDir of- Just tmpDir -> do- UTF8.hPutStrLn stderr "[makePDF] temp dir:"- UTF8.hPutStrLn stderr (T.pack tmpDir)+ Just tmpDir -> report $ MakePDFInfo "Temp dir:" (T.pack tmpDir) Nothing -> return ()- UTF8.hPutStrLn stderr "[makePDF] Command line:"- UTF8.hPutStrLn stderr $- T.pack program <> " " <> T.pack (unwords (map show programArgs))- UTF8.hPutStr stderr "\n"- UTF8.hPutStrLn stderr "[makePDF] Relevant environment variables:"+ report $ MakePDFInfo "Command line:"+ (T.pack program <> " " <> T.pack (unwords (map show programArgs))) -- we filter out irrelevant stuff to avoid leaking passwords and keys!- let isRelevant ("PATH",_) = True- isRelevant ("TMPDIR",_) = True- isRelevant ("PWD",_) = True- isRelevant ("LANG",_) = True- isRelevant ("HOME",_) = True- isRelevant ("LUA_PATH",_) = True- isRelevant ("LUA_CPATH",_) = True- isRelevant ("SHELL",_) = True- isRelevant ("TEXINPUTS",_) = True- isRelevant ("TEXMFOUTPUT",_) = True- isRelevant _ = False- mapM_ (UTF8.hPutStrLn stderr . tshow) (filter isRelevant env)- UTF8.hPutStr stderr "\n"- UTF8.hPutStrLn stderr "[makePDF] Source:"- UTF8.hPutStrLn stderr source+ let isRelevant e = (e `elem` [ "PKFONTS"+ , "AFMFONTS"+ , "BIBINPUTS"+ , "BLTXMLINPUTS"+ , "BSTINPUTS"+ , "CLUAINPUTS"+ , "CMAPFONTS"+ , "CWEBINPUTS"+ , "DVIPSHEADERS"+ , "ENCFONTS"+ , "FONTCIDMAPS"+ , "FONTFEATURES"+ , "GFFONTS"+ , "GLYPHFONTS"+ , "HOME"+ , "INDEXSTYLE"+ , "KPATHSEA_DEBUG"+ , "KPATHSEA_WARNING"+ , "LANG"+ , "LIGFONTS"+ , "LUAINPUTS"+ , "LUA_CPATH"+ , "LUA_PATH"+ , "MFBASES"+ , "MFINPUTS"+ , "MFPOOL"+ , "MFTINPUTS"+ , "MISCFONTS"+ , "MISSFONT_LOG"+ , "MLBIBINPUTS"+ , "MLBSTINPUTS"+ , "MPINPUTS"+ , "MPMEMS"+ , "MPPOOL"+ , "MPSUPPORT"+ , "OCPINPUTS"+ , "OFMFONTS"+ , "OPENTYPEFONTS"+ , "OPLFONTS"+ , "OTPINPUTS"+ , "OVFFONTS"+ , "OVPFONTS"+ , "PATH"+ , "PDFTEXCONFIG"+ , "PROGRAMFONTS"+ , "PSHEADERS"+ , "PWD"+ , "RISINPUTS"+ , "SELFAUTODIR"+ , "SELFAUTOLOC"+ , "SELFAUTOPARENT"+ , "SFDFONTS"+ , "SHELL"+ , "SOURCE_DATE_EPOCH"+ , "T1FONTS"+ , "T1INPUTS"+ , "T42FONTS"+ , "TEXBIB"+ , "TEXCONFIG"+ , "TEXDOCS"+ , "TEXFONTMAPS"+ , "TEXFONTS"+ , "TEXFORMATS"+ , "TEXINDEXSTYLE"+ , "TEXINPUTS"+ , "TEXMFCNF"+ , "TEXMFDBS"+ , "TEXMFINI"+ , "TEXMFSCRIPTS"+ , "TEXMFVAR"+ , "TEXPICTS"+ , "TEXPKS"+ , "TEXPOOL"+ , "TEXPSHEADERS"+ , "TEXSOURCES"+ , "TEX_HUSH"+ , "TFMFONTS"+ , "TMPDIR"+ , "TRFONTS"+ , "TTFONTS"+ , "USERPROFILE"+ , "USE_TEXMFVAR"+ , "USE_VARTEXFONTS"+ , "VARTEXFONTS"+ , "VFFONTS"+ , "WEB2C"+ , "WEBINPUTS"+ ]) || "TEXMF" `isPrefixOf` e+ report $ MakePDFInfo "Relevant environment variables:"+ (T.intercalate "\n" $ map tshow $ filter (isRelevant . fst) env)+ report $ MakePDFInfo "Source:" source handlePDFProgramNotFound :: String -> IE.IOError -> IO a handlePDFProgramNotFound program e
@@ -1,6 +1,6 @@ {- | Module : Text.Pandoc.Parsing- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -47,6 +47,7 @@ mathDisplay, withHorizDisplacement, withRaw,+ fromParsecError, escaped, characterReference, upperRoman,@@ -60,6 +61,8 @@ lineBlockLines, tableWith, tableWith',+ tableWithSpans,+ tableWithSpans', widthsFromIndices, gridTableWith, gridTableWith',@@ -67,6 +70,10 @@ TableNormalization (..), toTableComponents, toTableComponents',+ toTableComponentsWithSpans,+ toTableComponentsWithSpans',+ singleRowSpans,+ singleColumnSpans, readWith, readWithM, testStringWith,@@ -104,10 +111,9 @@ doubleCloseQuote, ellipses, dash,- nested, citeKey,- Parser,- ParserT,+ Parsec,+ ParsecT, Future(..), runF, askF,@@ -119,7 +125,7 @@ extractIdClass, insertIncludedFile, -- * Re-exports from Text.Parsec- Stream,+ Stream(..), runParser, runParserT, parse,@@ -154,6 +160,8 @@ setState, updateState, SourcePos,+ SourceName,+ updatePosString, getPosition, setPosition, sourceName,@@ -168,13 +176,19 @@ initialPos, Line, Column,- ParseError+ ParseError,+ errorMessages,+ messageString ) where import Text.Pandoc.Sources import Text.Parsec- ( setSourceName,+ ( Parsec,+ ParsecT,+ SourcePos,+ SourceName,+ setSourceName, Column, Line, incSourceLine,@@ -221,9 +235,11 @@ runParserT, runParser, ParseError,- SourcePos, Stream(..) )-import Text.Parsec.Pos (initialPos, newPos)+import Text.Parsec.Error (+ errorMessages,+ messageString )+import Text.Parsec.Pos (initialPos, newPos, updatePosString) import Text.Pandoc.Parsing.Capabilities ( guardDisabled, guardEnabled,@@ -268,7 +284,6 @@ manyTillChar, manyUntil, manyUntilChar,- nested, nonspaceChar, notFollowedBy', oneOfStrings,@@ -287,14 +302,21 @@ trimInlinesF, uri, withHorizDisplacement,- withRaw )+ withRaw,+ fromParsecError ) import Text.Pandoc.Parsing.GridTable ( gridTableWith, gridTableWith', tableWith, tableWith',+ tableWithSpans,+ tableWithSpans', toTableComponents, toTableComponents',+ toTableComponentsWithSpans,+ toTableComponentsWithSpans',+ singleRowSpans,+ singleColumnSpans, widthsFromIndices, TableComponents(..), TableNormalization(..) )@@ -329,5 +351,5 @@ ParserContext(..), ParserState(..), SubstTable )-import Text.Pandoc.Parsing.Types- ( ParserT, askF, asksF, returnF, runF, Future(..), Parser )+import Text.Pandoc.Parsing.Future+ ( askF, asksF, returnF, runF, Future(..) )
@@ -1,7 +1,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} {- | Module : Text.Pandoc.Parsing- Copyright : © 2006-2022 John MacFarlane+ Copyright : © 2006-2024 John MacFarlane License : GPL-2.0-or-later Maintainer : John MacFarlane <jgm@berkeley.edu> @@ -43,7 +43,8 @@ import Control.Monad (guard, when) import Data.Text (Text)-import Text.Parsec (ParsecT, SourcePos, Stream, getPosition, getState, updateState)+import Text.Parsec (SourcePos, Stream, ParsecT,+ getPosition, getState, updateState) import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Logging (LogMessage) import Text.Pandoc.Options@@ -51,15 +52,14 @@ , ReaderOptions(readerExtensions) , extensionEnabled )-import Text.Pandoc.Parsing.Types-import Text.Pandoc.Readers.LaTeX.Types (Macro)+import Text.Pandoc.TeX (Macro) import qualified Data.Map as M import qualified Data.Set as Set class HasReaderOptions st where extractReaderOptions :: st -> ReaderOptions- getOption :: (Stream s m t) => (ReaderOptions -> b) -> ParserT s st m b+ getOption :: (Stream s m t) => (ReaderOptions -> b) -> ParsecT s st m b -- default getOption f = f . extractReaderOptions <$> getState @@ -69,7 +69,7 @@ failIfInQuoteContext :: (HasQuoteContext st m, Stream s m t) => QuoteContext- -> ParserT s st m ()+ -> ParsecT s st m () failIfInQuoteContext context = do context' <- getQuoteContext when (context' == context) $ Prelude.fail "already inside quotes"@@ -97,34 +97,34 @@ -- | Add a log message. logMessage :: (Stream s m a, HasLogMessages st)- => LogMessage -> ParserT s st m ()+ => LogMessage -> ParsecT s st m () logMessage msg = updateState (addLogMessage msg) -- | Report all the accumulated log messages, according to verbosity level.-reportLogMessages :: (PandocMonad m, HasLogMessages st) => ParserT s st m ()+reportLogMessages :: (PandocMonad m, HasLogMessages st) => ParsecT s st m () reportLogMessages = do msgs <- getLogMessages <$> getState mapM_ report msgs -- | Succeed only if the extension is enabled. guardEnabled :: (Stream s m a, HasReaderOptions st)- => Extension -> ParserT s st m ()+ => Extension -> ParsecT s st m () guardEnabled ext = getOption readerExtensions >>= guard . extensionEnabled ext -- | Succeed only if the extension is disabled. guardDisabled :: (Stream s m a, HasReaderOptions st)- => Extension -> ParserT s st m ()+ => Extension -> ParsecT s st m () guardDisabled ext = getOption readerExtensions >>= guard . not . extensionEnabled ext -- | Update the position on which the last string ended. updateLastStrPos :: (Stream s m a, HasLastStrPosition st)- => ParserT s st m ()+ => ParsecT s st m () updateLastStrPos = getPosition >>= updateState . setLastStrPos . Just -- | Whether we are right after the end of a string.-notAfterString :: (Stream s m a, HasLastStrPosition st) => ParserT s st m Bool+notAfterString :: (Stream s m a, HasLastStrPosition st) => ParsecT s st m Bool notAfterString = do pos <- getPosition st <- getState
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Parsing.Citations-Copyright : © 2006-2022 John MacFarlane+Copyright : © 2006-2024 John MacFarlane License : GPL-2.0-or-later Maintainer : John MacFarlane <jgm@berkeley.edu> @@ -21,6 +21,7 @@ import Text.Parsec ( (<|>) , Stream(..)+ , ParsecT , lookAhead , many , option@@ -28,25 +29,25 @@ ) import Text.Pandoc.Parsing.Capabilities (HasLastStrPosition, notAfterString) import Text.Pandoc.Parsing.General-import Text.Pandoc.Parsing.Types (ParserT) import qualified Data.Text as T citeKey :: (Stream s m Char, UpdateSourcePos s Char, HasLastStrPosition st) => Bool -- ^ If True, allow expanded @{..} syntax.- -> ParserT s st m (Bool, Text)+ -> ParsecT s st m (Bool, Text) citeKey allowBraced = try $ do guard =<< notAfterString suppress_author <- option False (True <$ char '-') char '@' key <- simpleCiteIdentifier <|> if allowBraced- then charsInBalanced '{' '}' (satisfy (not . isSpace))+ then charsInBalanced '{' '}'+ (T.singleton <$> (satisfy (not . isSpace))) else mzero return (suppress_author, key) simpleCiteIdentifier :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Text+ => ParsecT s st m Text simpleCiteIdentifier = do firstChar <- alphaNum <|> char '_' <|> char '*' -- @* for wildcard in nocite let regchar = satisfy (\c -> isAlphaNum c || c == '_')@@ -54,4 +55,3 @@ rest <- many $ regchar <|> internal (oneOf ":.#$%&-+?<>~/") <|> try (oneOf ":/" <* lookAhead (char '/')) return $ T.pack $ firstChar:rest-
@@ -0,0 +1,49 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{- |+ Module : Text.Pandoc.Parsing.Future+ Copyright : Copyright (C) 2006-2024 John MacFarlane+ License : GPL-2.0-or-later+ Maintainer : John MacFarlane <jgm@berkeley.edu>++Future type for parsing.+-}++module Text.Pandoc.Parsing.Future+ ( Future (..)+ , runF+ , askF+ , asksF+ , returnF+ )+where++import Prelude hiding (Applicative(..))+import Control.Applicative (Applicative(..))+import Control.Monad.Reader+ ( asks, runReader, MonadReader(ask), Reader, ReaderT(ReaderT) )++-- | Reader monad wrapping the parser state. This is used to possibly+-- delay evaluation until all relevant information has been parsed and+-- made available in the parser state.+newtype Future s a = Future { runDelayed :: Reader s a }+ deriving (Monad, Applicative, Functor)++instance Semigroup a => Semigroup (Future s a) where+ (<>) = liftA2 (<>)++instance (Semigroup a, Monoid a) => Monoid (Future s a) where+ mempty = return mempty+ mappend = (<>)++-- | Run a delayed action with the given state.+runF :: Future s a -> s -> a+runF = runReader . runDelayed++askF :: Future s s+askF = Future ask++asksF :: (s -> a) -> Future s a+asksF f = Future $ asks f++returnF :: Monad m => a -> m (Future s a)+returnF = return . return
@@ -1,8 +1,9 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Parsing.General-Copyright : © 2006-2022 John MacFarlane+Copyright : © 2006-2024 John MacFarlane License : GPL-2.0-or-later Maintainer : John MacFarlane <jgm@berkeley.edu> @@ -37,7 +38,6 @@ , manyTillChar , manyUntil , manyUntilChar- , nested , nonspaceChar , notFollowedBy' , oneOfStrings@@ -58,19 +58,20 @@ , uri , withHorizDisplacement , withRaw+ , fromParsecError ) where import Control.Monad- ( guard- , join+ ( join , liftM , unless , void , when+ , MonadPlus(mzero) ) import Control.Monad.Except ( MonadError(throwError) )-import Control.Monad.Identity ( Identity(..), MonadPlus(mzero) )+import Control.Monad.Identity ( Identity(..) ) import Data.Char ( chr , isAlphaNum@@ -82,10 +83,12 @@ , toUpper ) import Data.Functor (($>))-import Data.List (intercalate)+import Data.List (intercalate, sortOn)+import Data.Ord (Down(..)) import Data.Maybe (fromMaybe) import Data.Text (Text)-import Text.HTML.TagSoup.Entity (lookupEntity)+import qualified Data.Text.Lazy.Builder as TB+import qualified Data.Text.Lazy as TL import Text.Pandoc.Asciify (toAsciiText) import Text.Pandoc.Builder (Attr, Inline(Str), Inlines, trimInlines) import Text.Pandoc.Class.PandocMonad (PandocMonad, readFileFromDirs, report)@@ -95,13 +98,20 @@ ( extensionEnabled , Extension(Ext_auto_identifiers, Ext_ascii_identifiers) , ReaderOptions(readerTabStop, readerExtensions) )-import Text.Pandoc.Shared (escapeURI, mapLeft, schemes, tshow, uniqueIdent)+import Text.Pandoc.Shared (tshow, uniqueIdent)+import Text.Pandoc.URI (schemes, escapeURI) import Text.Pandoc.Sources-import Text.Pandoc.XML (fromEntities)+import Text.Pandoc.XML (fromEntities, lookupEntity) import Text.Parsec ( (<|>)+ , Parsec , ParsecT , SourcePos+ , sourceLine+ , sourceColumn+ , sourceName+ , ParseError+ , errorPos , Stream(..) , between , choice@@ -128,15 +138,15 @@ ) import Text.Parsec.Pos (initialPos, newPos) import Text.Pandoc.Error- ( PandocError(PandocParseError, PandocParsecError) )+ ( PandocError(PandocParseError) ) import Text.Pandoc.Parsing.Capabilities import Text.Pandoc.Parsing.State-import Text.Pandoc.Parsing.Types ( Parser, ParserT, Future (..))-+import Text.Pandoc.Parsing.Future (Future (..)) import qualified Data.Set as Set import qualified Data.Text as T import qualified Text.Pandoc.Builder as B import qualified Text.Pandoc.UTF8 as UTF8 (putStrLn)+import qualified Data.Bifunctor as Bifunctor -- | Remove whitespace from start and end; just like @'trimInlines'@, -- but lifted into the 'Future' type.@@ -158,7 +168,7 @@ -- | Parse any line of text, returning the contents without the -- final newline.-anyLine :: Monad m => ParserT Sources st m Text+anyLine :: Monad m => ParsecT Sources st m Text anyLine = do -- This is much faster than: -- manyTill anyChar newline@@ -181,13 +191,13 @@ return this -- | Parse any line, include the final newline in the output-anyLineNewline :: Monad m => ParserT Sources st m Text+anyLineNewline :: Monad m => ParsecT Sources st m Text anyLineNewline = (<> "\n") <$> anyLine -- | Parse indent by specified number of spaces (or equiv. tabs) indentWith :: (Stream s m Char, UpdateSourcePos s Char) => HasReaderOptions st- => Int -> ParserT s st m Text+ => Int -> ParsecT s st m Text indentWith num = do tabStop <- getOption readerTabStop if num < tabStop@@ -197,28 +207,28 @@ -- | Like @many@, but packs its result. manyChar :: Stream s m t- => ParserT s st m Char- -> ParserT s st m Text+ => ParsecT s st m Char+ -> ParsecT s st m Text manyChar = fmap T.pack . many -- | Like @many1@, but packs its result. many1Char :: Stream s m t- => ParserT s st m Char- -> ParserT s st m Text+ => ParsecT s st m Char+ -> ParsecT s st m Text many1Char = fmap T.pack . many1 -- | Like @manyTill@, but packs its result. manyTillChar :: Stream s m t- => ParserT s st m Char- -> ParserT s st m a- -> ParserT s st m Text+ => ParsecT s st m Char+ -> ParsecT s st m a+ -> ParsecT s st m Text manyTillChar p = fmap T.pack . manyTill p -- | Like @manyTill@, but reads at least one item. many1Till :: (Show end, Stream s m t)- => ParserT s st m a- -> ParserT s st m end- -> ParserT s st m [a]+ => ParsecT s st m a+ -> ParsecT s st m end+ -> ParsecT s st m [a] many1Till p end = do notFollowedBy' end first <- p@@ -227,15 +237,15 @@ -- | Like @many1Till@, but packs its result many1TillChar :: (Show end, Stream s m t)- => ParserT s st m Char- -> ParserT s st m end- -> ParserT s st m Text+ => ParsecT s st m Char+ -> ParsecT s st m end+ -> ParsecT s st m Text many1TillChar p = fmap T.pack . many1Till p -- | Like @manyTill@, but also returns the result of end parser.-manyUntil :: ParserT s u m a- -> ParserT s u m b- -> ParserT s u m ([a], b)+manyUntil :: ParsecT s u m a+ -> ParsecT s u m b+ -> ParsecT s u m ([a], b) manyUntil p end = scan where scan = (do e <- end@@ -246,9 +256,9 @@ return (x:xs, e)) -- | Like @manyUntil@, but also packs its result.-manyUntilChar :: ParserT s u m Char- -> ParserT s u m b- -> ParserT s u m (Text, b)+manyUntilChar :: ParsecT s u m Char+ -> ParsecT s u m b+ -> ParsecT s u m (Text, b) manyUntilChar p = fmap go . manyUntil p where go (x, y) = (T.pack x, y)@@ -263,7 +273,7 @@ -- | A more general form of @notFollowedBy@. This one allows any -- type of parser to be specified, and succeeds only if that parser fails. -- It does not consume any input.-notFollowedBy' :: (Show b, Stream s m a) => ParserT s st m b -> ParserT s st m ()+notFollowedBy' :: (Show b, Stream s m a) => ParsecT s st m b -> ParsecT s st m () notFollowedBy' p = try $ join $ do a <- try p return (unexpected (show a)) <|>@@ -271,28 +281,26 @@ -- (This version due to Andrew Pimlott on the Haskell mailing list.) oneOfStrings' :: (Stream s m Char, UpdateSourcePos s Char)- => (Char -> Char -> Bool) -> [Text] -> ParserT s st m Text-oneOfStrings' f = fmap T.pack . oneOfStrings'' f . fmap T.unpack---- TODO: This should be re-implemented in a Text-aware way-oneOfStrings'' :: (Stream s m Char, UpdateSourcePos s Char)- => (Char -> Char -> Bool) -> [String] -> ParserT s st m String-oneOfStrings'' _ [] = Prelude.fail "no strings"-oneOfStrings'' matches strs = try $ do- c <- anyChar- let strs' = [xs | (x:xs) <- strs, x `matches` c]- case strs' of+ => (Char -> Char -> Bool) -> [Text] -> ParsecT s st m Text+oneOfStrings' _ [] = Prelude.fail "no strings to match"+oneOfStrings' matches strs =+ TL.toStrict . TB.toLazyText <$> try (go mempty strs)+ where+ go acc strs' = do+ c <- anyChar+ let strs'' = [t | Just (d, t) <- map T.uncons strs', matches c d]+ let !acc' = acc <> TB.singleton c+ case strs'' of [] -> Prelude.fail "not found"- _ -> (c:) <$> oneOfStrings'' matches strs'- <|> if "" `elem` strs'- then return [c]- else Prelude.fail "not found"+ _ -> if any T.null strs''+ then option acc' (try (go acc' strs''))+ else go acc' strs'' -- | Parses one of a list of strings. If the list contains -- two strings one of which is a prefix of the other, the longer -- string will be matched if possible. oneOfStrings :: (Stream s m Char, UpdateSourcePos s Char)- => [Text] -> ParserT s st m Text+ => [Text] -> ParsecT s st m Text oneOfStrings = oneOfStrings' (==) -- | Parses one of a list of strings (tried in order), case insensitive.@@ -300,7 +308,7 @@ -- TODO: This will not be accurate with general Unicode (neither -- Text.toLower nor Text.toCaseFold can be implemented with a map) oneOfStringsCI :: (Stream s m Char, UpdateSourcePos s Char)- => [Text] -> ParserT s st m Text+ => [Text] -> ParsecT s st m Text oneOfStringsCI = oneOfStrings' ciMatch where ciMatch x y = toLower' x == toLower' y -- this optimizes toLower by checking common ASCII case@@ -312,12 +320,12 @@ -- | Parses a space or tab. spaceChar :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Char+ => ParsecT s st m Char spaceChar = satisfy $ \c -> c == ' ' || c == '\t' -- | Parses a nonspace, nonnewline character. nonspaceChar :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Char+ => ParsecT s st m Char nonspaceChar = satisfy (not . isSpaceChar) isSpaceChar :: Char -> Bool@@ -329,23 +337,23 @@ -- | Skips zero or more spaces or tabs. skipSpaces :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m ()+ => ParsecT s st m () skipSpaces = skipMany spaceChar -- | Skips zero or more spaces or tabs, then reads a newline. blankline :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Char+ => ParsecT s st m Char blankline = try $ skipSpaces >> newline -- | Parses one or more blank lines and returns a string of newlines. blanklines :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Text+ => ParsecT s st m Text blanklines = T.pack <$> many1 blankline -- | Gobble n spaces; if tabs are encountered, expand them -- and gobble some or all of their spaces, leaving the rest. gobbleSpaces :: (HasReaderOptions st, Monad m)- => Int -> ParserT Sources st m ()+ => Int -> ParsecT Sources st m () gobbleSpaces 0 = return () gobbleSpaces n | n < 0 = error "gobbleSpaces called with negative number"@@ -353,7 +361,7 @@ char ' ' <|> eatOneSpaceOfTab gobbleSpaces (n - 1) -eatOneSpaceOfTab :: (HasReaderOptions st, Monad m) => ParserT Sources st m Char+eatOneSpaceOfTab :: (HasReaderOptions st, Monad m) => ParsecT Sources st m Char eatOneSpaceOfTab = do lookAhead (char '\t') pos <- getPosition@@ -372,7 +380,7 @@ -- | Gobble up to n spaces; if tabs are encountered, expand them -- and gobble some or all of their spaces, leaving the rest. gobbleAtMostSpaces :: (HasReaderOptions st, Monad m)- => Int -> ParserT Sources st m Int+ => Int -> ParsecT Sources st m Int gobbleAtMostSpaces 0 = return 0 gobbleAtMostSpaces n | n < 0 = error "gobbleAtMostSpaces called with negative number"@@ -382,39 +390,36 @@ -- | Parses material enclosed between start and end parsers. enclosed :: (Show end, Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m t -- ^ start parser- -> ParserT s st m end -- ^ end parser- -> ParserT s st m a -- ^ content parser (to be used repeatedly)- -> ParserT s st m [a]+ => ParsecT s st m t -- ^ start parser+ -> ParsecT s st m end -- ^ end parser+ -> ParsecT s st m a -- ^ content parser (to be used repeatedly)+ -> ParsecT s st m [a] enclosed start end parser = try $ start >> notFollowedBy space >> many1Till parser end -- | Parse string, case insensitive. stringAnyCase :: (Stream s m Char, UpdateSourcePos s Char)- => Text -> ParserT s st m Text-stringAnyCase = fmap T.pack . stringAnyCase' . T.unpack--stringAnyCase' :: (Stream s m Char, UpdateSourcePos s Char)- => String -> ParserT s st m String-stringAnyCase' [] = string ""-stringAnyCase' (x:xs) = do- firstChar <- char (toUpper x) <|> char (toLower x)- rest <- stringAnyCase' xs- return (firstChar:rest)+ => Text -> ParsecT s st m Text+stringAnyCase t = TL.toStrict . TB.toLazyText <$> go (T.unpack t)+ where+ go [] = string "" $> mempty+ go (x:xs) = do+ c <- char (toUpper x) <|> char (toLower x)+ rest <- go xs+ pure $ TB.singleton c <> rest -- TODO rewrite by just adding to Sources stream? -- | Parse contents of 'str' using 'parser' and return result. parseFromString :: Monad m- => ParserT Sources st m r+ => ParsecT Sources st m r -> Text- -> ParserT Sources st m r+ -> ParsecT Sources st m r parseFromString parser str = do oldPos <- getPosition oldInput <- getInput setInput $ toSources str setPosition $ initialPos $ sourceName oldPos <> "_chunk" result <- parser- spaces setInput oldInput setPosition oldPos return result@@ -422,9 +427,9 @@ -- | Like 'parseFromString' but specialized for 'ParserState'. -- This resets 'stateLastStrPos', which is almost always what we want. parseFromString' :: (Monad m, HasLastStrPosition u)- => ParserT Sources u m a+ => ParsecT Sources u m a -> Text- -> ParserT Sources u m a+ -> ParsecT Sources u m a parseFromString' parser str = do oldLastStrPos <- getLastStrPos <$> getState updateState $ setLastStrPos Nothing@@ -433,36 +438,31 @@ return res -- | Parse raw line block up to and including blank lines.-lineClump :: Monad m => ParserT Sources st m Text+lineClump :: Monad m => ParsecT Sources st m Text lineClump = blanklines <|> (T.unlines <$> many1 (notFollowedBy blankline >> anyLine)) -- | Parse a string of characters between an open character -- and a close character, including text between balanced -- pairs of open and close, which must be different. For example,--- @charsInBalanced '(' ')' anyChar@ will parse "(hello (there))"--- and return "hello (there)".-charsInBalanced :: (Stream s m Char, UpdateSourcePos s Char) => Char -> Char -> ParserT s st m Char- -> ParserT s st m Text+-- @charsInBalanced '(' ')' (Data.Text.singleton <$> anyChar)@ will parse+-- "(hello (there))" and return "hello (there)".+charsInBalanced :: (Stream s m Char, UpdateSourcePos s Char)+ => Char -> Char -> ParsecT s st m Text -> ParsecT s st m Text charsInBalanced open close parser = try $ do char open let isDelim c = c == open || c == close- raw <- many $ T.pack <$> many1 (notFollowedBy (satisfy isDelim) >> parser)+ raw <- many $ mconcat <$> many1 (notFollowedBy (satisfy isDelim) >> parser) <|> (do res <- charsInBalanced open close parser return $ T.singleton open <> res <> T.singleton close) char close- return $ T.concat raw---- old charsInBalanced would be:--- charsInBalanced open close (noneOf "\n" <|> char '\n' >> notFollowedBy blankline)--- old charsInBalanced' would be:--- charsInBalanced open close anyChar+ return $ mconcat raw -- Parsers for email addresses and URIs -- | Parses an email address; returns original and corresponding -- escaped mailto: URI.-emailAddress :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (Text, Text)+emailAddress :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m (Text, Text) emailAddress = try $ toResult <$> mailbox <*> (char '@' *> domain) where toResult mbox dom = let full = fromEntities $ T.pack $ mbox ++ '@':dom in (full, escapeURI $ "mailto:" <> full)@@ -482,14 +482,16 @@ xs <- many (satisfy isEmailChar) return (x:xs) isEmailChar c = isAlphaNum c || isEmailPunct c- isEmailPunct c = T.any (== c) "!\"#$%&'*+-/=?^_{|}~;"+ isEmailPunct c = c `Set.member` emailPunctChars +emailPunctChars :: Set.Set Char+emailPunctChars = Set.fromList "!\"#$%&'*+-/=?^_{|}~;" -uriScheme :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Text+uriScheme :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m Text uriScheme = oneOfStringsCI (Set.toList schemes) -- | Parses a URI. Returns pair of original and URI-escaped version.-uri :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (Text, Text)+uri :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m (Text, Text) uri = try $ do scheme <- uriScheme char ':'@@ -523,22 +525,22 @@ wordChar = satisfy isWordChar percentEscaped = try $ (:) <$> char '%' <*> many1 hexDigit- entity = try $ pure <$> characterReference+ entity = try $ T.unpack <$> characterReference punct = try $ many1 (char ',') <|> fmap pure (satisfy (\c -> not (isSpace c) && c /= '<' && c /= '>')) uriChunk = many1 wordChar <|> percentEscaped <|> entity <|> try (punct <* lookAhead (void wordChar <|> void percentEscaped)) uriChunkBetween l r = try $ do chunk <- between (char l) (char r) uriChunk- return (T.pack $ [l] ++ chunk ++ [r])+ return $ T.singleton l <> T.pack chunk <> T.singleton r -- | Applies a parser, returns tuple of its results and its horizontal -- displacement (the difference between the source column at the end -- and the source column at the beginning). Vertical displacement -- (source row) is ignored. withHorizDisplacement :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m a -- ^ Parser to apply- -> ParserT s st m (a, Int) -- ^ (result, displacement)+ => ParsecT s st m a -- ^ Parsec to apply+ -> ParsecT s st m (a, Int) -- ^ (result, displacement) withHorizDisplacement parser = do pos1 <- getPosition result <- parser@@ -573,28 +575,24 @@ -- | Parses backslash, then applies character parser. escaped :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Char -- ^ Parser for character to escape- -> ParserT s st m Char+ => ParsecT s st m Char -- ^ Parsec for character to escape+ -> ParsecT s st m Char escaped parser = try $ char '\\' >> parser -- | Parse character entity.-characterReference :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Char+characterReference :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m Text characterReference = try $ do char '&'- ent <- many1Till nonspaceChar (char ';')- let ent' = case ent of- '#':'X':xs -> '#':'x':xs -- workaround tagsoup bug- '#':_ -> ent- _ -> ent ++ ";"- case lookupEntity ent' of- Just (c : _) -> return c+ ent <- many1TillChar nonspaceChar (char ';')+ case lookupEntity (ent <> ";") of+ Just t -> return t _ -> Prelude.fail "entity not found" -- | Parses a character reference and returns a Str element.-charRef :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Inline-charRef = Str . T.singleton <$> characterReference+charRef :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m Inline+charRef = Str <$> characterReference -lineBlockLine :: Monad m => ParserT Sources st m Text+lineBlockLine :: Monad m => ParsecT Sources st m Text lineBlockLine = try $ do char '|' char ' '@@ -604,11 +602,11 @@ continuations <- many (try $ char ' ' >> anyLine) return $ white <> T.unwords (line : continuations) -blankLineBlockLine :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m Char+blankLineBlockLine :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m Char blankLineBlockLine = try (char '|' >> blankline) -- | Parses an RST-style line block and returns a list of strings.-lineBlockLines :: Monad m => ParserT Sources st m [Text]+lineBlockLines :: Monad m => ParsecT Sources st m [Text] lineBlockLines = try $ do lines' <- many1 (lineBlockLine <|> (T.singleton <$> blankLineBlockLine)) skipMany blankline@@ -617,19 +615,20 @@ -- | Removes the ParsecT layer from the monad transformer stack readWithM :: (Monad m, ToSources t)- => ParserT Sources st m a -- ^ parser+ => ParsecT Sources st m a -- ^ parser -> st -- ^ initial state -> t -- ^ input -> m (Either PandocError a) readWithM parser state input =- mapLeft (PandocParsecError sources)+ Bifunctor.first (fromParsecError sources) <$> runParserT parser state (initialSourceName sources) sources where sources = toSources input + -- | Parse a string with a given parser and state readWith :: ToSources t- => Parser Sources st a+ => Parsec Sources st a -> st -> t -> Either PandocError a@@ -637,7 +636,7 @@ -- | Parse a string with @parser@ (for testing). testStringWith :: Show a- => ParserT Sources ParserState Identity a+ => ParsecT Sources ParserState Identity a -> Text -> IO () testStringWith parser str = UTF8.putStrLn $ tshow $@@ -652,7 +651,7 @@ -- (explicit or automatically generated). registerHeader :: (Stream s m a, HasReaderOptions st, HasLogMessages st, HasIdentifierList st)- => Attr -> Inlines -> ParserT s st m Attr+ => Attr -> Inlines -> ParsecT s st m Attr registerHeader (ident,classes,kvs) header' = do ids <- extractIdentifierList <$> getState exts <- getOption readerExtensions@@ -673,19 +672,6 @@ updateState $ updateIdentifierList $ Set.insert ident return (ident,classes,kvs) --- This is used to prevent exponential blowups for things like:--- a**a*a**a*a**a*a**a*a**a*a**a*a**-nested :: Stream s m a- => ParserT s ParserState m a- -> ParserT s ParserState m a-nested p = do- nestlevel <- stateMaxNestingLevel <$> getState- guard $ nestlevel > 0- updateState $ \st -> st{ stateMaxNestingLevel = stateMaxNestingLevel st - 1 }- res <- p- updateState $ \st -> st{ stateMaxNestingLevel = nestlevel }- return res- token :: (Stream s m t) => (t -> Text) -> (t -> SourcePos)@@ -694,7 +680,7 @@ token pp pos match = tokenPrim (T.unpack . pp) (\_ t _ -> pos t) match infixr 5 <+?>-(<+?>) :: (Monoid a) => ParserT s st m a -> ParserT s st m a -> ParserT s st m a+(<+?>) :: (Monoid a) => ParsecT s st m a -> ParsecT s st m a -> ParsecT s st m a a <+?> b = a >>= flip fmap (try b <|> return mempty) . mappend extractIdClass :: Attr -> Attr@@ -702,16 +688,16 @@ where ident' = fromMaybe ident (lookup "id" kvs) cls' = maybe cls T.words $ lookup "class" kvs- kvs' = filter (\(k,_) -> k /= "id" || k /= "class") kvs+ kvs' = filter (\(k,_) -> k /= "id" && k /= "class") kvs insertIncludedFile :: (PandocMonad m, HasIncludeFiles st)- => ParserT a st m b -- ^ parser to apply+ => ParsecT a st m b -- ^ parser to apply -> (Text -> a) -- ^ convert Text to stream type -> [FilePath] -- ^ search path (directories) -> FilePath -- ^ path of file to include -> Maybe Int -- ^ start line (negative counts from end) -> Maybe Int -- ^ end line (negative counts from end)- -> ParserT a st m b+ -> ParsecT a st m b insertIncludedFile parser toStream dirs f mbstartline mbendline = do oldPos <- getPosition oldInput <- getInput@@ -749,3 +735,29 @@ Nothing -> numLines Just x | x >= 0 -> x | otherwise -> numLines + x -- negative from end++fromParsecError :: Sources -> ParseError -> PandocError+fromParsecError (Sources inputs) err' = PandocParseError msg+ where+ msg = "Error at " <> tshow err' <> errorContext+ errPos = errorPos err'+ errLine = sourceLine errPos+ errColumn = sourceColumn errPos+ errFile = sourceName errPos+ errorContext =+ case sortOn (Down . sourceLine . fst)+ [ (pos,t)+ | (pos,t) <- inputs+ , sourceName pos == errFile+ , sourceLine pos <= errLine+ ] of+ [] -> ""+ ((pos,txt):_) ->+ let ls = T.lines txt <> [""]+ ln = (errLine - sourceLine pos) + 1+ in case drop (ln - 1) ls of+ (l:_) | ln >= 1 ->+ T.concat ["\n", l+ ,"\n", T.replicate (errColumn - 1) " "+ ,"^"]+ _ -> ""
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Parsing.GridTable- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GPL-2.0-or-later Maintainer : John MacFarlane <jgm@berkeley.edu> @@ -14,12 +14,18 @@ , gridTableWith' , tableWith , tableWith'+ , tableWithSpans+ , tableWithSpans' , widthsFromIndices -- * Components of a plain-text table , TableComponents (..) , TableNormalization (..) , toTableComponents , toTableComponents'+ , toTableComponentsWithSpans+ , toTableComponentsWithSpans'+ , singleRowSpans+ , singleColumnSpans ) where @@ -31,10 +37,10 @@ import Text.Pandoc.Definition import Text.Pandoc.Parsing.Capabilities import Text.Pandoc.Parsing.General-import Text.Pandoc.Parsing.Types import Text.Pandoc.Sources-import Text.Parsec (Stream (..), optional, sepEndBy1, try)+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@@ -55,17 +61,30 @@ B.tableWith attr capt colspecs th tb tf -- | Bundles basic table components into a single value.-toTableComponents :: [Alignment] -> [Double] -> [Blocks] -> [[Blocks]]+toTableComponents :: [Alignment] -> [Double] -> [[Blocks]] -> [[Blocks]] -> TableComponents toTableComponents = toTableComponents' NoNormalization -- | Bundles basic table components into a single value, performing -- normalizations as necessary. toTableComponents' :: TableNormalization- -> [Alignment] -> [Double] -> [Blocks] -> [[Blocks]]+ -> [Alignment] -> [Double] -> [[Blocks]] -> [[Blocks]] -> TableComponents toTableComponents' normalization aligns widths heads rows =- let th = TableHead nullAttr (toHeaderRow normalization heads)+ toTableComponentsWithSpans' normalization aligns widths (singleSpansBlocks heads) (singleSpansBlocks rows)++-- | Bundles basic table components with span information into a single value.+toTableComponentsWithSpans :: [Alignment] -> [Double] -> [[(Blocks, RowSpan, ColSpan)]] -> [[(Blocks, RowSpan, ColSpan)]]+ -> TableComponents+toTableComponentsWithSpans = toTableComponentsWithSpans' NoNormalization++-- | Bundles basic table components with span information into a single value,+-- performing normalizations as necessary.+toTableComponentsWithSpans' :: TableNormalization+ -> [Alignment] -> [Double] -> [[(Blocks, RowSpan, ColSpan)]] -> [[(Blocks, RowSpan, ColSpan)]]+ -> TableComponents+toTableComponentsWithSpans' normalization aligns widths heads rows =+ let th = TableHead nullAttr (mapMaybe (toHeaderRow normalization) heads) tb = TableBody nullAttr 0 [] (map toRow rows) tf = TableFoot nullAttr [] colspecs = toColSpecs aligns widths@@ -103,8 +122,8 @@ -- blank lines, and ending with a footer (dashed line followed by blank -- line). gridTableWith :: (Monad m, Monad mf, HasLastStrPosition st, HasReaderOptions st)- => ParserT Sources st m (mf Blocks) -- ^ Block list parser- -> ParserT Sources st m (mf Blocks)+ => ParsecT Sources st m (mf Blocks) -- ^ Block list parser+ -> ParsecT Sources st m (mf Blocks) gridTableWith blocks = fmap tableFromComponents <$> gridTableWith' NoNormalization blocks @@ -113,8 +132,8 @@ gridTableWith' :: (Monad m, Monad mf, HasReaderOptions st, HasLastStrPosition st) => TableNormalization- -> ParserT Sources st m (mf Blocks) -- ^ Block list parser- -> ParserT Sources st m (mf TableComponents)+ -> ParsecT Sources st m (mf Blocks) -- ^ Block list parser+ -> ParsecT Sources st m (mf TableComponents) gridTableWith' normalization blocks = do tbl <- GT.gridTable <* optional blanklines let blkTbl = GT.mapCells@@ -135,9 +154,13 @@ let caption = B.emptyCaption return $ do rows'' <- mapM sequence rows'- let (hRows, bRows) =- splitAt (maybe 0 GT.fromRowIndex $ GT.arrayTableHead tbl)- (map (B.Row B.nullAttr) rows'')+ let headLen = maybe 0 GT.fromRowIndex $ GT.arrayTableHead tbl+ let (hRows, bRows') =+ splitAt headLen (map (B.Row B.nullAttr) rows'')+ let (bRows, fRows) =+ case GT.arrayTableFoot tbl of+ Just fIdx -> splitAt (GT.fromRowIndex fIdx - headLen - 1) bRows'+ Nothing -> (bRows', []) let thead = B.TableHead B.nullAttr $ case (hRows, normalization) of -- normalize header if necessary: remove header if it contains -- only a single row in which all cells are empty.@@ -151,7 +174,7 @@ in [B.Row nullAttr cells | not (null cells) && not (all simple cells)] _ -> hRows- let tfoot = B.TableFoot B.nullAttr []+ let tfoot = B.TableFoot B.nullAttr fRows let tbody = B.TableBody B.nullAttr 0 [] bRows return $ TableComponents nullAttr caption colspecs thead [tbody] tfoot @@ -177,7 +200,7 @@ fractionalColumnWidths :: GT.ArrayTable a -> Int -> [Double] fractionalColumnWidths gt charColumns =- let widths = map ((+1) . snd) $ -- include width of separator+ let widths = map ((+1) . snd) -- include width of separator (elems $ GT.arrayTableColSpecs gt) norm = fromIntegral $ max (sum widths + length widths - 2) charColumns in map (\w -> fromIntegral w / norm) widths@@ -188,23 +211,47 @@ -- 'lineParser', and 'footerParser'. tableWith :: (Stream s m Char, UpdateSourcePos s Char, HasReaderOptions st, Monad mf)- => ParserT s st m (mf [Blocks], [Alignment], [Int]) -- ^ header parser- -> ([Int] -> ParserT s st m (mf [Blocks])) -- ^ row parser- -> ParserT s st m sep -- ^ line parser- -> ParserT s st m end -- ^ footer parser- -> ParserT s st m (mf Blocks)+ => ParsecT s st m (mf [[Blocks]], [Alignment], [Int]) -- ^ header parser+ -> ([Int] -> ParsecT s st m (mf [Blocks])) -- ^ row parser+ -> ParsecT s st m sep -- ^ line parser+ -> ParsecT s st m end -- ^ footer parser+ -> ParsecT s st m (mf Blocks) tableWith hp rp lp fp = fmap tableFromComponents <$> tableWith' NoNormalization hp rp lp fp tableWith' :: (Stream s m Char, UpdateSourcePos s Char, HasReaderOptions st, Monad mf) => TableNormalization- -> ParserT s st m (mf [Blocks], [Alignment], [Int]) -- ^ header parser- -> ([Int] -> ParserT s st m (mf [Blocks])) -- ^ row parser- -> ParserT s st m sep -- ^ line parser- -> ParserT s st m end -- ^ footer parser- -> ParserT s st m (mf TableComponents)-tableWith' n11n headerParser rowParser lineParser footerParser = try $ do+ -> ParsecT s st m (mf [[Blocks]], [Alignment], [Int]) -- ^ header parser+ -> ([Int] -> ParsecT s st m (mf [Blocks])) -- ^ row parser+ -> ParsecT s st m sep -- ^ line parser+ -> ParsecT s st m end -- ^ footer parser+ -> ParsecT s st m (mf TableComponents)+tableWith' n11n headerParser rowParser lineParser footerParser =+ tableWithSpans' n11n headerParser' rowParser' lineParser footerParser+ where+ headerParser' = fmap (\(heads, aligns, indices) -> (fmap singleSpansBlocks heads, aligns, indices)) headerParser+ rowParser' indices = fmap (\row -> zip3 row (repeat 1) (repeat 1)) <$> rowParser indices++tableWithSpans :: (Stream s m Char, UpdateSourcePos s Char,+ HasReaderOptions st, Monad mf)+ => ParsecT s st m (mf [[(Blocks, RowSpan, ColSpan)]], [Alignment], [Int]) -- ^ header parser+ -> ([Int] -> ParsecT s st m (mf [(Blocks, RowSpan, ColSpan)])) -- ^ row parser+ -> ParsecT s st m sep -- ^ line parser+ -> ParsecT s st m end -- ^ footer parser+ -> ParsecT s st m (mf Blocks)+tableWithSpans hp rp lp fp = fmap tableFromComponents <$>+ tableWithSpans' NoNormalization hp rp lp fp++tableWithSpans' :: (Stream s m Char, UpdateSourcePos s Char,+ HasReaderOptions st, Monad mf)+ => TableNormalization+ -> ParsecT s st m (mf [[(Blocks, RowSpan, ColSpan)]], [Alignment], [Int]) -- ^ header parser+ -> ([Int] -> ParsecT s st m (mf [(Blocks, RowSpan, ColSpan)])) -- ^ row parser+ -> ParsecT s st m sep -- ^ line parser+ -> ParsecT s st m end -- ^ footer parser+ -> ParsecT s st m (mf TableComponents)+tableWithSpans' n11n headerParser rowParser lineParser footerParser = try $ do (heads, aligns, indices) <- headerParser lines' <- sequence <$> rowParser indices `sepEndBy1` lineParser footerParser@@ -212,15 +259,17 @@ let widths = if null indices then replicate (length aligns) 0.0 else widthsFromIndices numColumns indices- return $ toTableComponents' n11n aligns widths <$> heads <*> lines'+ return $ toTableComponentsWithSpans' n11n aligns widths <$> heads <*> lines' -toRow :: [Blocks] -> Row-toRow = Row nullAttr . map B.simpleCell+toRow :: [(Blocks, RowSpan, ColSpan)] -> Row+toRow = Row nullAttr . map (\(blocks, rowSpan, columnSpan) -> B.cell AlignDefault rowSpan columnSpan blocks) -toHeaderRow :: TableNormalization -> [Blocks] -> [Row]+toHeaderRow :: TableNormalization -> [(Blocks, RowSpan, ColSpan)] -> Maybe Row toHeaderRow = \case- NoNormalization -> \l -> [toRow l | not (null l)]- NormalizeHeader -> \l -> [toRow l | not (null l) && not (all null l)]+ NoNormalization -> \l -> if not (null l) then Just (toRow l) else Nothing+ NormalizeHeader -> \l -> if not (all nullHeaderRow l) then Just (toRow l) else Nothing+ where+ nullHeaderRow (l, _, _) = null l -- | Calculate relative widths of table columns, based on indices widthsFromIndices :: Int -- Number of columns on terminal@@ -245,4 +294,15 @@ then fromIntegral totLength else fromIntegral numColumns fracs = map (\l -> fromIntegral l / quotient) lengths in- tail fracs+ drop 1 fracs++-- | List of lists of `RowSpan` of 1.+singleRowSpans :: [[RowSpan]]+singleRowSpans = repeat $ repeat 1++-- | List of lists of `ColsSpan` of 1.+singleColumnSpans :: [[ColSpan]]+singleColumnSpans = repeat $ repeat 1++singleSpansBlocks :: [[Blocks]] -> [[(Blocks, RowSpan, ColSpan)]]+singleSpansBlocks blocks = zipWith3 zip3 blocks singleRowSpans singleColumnSpans
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Parsing.Lists-Copyright : © 2006-2022 John MacFarlane+Copyright : © 2006-2024 John MacFarlane License : GPL-2.0-or-later Maintainer : John MacFarlane <jgm@berkeley.edu> @@ -37,6 +37,7 @@ import Text.Pandoc.Sources import Text.Parsec ( (<|>)+ , ParsecT , Stream(..) , choice , getState@@ -48,7 +49,6 @@ , updateState ) import Text.Pandoc.Parsing.State-import Text.Pandoc.Parsing.Types (ParserT) import qualified Data.Map as M import qualified Data.Text as T@@ -56,7 +56,7 @@ -- | Parses a roman numeral (uppercase or lowercase), returns number. romanNumeral :: (Stream s m Char, UpdateSourcePos s Char) => Bool -- ^ Uppercase if true- -> ParserT s st m Int+ -> ParsecT s st m Int romanNumeral upperCase = do let rchar uc = char $ if upperCase then uc else toLower uc let one = rchar 'I'@@ -88,19 +88,19 @@ else return total -- | Parses an uppercase roman numeral and returns (UpperRoman, number).-upperRoman :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int)+upperRoman :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m (ListNumberStyle, Int) upperRoman = do num <- romanNumeral True return (UpperRoman, num) -- | Parses a lowercase roman numeral and returns (LowerRoman, number).-lowerRoman :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int)+lowerRoman :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m (ListNumberStyle, Int) lowerRoman = do num <- romanNumeral False return (LowerRoman, num) -- | Parses a decimal numeral and returns (Decimal, number).-decimal :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int)+decimal :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m (ListNumberStyle, Int) decimal = do num <- many1 digit return (Decimal, fromMaybe 1 $ safeRead $ T.pack num)@@ -110,48 +110,52 @@ -- example number is incremented in parser state, and the label -- (if present) is added to the label table. exampleNum :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s ParserState m (ListNumberStyle, Int)+ => ParsecT s ParserState m (ListNumberStyle, Int) exampleNum = do char '@'- lab <- mconcat . map T.pack <$>+ lab <- T.pack . concat <$> many (many1 alphaNum <|> try (do c <- char '_' <|> char '-' cs <- many1 alphaNum return (c:cs))) st <- getState- let num = stateNextExample st- let newlabels = if T.null lab- then stateExamples st- else M.insert lab num $ stateExamples st- updateState $ \s -> s{ stateNextExample = num + 1- , stateExamples = newlabels }- return (Example, num)+ case M.lookup lab (stateExamples st) of+ Nothing -> do -- new label+ let num = stateNextExample st+ let newlabels = if T.null lab+ then stateExamples st+ else M.insert lab num $ stateExamples st+ updateState $ \s -> s{ stateNextExample = num + 1+ , stateExamples = newlabels }+ return (Example, num)+ Just num -> -- reuse existing label+ return (Example, num) -- | Parses a '#' returns (DefaultStyle, 1).-defaultNum :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int)+defaultNum :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m (ListNumberStyle, Int) defaultNum = do char '#' return (DefaultStyle, 1) -- | Parses a lowercase letter and returns (LowerAlpha, number).-lowerAlpha :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int)+lowerAlpha :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m (ListNumberStyle, Int) lowerAlpha = do ch <- satisfy isAsciiLower return (LowerAlpha, ord ch - ord 'a' + 1) -- | Parses an uppercase letter and returns (UpperAlpha, number).-upperAlpha :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int)+upperAlpha :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m (ListNumberStyle, Int) upperAlpha = do ch <- satisfy isAsciiUpper return (UpperAlpha, ord ch - ord 'A' + 1) -- | Parses a roman numeral i or I-romanOne :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m (ListNumberStyle, Int)+romanOne :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m (ListNumberStyle, Int) romanOne = (char 'i' >> return (LowerRoman, 1)) <|> (char 'I' >> return (UpperRoman, 1)) -- | Parses an ordered list marker and returns list attributes.-anyOrderedListMarker :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s ParserState m ListAttributes+anyOrderedListMarker :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s ParserState m ListAttributes anyOrderedListMarker = choice [delimParser numParser | delimParser <- [inPeriod, inOneParen, inTwoParens], numParser <- [decimal, exampleNum, defaultNum, romanOne,@@ -159,8 +163,8 @@ -- | Parses a list number (num) followed by a period, returns list attributes. inPeriod :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m (ListNumberStyle, Int)- -> ParserT s st m ListAttributes+ => ParsecT s st m (ListNumberStyle, Int)+ -> ParsecT s st m ListAttributes inPeriod num = try $ do (style, start) <- num char '.'@@ -171,8 +175,8 @@ -- | Parses a list number (num) followed by a paren, returns list attributes. inOneParen :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m (ListNumberStyle, Int)- -> ParserT s st m ListAttributes+ => ParsecT s st m (ListNumberStyle, Int)+ -> ParsecT s st m ListAttributes inOneParen num = try $ do (style, start) <- num char ')'@@ -180,8 +184,8 @@ -- | Parses a list number (num) enclosed in parens, returns list attributes. inTwoParens :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m (ListNumberStyle, Int)- -> ParserT s st m ListAttributes+ => ParsecT s st m (ListNumberStyle, Int)+ -> ParsecT s st m ListAttributes inTwoParens num = try $ do char '(' (style, start) <- num@@ -193,7 +197,7 @@ orderedListMarker :: (Stream s m Char, UpdateSourcePos s Char) => ListNumberStyle -> ListNumberDelim- -> ParserT s ParserState m Int+ -> ParsecT s ParserState m Int orderedListMarker style delim = do let num = defaultNum <|> -- # can continue any kind of list case style of
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Parsing.Math-Copyright : © 2006-2022 John MacFarlane+Copyright : © 2006-2024 John MacFarlane License : GPL-2.0-or-later Maintainer : John MacFarlane <jgm@berkeley.edu> @@ -17,20 +17,21 @@ import Control.Monad (mzero, when) import Data.Text (Text)-import Text.Parsec ((<|>), Stream(..), notFollowedBy, skipMany, try)+import Text.Parsec ((<|>), ParsecT, Stream(..), notFollowedBy, many1, try) import Text.Pandoc.Options ( Extension(Ext_tex_math_dollars, Ext_tex_math_single_backslash, Ext_tex_math_double_backslash) ) import Text.Pandoc.Parsing.Capabilities (HasReaderOptions, guardEnabled) import Text.Pandoc.Parsing.General-import Text.Pandoc.Parsing.Types (ParserT) import Text.Pandoc.Shared (trimMath) import Text.Pandoc.Sources (UpdateSourcePos, anyChar, char, digit, newline, satisfy, space, string) import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TB -mathInlineWith :: (Stream s m Char, UpdateSourcePos s Char) => Text -> Text -> ParserT s st m Text+mathInlineWith :: (Stream s m Char, UpdateSourcePos s Char) => Text -> Text -> ParsecT s st m Text mathInlineWith op cl = try $ do textStr op when (op == "$") $ notFollowedBy space@@ -43,42 +44,47 @@ (try (string "text" >> (("\\text" <>) <$> inBalancedBraces 0 "")) <|> (\c -> T.pack ['\\',c]) <$> anyChar))- <|> do (blankline <* notFollowedBy' blankline) <|>- (spaceChar <* skipMany spaceChar)- notFollowedBy (char '$')- return " "+ <|> ("\n" <$ blankline <* notFollowedBy' blankline <* notFollowedBy (char '$'))+ <|> (T.pack <$> many1 spaceChar <* notFollowedBy (char '$')) ) (try $ textStr cl) notFollowedBy digit -- to prevent capture of $5 return $ trimMath $ T.concat words' where- inBalancedBraces :: (Stream s m Char, UpdateSourcePos s Char) => Int -> Text -> ParserT s st m Text- inBalancedBraces n = fmap T.pack . inBalancedBraces' n . T.unpack+ inBalancedBraces :: (Stream s m Char, UpdateSourcePos s Char)+ => Int -> Text -> ParsecT s st m Text+ inBalancedBraces n t =+ TL.toStrict . TB.toLazyText <$>+ go n False (TB.fromText t) (not (T.null t)) - inBalancedBraces' :: (Stream s m Char, UpdateSourcePos s Char) => Int -> String -> ParserT s st m String- inBalancedBraces' 0 "" = do+ -- go depth lastWasBackslash accumulator started+ go :: (Stream s m Char, UpdateSourcePos s Char)+ => Int -> Bool -> TB.Builder -> Bool -> ParsecT s st m TB.Builder+ go 0 _ acc False = do c <- anyChar if c == '{'- then inBalancedBraces' 1 "{"+ then go 1 False (acc <> TB.singleton '{') True else mzero- inBalancedBraces' 0 s = return $ reverse s- inBalancedBraces' numOpen ('\\':xs) = do+ go 0 _ acc True = return acc+ go depth True acc _ = do c <- anyChar- inBalancedBraces' numOpen (c:'\\':xs)- inBalancedBraces' numOpen xs = do+ go depth False (acc <> TB.singleton c) True+ go depth False acc _ = do c <- anyChar+ let acc' = acc <> TB.singleton c case c of- '}' -> inBalancedBraces' (numOpen - 1) (c:xs)- '{' -> inBalancedBraces' (numOpen + 1) (c:xs)- _ -> inBalancedBraces' numOpen (c:xs)+ '\\' -> go depth True acc' True+ '}' -> go (depth - 1) False acc' True+ '{' -> go (depth + 1) False acc' True+ _ -> go depth False acc' True -mathDisplayWith :: (Stream s m Char, UpdateSourcePos s Char) => Text -> Text -> ParserT s st m Text+mathDisplayWith :: (Stream s m Char, UpdateSourcePos s Char) => Text -> Text -> ParsecT s st m Text mathDisplayWith op cl = try $ fmap T.pack $ do textStr op many1Till (satisfy (/= '\n') <|> (newline <* notFollowedBy' blankline)) (try $ textStr cl) mathDisplay :: (HasReaderOptions st, Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Text+ => ParsecT s st m Text mathDisplay = (guardEnabled Ext_tex_math_dollars >> mathDisplayWith "$$" "$$") <|> (guardEnabled Ext_tex_math_single_backslash >>@@ -87,7 +93,7 @@ mathDisplayWith "\\\\[" "\\\\]") mathInline :: (HasReaderOptions st, Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Text+ => ParsecT s st m Text mathInline = (guardEnabled Ext_tex_math_dollars >> mathInlineWith "$" "$") <|> (guardEnabled Ext_tex_math_single_backslash >>
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Parsing.Smart-Copyright : © 2006-2022 John MacFarlane+Copyright : © 2006-2024 John MacFarlane License : GPL-2.0-or-later Maintainer : John MacFarlane <jgm@berkeley.edu> @@ -33,17 +33,16 @@ import Text.Pandoc.Sources import Text.Pandoc.Parsing.Capabilities import Text.Pandoc.Parsing.General-import Text.Pandoc.Parsing.Types (ParserT) import Text.Parsec ( (<|>) , Stream(..)+ , ParsecT , choice , lookAhead , manyTill , notFollowedBy , try )- import qualified Text.Pandoc.Builder as B -- | Parses various ASCII punctuation, quotes, and apostrophe in a smart@@ -53,8 +52,8 @@ smartPunctuation :: (HasReaderOptions st, HasLastStrPosition st, HasQuoteContext st m, Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Inlines- -> ParserT s st m Inlines+ => ParsecT s st m Inlines+ -> ParsecT s st m Inlines smartPunctuation inlineParser = do guardEnabled Ext_smart choice [ quoted inlineParser, apostrophe, doubleCloseQuote, dash, ellipses ]@@ -63,16 +62,16 @@ -- quoting conventions. quoted :: (HasLastStrPosition st, HasQuoteContext st m, Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Inlines- -> ParserT s st m Inlines+ => ParsecT s st m Inlines+ -> ParsecT s st m Inlines quoted inlineParser = doubleQuoted inlineParser <|> singleQuoted inlineParser -- | Parses inline text in single quotes, assumes English quoting -- conventions. singleQuoted :: (HasLastStrPosition st, HasQuoteContext st m, Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Inlines- -> ParserT s st m Inlines+ => ParsecT s st m Inlines+ -> ParsecT s st m Inlines singleQuoted inlineParser = do singleQuoteStart (B.singleQuoted . mconcat <$>@@ -84,8 +83,8 @@ -- conventions. doubleQuoted :: (HasQuoteContext st m, HasLastStrPosition st, Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Inlines- -> ParserT s st m Inlines+ => ParsecT s st m Inlines+ -> ParsecT s st m Inlines doubleQuoted inlineParser = do doubleQuoteStart (B.doubleQuoted . mconcat <$>@@ -93,12 +92,6 @@ (withQuoteContext InDoubleQuote (manyTill inlineParser doubleQuoteEnd))) <|> pure (B.str "\8220") -charOrRef :: (Stream s m Char, UpdateSourcePos s Char) => [Char] -> ParserT s st m Char-charOrRef cs =- oneOf cs <|> try (do c <- characterReference- guard (c `elem` cs)- return c)- -- | Succeeds if the parser is -- -- * not within single quoted text;@@ -109,19 +102,19 @@ -- Gobbles the quote character on success. singleQuoteStart :: (HasLastStrPosition st, HasQuoteContext st m, Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m ()+ => ParsecT s st m () singleQuoteStart = do failIfInQuoteContext InSingleQuote -- single quote start can't be right after str guard =<< notAfterString try $ do- charOrRef "'\8216\145"+ char '\'' void $ lookAhead (satisfy (not . isSpaceChar)) singleQuoteEnd :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m ()+ => ParsecT s st m () singleQuoteEnd = try $ do- charOrRef "'\8217\146"+ char '\'' notFollowedBy alphaNum -- | Succeeds if the parser is@@ -137,33 +130,33 @@ doubleQuoteStart :: (HasLastStrPosition st, HasQuoteContext st m, Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m ()+ => ParsecT s st m () doubleQuoteStart = do failIfInQuoteContext InDoubleQuote guard =<< notAfterString- try $ do charOrRef "\"\8220\147"+ try $ do char '"' void $ lookAhead (satisfy (not . isSpaceChar)) -- | Parses a closing quote character. doubleQuoteEnd :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m ()-doubleQuoteEnd = void (charOrRef "\"\8221\148")+ => ParsecT s st m ()+doubleQuoteEnd = void (char '"') -- | Parses an ASCII apostrophe (@'@) or right single quotation mark and -- returns a RIGHT SINGLE QUOtatiON MARK character. apostrophe :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Inlines+ => ParsecT s st m Inlines apostrophe = (char '\'' <|> char '\8217') >> return (B.str "\8217") -- | Parses an ASCII quotation mark character and returns a RIGHT DOUBLE -- QUOTATION MARK. doubleCloseQuote :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Inlines+ => ParsecT s st m Inlines doubleCloseQuote = B.str "\8221" <$ char '"' -- | Parses three dots as HORIZONTAL ELLIPSIS. ellipses :: (Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Inlines+ => ParsecT s st m Inlines ellipses = try (string "..." >> return (B.str "\8230")) -- | Parses two hyphens as EN DASH and three as EM DASH.@@ -172,7 +165,7 @@ -- parsed as EM DASH, and one hyphen is parsed as EN DASH if it is -- followed by a digit. dash :: (HasReaderOptions st, Stream s m Char, UpdateSourcePos s Char)- => ParserT s st m Inlines+ => ParsecT s st m Inlines dash = try $ do oldDashes <- extensionEnabled Ext_old_dashes <$> getOption readerExtensions if oldDashes
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Parsing- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GPL-2.0-or-later Maintainer : John MacFarlane <jgm@berkeley.edu> @@ -32,8 +32,8 @@ import Text.Pandoc.Logging (LogMessage) import Text.Pandoc.Options (ReaderOptions) import Text.Pandoc.Parsing.Capabilities-import Text.Pandoc.Parsing.Types-import Text.Pandoc.Readers.LaTeX.Types (Macro)+import Text.Pandoc.Parsing.Future+import Text.Pandoc.TeX (Macro) import qualified Data.Map as M import qualified Data.Set as Set@@ -46,7 +46,6 @@ , stateQuoteContext :: QuoteContext -- ^ Inside quoted environment? , stateAllowLinks :: Bool -- ^ Allow parsing of links , stateAllowLineBreaks :: Bool -- ^ Allow parsing of line breaks- , stateMaxNestingLevel :: Int -- ^ Max # of nested Strong/Emph , stateLastStrPos :: Maybe SourcePos -- ^ Position after last str parsed , stateKeys :: KeyTable -- ^ List of reference keys , stateHeaderKeys :: KeyTable -- ^ List of implicit header ref keys@@ -141,7 +140,6 @@ , stateQuoteContext = NoQuote , stateAllowLinks = True , stateAllowLineBreaks = True- , stateMaxNestingLevel = 6 , stateLastStrPos = Nothing , stateKeys = M.empty , stateHeaderKeys = M.empty@@ -188,4 +186,4 @@ type KeyTable = M.Map Key (Target, Attr) -type SubstTable = M.Map Key Inlines+type SubstTable = M.Map Key Blocks
@@ -1,58 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{- |- Module : Text.Pandoc.Parsing- Copyright : Copyright (C) 2006-2022 John MacFarlane- License : GPL-2.0-or-later- Maintainer : John MacFarlane <jgm@berkeley.edu>--Types and type-related functions for parsers.--}--module Text.Pandoc.Parsing.Types- ( Parser- , ParserT- , Future (..)- , runF- , askF- , asksF- , returnF- )-where--import Prelude hiding (Applicative(..))-import Control.Applicative (Applicative(..))-import Control.Monad.Reader- ( asks, runReader, MonadReader(ask), Reader, ReaderT(ReaderT) )-import Text.Parsec ( Parsec , ParsecT )---- | Generic parser type used by many pandoc readers.-type Parser t s = Parsec t s---- | Generic parser transformer used by many pandoc readers.-type ParserT = ParsecT---- | Reader monad wrapping the parser state. This is used to possibly--- delay evaluation until all relevant information has been parsed and--- made available in the parser state.-newtype Future s a = Future { runDelayed :: Reader s a }- deriving (Monad, Applicative, Functor)--instance Semigroup a => Semigroup (Future s a) where- (<>) = liftA2 (<>)--instance (Semigroup a, Monoid a) => Monoid (Future s a) where- mempty = return mempty- mappend = (<>)---- | Run a delayed action with the given state.-runF :: Future s a -> s -> a-runF = runReader . runDelayed--askF :: Future s s-askF = Future ask--asksF :: (s -> a) -> Future s a-asksF f = Future $ asks f--returnF :: Monad m => a -> m (Future s a)-returnF = return . return
@@ -1,6 +1,6 @@ {- | Module : Text.Pandoc.Process- Copyright : Copyright (C) 2013-2022 John MacFarlane+ Copyright : Copyright (C) 2013-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -1,10 +1,11 @@+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE MonoLocalBinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-} {- | Module : Text.Pandoc.Readers- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -24,8 +25,11 @@ -- * Readers: converting /to/ Pandoc format Reader (..) , readers+ , readAsciiDoc , readDocx- , readOdt+ , readPptx+ , readXlsx+ , readODT , readMarkdown , readCommonMark , readCreole@@ -49,6 +53,8 @@ , readTxt2Tags , readEPUB , readMuse+ , readMan+ , readMdoc , readFB2 , readIpynb , readCSV@@ -59,28 +65,34 @@ , readEndNoteXML , readRIS , readRTF+ , readTypst+ , readDjot+ , readPod+ , readXML -- * Miscellaneous , getReader , getDefaultExtensions ) where -import Control.Monad (unless) import Control.Monad.Except (throwError) import Data.Aeson import qualified Data.ByteString.Lazy as BL import Data.Text (Text) import qualified Data.Text as T-import Text.Pandoc.Shared (tshow) import Text.Pandoc.Class import Text.Pandoc.Definition import Text.Pandoc.Error import Text.Pandoc.Extensions+import qualified Text.Pandoc.Format as Format import Text.Pandoc.Options+import Text.Pandoc.Readers.AsciiDoc import Text.Pandoc.Readers.CommonMark import Text.Pandoc.Readers.Markdown import Text.Pandoc.Readers.Creole import Text.Pandoc.Readers.DocBook import Text.Pandoc.Readers.Docx+import Text.Pandoc.Readers.Pptx+import Text.Pandoc.Readers.Xlsx import Text.Pandoc.Readers.DokuWiki import Text.Pandoc.Readers.EPUB import Text.Pandoc.Readers.FB2@@ -93,9 +105,10 @@ import Text.Pandoc.Readers.MediaWiki import Text.Pandoc.Readers.Muse import Text.Pandoc.Readers.Native-import Text.Pandoc.Readers.Odt+import Text.Pandoc.Readers.ODT import Text.Pandoc.Readers.OPML import Text.Pandoc.Readers.Org+import Text.Pandoc.Readers.Pod import Text.Pandoc.Readers.RST import Text.Pandoc.Readers.Textile import Text.Pandoc.Readers.TikiWiki@@ -103,12 +116,16 @@ import Text.Pandoc.Readers.Txt2Tags import Text.Pandoc.Readers.Vimwiki import Text.Pandoc.Readers.Man+import Text.Pandoc.Readers.Mdoc import Text.Pandoc.Readers.CSV import Text.Pandoc.Readers.CslJson import Text.Pandoc.Readers.BibTeX import Text.Pandoc.Readers.EndNote import Text.Pandoc.Readers.RIS 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) @@ -127,6 +144,7 @@ ,("markdown_mmd", TextReader readMarkdown) ,("commonmark" , TextReader readCommonMark) ,("commonmark_x" , TextReader readCommonMark)+ ,("asciidoc" , TextReader readAsciiDoc) ,("creole" , TextReader readCreole) ,("dokuwiki" , TextReader readDokuWiki) ,("gfm" , TextReader readCommonMark)@@ -138,6 +156,7 @@ ,("org" , TextReader readOrg) ,("textile" , TextReader readTextile) -- TODO : textile+lhs ,("html" , TextReader readHtml)+ ,("bits" , TextReader readJATS) ,("jats" , TextReader readJATS) ,("jira" , TextReader readJira) ,("latex" , TextReader readLaTeX)@@ -145,7 +164,9 @@ ,("twiki" , TextReader readTWiki) ,("tikiwiki" , TextReader readTikiWiki) ,("docx" , ByteStringReader readDocx)- ,("odt" , ByteStringReader readOdt)+ ,("pptx" , ByteStringReader readPptx)+ ,("xlsx" , ByteStringReader readXlsx)+ ,("odt" , ByteStringReader readODT) ,("t2t" , TextReader readTxt2Tags) ,("epub" , ByteStringReader readEPUB) ,("muse" , TextReader readMuse)@@ -160,31 +181,21 @@ ,("endnotexml" , TextReader readEndNoteXML) ,("ris" , TextReader readRIS) ,("rtf" , TextReader readRTF)- ]+ ,("typst" , TextReader readTypst)+ ,("djot" , TextReader readDjot)+ ,("mdoc" , TextReader readMdoc)+ ,("pod" , TextReader readPod)+ ,("xml" , TextReader readXML)+ ] --- | Retrieve reader, extensions based on formatSpec (format+extensions).-getReader :: PandocMonad m => Text -> m (Reader m, Extensions)-getReader s =- case parseFormatSpec s of- Left e -> throwError $ PandocAppError $- "Error parsing reader format " <> tshow s <> ": " <> tshow e- Right (readerName, extsToEnable, extsToDisable) ->- case lookup readerName readers of- Nothing -> throwError $ PandocUnknownReaderError- readerName- Just r -> do- let allExts = getAllExtensions readerName- let exts = foldr disableExtension- (foldr enableExtension- (getDefaultExtensions readerName)- extsToEnable) extsToDisable- mapM_ (\ext ->- unless (extensionEnabled ext allExts) $- throwError $- PandocUnsupportedExtensionError- (T.drop 4 $ T.pack $ show ext) readerName)- (extsToEnable ++ extsToDisable)- return (r, exts)+-- | Retrieve reader, extensions based on format spec (format+extensions).+getReader :: PandocMonad m => Format.FlavoredFormat -> m (Reader m, Extensions)+getReader flvrd = do+ let readerName = Format.formatName flvrd+ case lookup readerName readers of+ Nothing -> throwError $ PandocUnknownReaderError readerName+ Just r -> (r,) <$>+ Format.applyExtensionsDiff (Format.getExtensionsConfig readerName) flvrd -- | Read pandoc document from JSON format. readJSON :: (PandocMonad m, ToSources a)
@@ -0,0 +1,416 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}++{- |+ Module : Text.Pandoc.Readers.AsciiDoc+ Copyright : Copyright (C) 2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Reads and evaluates a AsciiDoc document as a Pandoc AST.+-}+module Text.Pandoc.Readers.AsciiDoc+ ( readAsciiDoc+ )+where++import Text.Pandoc.Class+import Text.Pandoc.Options+import Text.Pandoc.Definition+import Text.Pandoc.Walk+import Text.Pandoc.Shared (addPandocAttributes, blocksToInlines, safeRead,+ tshow)+import qualified Text.Pandoc.UTF8 as UTF8+import qualified AsciiDoc as A+import Text.Pandoc.Error+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Readers.HTML (readHtml)+import Control.Monad.Except (throwError)+import Control.Monad+import Text.Pandoc.Parsing (newPos, sourceName)+import Text.Pandoc.Logging+import Text.Pandoc.Sources+import Control.Monad.State+import qualified Data.List as L+import Data.Char (chr, ord)+import qualified Data.Text as T+import qualified Data.Map as M+import Data.Maybe (fromMaybe)++-- import Debug.Trace++-- | Read AsciiDoc from an input string and return a Pandoc document.+readAsciiDoc :: (PandocMonad m, ToSources a) => ReaderOptions -> a -> m Pandoc+readAsciiDoc _opts inp = do+ let Sources sources = toSources inp+ (mconcat <$> mapM+ (\(sourcepos, t) ->+ A.parseDocument getIncludeFile raiseError (sourceName sourcepos) t)+ sources)+ >>= resolveFootnotes+ >>= resolveStem+ >>= resolveIcons+ >>= toPandoc+ where+ getIncludeFile fp = UTF8.toText <$> readFileStrict fp+ raiseError fp pos msg = throwError $ PandocParseError $ T.pack+ $ msg <> " at " <> show fp <>+ " char " <> show pos++toPandoc :: PandocMonad m => A.Document -> m Pandoc+toPandoc doc =+ Pandoc <$> doMeta (A.docMeta doc)+ <*> (B.toList <$> doBlocks (A.docBlocks doc))++resolveFootnotes :: Monad m => A.Document -> m A.Document+resolveFootnotes doc = do+ evalStateT (A.mapInlines go doc) (mempty :: M.Map T.Text [A.Inline])+ where+ go (A.Inline attr (A.Footnote (Just (A.FootnoteId fnid)) ils)) = do+ fnmap <- get+ case M.lookup fnid fnmap of+ Just ils' ->+ pure $ A.Inline attr (A.Footnote (Just (A.FootnoteId fnid)) ils')+ Nothing -> do+ put $ M.insert fnid ils fnmap+ pure $ A.Inline attr (A.Footnote (Just (A.FootnoteId fnid)) ils)+ go x = pure x++resolveStem :: Monad m => A.Document -> m A.Document+resolveStem doc = do+ let defaultType = case M.lookup "stem" (A.docAttributes (A.docMeta doc)) of+ Just "asciimath" -> A.AsciiMath+ _ -> A.LaTeXMath+ let doInlineStem (A.Inline attr (A.Math Nothing t)) =+ pure $ A.Inline attr (A.Math (Just defaultType) t)+ doInlineStem x = pure x+ let doBlockStem (A.Block attr mbtit (A.MathBlock Nothing t)) =+ pure $ A.Block attr mbtit (A.MathBlock (Just defaultType) t)+ doBlockStem x = A.mapInlines doInlineStem x+ A.mapBlocks doBlockStem doc++-- resolve icons as either characters in an icon font or images+resolveIcons :: Monad m => A.Document -> m A.Document+resolveIcons doc = A.mapInlines fromIcon doc+ where+ docattrs = A.docAttributes (A.docMeta doc)+ iconFont = case M.lookup "icons" docattrs of+ Just "font" -> True+ _ -> False+ iconsdir = fromMaybe "./images/icons" $ M.lookup "iconsdir" docattrs+ icontype = fromMaybe "png" $ M.lookup "icontype" docattrs+ addClasses cls (A.Attr ps kvs) =+ A.Attr ps $+ case M.lookup "role" kvs of+ Just r -> M.insert "role" (T.unwords (r : cls)) kvs+ Nothing -> M.insert "role" (T.unwords cls) kvs+ fromIcon (A.Inline attr (A.Icon name)) =+ if iconFont+ then pure $+ A.Inline (addClasses ["fa", "fa-" <> name] attr) (A.Span [])+ else pure $ -- default is to use an image+ A.Inline (addClasses ["icon"] attr)+ (A.InlineImage+ (A.Target+ (iconsdir <> "/" <> name <> "." <> icontype))+ Nothing Nothing Nothing)+ fromIcon x = pure x++addAttribution :: Maybe A.Attribution -> B.Blocks -> B.Blocks+addAttribution Nothing bs = bs+addAttribution (Just (A.Attribution t)) bs = B.fromList $+ case B.toList bs of+ [B.Div attr bls] -> [B.Div attr (bls ++ [attrBlock])]+ [B.BlockQuote bls] -> [B.BlockQuote (bls ++ [attrBlock])]+ xs -> xs ++ [attrBlock]+ where+ attrBlock = Para (B.toList $ B.text $ "\x2014 " <> t)++doMeta :: PandocMonad m => A.Meta -> m B.Meta+doMeta meta = do+ tit' <- doInlines (A.docTitle meta)+ pure $+ (if tit' == mempty+ then id+ else B.setMeta "title" tit') .+ (case A.docAuthors meta of+ [] -> id+ as -> B.setMeta "author" (map fromAuthor as)) .+ (case A.docRevision meta of+ Nothing -> id+ Just (A.Revision vers mbdate mbremark) ->+ B.setMeta "version" vers .+ maybe id (B.setMeta "date") mbdate .+ maybe id (B.setMeta "remark") mbremark) .+ flip (L.foldl' (\m (k,v) ->+ -- leave out flags that are set just for processing+ if k == "sectids" || k == "stem"+ then m+ else if T.null v+ then B.setMeta k True m+ else B.setMeta k v m))+ (M.toList (A.docAttributes meta))+ $ mempty++fromAuthor :: A.Author -> B.Inlines+fromAuthor au = B.text (A.authorName au) <>+ maybe mempty (\email ->+ " (" <> B.link ("mailto:" <> email) "" (B.str email) <> ")")+ (A.authorEmail au)++doBlocks :: PandocMonad m => [A.Block] -> m B.Blocks+doBlocks = fmap mconcat . mapM doBlock++addBlockAttr :: A.Attr -> B.Blocks -> B.Blocks+addBlockAttr (A.Attr _ kvs') bs =+ case B.toList bs of+ x@(B.OrderedList{}) : xs -> -- "start" is handled in list attribs+ addPandocAttributes (M.toList $ M.delete "start" kvs)+ (B.singleton x) <> B.fromList xs+ x:xs -> addPandocAttributes (M.toList kvs) (B.singleton x)+ <> B.fromList xs+ [] -> mempty+ where+ kvs = M.mapKeys (\k -> if k == "role" then "class" else k) kvs'++addBlockTitle :: B.Inlines -> B.Blocks -> B.Blocks+addBlockTitle tit' bs =+ let tit = B.toList tit'+ in case B.toList bs of+ [B.Table attr _ colspecs thead tbody tfoot] ->+ B.singleton $ B.Table attr (B.Caption Nothing [B.Plain tit])+ colspecs thead tbody tfoot+ [B.Figure attr _ bs'] ->+ B.singleton $ B.Figure attr (B.Caption Nothing [B.Plain tit]) bs'+ [B.Div attr (B.Div ("",["title"],[]) [Para _] : bs')] ->+ -- replace existing title, which might be e.g. "Note"+ B.singleton $ B.Div attr (B.Div ("",["title"],[]) [B.Para tit] : bs')+ [B.Div attr bs'] -> -- put title Div inside+ B.singleton $ B.Div attr (B.Div ("",["title"],[]) [B.Para tit] : bs')+ _ -> B.divWith B.nullAttr (B.divWith ("",["title"],[]) (B.para tit') <> bs)++doBlock :: PandocMonad m => A.Block -> m B.Blocks+doBlock (A.Block attr@(A.Attr ps kvs) mbtitle bt) = do+ mbtitle' <- case mbtitle of+ Nothing -> pure Nothing+ Just (A.BlockTitle ils) -> Just <$> doInlines ils+ addBlockAttr attr . maybe id addBlockTitle mbtitle' <$>+ case bt of+ A.Section (A.Level lev) ils bs -> do+ ils' <- doInlines ils+ bs' <- doBlocks bs+ pure $ (B.header lev ils') <> bs'+ A.DiscreteHeading (A.Level lev) ils ->+ B.header lev <$> doInlines ils+ A.Paragraph ils -> B.para <$> doInlines ils+ A.LiteralBlock t -> pure $ B.codeBlock t+ A.Listing mblang lns -> do+ let fromCallout (A.Callout i)+ | i <= 20 = T.pack [' ', chr (0x2460 + i - 1)]+ | otherwise = "<" <> tshow i <> ">"+ let fromSourceLine (A.SourceLine t callouts) =+ t <> mconcat (map fromCallout callouts)+ let code = T.intercalate "\n" $ map fromSourceLine lns+ let classes = case mblang of+ Nothing -> []+ Just (A.Language l) -> [l]+ pure $ B.codeBlockWith ("", classes, []) code+ A.IncludeListing _ _ Nothing -> pure mempty+ A.IncludeListing mblang _fp (Just lns) ->+ doBlock (A.Block mempty mbtitle (A.Listing mblang lns))+ A.ExampleBlock bs -> B.divWith ("",["example"],[]) <$> doBlocks bs+ A.Sidebar bs -> B.divWith ("",["sidebar"],[]) <$> doBlocks bs+ A.OpenBlock bs -> B.divWith ("",[],[]) <$> doBlocks bs+ A.QuoteBlock mbattrib bs ->+ addAttribution mbattrib . B.blockQuote <$> doBlocks bs+ A.Verse mbattrib bs ->+ addAttribution mbattrib . B.blockQuote <$> doBlocks bs+ -- TODO when texmath's asciimath parser works, convert:+ A.MathBlock (Just A.AsciiMath) t -> pure $ B.para $ B.displayMath t+ A.MathBlock (Just A.LaTeXMath) t -> pure $ B.para $ B.displayMath t+ A.MathBlock Nothing _ ->+ throwError $ PandocParseError "Encountered math type Nothing"+ A.List (A.BulletList _) items ->+ B.bulletList <$> mapM doItem items+ A.List A.CheckList items ->+ B.bulletList <$> mapM doItem items+ A.List (A.OrderedList _ mbstart) items -> do+ let start = fromMaybe (1 :: Int)+ (mbstart `mplus` (M.lookup "start" kvs >>= safeRead))+ let getStyle xs = case xs of+ "arabic":_ -> Decimal+ "decimal":_ -> Decimal+ "loweralpha":_ -> LowerAlpha+ "upperalpha":_ -> UpperAlpha+ "lowerroman":_ -> LowerRoman+ "upperroman":_ -> UpperRoman+ _:rest -> getStyle rest+ [] -> DefaultStyle+ let sty = getStyle ps+ let delim = DefaultDelim+ B.orderedListWith (start, sty, delim) <$> mapM doItem items+ A.List A.CalloutList items ->+ B.divWith ("",["callout-list"],[]) . B.orderedList <$> mapM doItem items+ A.DefinitionList items+ | "ordered" `elem` ps ->+ B.orderedList <$>+ mapM (fmap (B.definitionList . (:[])) . doDefListItem) items+ | otherwise -> B.definitionList <$> mapM doDefListItem items+ A.Table specs mbHeader rows mbFooter -> do+ let toAlign A.AlignLeft = B.AlignLeft+ toAlign A.AlignCenter = B.AlignCenter+ toAlign A.AlignRight = B.AlignRight+ let fromCell (A.TableCell bs mbHorizAlign _mbVertAlign colspan rowspan) =+ B.Cell B.nullAttr (maybe B.AlignDefault toAlign mbHorizAlign)+ (B.RowSpan rowspan) (B.ColSpan colspan) . B.toList+ <$> doBlocks bs+ let fromRow (A.TableRow cs) = B.Row B.nullAttr <$> mapM fromCell cs+ tbody <- B.TableBody B.nullAttr (B.RowHeadColumns 0) [] <$> mapM fromRow rows+ thead <- B.TableHead B.nullAttr <$> maybe (pure []) (mapM fromRow) mbHeader+ tfoot <- B.TableFoot B.nullAttr <$> maybe (pure []) (mapM fromRow) mbFooter+ let totalWidth = sum $ map (fromMaybe 1 . A.colWidth) specs+ let toColSpec spec = (maybe B.AlignDefault toAlign (A.colHorizAlign spec),+ maybe B.ColWidthDefault+ (B.ColWidth . (\x ->+ fromIntegral x / fromIntegral totalWidth))+ (A.colWidth spec))+ let colspecs = map toColSpec specs+ pure $ B.table (B.Caption Nothing mempty) -- added by addBlockTitle+ colspecs thead [tbody] tfoot+ A.BlockImage target mbalt mbw mbh -> do+ img' <- doInline (A.Inline mempty (A.InlineImage target mbalt mbw mbh))+ -- TODO have a global function that adds the title to caption here:+ pure $ B.figure (Caption Nothing mempty) -- added by addBlockTitle+ (B.plain img')+ -- TODO alt text?+ A.BlockAudio (A.Target t) ->+ pure $ B.plain $ B.image t "" (B.str t)+ -- TODO alt text?+ A.BlockVideo (A.Target t) ->+ pure $ B.plain $ B.image t "" (B.str t)+ A.TOC -> pure $ B.divWith ("toc",[],[]) mempty+ A.Admonition admonitionType bs -> do+ let admon = T.pack $ show admonitionType+ bs' <- doBlocks bs+ pure $ B.divWith ("",[T.toLower admon],[])+ $ B.divWith ("",["title"],[]) (B.para (B.str admon)) <> bs'+ A.PageBreak ->+ pure $ B.divWith ("", ["page-break"], [("wrapper", "1")]) B.horizontalRule+ A.ThematicBreak -> pure $ B.horizontalRule+ A.Include fp (Just bs) ->+ B.divWith ("",["included"],[("path",T.pack fp)]) <$> doBlocks bs+ A.Include fp Nothing -> do+ report $ CouldNotLoadIncludeFile (T.pack fp) (newPos "" 0 0)+ pure mempty+ A.PassthroughBlock t ->+ case runPure (readHtml def{+ readerExtensions = extensionsFromList [Ext_raw_html]+ } t) of+ Left _ -> pure $ B.rawBlock "html" t+ Right (Pandoc _ bs) -> pure $ B.fromList bs++doItem :: PandocMonad m => A.ListItem -> m B.Blocks+doItem (A.ListItem Nothing bs) = doBlocks bs+doItem (A.ListItem (Just checkstate) bs) = do+ bs' <- doBlocks bs+ let check = case checkstate of+ A.Checked -> Str "\9746"+ A.Unchecked -> Str "\9744"+ pure $ B.fromList+ $ case B.toList bs' of+ (B.Para ils : rest) -> B.Para (check : B.Space : ils) : rest+ (B.Plain ils : rest) -> B.Plain (check : B.Space : ils) : rest+ rest -> B.Para [check] : rest++doDefListItem :: PandocMonad m+ => ([A.Inline], [A.Block]) -> m (B.Inlines , [B.Blocks])+doDefListItem (lab, bs) = do+ lab' <- doInlines lab+ bs' <- doBlocks bs+ pure (lab', [bs'])++doInlines :: PandocMonad m => [A.Inline] -> m B.Inlines+doInlines = fmap mconcat . mapM doInline++doInline :: PandocMonad m => A.Inline -> m B.Inlines+doInline (A.Inline (A.Attr _ps kvs') it) = do+ let kvs = M.mapKeys (\k -> if k == "role" then "class" else k) kvs'+ addPandocAttributes (M.toList kvs) <$>+ case it of+ A.Str t -> pure $ B.text t+ A.HardBreak -> pure B.linebreak+ A.Bold ils -> B.strong <$> doInlines ils+ A.Italic ils -> B.emph <$> doInlines ils+ A.Monospace ils -> walk monospaceStr <$> doInlines ils+ A.Superscript ils -> B.superscript <$> doInlines ils+ A.Subscript ils -> B.subscript <$> doInlines ils+ A.Highlight ils -> B.spanWith ("",["mark"],[]) <$> doInlines ils+ A.Strikethrough ils -> B.strikeout <$> doInlines ils+ A.DoubleQuoted ils -> B.doubleQuoted <$> doInlines ils+ A.SingleQuoted ils -> B.singleQuoted <$> doInlines ils+ -- TODO when texmath's asciimath parser works, convert:+ A.Math (Just A.AsciiMath) t -> pure $ B.math t+ A.Math (Just A.LaTeXMath) t -> pure $ B.math t+ A.Math Nothing _ ->+ throwError $ PandocParseError "Encountered math type Nothing"+ A.Icon t -> pure $ B.spanWith ("",["icon"],[("name",t)])+ (B.str ("[" <> t <> "]"))+ A.Button t -> pure $ B.spanWith ("",["button"],[])+ (B.strong $ B.str ("[" <> t <> "]"))+ A.Kbd ts -> pure $ mconcat $ L.intersperse (B.str "+") $+ map (B.spanWith ("",["kbd"],[]) . B.strong . B.str) ts+ A.Menu ts -> pure $ B.spanWith ("",["menu"],[]) $+ B.strong $ B.text $ T.intercalate " › " ts+ -- TODO do we need linktype?+ A.Link _linkType (A.Target t) ils -> B.link t "" <$> doInlines ils+ A.InlineImage (A.Target url) mbalt mbwidth mbheight -> do+ let alt = case mbalt of+ Just (A.AltText t) -> B.text t+ Nothing -> mempty+ width = case mbwidth of+ Just (A.Width n) -> [("width", T.pack $ show n <> "px")]+ Nothing -> []+ height = case mbheight of+ Just (A.Height n) -> [("height", T.pack $ show n <> "px")]+ Nothing -> []+ pure $ B.imageWith ("",[], width ++ height) url "" alt+ A.Footnote _ ils -> B.note . B.para <$> doInlines ils+ A.InlineAnchor t _ -> pure $ B.spanWith (t, [], []) mempty+ A.BibliographyAnchor t _ -> pure $ B.spanWith (t, [], []) mempty+ A.CrossReference t Nothing ->+ pure $ B.linkWith ("",["cross-reference"],[]) ("#" <> t) "" (B.str t)+ A.CrossReference t (Just ils) -> do+ B.linkWith ("",["cross-reference"],[]) ("#" <> t) "" <$> doInlines ils+ A.AttributeReference (A.AttributeName t) -> -- if this is here, it's unresolved+ pure $ B.str ("{" <> t <> "}")+ A.Span ils -> B.spanWith B.nullAttr <$> doInlines ils+ A.IndexEntry (A.TermInText t) ->+ pure $ B.spanWith ("",["index"],[("term",t)]) (B.text t)+ A.IndexEntry (A.TermConcealed ts) ->+ pure $ B.spanWith ("",["index"],[("term",T.intercalate "," ts)]) mempty+ A.Counter name ctype val ->+ pure $ B.spanWith ("",["counter"],[("name",name)]) $ B.str $+ case ctype of+ A.DecimalCounter -> tshow val+ A.UpperAlphaCounter -> T.singleton $ chr (ord 'A' + val - 1)+ A.LowerAlphaCounter -> T.singleton $ chr (ord 'a' + val - 1)+ -- Passthrough is hard to get right, because pandoc's RawInline needs+ -- a format specifier. Often in asciidoc passthrough is used as a form+ -- of escaping, so the best approach seems to be treating it as HTML+ -- and parsing it:+ A.Passthrough t -> do+ case runPure (readHtml def{+ readerExtensions = extensionsFromList [Ext_raw_html]+ } t) of+ Left _ -> pure $ B.rawInline "html" t+ Right (Pandoc _ bs) -> pure $ B.fromList . blocksToInlines $ bs++monospaceStr :: Inline -> Inline+monospaceStr (Str t) = Code B.nullAttr t+monospaceStr x = x
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.BibTeX- Copyright : Copyright (C) 2020-2022 John MacFarlane+ Copyright : Copyright (C) 2020-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -23,6 +23,7 @@ import Text.Pandoc.Options import Text.Pandoc.Definition import Text.Pandoc.Builder (setMeta, cite, str)+import Text.Pandoc.Parsing (fromParsecError) import Citeproc (Lang(..), parseLang) import Citeproc.Locale (getLocale) import Text.Pandoc.Error (PandocError(..))@@ -63,7 +64,7 @@ Left _ -> throwError $ PandocCiteprocError e Right l -> return l case BibTeX.readBibtexString variant locale (const True) t of- Left e -> throwError $ PandocParsecError (toSources t) e+ Left e -> throwError $ fromParsecError (toSources t) e Right refs -> return $ setMeta "references" (map referenceToMetaValue refs) . setMeta "nocite"
@@ -3,7 +3,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Text.Pandoc.Readers.CSV- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -21,11 +21,12 @@ import Text.Pandoc.Definition import qualified Text.Pandoc.Builder as B import Text.Pandoc.Class (PandocMonad)-import Text.Pandoc.Error import Text.Pandoc.Sources (ToSources(..), sourcesToText) import Text.Pandoc.Options (ReaderOptions) import Control.Monad.Except (throwError) import Data.Text (Text)+import Data.List (intersperse)+import Text.Pandoc.Parsing (fromParsecError) readCSV :: (PandocMonad m, ToSources a) => ReaderOptions -- ^ Reader options@@ -60,7 +61,8 @@ (TableFoot nullAttr []) where capt = B.emptyCaption numcols = length r- toplain = B.simpleCell . B.plain . B.text . T.strip+ toplain = B.simpleCell . B.plain . mconcat .+ intersperse B.linebreak . map B.text . T.lines toRow = Row nullAttr . map toplain toHeaderRow l = [toRow l | not (null l)] hdrs = toHeaderRow r@@ -68,4 +70,4 @@ aligns = replicate numcols AlignDefault widths = replicate numcols ColWidthDefault Right [] -> return $ B.doc mempty- Left e -> throwError $ PandocParsecError (toSources [("",txt)]) e+ Left e -> throwError $ fromParsecError (toSources [("",txt)]) e
@@ -3,7 +3,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Text.Pandoc.Readers.CommonMark- Copyright : Copyright (C) 2015-2022 John MacFarlane+ Copyright : Copyright (C) 2015-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -25,15 +25,15 @@ import Text.Pandoc.Definition import Text.Pandoc.Builder as B import Text.Pandoc.Options-import Text.Pandoc.Error import Text.Pandoc.Readers.Metadata (yamlMetaBlock)-import Control.Monad.Except+import Control.Monad (MonadPlus(mzero))+import Control.Monad.Except ( MonadError(throwError) ) import Data.Functor.Identity (runIdentity) import Data.Typeable import Text.Pandoc.Parsing (runParserT, getInput, getPosition, runF, defaultParserState, option, many1, anyChar,- Sources(..), ToSources(..), ParserT, Future,- sourceName, sourceLine, incSourceLine)+ Sources(..), ToSources(..), ParsecT, Future,+ incSourceLine, fromParsecError) import Text.Pandoc.Walk (walk) import qualified Data.Text as T import qualified Data.Attoparsec.Text as A@@ -70,6 +70,14 @@ let toks = concatMap sourceToToks (unSources sources) readCommonMarkBody opts sources toks +makeFigures :: Block -> Block+makeFigures (Para [Image (ident,classes,kvs) alt (src,tit)])+ | not (null alt) =+ Figure (ident,[],[])+ (Caption Nothing [Plain alt])+ [Plain [Image ("",classes,kvs) alt (src,tit)]]+makeFigures b = b+ sourceToToks :: (SourcePos, Text) -> [Tok] sourceToToks (pos, s) = map adjust $ tokenize (sourceName pos) s where@@ -80,7 +88,7 @@ metaValueParser :: Monad m- => ReaderOptions -> ParserT Sources st m (Future st MetaValue)+ => ReaderOptions -> ParsecT Sources st m (Future st MetaValue) metaValueParser opts = do inp <- option "" $ T.pack <$> many1 anyChar let toks = concatMap sourceToToks (unSources (toSources inp))@@ -90,17 +98,40 @@ readCommonMarkBody :: PandocMonad m => ReaderOptions -> Sources -> [Tok] -> m Pandoc readCommonMarkBody opts s toks =+ (if isEnabled Ext_implicit_figures opts+ then walk makeFigures+ else id) .+ (if isEnabled Ext_tex_math_gfm opts+ then walk handleGfmMath+ else id) . (if readerStripComments opts then walk stripBlockComments . walk stripInlineComments else id) <$> if isEnabled Ext_sourcepos opts then case runIdentity (parseCommonmarkWith (specFor opts) toks) of- Left err -> throwError $ PandocParsecError s err+ Left err -> throwError $ fromParsecError s err Right (Cm bls :: Cm SourceRange Blocks) -> return $ B.doc bls else case runIdentity (parseCommonmarkWith (specFor opts) toks) of- Left err -> throwError $ PandocParsecError s err+ Left err -> throwError $ fromParsecError s err Right (Cm bls :: Cm () Blocks) -> return $ B.doc bls +handleGfmMath :: Block -> Block+handleGfmMath (CodeBlock ("",["math"],[]) raw) = Para [Math DisplayMath raw]+handleGfmMath x = walk handleGfmMathInline x++handleGfmMathInline :: Inline -> Inline+handleGfmMathInline (Math InlineMath math'') =+ let math' = T.replace "\\\\{" "\\{" . T.replace "\\\\}" "\\}" $ math''+ -- see #10631+ (ticks, rest) = T.span (== '`') math'+ in if T.null ticks+ then Math InlineMath math'+ else case T.stripSuffix ticks rest of+ Just middle | not (T.null middle) && (T.last middle /= '`')+ -> Math InlineMath middle+ _ -> Math InlineMath math'+handleGfmMathInline x = x+ stripBlockComments :: Block -> Block stripBlockComments (RawBlock (B.Format "html") s) = RawBlock (B.Format "html") (removeComments s)@@ -141,6 +172,7 @@ [ (bracketedSpanSpec <>) | isEnabled Ext_bracketed_spans opts ] ++ [ (rawAttributeSpec <>) | isEnabled Ext_raw_attribute opts ] ++ [ (attributesSpec <>) | isEnabled Ext_attributes opts ] +++ [ (alertSpec <>) | isEnabled Ext_alerts opts ] ++ [ (<> pipeTableSpec) | isEnabled Ext_pipe_tables opts ] ++ -- see #6739 [ (autolinkSpec <>) | isEnabled Ext_autolink_bare_uris opts ] ++@@ -156,6 +188,9 @@ [ (footnoteSpec <>) | isEnabled Ext_footnotes opts ] ++ [ (definitionListSpec <>) | isEnabled Ext_definition_lists opts ] ++ [ (taskListSpec <>) | isEnabled Ext_task_lists opts ] +++ [ (wikilinksSpec TitleAfterPipe <>)+ | isEnabled Ext_wikilinks_title_after_pipe opts ] +++ [ (wikilinksSpec TitleBeforePipe <>)+ | isEnabled Ext_wikilinks_title_before_pipe opts ] ++ [ (rebaseRelativePathsSpec <>) | isEnabled Ext_rebase_relative_paths opts ]-
@@ -13,7 +13,8 @@ module Text.Pandoc.Readers.Creole ( readCreole ) where -import Control.Monad.Except (guard, liftM2, throwError)+import Control.Monad+import Control.Monad.Except (throwError) import qualified Data.Foldable as F import Data.Maybe (fromMaybe) import Data.Text (Text)@@ -36,7 +37,7 @@ Left e -> throwError e Right d -> return d -type CRLParser = ParserT Sources ParserState+type CRLParser = ParsecT Sources ParserState -- -- Utility functions@@ -148,7 +149,7 @@ <$> (string "|=" >> many1Till inline cellEnd) row = try $ skipSpaces >> many1Till cell rowEnd cell = B.plain . B.trimInlines . mconcat- <$> (char '|' >> many1Till inline cellEnd)+ <$> (char '|' >> manyTill inline cellEnd) rowEnd = try $ optional (char '|') >> skipSpaces >> newline cellEnd = lookAhead $ try $ char '|' <|> rowEnd
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.CslJson- Copyright : Copyright (C) 2020-2022 John MacFarlane+ Copyright : Copyright (C) 2020-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -1,83 +0,0 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Readers.Custom- Copyright : Copyright (C) 2021-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Supports custom parsers written in Lua which produce a Pandoc AST.--}-module Text.Pandoc.Readers.Custom ( readCustom ) where-import Control.Exception-import Control.Monad (when)-import Control.Monad.IO.Class (MonadIO)-import Data.Maybe (fromMaybe)-import HsLua as Lua hiding (Operation (Div))-import Text.Pandoc.Definition-import Text.Pandoc.Class (PandocMonad, findFileWithDataFallback, report)-import Text.Pandoc.Logging-import Text.Pandoc.Lua (Global (..), runLua, setGlobals)-import Text.Pandoc.Lua.PandocLua-import Text.Pandoc.Lua.Marshal.Pandoc (peekPandoc)-import Text.Pandoc.Options-import Text.Pandoc.Sources (ToSources(..), sourcesToText)-import qualified Data.Text as T---- | Convert custom markup to Pandoc.-readCustom :: (PandocMonad m, MonadIO m, ToSources s)- => FilePath -> ReaderOptions -> s -> m Pandoc-readCustom luaFile opts srcs = do- let globals = [ PANDOC_SCRIPT_FILE luaFile ]- luaFile' <- fromMaybe luaFile <$> findFileWithDataFallback "readers" luaFile- res <- runLua $ do- setGlobals globals- stat <- dofileTrace luaFile'- -- check for error in lua script (later we'll change the return type- -- to handle this more gracefully):- when (stat /= Lua.OK)- Lua.throwErrorAsException- parseCustom- case res of- Left msg -> throw msg- Right doc -> return doc- where- parseCustom = do- let input = toSources srcs- getglobal "Reader"- push input- push opts- pcallTrace 2 1 >>= \case- OK -> forcePeek $ peekPandoc top- ErrRun -> do- -- Caught a runtime error. Check if parsing might work if we- -- pass a string instead of a Sources list, then retry.- runPeek (peekText top) >>= \case- Failure {} ->- -- not a string error object. Bail!- throwErrorAsException- Success errmsg -> do- if "string expected, got pandoc Sources" `T.isInfixOf` errmsg- then do- pop 1- _ <- unPandocLua $ do- report $ Deprecated "old Reader function signature" $- T.unlines- [ "Reader functions should accept a sources list; "- , "functions expecting `string` input are deprecated. "- , "Use `tostring` to convert the first argument to a "- , "string."- ]- getglobal "Reader"- push $ sourcesToText input -- push sources as string- push opts- callTrace 2 1- forcePeek $ peekPandoc top- else- -- nothing we can do here- throwErrorAsException- _ -> -- not a runtime error, we won't be able to recover from that- throwErrorAsException
@@ -0,0 +1,273 @@+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++{- |+ Module : Text.Pandoc.Readers.Djot+ Copyright : Copyright (C) 2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Reads and evaluates a Djot document as a Pandoc AST.+-}+module Text.Pandoc.Readers.Djot+ ( readDjot+ )+where++import Text.Pandoc.Class+import Text.Pandoc.Sources+import Text.Parsec.Pos (newPos)+import Text.Pandoc.Options+import Text.Pandoc.Definition+import Text.Pandoc.Shared (addPandocAttributes, tshow)+import qualified Text.Pandoc.UTF8 as UTF8+import Djot (ParseOptions(..), SourcePosOption(..), parseDoc, Pos(..))+import qualified Djot.AST as D+import Text.Pandoc.Error (PandocError(..))+import Control.Monad.Except (throwError)+import qualified Data.Text as T+import Text.Pandoc.Builder+import Text.Pandoc.Logging+import Text.Pandoc.Emoji (emojiToInline)+import Control.Monad.Reader+import qualified Data.Foldable as F+import Data.ByteString (ByteString)+-- import Debug.Trace++-- | Read Djot from an input string and return a Pandoc document.+readDjot :: (PandocMonad m, ToSources a) => ReaderOptions -> a -> m Pandoc+readDjot opts inp = do+ let sources = toSources inp+ case parseDoc ParseOptions{ sourcePositions =+ if isEnabled Ext_sourcepos opts+ then AllSourcePos+ else NoSourcePos }+ (UTF8.fromText $ sourcesToText sources) of+ Left e -> throwError $ PandocParseError $ T.pack $ show e+ Right d ->+ runReaderT (doc <$> convertBlocks (D.docBlocks d))+ Env{ references = D.docReferences d <> D.docAutoReferences d+ , footnotes = D.docFootnotes d+ }++data Env =+ Env{ references :: D.ReferenceMap+ , footnotes :: D.NoteMap+ }+ deriving (Show, Ord, Eq)++convertBlocks :: PandocMonad m => D.Blocks -> ReaderT Env m Blocks+convertBlocks = fmap mconcat . mapM convertBlock . F.toList . D.unMany++convertBlock :: PandocMonad m => D.Node D.Block -> ReaderT Env m Blocks+convertBlock (D.Node pos attr bl) = addAttrToBlock pos attr <$>+ case bl of+ D.Para ils -> para <$> convertInlines ils+ D.Section bls -> divWith ("",["section"],[]) <$> convertBlocks bls+ D.Heading lev ils -> header lev <$> convertInlines ils+ D.BlockQuote bls -> blockQuote <$> convertBlocks bls+ D.CodeBlock lang bs -> pure $+ codeBlockWith ("", [UTF8.toText lang], []) $ UTF8.toText bs+ D.Div bls -> divWith nullAttr <$> convertBlocks bls+ D.OrderedList olattr listSpacing items ->+ orderedListWith olattr' .+ (case listSpacing of+ D.Tight -> map toTight+ D.Loose -> id) <$> mapM convertBlocks items+ where+ olattr' = ( D.orderedListStart olattr+ , case D.orderedListStyle olattr of+ D.Decimal -> Decimal+ D.LetterUpper -> UpperAlpha+ D.LetterLower -> LowerAlpha+ D.RomanUpper -> UpperRoman+ D.RomanLower -> LowerRoman+ , case D.orderedListDelim olattr of+ D.RightPeriod -> Period+ D.RightParen -> OneParen+ D.LeftRightParen -> TwoParens+ )+ D.BulletList listSpacing items ->+ bulletList .+ (case listSpacing of+ D.Tight -> map toTight+ D.Loose -> id) <$> mapM convertBlocks items+ D.TaskList listSpacing items ->+ bulletList .+ (case listSpacing of+ D.Tight -> map toTight+ D.Loose -> id) <$> mapM toTaskListItem items+ D.DefinitionList listSpacing items ->+ definitionList .+ (case listSpacing of+ D.Tight -> map (\(t,d) -> (t, map toTight d))+ D.Loose -> id) <$> mapM toDlItem items+ where+ toDlItem (ils,bls) = (,) <$> convertInlines ils+ <*> ((:[]) <$> convertBlocks bls)+ D.ThematicBreak -> pure horizontalRule+ D.Table mbCaption rows -> do+ capt <- case mbCaption of+ Just (D.Caption bls') ->+ Caption Nothing . toList <$> convertBlocks bls'+ Nothing -> pure $ Caption Nothing mempty+ let toAlign D.AlignLeft = AlignLeft+ toAlign D.AlignRight = AlignRight+ toAlign D.AlignCenter = AlignCenter+ toAlign D.AlignDefault = AlignDefault+ let toColSpec (D.Cell _ align _) = (toAlign align, ColWidthDefault)+ let colspecs = case rows of+ [] -> []+ (cells:_) -> map toColSpec cells+ let (headrow, rest) =+ case rows of+ (r@(D.Cell D.HeadCell _ _ : _) : rs) -> (r, rs)+ _ -> ([],rows)+ let getBody bods row =+ case row of+ (D.Cell D.HeadCell _ _ : _) ->+ case bods of+ [] -> [([row],[])]+ ([],_):_ -> (([row],[]):bods)+ (hs,bs):rs -> (hs,row:bs):rs+ _ -> case bods of+ (hs,bs):rs -> (hs,row:bs):rs+ [] -> [([],[row])]+ let reverseSnd (as,bs) = (as,reverse bs)+ let bodies = reverse $ map reverseSnd $ F.foldl' getBody [] rest+ let toCell (D.Cell _ al ils) =+ Cell nullAttr (toAlign al) (RowSpan 1) (ColSpan 1)+ . (\is -> [Para $ toList is]) <$> convertInlines ils+ let toRow = fmap (Row nullAttr) . mapM toCell+ thead <- TableHead mempty <$> mapM toRow [headrow]+ let toTableBody (hs, rs) =+ TableBody mempty (RowHeadColumns 0) <$>+ mapM toRow hs <*> mapM toRow rs+ tbodies <- mapM toTableBody bodies+ let tfoot = TableFoot mempty []+ pure $ singleton $ Table mempty capt colspecs thead tbodies tfoot+ D.RawBlock (D.Format fmt) bs -> pure $+ rawBlock (UTF8.toText fmt) (UTF8.toText bs)++addAttrToBlock :: Pos -> D.Attr -> Blocks -> Blocks+addAttrToBlock pos (D.Attr as) =+ addPandocAttributes $+ case pos of+ NoPos -> textkvs+ Pos sl sc el ec ->+ ("data-pos", tshow sl <> ":" <> tshow sc <>+ "-" <> tshow el <> ":" <> tshow ec) : textkvs+ where+ textkvs = (map (\(k,v) -> (UTF8.toText k, UTF8.toText v))+ (filter (not . internalAttribute) as))++addAttrToInline :: Pos -> D.Attr -> Inlines -> Inlines+addAttrToInline pos (D.Attr as) =+ addPandocAttributes $+ case pos of+ NoPos -> textkvs+ Pos sl sc el ec ->+ ("data-pos", tshow sl <> ":" <> tshow sc <>+ "-" <> tshow el <> ":" <> tshow ec) : textkvs+ where+ textkvs = (map (\(k,v) -> (UTF8.toText k, UTF8.toText v))+ (filter (not . internalAttribute) as))++convertInlines :: PandocMonad m => D.Inlines -> ReaderT Env m Inlines+convertInlines = fmap mconcat . mapM convertInline . F.toList . D.unMany++convertInline :: PandocMonad m => D.Node D.Inline -> ReaderT Env m Inlines+convertInline (D.Node pos attr il) = addAttrToInline pos attr <$>+ case il of+ D.Str bs -> pure $ text (UTF8.toText bs)+ D.Emph ils -> emph <$> convertInlines ils+ D.Strong ils -> strong <$> convertInlines ils+ D.Highlight ils -> spanWith ("",["mark"],[]) <$> convertInlines ils+ D.Insert ils -> spanWith ("",["inserted"],[]) <$> convertInlines ils+ D.Delete ils -> spanWith ("",["deleted"],[]) <$> convertInlines ils+ D.Subscript ils -> subscript <$> convertInlines ils+ D.Superscript ils -> superscript <$> convertInlines ils+ D.Span ils -> spanWith nullAttr <$> convertInlines ils+ D.Quoted D.DoubleQuotes ils -> doubleQuoted <$> convertInlines ils+ D.Quoted D.SingleQuotes ils -> singleQuoted <$> convertInlines ils+ D.Verbatim bs -> pure $ code (UTF8.toText bs)+ D.Symbol bs -> pure $+ let s = UTF8.toText bs+ in maybe (spanWith ("",["symbol"],[]) (str s)) singleton $ emojiToInline s+ D.Math sty bs -> pure $+ (case sty of+ D.DisplayMath -> displayMath+ D.InlineMath -> math) (UTF8.toText bs)+ D.Link ils target ->+ case target of+ D.Direct url -> link (UTF8.toText url) "" <$> convertInlines ils+ D.Reference label -> do+ refs <- asks references+ case D.lookupReference label refs of+ Just (url, lattr) ->+ addAttrToInline pos lattr .+ link (UTF8.toText url) "" <$> convertInlines ils+ Nothing -> do+ report $ ReferenceNotFound (UTF8.toText label) (newPos "" 0 0)+ link "" "" <$> convertInlines ils+ D.Image ils target ->+ case target of+ D.Direct url -> image (UTF8.toText url) "" <$> convertInlines ils+ D.Reference label -> do+ refs <- asks references+ case D.lookupReference label refs of+ Just (url, lattr) ->+ addAttrToInline pos lattr .+ image (UTF8.toText url) "" <$> convertInlines ils+ Nothing -> do+ report $ ReferenceNotFound (UTF8.toText label) (newPos "" 0 0)+ image "" "" <$> convertInlines ils+ D.FootnoteReference bs -> do+ notes <- asks footnotes+ case D.lookupNote bs notes of+ Just bls -> note <$> convertBlocks bls+ Nothing -> do+ -- TODO consider new warning for this?+ report $ IgnoredElement ("Undefined footnote reference " <> tshow bs)+ pure mempty+ D.UrlLink bs -> do+ let url = UTF8.toText bs+ pure $ linkWith ("",["uri"],[]) url "" (str url)+ D.EmailLink bs -> do+ let email = UTF8.toText bs+ pure $ linkWith ("",["email"],[]) ("mailto:" <> email) "" (str email)+ D.RawInline (D.Format fbs) bs -> pure $+ rawInline (UTF8.toText fbs) (UTF8.toText bs)+ D.NonBreakingSpace -> pure $ str "\160"+ D.SoftBreak -> pure softbreak+ D.HardBreak -> pure linebreak++internalAttribute :: (ByteString, ByteString) -> Bool+internalAttribute ("_implicit",_) = True+internalAttribute ("_autogen",_) = True+internalAttribute _ = False++toTight :: Blocks -> Blocks+toTight (Many bls) = Many $ paraToPlain <$> bls+ where+ paraToPlain (Para ils) = Plain ils+ paraToPlain x = x++toTaskListItem :: PandocMonad m+ => (D.TaskStatus, D.Blocks) -> ReaderT Env m Blocks+toTaskListItem (status, bls) = do+ bls' <- convertBlocks bls+ case toList bls' of+ (Para ils : rest) -> pure $+ fromList $ Para (Str taskmarker : Space : ils) : rest+ _ -> pure $ para (str taskmarker) <> bls'+ where+ taskmarker+ | status == D.Complete = "[X]"+ | otherwise = "[ ]"
@@ -1,9 +1,10 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TemplateHaskell #-} {- | Module : Text.Pandoc.Readers.DocBook- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -13,11 +14,19 @@ Conversion of DocBook XML to 'Pandoc' document. -} module Text.Pandoc.Readers.DocBook ( readDocBook ) where+import Control.Monad (MonadPlus(mplus))+import Control.Applicative () import Control.Monad.State.Strict+ ( MonadTrans(lift),+ StateT(runStateT),+ MonadState(get),+ gets,+ modify ) import Data.ByteString (ByteString) import Data.FileEmbed import Data.Char (isSpace, isLetter, chr) import Data.Default+import Data.List.Split (splitWhen) import Data.Either (rights) import Data.Foldable (asum) import Data.Generics@@ -31,17 +40,20 @@ import qualified Data.Text as T import qualified Data.Text.Lazy as TL import Control.Monad.Except (throwError)-import Text.HTML.TagSoup.Entity (lookupEntity)+import Text.Pandoc.XML (lookupEntity) import Text.Pandoc.Error (PandocError(..)) import Text.Pandoc.Builder import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Options import Text.Pandoc.Logging (LogMessage(..))-import Text.Pandoc.Shared (safeRead, extractSpaces)+import Text.Pandoc.Shared (safeRead, addPandocAttributes) import Text.Pandoc.Sources (ToSources(..), sourcesToText)+import Text.Pandoc.Transforms (headerShift) import Text.TeXMath (readMathML, writeTeX) import qualified Data.Map as M import Text.Pandoc.XML.Light+import Text.Pandoc.Walk (query)+import Text.Read (readMaybe) {- @@ -161,7 +173,7 @@ [ ] errorname - An error name [ ] errortext - An error message. [ ] errortype - The classification of an error message-[ ] example - A formal example, with a title+[x] example - A formal example, with a title [ ] exceptionname - The name of an exception [ ] fax - A fax number [ ] fieldsynopsis - The name of a field in a class definition@@ -313,7 +325,7 @@ [x] para - A paragraph [ ] paramdef - Information about a function parameter in a programming language [x] parameter - A value or a symbolic reference to a value-[ ] part - A division in a book+[x] part - A division in a book [ ] partinfo - Meta-information for a Part [ ] partintro - An introduction to the contents of a part [ ] personblurb - A short description or note about a person@@ -426,7 +438,7 @@ [ ] shortaffil - A brief description of an affiliation [ ] shortcut - A key combination for an action that is also accessible through a menu-[ ] sidebar - A portion of a document that is isolated from the main+[x] sidebar - A portion of a document that is isolated from the main narrative flow [ ] sidebarinfo - Meta-information for a Sidebar [x] simpara - A paragraph that contains only text and inline markup, no block@@ -530,13 +542,13 @@ type DB m = StateT DBState m -data DBState = DBState{ dbSectionLevel :: Int- , dbQuoteType :: QuoteType- , dbMeta :: Meta- , dbBook :: Bool- , dbFigureTitle :: Inlines- , dbFigureId :: Text- , dbContent :: [Content]+data DBState = DBState{ dbSectionLevel :: Int+ , dbQuoteType :: QuoteType+ , dbMeta :: Meta+ , dbBook :: Bool+ , dbContent :: [Content]+ , dbLiteralLayout :: Bool+ , dbElementStack :: [Text] } deriving Show instance Default DBState where@@ -544,9 +556,10 @@ , dbQuoteType = DoubleQuote , dbMeta = mempty , dbBook = False- , dbFigureTitle = mempty- , dbFigureId = mempty- , dbContent = [] }+ , dbContent = []+ , dbLiteralLayout = False+ , dbElementStack = []+ } readDocBook :: (PandocMonad m, ToSources a)@@ -560,7 +573,14 @@ docbookEntityMap (TL.fromStrict . handleInstructions . sourcesToText $ sources) (bs, st') <- flip runStateT (def{ dbContent = tree }) $ mapM parseBlock tree- return $ Pandoc (dbMeta st') (toList . mconcat $ bs)+ let headerLevel (Header n _ _) = [n]+ headerLevel _ = []+ let bottomLevel = maybe 1 minimum $ nonEmpty $ query headerLevel bs+ return $+ -- handle the case where you have <part> or <chapter>+ (if bottomLevel < 1+ then headerShift (1 - bottomLevel)+ else id) $ Pandoc (dbMeta st') $ toList $ mconcat bs -- We treat certain processing instructions by converting them to tags -- beginning "pi-".@@ -582,11 +602,15 @@ tit <- case filterChild (named "title") e of Just t -> getInlines t Nothing -> return mempty- let ident = attrValue "id" e- modify $ \st -> st{ dbFigureTitle = tit, dbFigureId = ident }- res <- getBlocks e- modify $ \st -> st{ dbFigureTitle = mempty, dbFigureId = mempty }- return res+ contents <- getBlocks e+ let contents' =+ case toList contents of+ [Para [img@Image{}]] -> plain (fromList [img])+ _ -> contents+ return $ figureWith+ (attrValue "id" e, [], [])+ (simpleCaption $ plain tit)+ contents' -- convenience function to get an attribute value, defaulting to "" attrValue :: Text -> Element -> Text@@ -600,9 +624,13 @@ -- addMetadataFromElement :: PandocMonad m => Element -> DB m Blocks-addMetadataFromElement e =- mempty <$ mapM_ handleMetadataElement+addMetadataFromElement e = do+ -- Add metadata if at root or appropriate parent element+ elementStack <- gets dbElementStack+ if take 1 elementStack `elem` [[], ["book"], ["article"]]+ then mempty <$ mapM_ handleMetadataElement (filterChildren ((isMetadataField . qName . elName)) e)+ else return mempty where handleMetadataElement elt = case qName (elName elt) of@@ -703,9 +731,7 @@ , "articleinfo" , "attribution" , "authorinitials"- , "bibliodiv" , "biblioentry"- , "bibliography" , "bibliomisc" , "bibliomixed" , "blockquote"@@ -739,34 +765,24 @@ , "mediaobject" , "orderedlist" , "para"+ , "part"+ , "partinfo" , "preface" , "procedure" , "programlisting"- , "qandadiv" , "question"- , "refsect1" , "refsect1info"- , "refsect2" , "refsect2info"- , "refsect3" , "refsect3info"- , "refsection" , "refsectioninfo" , "screen"- , "sect1" , "sect1info"- , "sect2" , "sect2info"- , "sect3" , "sect3info"- , "sect4" , "sect4info"- , "sect5" , "sect5info"- , "section" , "sectioninfo" , "simpara"- , "simplesect" , "substeps" , "subtitle" , "table"@@ -774,11 +790,20 @@ , "titleabbrev" , "toc" , "variablelist"- ] ++ admonitionTags+ ] ++ sectionTags ++ admonitionTags +sectionTags :: [Text]+sectionTags = ["bibliography", "bibliodiv"+ , "sect1", "sect2", "sect3", "sect4", "sect5", "section", "simplesect"+ , "refsect1", "refsect2", "refsect3", "refsection", "qandadiv"+ ]+ admonitionTags :: [Text] admonitionTags = ["caution","danger","important","note","tip","warning"] +titledBlockElements :: [Text]+titledBlockElements = ["example", "formalpara", "sidebar"]+ -- Trim leading and trailing newline characters trimNl :: Text -> Text trimNl = T.dropAround (== '\n')@@ -796,41 +821,47 @@ -- A DocBook mediaobject is a wrapper around a set of alternative presentations getMediaobject :: PandocMonad m => Element -> DB m Inlines getMediaobject e = do- figTitle <- gets dbFigureTitle- ident <- gets dbFigureId- (imageUrl, attr) <-- case filterElements (named "imageobject") e of- [] -> return (mempty, nullAttr)- (z:_) -> case filterChild (named "imagedata") z of- Nothing -> return (mempty, nullAttr)- Just i -> let atVal a = attrValue a i- w = case atVal "width" of- "" -> []- d -> [("width", d)]- h = case atVal "depth" of- "" -> []- d -> [("height", d)]- id' = case atVal "id" of- x | T.null x -> ident- | otherwise -> x- cs = T.words $ atVal "role"- atr = (id', cs, w ++ h)- in return (atVal "fileref", atr)- let getCaption el = case filterChild (\x -> named "caption" x+ let (imageUrl, tit, attr) =+ case filterElements (named "imageobject") e of+ [] -> (mempty, mempty, nullAttr)+ (z:_) ->+ let tit' = maybe "" strContent $+ filterChild (named "objectinfo") z >>=+ filterChild (named "title")+ (imageUrl', attr') =+ case filterChild (named "imagedata") z of+ Nothing -> (mempty, nullAttr)+ Just i -> let atVal a = attrValue a i+ w = case atVal "width" of+ "" -> []+ d -> [("width", d)]+ h = case atVal "depth" of+ "" -> []+ d -> [("height", d)]+ id' = atVal "id"+ cs = T.words $ atVal "role"+ atr = (id', cs, w ++ h)+ in (atVal "fileref", atr)+ in (imageUrl', tit', attr')+ let capt = case filterChild (\x -> named "caption" x || named "textobject" x- || named "alt" x) el of+ || named "alt" x) e of Nothing -> return mempty- Just z -> mconcat <$>+ Just z -> trimInlines . mconcat <$> mapM parseInline (elContent z)- let (capt, title) = if null figTitle- then (getCaption e, "")- else (return figTitle, "fig:")- fmap (imageWith attr imageUrl title) capt+ fmap (imageWith attr imageUrl tit) capt getBlocks :: PandocMonad m => Element -> DB m Blocks-getBlocks e = mconcat <$>- mapM parseBlock (elContent e)+getBlocks e = do+ modify (\st -> st{ dbElementStack = qName (elName e) : dbElementStack st })+ blocks <- mconcat <$> mapM parseBlock (elContent e)+ modify (\st -> st{ dbElementStack = drop 1 $ dbElementStack st })+ return blocks +getRoleAttr :: Element -> [(Text, Text)] -- extract role attribute and add it to the attribute list+getRoleAttr e = case attrValue "role" e of+ "" -> []+ r -> [("role", r)] parseBlock :: PandocMonad m => Content -> DB m Blocks parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE@@ -838,21 +869,15 @@ then return mempty else return $ plain $ trimInlines $ text s parseBlock (CRef x) = return $ plain $ str $ T.toUpper x-parseBlock (Elem e) =- case qName (elName e) of+parseBlock (Elem e) = do+ parsedBlock <- case qName (elName e) of "toc" -> skip -- skip TOC, since in pandoc it's autogenerated "index" -> skip -- skip index, since page numbers meaningless "para" -> parseMixed para (elContent e)- "formalpara" -> do- tit <- case filterChild (named "title") e of- Just t -> divWith ("",["formalpara-title"],[]) .- para . strong <$> getInlines t- Nothing -> return mempty- (tit <>) <$> parseMixed para (elContent e) "simpara" -> parseMixed para (elContent e) "ackno" -> parseMixed para (elContent e) "epigraph" -> parseBlockquote- "blockquote" -> parseBlockquote+ "blockquote" -> withOptionalTitle parseBlockquote "attribution" -> skip "titleabbrev" -> skip "authorinitials" -> skip@@ -865,7 +890,8 @@ "bibliomisc" -> parseMixed para (elContent e) "bibliomixed" -> parseMixed para (elContent e) "equation" -> para <$> equation e displayMath- "informalequation" -> para <$> equation e displayMath+ "informalequation" -> divWith (attrValue "id" e,["informalequation"],[]) .+ para <$> equation e displayMath "glosssee" -> para . (\ils -> text "See " <> ils <> str ".") <$> getInlines e "glossseealso" -> para . (\ils -> text "See also " <> ils <> str ".")@@ -876,6 +902,7 @@ "glosslist" -> definitionList <$> mapM parseGlossEntry (filterChildren (named "glossentry") e) "chapter" -> modify (\st -> st{ dbBook = True}) >> sect 0+ "part" -> modify (\st -> st{ dbBook = True}) >> sect (-1) "appendix" -> sect 0 "preface" -> sect 0 "bridgehead" -> para . strong <$> getInlines e@@ -892,7 +919,8 @@ "refsect2" -> sect 2 "refsect3" -> sect 3 "refsection" -> gets dbSectionLevel >>= sect . (+1)- l | l `elem` admonitionTags -> parseAdmonition l+ l | l `elem` titledBlockElements -> parseAdmonition False l+ l | l `elem` admonitionTags -> parseAdmonition True l "area" -> skip "areaset" -> skip "areaspec" -> skip@@ -900,9 +928,10 @@ "question" -> addToStart (strong (str "Q:") <> str " ") <$> getBlocks e "answer" -> addToStart (strong (str "A:") <> str " ") <$> getBlocks e "abstract" -> blockQuote <$> getBlocks e- "calloutlist" -> bulletList <$> callouts- "itemizedlist" -> bulletList . handleCompact <$> listitems- "orderedlist" -> do+ "calloutlist" -> withOptionalTitle $ bulletList <$> callouts+ "itemizedlist" -> withOptionalTitle $+ bulletList . handleCompact <$> listitems+ "orderedlist" -> withOptionalTitle $ do let listStyle = case attrValue "numeration" e of "arabic" -> Decimal "loweralpha" -> LowerAlpha@@ -910,13 +939,12 @@ "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- "procedure" -> bulletList <$> steps+ "procedure" -> orderedList <$> steps+ "substeps" -> orderedList <$> steps "figure" -> getFigure e "informalfigure" -> getFigure e "mediaobject" -> para <$> getMediaobject e@@ -934,6 +962,7 @@ "sect4info" -> skip -- keywords & other metadata "sect5info" -> skip -- keywords & other metadata "chapterinfo" -> skip -- keywords & other metadata+ "partinfo" -> skip -- keywords & other metadata "glossaryinfo" -> skip -- keywords & other metadata "appendixinfo" -> skip -- keywords & other metadata "bookinfo" -> addMetadataFromElement e@@ -946,13 +975,16 @@ "informalexample" -> divWith ("", ["informalexample"], []) <$> getBlocks e "linegroup" -> lineBlock <$> lineItems- "literallayout" -> codeBlockWithLang+ "literallayout" -> literalLayout "screen" -> codeBlockWithLang "programlisting" -> codeBlockWithLang "?xml" -> return mempty "title" -> return mempty -- handled in parent element "subtitle" -> return mempty -- handled in parent element _ -> skip >> getBlocks e+ if qName (elName e) `elem` sectionTags+ then return parsedBlock+ else return $ addPandocAttributes (getRoleAttr e) parsedBlock where skip = do let qn = qName $ elName e let name = if "pi-" `T.isPrefixOf` qn@@ -961,6 +993,7 @@ lift $ report $ IgnoredElement name return mempty + compactSpacing = case attrValue "spacing" e of "compact" -> True _ -> False@@ -969,6 +1002,17 @@ then map (fmap paraToPlain) else id + literalLayout+ | "monospaced" `elem` (T.words (attrValue "class" e))+ = codeBlockWithLang+ | otherwise = do+ oldLiteralLayout <- gets dbLiteralLayout+ modify $ \st -> st{ dbLiteralLayout = True }+ content <- mconcat <$> mapM parseInline (elContent e)+ let ls = map fromList . splitWhen (== LineBreak) . toList $ content+ modify $ \st -> st{ dbLiteralLayout = oldLiteralLayout }+ return $ lineBlock ls+ codeBlockWithLang = do let classes' = case attrValue "language" e of "" -> []@@ -1002,6 +1046,11 @@ items' <- mapM getBlocks items return (mconcat $ intersperse (str "; ") terms', items') parseTable = do+ let elId = attrValue "id" e+ let attrs = case attrValue "tabstyle" e of+ "" -> []+ x -> [("custom-style", x)]+ let classes = T.words $ attrValue "class" e let isCaption x = named "title" x || named "caption" x capt <- case filterChild isCaption e of Just t -> getInlines t@@ -1016,9 +1065,8 @@ cs -> mapMaybe (findAttr (unqual "colname" )) cs let isRow x = named "row" x || named "tr" x headrows <- case filterChild (named "thead") e' of- Just h -> case filterChild isRow h of- Just x -> parseRow colnames x- Nothing -> return []+ Just h -> mapM (parseRow colnames)+ $ filterChildren isRow h Nothing -> return [] bodyrows <- case filterChild (named "tbody") e' of Just b -> mapM (parseRow colnames)@@ -1032,7 +1080,7 @@ || x == '.') w if n > 0 then Just n else Nothing let numrows = maybe 0 maximum $ nonEmpty- $ map length bodyrows+ $ map length (bodyrows ++ headrows) let aligns = case colspecs of [] -> replicate numrows AlignDefault cs -> map toAlignment cs@@ -1054,10 +1102,10 @@ in ColWidth . scale <$> ws' Nothing -> replicate numrows ColWidthDefault let toRow = Row nullAttr- toHeaderRow l = [toRow l | not (null l)]- return $ table (simpleCaption $ plain capt)+ 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@@ -1072,7 +1120,10 @@ modify $ \st -> st{ dbSectionLevel = n } b <- getBlocks e modify $ \st -> st{ dbSectionLevel = n - 1 }- return $ headerWith (elId, classes, maybeToList titleabbrevElAsAttr++attrs) n' headerText <> b+ let hdr = addPandocAttributes (getRoleAttr e)+ $ headerWith (elId, classes, maybeToList titleabbrevElAsAttr ++ attrs)+ n' headerText+ return $ hdr <> b titleabbrevElAsAttr = case filterChild (named "titleabbrev") e `mplus` (filterChild (named "info") e >>=@@ -1080,22 +1131,37 @@ Just t -> Just ("titleabbrev", strContentRecursive t) Nothing -> Nothing lineItems = mapM getInlines $ filterChildren (named "line") e++ -- <title> elements can be directly nested inside an admonition block, use+ -- it if it's there. It is unclear whether we should include the label in+ -- the title: docbook references are ambiguous on that, and some implementations of admonitions+ -- (e.g. asciidoctor) just use an icon in all cases. To be conservative, we don't+ -- include the label and leave it to styling.+ --+ getTitle = case filterChild (named "title") e of+ Just t -> Just <$> getInlines t+ Nothing -> return Nothing+ withOptionalTitle p = do+ mbt <- getTitle+ b <- p+ case mbt of+ Nothing -> return b+ Just t -> return $ divWith (attrValue "id" e, [], getRoleAttr e)+ (divWith ("", ["title"], []) (plain t) <> b)+ -- Admonitions are parsed into a div. Following other Docbook tools that output HTML, -- we parse the optional title as a div with the @title@ class, and give the -- block itself a class corresponding to the admonition name.- parseAdmonition label = do- -- <title> elements can be directly nested inside an admonition block, use- -- it if it's there. It is unclear whether we should include the label in- -- the title: docbook references are ambiguous on that, and some implementations of admonitions- -- (e.g. asciidoctor) just use an icon in all cases. To be conservative, we don't- -- include the label and leave it to styling.- title <- case filterChild (named "title") e of- Just t -> divWith ("", ["title"], []) . plain <$> getInlines t- Nothing -> return mempty- -- this will ignore the title element if it is present+ parseAdmonition alwaysIncludeTitle label = do+ mbt <- getTitle+ -- this will ignore the title element if it is present: b <- getBlocks e+ let t = maybe mempty (divWith ("", ["title"], []) . plain)+ (case mbt of+ Nothing | alwaysIncludeTitle -> Just mempty+ _ -> mbt) -- we also attach the label as a class, so it can be styled properly- return $ divWith (attrValue "id" e,[label],[]) (title <> b)+ return $ divWith (attrValue "id" e,[label],[]) (t <> b) toAlignment :: Element -> Alignment toAlignment c = case findAttr (unqual "align") c of@@ -1119,7 +1185,7 @@ parseRow :: PandocMonad m => [Text] -> Element -> DB m [Cell] parseRow cn = do- let isEntry x = named "entry" x || named "td" x || named "th" x+ let isEntry x = named "entry" x || named "td" x || named "th" x mapM (parseEntry cn) . filterChildren isEntry parseEntry :: PandocMonad m => [Text] -> Element -> DB m Cell@@ -1136,9 +1202,18 @@ case (mStrt, mEnd) of (Just start, Just end) -> colDistance start end _ -> 1+ let rowDistance mr = do+ case readMaybe $ T.unpack mr :: Maybe Int of+ Just moreRow -> RowSpan $ moreRow + 1+ _ -> 1+ let toRowSpan en = do+ case findAttr (unqual "morerows") en of+ Just moreRow -> rowDistance moreRow+ _ -> 1 let colSpan = toColSpan el+ let rowSpan = toRowSpan el let align = toAlignment el- (fmap (cell align 1 colSpan) . parseMixed plain . elContent) el+ (fmap (cell align rowSpan colSpan) . parseMixed plain . elContent) el getInlines :: PandocMonad m => Element -> DB m Inlines getInlines e' = trimInlines . mconcat <$>@@ -1164,11 +1239,18 @@ _ -> Just (n, attrValue n e) parseInline :: PandocMonad m => Content -> DB m Inlines-parseInline (Text (CData _ s _)) = return $ text s+parseInline (Text (CData _ s _)) = do+ literalLayout <- gets dbLiteralLayout+ if literalLayout+ then do+ let ls = T.splitOn "\n" s+ let toLiteralLine = str . T.map (\c -> if c == ' ' then '\xa0' else c)+ return $ mconcat $ intersperse linebreak $ map toLiteralLine ls+ else return $ text s parseInline (CRef ref) =- return $ text $ maybe (T.toUpper ref) T.pack $ lookupEntity (T.unpack ref)-parseInline (Elem e) =- case qName (elName e) of+ return $ text $ fromMaybe (T.toUpper ref) $ lookupEntity ref+parseInline (Elem e) = do+ parsedInline <- case qName (elName e) of "anchor" -> do return $ spanWith (attrValue "id" e, [], []) mempty "phrase" -> do@@ -1265,7 +1347,10 @@ "ulink" -> innerInlines (link (attrValue "url" e) "") "link" -> do ils <- innerInlines id- let href = case findAttr (QName "href" (Just "http://www.w3.org/1999/xlink") Nothing) e of+ let href = case findAttrBy+ (\case+ QName "href" _ _ -> True+ _ -> False) e of Just h -> h _ -> "#" <> attrValue "linkend" e let ils' = if ils == mempty then str href else ils@@ -1273,9 +1358,11 @@ return $ linkWith attr href "" ils' "foreignphrase" -> innerInlines emph "emphasis" -> case attrValue "role" e of+ "bf" -> innerInlines strong "bold" -> innerInlines strong "strong" -> innerInlines strong "strikethrough" -> innerInlines strikeout+ "underline" -> innerInlines underline _ -> innerInlines emph "footnote" -> note . mconcat <$> mapM parseBlock (elContent e)@@ -1285,6 +1372,9 @@ -- <?asciidor-br?> to in handleInstructions, above. "pi-asciidoc-br" -> return linebreak _ -> skip >> innerInlines id+ return $ case qName (elName e) of+ "emphasis" -> parsedInline+ _ -> addPandocAttributes (getRoleAttr e) parsedInline where skip = do let qn = qName $ elName e let name = if "pi-" `T.isPrefixOf` qn@@ -1293,8 +1383,7 @@ lift $ report $ IgnoredElement name return mempty - innerInlines f = extractSpaces f . mconcat <$>- mapM parseInline (elContent e)+ innerInlines f = f . mconcat <$> mapM parseInline (elContent e) codeWithLang = do let classes' = case attrValue "language" e of "" -> []@@ -1333,6 +1422,8 @@ xrefTitleByElem el | not (T.null xrefLabel) = xrefLabel | otherwise = case qName (elName el) of+ "book" -> descendantContent "title" el+ "part" -> descendantContent "title" el "chapter" -> descendantContent "title" el "section" -> descendantContent "title" el "sect1" -> descendantContent "title" el@@ -1343,6 +1434,7 @@ "cmdsynopsis" -> descendantContent "command" el "funcsynopsis" -> descendantContent "function" el "figure" -> descendantContent "title" el+ "table" -> descendantContent "title" el _ -> qName (elName el) <> "_title" where xrefLabel = attrValue "xreflabel" el
@@ -2,6 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Readers.Docx@@ -23,7 +24,7 @@ - [X] Para - [X] CodeBlock (styled with `SourceCode`)- - [X] BlockQuote (styled with `Quote`, `BlockQuote`, or, optionally,+ - [X] BlockQuote (styled with `Quote`, `BlockQuote`, `Intense Quote` or, optionally, indented) - [X] OrderedList - [X] BulletList@@ -59,20 +60,30 @@ ) where import Codec.Archive.Zip+import Control.Monad ( liftM, unless ) import Control.Monad.Reader+ ( asks,+ MonadReader(local),+ MonadTrans(lift),+ ReaderT(runReaderT) ) import Control.Monad.State.Strict+ ( StateT,+ gets,+ modify,+ evalStateT ) import Data.Bifunctor (bimap, first) import qualified Data.ByteString.Lazy as B import Data.Default (Default)-import Data.List (delete, intersect, foldl')+import Data.List (delete, intersect)+import qualified Data.List as L import Data.Char (isSpace) import qualified Data.Map as M import qualified Data.Text as T-import Data.Maybe (catMaybes, isJust, fromMaybe, mapMaybe)+import Data.Maybe (isJust, fromMaybe, mapMaybe) import Data.Sequence (ViewL (..), viewl) import qualified Data.Sequence as Seq import qualified Data.Set as Set-import Citeproc (ItemId(..), Reference(..), CitationItem(..))+import Citeproc (ItemId(..), Val(TextVal,FancyVal), Reference(..), CitationItem(..)) import qualified Citeproc import Text.Pandoc.Builder as Pandoc import Text.Pandoc.MediaBag (MediaBag)@@ -83,7 +94,7 @@ import Text.Pandoc.Shared import Text.Pandoc.Walk import Text.TeXMath (writeTeX)-import Control.Monad.Except (throwError)+import Control.Monad.Except (throwError, catchError) import Text.Pandoc.Class.PandocMonad (PandocMonad) import qualified Text.Pandoc.Class.PandocMonad as P import Text.Pandoc.Error@@ -94,7 +105,6 @@ import Text.Pandoc.UTF8 (fromTextLazy) import Text.Pandoc.Citeproc.MetaValue (referenceToMetaValue) import Text.Pandoc.Readers.EndNote (readEndNoteXMLCitation)-import Text.Pandoc.Sources (toSources) readDocx :: PandocMonad m => ReaderOptions@@ -117,12 +127,12 @@ , docxAnchorSet :: Set.Set T.Text , docxImmedPrevAnchor :: Maybe T.Text , docxMediaBag :: MediaBag+ , docxNumberedHeadings :: Bool , docxDropCap :: Inlines -- keep track of (numId, lvl) values for -- restarting , docxListState :: M.Map (T.Text, T.Text) Integer , docxPrevPara :: Inlines- , docxTableCaptions :: [Blocks] , docxReferences :: M.Map ItemId (Reference Inlines) } @@ -131,10 +141,10 @@ , docxAnchorSet = mempty , docxImmedPrevAnchor = Nothing , docxMediaBag = mempty+ , docxNumberedHeadings = False , docxDropCap = mempty , docxListState = M.empty , docxPrevPara = mempty- , docxTableCaptions = [] , docxReferences = mempty } @@ -192,6 +202,8 @@ inlines <- smushInlines <$> mapM parPartToInlines parParts remaining <- bodyPartsToMeta' bps let+ -- for titles, we just take the first one and ignore the rest, #10359:+ f _ x | metaField == "title" || metaField == "subtitle" = x f (MetaInlines ils) (MetaInlines ils') = MetaBlocks [Para ils, Para ils'] f (MetaInlines ils) (MetaBlocks blks) = MetaBlocks (Para ils : blks) f m (MetaList mv) = MetaList (m : mv)@@ -233,7 +245,7 @@ isBlockQuote :: ParStyle -> Bool isBlockQuote = isInheritedFromStyles [- "Quote", "Block Text", "Block Quote", "Block Quotation"+ "Quote", "Block Text", "Block Quote", "Block Quotation", "Intense Quote" ] runElemToInlines :: RunElem -> Inlines@@ -294,6 +306,9 @@ emph . go rPr{isItalic = Nothing, isItalicCTL = Nothing} | Just True <- bold rPr = strong . go rPr{isBold = Nothing, isBoldCTL = Nothing}+ | Just v <- rHighlight rPr+ , v /= "none" =+ spanWith ("",["mark"],[]) . go rPr{rHighlight = Nothing} | Just True <- isSmallCaps rPr = smallcaps . go rPr{isSmallCaps = Nothing} | Just True <- isStrike rPr =@@ -344,9 +359,10 @@ blocksToInlinesWarn :: PandocMonad m => T.Text -> Blocks -> DocxContext m Inlines blocksToInlinesWarn cmtId blks = do let paraOrPlain :: Block -> Bool- paraOrPlain (Para _) = True- paraOrPlain (Plain _) = True- paraOrPlain _ = False+ paraOrPlain (Para _) = True+ paraOrPlain (Plain _) = True+ paraOrPlain (Div _ nested) = all paraOrPlain nested+ paraOrPlain _ = False unless (all paraOrPlain blks) $ lift $ P.report $ DocxParserWarning $ "Docx comment " <> cmtId <> " will not retain formatting"@@ -372,22 +388,22 @@ parPartToInlines' :: PandocMonad m => ParPart -> DocxContext m Inlines parPartToInlines' (PlainRun r) = runToInlines r-parPartToInlines' (ChangedRuns (TrackedChange Insertion (ChangeInfo _ author date)) runs) = do+parPartToInlines' (ChangedRuns (TrackedChange Insertion (ChangeInfo _ author date)) pparts) = do opts <- asks docxOptions case readerTrackChanges opts of- AcceptChanges -> smushInlines <$> mapM runToInlines runs+ AcceptChanges -> smushInlines <$> mapM parPartToInlines pparts RejectChanges -> return mempty AllChanges -> do- ils <- smushInlines <$> mapM runToInlines runs+ ils <- smushInlines <$> mapM parPartToInlines pparts let attr = ("", ["insertion"], addAuthorAndDate author date) return $ spanWith attr ils-parPartToInlines' (ChangedRuns (TrackedChange Deletion (ChangeInfo _ author date)) runs) = do+parPartToInlines' (ChangedRuns (TrackedChange Deletion (ChangeInfo _ author date)) pparts) = do opts <- asks docxOptions case readerTrackChanges opts of AcceptChanges -> return mempty- RejectChanges -> smushInlines <$> mapM runToInlines runs+ RejectChanges -> smushInlines <$> mapM parPartToInlines pparts AllChanges -> do- ils <- smushInlines <$> mapM runToInlines runs+ ils <- smushInlines <$> mapM parPartToInlines pparts let attr = ("", ["deletion"], addAuthorAndDate author date) return $ spanWith attr ils parPartToInlines' (CommentStart cmtId author date bodyParts) = do@@ -426,11 +442,10 @@ -- avoid an extra pass. immedPrevAnchor <- gets docxImmedPrevAnchor case immedPrevAnchor of- Just prevAnchor -> do- unless inHdrBool- (modify $ \s -> s { docxAnchorMap = M.insert anchor prevAnchor anchorMap})+ Just prevAnchor | not inHdrBool -> do+ (modify $ \s -> s { docxAnchorMap = M.insert anchor prevAnchor anchorMap}) return mempty- Nothing -> do+ _ -> do exts <- asks (readerExtensions . docxOptions) let newAnchor = if not inHdrBool && anchor `elem` M.elems anchorMap@@ -455,18 +470,34 @@ return $ link target "" ils parPartToInlines' (PlainOMath exps) = return $ math $ writeTeX exps+parPartToInlines' (OMathPara exps) =+ return $ displayMath $ writeTeX exps parPartToInlines' (Field info children) = case info of HyperlinkField url -> parPartToInlines' $ ExternalHyperLink url children+ IndexrefField ie ->+ pure $ spanWith ("",["indexref"],+ (("entry", entryTitle ie) :+ maybe [] (\x -> [("crossref",x)]) (entrySee ie)+ ++ maybe [] (\x -> [("yomi",x)]) (entryYomi ie)+ ++ [("bold","") | entryBold ie]+ ++ [("italic","") | entryItalic ie])) mempty PagerefField fieldAnchor True -> parPartToInlines' $ InternalHyperLink fieldAnchor children+ CrossrefField fieldAnchor True -> parPartToInlines' $ InternalHyperLink fieldAnchor children EndNoteCite t -> do formattedCite <- smushInlines <$> mapM parPartToInlines' children opts <- asks docxOptions if isEnabled Ext_citations opts- then do- citation <- readEndNoteXMLCitation (toSources t)- cs <- handleCitation citation- return $ cite cs formattedCite+ then catchError+ (do citation <- readEndNoteXMLCitation t+ cs <- handleCitation citation+ return $ cite cs formattedCite)+ (\case+ PandocXMLError _ msg -> do+ P.report $ DocxParserWarning+ ("Cannot parse EndNote citation: " <> msg)+ return formattedCite+ e -> throwError e) else return formattedCite CslCitation t -> do formattedCite <- smushInlines <$> mapM parPartToInlines' children@@ -492,14 +523,26 @@ else smushInlines <$> mapM parPartToInlines' children _ -> smushInlines <$> mapM parPartToInlines' children +-- Helper function to convert CitationItemType to CitationMode+convertCitationMode :: Citeproc.CitationItemType -> CitationMode+convertCitationMode itemType = case itemType of+ Citeproc.NormalCite -> NormalCitation+ Citeproc.SuppressAuthor -> SuppressAuthor+ Citeproc.AuthorOnly -> AuthorInText+ -- Turn a 'Citeproc.Citation' into a list of 'Text.Pandoc.Definition.Citation', -- and store the embedded bibliographic data in state. handleCitation :: PandocMonad m => Citeproc.Citation T.Text -> DocxContext m [Citation] handleCitation citation = do+ let getItemId item =+ case citationItemData item >>= M.lookup "citation-key" . referenceVariables of+ Just (TextVal k) -> ItemId k+ Just (FancyVal k) -> ItemId k+ _ -> citationItemId item let toPandocCitation item =- Citation{ citationId = unItemId (Citeproc.citationItemId item)+ Citation{ citationId = unItemId (getItemId item) , citationPrefix = maybe [] (toList . text) $ Citeproc.citationItemPrefix item , citationSuffix = (toList . text) $@@ -508,13 +551,16 @@ <> x <> " ") (Citeproc.citationItemLocator item) <> fromMaybe mempty (Citeproc.citationItemSuffix item)- , citationMode = NormalCitation -- TODO for now+ , citationMode = convertCitationMode (Citeproc.citationItemType item) , citationNoteNum = 0 , citationHash = 0 } let items = Citeproc.citationItems citation let cs = map toPandocCitation items- refs <- mapM (traverse (return . text)) $- mapMaybe Citeproc.citationItemData items+ let refs = mapMaybe (\item -> fmap (\itemData -> text <$>+ -- see #10366, sometimes itemData has a different+ -- id and we need to use the same one:+ itemData{ referenceId = getItemId item })+ (Citeproc.citationItemData item)) items modify $ \st -> st{ docxReferences = foldr (\ref -> M.insert (referenceId ref) ref)@@ -522,7 +568,6 @@ refs } return cs - isAnchorSpan :: Inline -> Bool isAnchorSpan (Span (_, ["anchor"], []) _) = True isAnchorSpan _ = False@@ -570,10 +615,11 @@ singleParaToPlain blks = blks cellToCell :: PandocMonad m => RowSpan -> Docx.Cell -> DocxContext m Pandoc.Cell-cellToCell rowSpan (Docx.Cell gridSpan _ bps) = do+cellToCell rowSpan (Docx.Cell align gridSpan _ bps) = do blks <- smushBlocks <$> mapM bodyPartToBlocks bps let blks' = singleParaToPlain $ fromList $ blocksToDefinitions $ blocksToBullets $ toList blks- return (cell AlignDefault rowSpan (ColSpan (fromIntegral gridSpan)) blks')+ return (cell (convertAlign align)+ rowSpan (ColSpan (fromIntegral gridSpan)) blks') rowsToRows :: PandocMonad m => [Docx.Row] -> DocxContext m [Pandoc.Row] rowsToRows rows = do@@ -584,8 +630,8 @@ splitHeaderRows :: Bool -> [Docx.Row] -> ([Docx.Row], [Docx.Row]) splitHeaderRows hasFirstRowFormatting rs = bimap reverse reverse $ fst $ if hasFirstRowFormatting- then foldl' f ((take 1 rs, []), True) (drop 1 rs)- else foldl' f (([], []), False) rs+ then L.foldl' f ((take 1 rs, []), True) (drop 1 rs)+ else L.foldl' f (([], []), False) rs where f ((headerRows, bodyRows), previousRowWasHeader) r@(Docx.Row h cs) | h == HasTblHeader || (previousRowWasHeader && any isContinuationCell cs)@@ -593,7 +639,7 @@ | otherwise = ((headerRows, r : bodyRows), False) - isContinuationCell (Docx.Cell _ vm _) = vm == Docx.Continue+ isContinuationCell (Docx.Cell _ _ vm _) = vm == Docx.Continue -- like trimInlines, but also take out linebreaks@@ -609,10 +655,10 @@ paragraphStyleToTransform :: PandocMonad m => ParagraphStyle -> DocxContext m (Blocks -> Blocks) paragraphStyleToTransform pPr =- let stylenames = map getStyleName (pStyle pPr)- transform = if (`elem` listParagraphStyles) `any` stylenames || relativeIndent pPr <= 0- then id- else blockQuote+ let transform = if relativeIndent pPr > 0 && not (numbered pPr) &&+ not (any ((`elem` listParagraphStyles) . getStyleName) (pStyle pPr))+ then blockQuote+ else id in do extStylesEnabled <- asks (isEnabled Ext_styles . docxOptions) return $ foldr (\parStyle transform' ->@@ -643,12 +689,35 @@ where go c | isSpace c = '-' | otherwise = c -bodyPartToTableCaption :: PandocMonad m => BodyPart -> DocxContext m (Maybe Blocks)-bodyPartToTableCaption (TblCaption pPr parparts) =- Just <$> bodyPartToBlocks (Paragraph pPr parparts)-bodyPartToTableCaption _ = pure Nothing- bodyPartToBlocks :: PandocMonad m => BodyPart -> DocxContext m Blocks+bodyPartToBlocks (Heading n style pPr numId lvl mblvlInfo parparts) = do+ ils <- local (\s-> s{docxInHeaderBlock=True})+ (smushInlines <$> mapM parPartToInlines parparts)+ let classes = map normalizeToClassName . delete style+ $ getStyleNames (pStyle pPr)+ hasNumbering <- gets docxNumberedHeadings+ let addNum = if hasNumbering && not (numbered pPr)+ then (++ ["unnumbered"])+ else id+ if T.null numId+ then pure ()+ else do+ -- We check whether this current numId has previously been used,+ -- since Docx expects us to pick up where we left off.+ listState <- gets docxListState+ let start = case M.lookup (numId, lvl) listState of+ Nothing -> case mblvlInfo of+ Nothing -> 1+ Just (Level _ _ _ z) -> fromMaybe 1 z+ Just z -> z + 1+ modify $ \st -> st{ docxListState =+ -- expire all the continuation data for lists of level > this one:+ -- a new level 1 list item resets continuation for level 2++ -- see #10258+ let notExpired (_, lvl') _ = lvl' <= lvl+ in M.insert (numId, lvl) start+ (M.filterWithKey notExpired listState) }+ makeHeaderAnchor $ headerWith ("", addNum classes, []) n ils bodyPartToBlocks (Paragraph pPr parparts) | Just True <- pBidi pPr = do let pPr' = pPr { pBidi = Nothing }@@ -661,11 +730,6 @@ codeBlock $ T.concat $ map parPartToText parparts- | Just (style, n) <- pHeading pPr = do- ils <-local (\s-> s{docxInHeaderBlock=True})- (smushInlines <$> mapM parPartToInlines parparts)- makeHeaderAnchor $- headerWith ("", map normalizeToClassName . delete style $ getStyleNames (pStyle pPr), []) n ils | otherwise = do ils <- trimSps . smushInlines <$> mapM parPartToInlines parparts prevParaIls <- gets docxPrevPara@@ -739,42 +803,58 @@ let pPr' = pPr {pStyle = constructBogusParStyleData "list-paragraph": pStyle pPr} in bodyPartToBlocks $ Paragraph pPr' parparts-bodyPartToBlocks (TblCaption _ _) =- return $ para mempty -- collected separately-bodyPartToBlocks (Tbl _ _ _ []) =- return $ para mempty-bodyPartToBlocks (Tbl cap grid look parts) = do- captions <- gets docxTableCaptions- fullCaption <- case captions of- c : cs -> do- modify (\s -> s { docxTableCaptions = cs })- return c- [] -> return $ if T.null cap then mempty else plain (text cap)+bodyPartToBlocks (Captioned parstyle parparts bpart) = do+ bs <- bodyPartToBlocks bpart+ captContents <- bodyPartToBlocks (Paragraph parstyle parparts)+ let capt = Caption Nothing (toList captContents)+ let toCaptioned attr' bls = case bls of+ [Table attr _cap colspecs thead tbodies tfoot]+ -> singleton $ Table (attr <> attr') capt colspecs thead tbodies tfoot+ [Figure attr _cap blks]+ -> singleton $ Figure (attr <> attr') capt blks+ [Para im@[Image{}]]+ -> singleton $ Figure attr' capt [Plain im]+ [Div attr bls']+ -> toCaptioned (attr <> attr') bls'+ [BlockQuote bls']+ -> toCaptioned attr' bls'+ _ -> captContents+ pure $ toCaptioned nullAttr (toList bs)+bodyPartToBlocks (Tbl _ _ _ _ []) =+ return mempty+bodyPartToBlocks (Tbl mbsty cap grid look parts) = do+ let fullCaption = if T.null cap then mempty else plain (text cap) let shortCaption = if T.null cap then Nothing else Just (toList (text cap)) cap' = caption shortCaption fullCaption (hdr, rows) = splitHeaderRows (firstRowFormatting look) parts let width = maybe 0 maximum $ nonEmpty $ map rowLength parts rowLength :: Docx.Row -> Int- rowLength (Docx.Row _ c) = sum (fmap (\(Docx.Cell gridSpan _ _) -> fromIntegral gridSpan) c)+ rowLength (Docx.Row _ c) = sum (fmap (\(Docx.Cell _ gridSpan _ _) -> fromIntegral gridSpan) c) headerCells <- rowsToRows hdr bodyCells <- rowsToRows rows - -- Horizontal column alignment goes to the default at the moment. Getting- -- it might be difficult, since there doesn't seem to be a column entity- -- in docx.- let alignments = replicate width AlignDefault- totalWidth = sum grid- widths = (\w -> ColWidth (fromInteger w / fromInteger totalWidth)) <$> grid+ -- Horizontal column alignment is taken from the first row's cells.+ let getAlignment (Docx.Cell al colspan _ _) = replicate (fromIntegral colspan)+ $ convertAlign al+ alignments = case rows of+ [] -> replicate width Pandoc.AlignDefault+ Docx.Row _ cs : _ -> concatMap getAlignment cs+ widths = map (\n -> if n == 0+ then ColWidthDefault+ else ColWidth n) grid - return $ table cap'+ extStylesEnabled <- asks (isEnabled Ext_styles . docxOptions)+ let attr = case mbsty of+ Just sty | extStylesEnabled -> ("", [], [("custom-style", sty)])+ _ -> nullAttr+ return $ tableWith attr cap' (zip alignments widths) (TableHead nullAttr headerCells) [TableBody nullAttr 0 [] bodyCells] (TableFoot nullAttr [])-bodyPartToBlocks (OMathPara e) =- return $ para $ displayMath (writeTeX e)+bodyPartToBlocks HRule = pure Pandoc.horizontalRule -- replace targets with generated anchors. rewriteLink' :: PandocMonad m => Inline -> DocxContext m Inline@@ -811,8 +891,9 @@ bodyToOutput (Body bps) = do let (metabps, blkbps) = sepBodyParts bps meta <- bodyPartsToMeta metabps- captions <- catMaybes <$> mapM bodyPartToTableCaption blkbps- modify (\s -> s { docxTableCaptions = captions })+ let isNumberedPara (Paragraph pPr _) = numbered pPr+ isNumberedPara _ = False+ modify (\s -> s { docxNumberedHeadings = any isNumberedPara blkbps }) blks <- smushBlocks <$> mapM bodyPartToBlocks blkbps blks' <- rewriteLinks $ blocksToDefinitions $ blocksToBullets $ toList blks blks'' <- removeOrphanAnchors blks'@@ -833,3 +914,10 @@ addAuthorAndDate :: T.Text -> Maybe T.Text -> [(T.Text, T.Text)] addAuthorAndDate author mdate = ("author", author) : maybe [] (\date -> [("date", date)]) mdate++convertAlign :: Docx.Align -> Pandoc.Alignment+convertAlign al = case al of+ Docx.AlignDefault -> Pandoc.AlignDefault+ Docx.AlignLeft -> Pandoc.AlignLeft+ Docx.AlignCenter -> Pandoc.AlignCenter+ Docx.AlignRight -> Pandoc.AlignRight
@@ -2,7 +2,7 @@ {- | Module : Text.Pandoc.Readers.Docx.Combine Copyright : © 2014-2020 Jesse Rosenthal <jrosenthal@jhu.edu>,- 2014-2022 John MacFarlane <jgm@berkeley.edu>,+ 2014-2024 John MacFarlane <jgm@berkeley.edu>, 2020 Nikolay Yakimov <root@livid.pp.ru> License : GNU GPL, version 2 or above @@ -52,12 +52,13 @@ -} -module Text.Pandoc.Readers.Docx.Combine ( smushInlines+module Text.Pandoc.Readers.Docx.Combine ( combineBlocks+ , smushInlines , smushBlocks ) where -import Data.List+import qualified Data.List as L import Data.Bifunctor import Data.Sequence ( ViewL (..), ViewR (..), viewl, viewr, spanr, spanl , (><), (|>) )@@ -135,9 +136,9 @@ combineSingletonInlines x y = let (xfs, xs) = unstackInlines x (yfs, ys) = unstackInlines y- shared = xfs `intersect` yfs- x_remaining = xfs \\ shared- y_remaining = yfs \\ shared+ shared = xfs `L.intersect` yfs+ x_remaining = xfs L.\\ shared+ y_remaining = yfs L.\\ shared x_rem_attr = filter isAttrModifier x_remaining y_rem_attr = filter isAttrModifier y_remaining in@@ -182,7 +183,7 @@ smushInlines :: [Inlines] -> Inlines smushInlines xs = combineInlines xs' mempty- where xs' = foldl' combineInlines mempty xs+ where xs' = L.foldl' combineInlines mempty xs smushBlocks :: [Blocks] -> Blocks-smushBlocks xs = foldl' combineBlocks mempty xs+smushBlocks xs = L.foldl' combineBlocks mempty xs
@@ -12,20 +12,31 @@ ECMA-376-1:2016, §17.16.5 -} module Text.Pandoc.Readers.Docx.Fields ( FieldInfo(..)+ , IndexEntry(..) , parseFieldInfo ) where import Data.Functor (($>), void) import qualified Data.Text as T-import Text.Parsec-import Text.Parsec.Text (Parser)+import Text.Pandoc.Parsing+import Data.Maybe (isJust) type URL = T.Text type Anchor = T.Text +data IndexEntry = IndexEntry+ { entryTitle :: T.Text+ , entrySee :: Maybe T.Text+ , entryYomi :: Maybe T.Text+ , entryBold :: Bool+ , entryItalic :: Bool }+ deriving (Show)+ data FieldInfo = HyperlinkField URL -- The boolean indicates whether the field is a hyperlink. | PagerefField Anchor Bool+ | CrossrefField Anchor Bool+ | IndexrefField IndexEntry | CslCitation T.Text | CslBibliography | EndNoteCite T.Text@@ -33,30 +44,35 @@ | UnknownField deriving (Show) +type Parser = Parsec T.Text ()+ parseFieldInfo :: T.Text -> Either ParseError FieldInfo parseFieldInfo = parse fieldInfo "" fieldInfo :: Parser FieldInfo-fieldInfo =- try (HyperlinkField <$> hyperlink)- <|>- try ((uncurry PagerefField) <$> pageref)- <|>- try addIn- <|>- return UnknownField+fieldInfo = do+ spaces+ hyperlink+ <|>+ pageref+ <|>+ indexref+ <|>+ crossref+ <|>+ addIn+ <|>+ return UnknownField addIn :: Parser FieldInfo addIn = do- spaces string "ADDIN" spaces try cslCitation <|> cslBibliography <|> endnoteCite <|> endnoteRefList cslCitation :: Parser FieldInfo cslCitation = do- optional (string "ZOTERO_ITEM")- spaces+ optional (string "ZOTERO_ITEM" *> spaces) string "CSL_CITATION" spaces CslCitation <$> getInput@@ -94,44 +110,58 @@ unquotedString = T.pack <$> manyTill anyChar (try $ void (lookAhead space) <|> eof) fieldArgument :: Parser T.Text-fieldArgument = quotedString <|> unquotedString---- there are other switches, but this is the only one I've seen in the wild so far, so it's the first one I'll implement. See §17.16.5.25-hyperlinkSwitch :: Parser (T.Text, T.Text)-hyperlinkSwitch = do- sw <- string "\\l"- spaces- farg <- fieldArgument- return (T.pack sw, farg)+fieldArgument = do+ notFollowedBy (char '\\') -- switch+ quotedString <|> unquotedString -hyperlink :: Parser URL+hyperlink :: Parser FieldInfo hyperlink = do- many space string "HYPERLINK" spaces- farg <- fieldArgument- switches <- spaces *> many hyperlinkSwitch- let url = case switches of- ("\\l", s) : _ -> farg <> "#" <> s- _ -> farg- return url+ farg <- option "" $ notFollowedBy (char '\\') *> fieldArgument+ switches <- many fieldSwitch+ let url = case [s | ('l',s) <- switches] of+ [s] -> farg <> "#" <> s+ _ -> farg+ return $ HyperlinkField url -- See §17.16.5.45-pagerefSwitch :: Parser (T.Text, T.Text)-pagerefSwitch = do- sw <- string "\\h"+fieldSwitch :: Parser (Char, T.Text)+fieldSwitch = try $ do spaces- farg <- fieldArgument- return (T.pack sw, farg)+ char '\\'+ c <- anyChar+ spaces+ farg <- option mempty fieldArgument+ return (c, farg) -pageref :: Parser (Anchor, Bool)+pageref :: Parser FieldInfo pageref = do- many space string "PAGEREF" spaces farg <- fieldArgument- switches <- spaces *> many pagerefSwitch- let isLink = case switches of- ("\\h", _) : _ -> True - _ -> False- return (farg, isLink)+ switches <- many fieldSwitch+ let isLink = any ((== 'h') . fst) switches+ return $ PagerefField farg isLink++crossref :: Parser FieldInfo+crossref = do+ string "REF"+ spaces+ farg <- fieldArgument+ switches <- many fieldSwitch+ let isLink = any ((== 'h') . fst) switches+ return $ CrossrefField farg isLink++-- second element of tuple is optional "see".+indexref :: Parser FieldInfo+indexref = do+ string "XE"+ spaces+ farg <- fieldArgument+ switches <- spaces *> many fieldSwitch+ return $ IndexrefField $ IndexEntry{ entryTitle = farg+ , entrySee = lookup 't' switches+ , entryYomi = lookup 'y' switches+ , entryBold = isJust (lookup 'b' switches)+ , entryItalic = isJust (lookup 'i' switches) }
@@ -1,3 +1,4 @@+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.Docx.Lists@@ -18,10 +19,11 @@ ) where import Data.List+import Data.Char (isDigit) import Data.Maybe import Data.String (fromString) import qualified Data.Text as T-import Text.Pandoc.Generic (bottomUp)+import Text.Pandoc.Walk (walk) import Text.Pandoc.JSON import Text.Pandoc.Readers.Docx.Parse (ParaStyleName) import Text.Pandoc.Shared (trim, safeRead)@@ -58,9 +60,9 @@ ("decimal", Decimal)] listDelimMap :: [(T.Text, ListNumberDelim)]-listDelimMap = [("%1)", OneParen),- ("(%1)", TwoParens),- ("%1.", Period)]+listDelimMap = [("%)", OneParen),+ ("(%)", TwoParens),+ ("%.", Period)] getListType :: Block -> Maybe ListType getListType b@(Div (_, _, kvs) _) | isListItem b =@@ -72,7 +74,7 @@ case frmt of Just "bullet" -> Just Itemized Just f ->- case txt of+ case T.filter (not . isDigit) <$> txt of Just t -> Just $ Enumerated ( fromMaybe 1 (start >>= safeRead) :: Int, fromMaybe DefaultStyle (lookup f listStyleMap),@@ -122,25 +124,48 @@ flatToBullets' :: Integer -> [Block] -> [Block] flatToBullets' _ [] = []-flatToBullets' num xs@(b : elems)- | getLevelN b == num = b : flatToBullets' num elems- | otherwise =- let bNumId = getNumIdN b- bLevel = getLevelN b- (children, remaining) =- span- (\b' ->- getLevelN b' > bLevel ||- (getLevelN b' == bLevel && getNumIdN b' == bNumId))- xs- in- case getListType b of- Just (Enumerated attr) ->- OrderedList attr (separateBlocks $ flatToBullets' bLevel children) :- flatToBullets' num remaining- _ ->- BulletList (separateBlocks $ flatToBullets' bLevel children) :- flatToBullets' num remaining+flatToBullets' num xs@(b : elems) =+ if getLevelN b == num+ then (case bCheckmark of+ Just checked -> addCheckmark checked b+ Nothing -> b) : flatToBullets' num elems+ else case getListType b of+ Just (Enumerated attr) ->+ OrderedList attr (separateBlocks $ flatToBullets' bLevel children) :+ flatToBullets' num remaining+ _ ->+ BulletList (separateBlocks $ flatToBullets' bLevel children) :+ flatToBullets' num remaining+ where+ bNumId = getNumIdN b+ bLevel = getLevelN b+ isCheckmark (Just "\9744") = Just False+ isCheckmark (Just "\9746") = Just True+ isCheckmark _ = Nothing+ bCheckmark =+ case getListType b of+ Just Itemized -> isCheckmark (getText b)+ _ -> Nothing+ addCheckmark checked (Div attrs [Para ils]) =+ Div attrs [Para (Str (if checked then "\9746" else "\9744") : Space : ils)]+ addCheckmark checked (Div attrs [Plain ils]) =+ Div attrs [Plain (Str (if checked then "\9746" else "\9744") : Space : ils)]+ addCheckmark _ x = x+ (children, remaining) =+ span+ (\b' ->+ getLevelN b' > bLevel ||+ (getLevelN b' == bLevel &&+ (getNumIdN b' == bNumId ||+ (case bCheckmark of+ Just _ ->+ case getText b' of+ Just "" -> True+ Just " " -> True+ Just x -> isJust (isCheckmark (Just x))+ Nothing -> False+ Nothing -> False))))+ xs flatToBullets :: [Block] -> [Block] flatToBullets elems = flatToBullets' (-1) elems@@ -153,7 +178,7 @@ blocksToBullets :: [Block] -> [Block] blocksToBullets blks = map singleItemHeaderToHeader $- bottomUp removeListDivs $ flatToBullets (handleListParagraphs blks)+ walk removeListDivs $ flatToBullets (handleListParagraphs blks) plainParaInlines :: Block -> [Inline] plainParaInlines (Plain ils) = ils
@@ -1,4 +1,4 @@-{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TupleSections #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {- |@@ -30,17 +30,20 @@ , RunStyle(..) , VertAlign(..) , ParIndentation(..)+ , Justification(..) , ParagraphStyle(..) , ParStyle , CharStyle(cStyleData) , Row(..) , TblHeader(..)+ , Align(..) , Cell(..) , VMerge(..) , TrackedChange(..) , ChangeType(..) , ChangeInfo(..) , FieldInfo(..)+ , IndexEntry(..) , Level(..) , ParaStyleName , CharStyleName@@ -55,14 +58,16 @@ , constructBogusParStyleData , leftBiasedMergeRunStyle , rowsToRowspans+ , extractTarget ) where import Text.Pandoc.Readers.Docx.Parse.Styles import Codec.Archive.Zip import Control.Applicative ((<|>))+import Control.Monad import Control.Monad.Except import Control.Monad.Reader import Control.Monad.State.Strict-import Data.Bits ((.|.))+import Data.Bits ((.&.)) import qualified Data.ByteString.Lazy as B import Data.Char (chr, ord, readLitChar) import Data.List@@ -77,21 +82,23 @@ import qualified Text.Pandoc.UTF8 as UTF8 import Text.TeXMath (Exp) import Text.TeXMath.Readers.OMML (readOMML)-import Text.TeXMath.Unicode.Fonts (Font (..), getUnicode, textToFont)+import Text.Pandoc.Readers.Docx.Symbols (symbolMap, Font(..), textToFont) import Text.Pandoc.XML.Light ( filterChild, findElement, strContent, showElement, findAttr,+ filterChild, filterChildrenName, filterElementName,+ filterElementsName,+ lookupAttrBy, parseXMLElement, elChildren, QName(QName, qName), Content(Elem),- Element(elContent, elName),- findElements )+ Element(..)) data ReaderEnv = ReaderEnv { envNotes :: Notes , envComments :: Comments@@ -103,6 +110,7 @@ , envParStyles :: ParStyleMap , envLocation :: DocumentLocation , envDocXmlPath :: FilePath+ , envTextWidth :: Int } deriving Show @@ -112,7 +120,7 @@ deriving Show data FldCharState = FldCharOpen- | FldCharFieldInfo FieldInfo+ | FldCharFieldInfo T.Text | FldCharContent FieldInfo [ParPart] deriving (Show) @@ -151,8 +159,55 @@ = concatMap (unwrapElement ns) (elChildren sdtContent) | isElem ns "w" "smartTag" element = concatMap (unwrapElement ns) (elChildren element)+ | isElem ns "w" "p" element+ , _:_ <- findChildrenByName ns "w" "r" element >>= findTextboxes+ = let result = splitP (elContent element) [] -- handle #9214, #11053+ in [element{ elName = QName "textbox-image" Nothing Nothing+ , elContent = map Elem result }]+ | isElem ns "w" "r" element+ , Just fallback <- findChildByName ns "mc" "AlternateContent" element >>=+ findChildByName ns "mc" "Fallback"+ = [element{ elContent = concatMap (unwrapContent ns) (elContent fallback) }] | otherwise = [element{ elContent = concatMap (unwrapContent ns) (elContent element) }]+ where+ -- Split a w:p's children around textbox-bearing runs, preserving order.+ -- Non-textbox content is grouped into a copy of the original w:p;+ -- textbox content is unwrapped into sibling elements in place.+ splitP [] acc = [wrapP acc | hasContent acc]+ splitP (c:cs) acc+ | Elem el <- c+ , isElem ns "w" "r" el+ , tbs@(_:_) <- findTextboxes el+ = [wrapP acc | hasContent acc]+ ++ concatMap (unwrapElement ns) (concatMap elChildren tbs)+ ++ splitP cs []+ | otherwise+ = splitP cs (acc ++ [c])+ wrapP cs = element{ elContent = concatMap (unwrapContent ns) cs }+ hasContent = any (\case Elem el -> isElem ns "w" "r" el+ && any (isContentElem . elName)+ (elChildren el)+ _ -> False)+ isContentElem n = qName n `elem`+ ["t", "drawing", "pict", "br", "tab", "sym", "fldChar", "instrText"]+ -- Search textbox content in the run's effective children.+ -- If AlternateContent is present, use only the fallback branch,+ -- matching the w:r unwrapping logic and avoiding duplicate textbox+ -- extraction when both direct and fallback encodings are present.+ findRunFallback run =+ findChildByName ns "mc" "AlternateContent" run >>=+ findChildByName ns "mc" "Fallback"+ findTextboxes run =+ findTextboxContent =<<+ case findRunFallback run of+ Just fallback -> findChildrenByName ns "w" "pict" fallback+ Nothing -> findChildrenByName ns "w" "pict" run+ findTextboxContent pict =+ (findChildrenByName ns "v" "shape" pict <>+ findChildrenByName ns "v" "rect" pict) >>=+ findChildrenByName ns "v" "textbox" >>=+ findChildrenByName ns "w" "txbxContent" unwrapContent :: NameSpaces -> Content -> [Content] unwrapContent ns (Elem element) = map Elem $ unwrapElement ns element@@ -217,31 +272,42 @@ data TrackedChange = TrackedChange ChangeType ChangeInfo deriving Show -data ParagraphStyle = ParagraphStyle { pStyle :: [ParStyle]- , indentation :: Maybe ParIndentation- , dropCap :: Bool- , pChange :: Maybe TrackedChange- , pBidi :: Maybe Bool+data Justification = JustifyBoth | JustifyLeft | JustifyRight | JustifyCenter+ deriving (Show, Eq)++data ParagraphStyle = ParagraphStyle { pStyle :: [ParStyle]+ , indentation :: Maybe ParIndentation+ , justification :: Maybe Justification+ , numbered :: Bool+ , dropCap :: Bool+ , pChange :: Maybe TrackedChange+ , pBidi :: Maybe Bool+ , pKeepNext :: Bool } deriving Show defaultParagraphStyle :: ParagraphStyle defaultParagraphStyle = ParagraphStyle { pStyle = [] , indentation = Nothing- , dropCap = False- , pChange = Nothing- , pBidi = Just False+ , justification = Nothing+ , numbered = False+ , dropCap = False+ , pChange = Nothing+ , pBidi = Just False+ , pKeepNext = False } data BodyPart = Paragraph ParagraphStyle [ParPart]+ | Heading Int ParaStyleName ParagraphStyle T.Text T.Text (Maybe Level)+ [ParPart] | ListItem ParagraphStyle T.Text T.Text (Maybe Level) [ParPart]- | Tbl T.Text TblGrid TblLook [Row]- | TblCaption ParagraphStyle [ParPart]- | OMathPara [Exp]+ | Tbl (Maybe T.Text) T.Text TblGrid TblLook [Row]+ | Captioned ParagraphStyle [ParPart] BodyPart+ | HRule deriving Show -type TblGrid = [Integer]+type TblGrid = [Double] newtype TblLook = TblLook {firstRowFormatting::Bool} deriving Show@@ -253,9 +319,15 @@ data TblHeader = HasTblHeader | NoTblHeader deriving (Show, Eq) -data Cell = Cell GridSpan VMerge [BodyPart]+data Align = AlignDefault | AlignLeft | AlignRight | AlignCenter+ deriving (Show, Eq)++data Cell = Cell Align GridSpan VMerge [BodyPart] deriving Show +emptyCell :: Cell+emptyCell = Cell AlignDefault 1 Restart []+ type GridSpan = Integer data VMerge = Continue@@ -266,7 +338,7 @@ rowsToRowspans :: [Row] -> [[(Int, Cell)]] rowsToRowspans rows = let- removeMergedCells = fmap (filter (\(_, Cell _ vmerge _) -> vmerge == Restart))+ removeMergedCells = fmap (filter (\(_, Cell _ _ vmerge _) -> vmerge == Restart)) in removeMergedCells (foldr f [] rows) where f :: Row -> [[(Int, Cell)]] -> [[(Int, Cell)]]@@ -278,13 +350,13 @@ -> Maybe Integer -- Number of columns left below -> Maybe [(Int, Cell)] -- (rowspan so far, cell) for the row below this one -> [(Int, Cell)] -- (rowspan so far, cell) for this row- g cells _ Nothing = zip (repeat 1) cells+ g cells _ Nothing = map (1,) cells g cells columnsLeftBelow (Just rowBelow) = case cells of [] -> []- thisCell@(Cell thisGridSpan _ _) : restOfRow -> case rowBelow of- [] -> zip (repeat 1) cells- (spanSoFarBelow, Cell gridSpanBelow vmerge _) : _ ->+ thisCell@(Cell _ thisGridSpan _ _) : restOfRow -> case rowBelow of+ [] -> map (1,) cells+ (spanSoFarBelow, Cell _ gridSpanBelow vmerge _) : _ -> let spanSoFar = case vmerge of Restart -> 1 Continue -> 1 + spanSoFarBelow@@ -294,7 +366,7 @@ dropColumns :: Integer -> [(a, Cell)] -> (Integer, [(a, Cell)]) dropColumns n [] = (n, [])- dropColumns n cells@((_, Cell gridSpan _ _) : otherCells) =+ dropColumns n cells@((_, Cell _ gridSpan _ _) : otherCells) = if n < gridSpan then (gridSpan - n, cells) else dropColumns (n - gridSpan) otherCells@@ -309,6 +381,7 @@ , isStrike = isStrike a <|> isStrike b , isRTL = isRTL a <|> isRTL b , isForceCTL = isForceCTL a <|> isForceCTL b+ , rHighlight = rHighlight a <|> rHighlight b , rVertAlign = rVertAlign a <|> rVertAlign b , rUnderline = rUnderline a <|> rUnderline b , rParentStyle = rParentStyle a@@ -318,7 +391,7 @@ type Extent = Maybe (Double, Double) data ParPart = PlainRun Run- | ChangedRuns TrackedChange [Run]+ | ChangedRuns TrackedChange [ParPart] | CommentStart CommentId Author (Maybe CommentDate) [BodyPart] | CommentEnd CommentId | BookMark BookMarkId Anchor@@ -328,6 +401,7 @@ | Chart -- placeholder for now | Diagram -- placeholder for now | PlainOMath [Exp]+ | OMathPara [Exp] | Field FieldInfo [ParPart] deriving Show @@ -367,6 +441,7 @@ rels = archiveToRelationships archive docXmlPath media = filteredFilesFromArchive archive filePathIsMedia (styles, parstyles) = archiveToStyles archive+ textWidth = archiveToTextWidth archive rEnv = ReaderEnv { envNotes = notes , envComments = comments , envNumbering = numbering@@ -377,6 +452,7 @@ , envParStyles = parstyles , envLocation = InDocument , envDocXmlPath = docXmlPath+ , envTextWidth = fromMaybe 9360 textWidth } rState = ReaderState { stateWarnings = [] , stateFldCharState = []@@ -397,8 +473,10 @@ entry <- findEntryByPath "_rels/.rels" zf relsElem <- parseXMLFromEntry entry let rels = filterChildrenName (\n -> qName n == "Relationship") relsElem- rel <- find (\e -> findAttr (QName "Type" Nothing Nothing) e ==- Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")+ rel <- find (\e ->+ case findAttr (QName "Type" Nothing Nothing) e of+ Just u -> isNamespace "officeDocument" "relationships/officeDocument" u+ Nothing -> False) rels fp <- findAttr (QName "Target" Nothing Nothing) rel -- sometimes there will be a leading slash, which windows seems to@@ -419,9 +497,17 @@ return $ Document namespaces body elemToBody :: NameSpaces -> Element -> D Body-elemToBody ns element | isElem ns "w" "body" element =- fmap Body (mapD (elemToBodyPart ns) (elChildren element))-elemToBody _ _ = throwError WrongElem+elemToBody ns element+ | isElem ns "w" "body" element =+ Body . addCaptioned <$> concatMapM (elemToBodyParts ns) (elChildren element)+ | otherwise = throwError WrongElem+ where+ elemToBodyParts ns' el+ | qName (elName el) == "textbox-image"+ = addSplitGroupCaptioned . splitMixedParagraphs+ <$> mapD (elemToBodyPart ns') (elChildren el)+ | otherwise+ = ((:[]) <$> elemToBodyPart ns' el) `catchError` (\_ -> return []) archiveToStyles :: Archive -> (CharStyleMap, ParStyleMap) archiveToStyles = archiveToStyles' getStyleId getStyleId@@ -484,26 +570,26 @@ then Just InDocument else Nothing -relElemToRelationship :: FilePath -> DocumentLocation -> Element+relElemToRelationship :: DocumentLocation -> Element -> Maybe Relationship-relElemToRelationship fp relType element | qName (elName element) == "Relationship" =+relElemToRelationship relType element | qName (elName element) == "Relationship" = do relId <- findAttr (QName "Id" Nothing Nothing) element target <- findAttr (QName "Target" Nothing Nothing) element- -- target may be relative (media/image1.jpeg) or absolute- -- (/word/media/image1.jpeg); we need to relativize it (see #7374)- let frontOfFp = T.pack $ takeWhile (/= '_') fp- let target' = fromMaybe target $- T.stripPrefix frontOfFp $ T.dropWhile (== '/') target- return $ Relationship relType relId target'-relElemToRelationship _ _ _ = Nothing+ -- target may be relative (media/image1.jpeg) or absolute (/word/media/image1.jpg)+ return $ Relationship relType relId target+relElemToRelationship _ _ = Nothing +extractTarget :: Element -> Maybe Target+extractTarget element = do (Relationship _ _ target) <- relElemToRelationship InDocument element+ return target+ filePathToRelationships :: Archive -> FilePath -> FilePath -> [Relationship] filePathToRelationships ar docXmlPath fp | Just relType <- filePathToRelType fp docXmlPath , Just entry <- findEntryByPath fp ar , Just relElems <- parseXMLFromEntry entry =- mapMaybe (relElemToRelationship fp relType) $ elChildren relElems+ mapMaybe (relElemToRelationship relType) $ elChildren relElems filePathToRelationships _ _ _ = [] archiveToRelationships :: Archive -> FilePath -> [Relationship]@@ -594,6 +680,20 @@ archiveToNumbering archive = fromMaybe (Numbering mempty [] []) (archiveToNumbering' archive) +archiveToTextWidth :: Archive -> Maybe Int+archiveToTextWidth zf = do+ entry <- findEntryByPath "word/document.xml" zf+ docElem <- parseXMLFromEntry entry+ let ns = elemToNameSpaces docElem+ sectElem <- findChildByName ns "w" "body" docElem >>= findChildByName ns "w" "sectPr"+ pgWidth <- findChildByName ns "w" "pgSz" sectElem+ >>= findAttrByName ns "w" "w" >>= safeRead+ pgMar <- findChildByName ns "w" "pgMar" sectElem+ leftMargin <- findAttrByName ns "w" "left" pgMar >>= safeRead+ rightMargin <- findAttrByName ns "w" "right" pgMar >>= safeRead+ gutter <- findAttrByName ns "w" "gutter" pgMar >>= safeRead+ return $ pgWidth - (leftMargin + rightMargin + gutter)+ elemToNotes :: NameSpaces -> Text -> Element -> Maybe (M.Map T.Text Element) elemToNotes ns notetype element | isElem ns "w" (notetype <> "s") element =@@ -622,11 +722,20 @@ --------------------------------------------- elemToTblGrid :: NameSpaces -> Element -> D TblGrid-elemToTblGrid ns element | isElem ns "w" "tblGrid" element =+elemToTblGrid ns element | isElem ns "w" "tblGrid" element = do let cols = findChildrenByName ns "w" "gridCol" element- in- mapD (\e -> maybeToD (findAttrByName ns "w" "w" e >>= stringToInteger))- cols+ textWidth <- asks envTextWidth+ -- space between cols is 10 twips, so we subtract this:+ let totalWidth = textWidth - (10 * (length cols - 1))+ let toFraction :: Int -> Double+ toFraction x = fromIntegral x / fromIntegral totalWidth+ let normalizeFractions xs =+ case sum xs of+ tot | tot > 1.0 -> map (/ tot) xs+ _ -> xs+ normalizeFractions <$>+ mapD (\e -> maybeToD (findAttrByName ns "w" "w" e >>=+ fmap toFraction . safeRead)) cols elemToTblGrid _ _ = throwError WrongElem elemToTblLook :: NameSpaces -> Element -> D TblLook@@ -647,12 +756,21 @@ elemToRow :: NameSpaces -> Element -> D Row elemToRow ns element | isElem ns "w" "tr" element = do+ let properties = findChildByName ns "w" "trPr" element+ let gridBefore = properties+ >>= findChildByName ns "w" "gridBefore"+ >>= findAttrByName ns "w" "val"+ >>= stringToInteger let cellElems = findChildrenByName ns "w" "tc" element+ let beforeCells = genericReplicate (fromMaybe 0 gridBefore) emptyCell cells <- mapD (elemToCell ns) cellElems- let hasTblHeader = maybe NoTblHeader (const HasTblHeader)- (findChildByName ns "w" "trPr" element- >>= findChildByName ns "w" "tblHeader")- return $ Row hasTblHeader cells+ let hasTblHeader =+ case (properties >>= findChildByName ns "w" "tblHeader") of+ Nothing -> NoTblHeader+ Just he -> case findAttrByName ns "w" "val" he of+ Just "0" -> NoTblHeader+ _ -> HasTblHeader+ return $ Row hasTblHeader (beforeCells ++ cells) elemToRow _ _ = throwError WrongElem elemToCell :: NameSpaces -> Element -> D Cell@@ -673,14 +791,23 @@ "restart" -> Just Restart _ -> Nothing cellContents <- mapD (elemToBodyPart ns) (elChildren element)- return $ Cell (fromMaybe 1 gridSpan) vMerge cellContents+ let align = case cellContents of -- take alignment from first paragraph+ Paragraph pstyle _ : _ ->+ case justification pstyle of+ Just JustifyBoth -> AlignLeft+ Just JustifyLeft -> AlignLeft+ Just JustifyRight -> AlignRight+ Just JustifyCenter -> AlignCenter+ Nothing -> AlignDefault+ _ -> AlignDefault+ return $ Cell align (fromMaybe 1 gridSpan) vMerge cellContents elemToCell _ _ = throwError WrongElem testBitMask :: Text -> Int -> Bool testBitMask bitMaskS n = case (reads ("0x" ++ T.unpack bitMaskS) :: [(Int, String)]) of [] -> False- ((n', _) : _) -> (n' .|. n) /= 0+ ((n', _) : _) -> (n' .&. n) /= 0 pHeading :: ParagraphStyle -> Maybe (ParaStyleName, Int) pHeading = getParStyleField headingLev . pStyle@@ -688,51 +815,117 @@ pNumInfo :: ParagraphStyle -> Maybe (T.Text, T.Text) pNumInfo = getParStyleField numInfo . pStyle +mkListItem :: ParagraphStyle -> Text -> Text -> [ParPart] -> D BodyPart+mkListItem parstyle numId lvl parparts = do+ lvlInfo <- lookupLevel numId lvl <$> asks envNumbering+ return $ ListItem parstyle numId lvl lvlInfo parparts+ pStyleIndentation :: ParagraphStyle -> Maybe ParIndentation pStyleIndentation style = (getParStyleField indent . pStyle) style +addCaptioned :: [BodyPart] -> [BodyPart]+addCaptioned [] = []+addCaptioned (Paragraph parstyle parparts : x : xs)+ | hasCaptionStyle parstyle+ , isCaptionable x+ = Captioned parstyle parparts x : addCaptioned xs+addCaptioned (x : Paragraph parstyle parparts : xs)+ | hasCaptionStyle parstyle+ , not (pKeepNext parstyle)+ , isCaptionable x+ = Captioned parstyle parparts x : addCaptioned xs+addCaptioned (x:xs) = x : addCaptioned xs++-- Split paragraphs that contain both a Drawing and text into two body parts,+-- so that the captioning logic can combine them.+splitMixedParagraphs :: [BodyPart] -> [BodyPart]+splitMixedParagraphs [] = []+splitMixedParagraphs (Paragraph ps parts : rest)+ | (drawings@(_:_), texts@(_:_)) <- partition isDrawingPart parts+ = Paragraph ps drawings : Paragraph ps texts : splitMixedParagraphs rest+ where isDrawingPart Drawing{} = True+ isDrawingPart _ = False+splitMixedParagraphs (x:xs) = x : splitMixedParagraphs xs++-- For textbox-image groups: combine image + any adjacent text into Captioned+addSplitGroupCaptioned :: [BodyPart] -> [BodyPart]+addSplitGroupCaptioned [] = []+addSplitGroupCaptioned (Paragraph parstyle parparts : x : xs)+ | isCaptionable x+ = Captioned parstyle parparts x : addSplitGroupCaptioned xs+addSplitGroupCaptioned (x : Paragraph parstyle parparts : xs)+ | isCaptionable x+ = Captioned parstyle parparts x : addSplitGroupCaptioned xs+addSplitGroupCaptioned (x:xs) = x : addSplitGroupCaptioned xs++isCaptionable :: BodyPart -> Bool+isCaptionable (Paragraph _ [Drawing{}]) = True+isCaptionable (Tbl{}) = True+isCaptionable _ = False+ elemToBodyPart :: NameSpaces -> Element -> D BodyPart elemToBodyPart ns element- | isElem ns "w" "p" element- , (c:_) <- findChildrenByName ns "m" "oMathPara" element = do- expsLst <- eitherToD $ readOMML $ showElement c- return $ OMathPara expsLst+ | isElem ns "m" "oMathPara" element = do+ expsLst <- eitherToD $ readOMML $ showElement element+ parstyle <- elemToParagraphStyle ns element+ <$> asks envParStyles+ <*> asks envNumbering+ return $ Paragraph parstyle [OMathPara expsLst] elemToBodyPart ns element | isElem ns "w" "p" element , Just (numId, lvl) <- getNumInfo ns element = do- parstyle <- elemToParagraphStyle ns element <$> asks envParStyles+ lvlInfo <- lookupLevel numId lvl <$> asks envNumbering+ parstyle <- elemToParagraphStyle ns element+ <$> asks envParStyles+ <*> asks envNumbering parparts <- mconcat <$> mapD (elemToParPart ns) (elChildren element)- levelInfo <- lookupLevel numId lvl <$> asks envNumbering- return $ ListItem parstyle numId lvl levelInfo parparts+ case pHeading parstyle of+ Nothing -> mkListItem parstyle numId lvl parparts+ Just (parstylename, lev)+ -> return $ Heading lev parstylename parstyle numId lvl lvlInfo parparts elemToBodyPart ns element+ | isElem ns "w" "p" element+ , [Elem ppr] <- elContent element+ , isElem ns "w" "pPr" ppr+ , [Elem pbdr] <- elContent ppr+ , isElem ns "w" "pBdr" pbdr+ = return HRule+ -- for this style of horizontal rule, see+ -- https://support.microsoft.com/en-us/office/insert-a-horizontal-line-9bf172f6-5908-4791-9bb9-2c952197b1a9+elemToBodyPart ns element -- pandoc-style horizontal rule+ | isElem ns "w" "p" element+ , [Elem r] <- elContent element+ , isElem ns "w" "r" r+ , [Elem pict] <- elContent r+ , isElem ns "w" "pict" pict+ , [Elem rect] <- elContent pict+ , isElem ns "v" "rect" rect+ = return HRule+elemToBodyPart ns element | isElem ns "w" "p" element = do- parstyle <- elemToParagraphStyle ns element <$> asks envParStyles- parparts' <- mconcat <$> mapD (elemToParPart ns) (elChildren element)+ parstyle <- elemToParagraphStyle ns element+ <$> asks envParStyles+ <*> asks envNumbering++ let children =+ (if hasCaptionStyle parstyle+ then stripCaptionLabel+ else id) (elChildren element)++ parparts' <- mconcat <$> mapD (elemToParPart ns) children fldCharState <- gets stateFldCharState modify $ \st -> st {stateFldCharState = emptyFldCharContents fldCharState} -- Word uses list enumeration for numbered headings, so we only -- want to infer a list from the styles if it is NOT a heading.- let parparts = parparts' ++ (openFldCharsToParParts fldCharState) in- case pHeading parstyle of- Nothing | Just (numId, lvl) <- pNumInfo parstyle -> do- levelInfo <- lookupLevel numId lvl <$> asks envNumbering- return $ ListItem parstyle numId lvl levelInfo parparts- _ -> let- hasCaptionStyle = elem "Caption" (pStyleId <$> pStyle parstyle)-- hasSimpleTableField = fromMaybe False $ do- fldSimple <- findChildByName ns "w" "fldSimple" element- instr <- findAttrByName ns "w" "instr" fldSimple- pure ("Table" `elem` T.words instr)-- hasComplexTableField = fromMaybe False $ do- instrText <- findElementByName ns "w" "instrText" element- pure ("Table" `elem` T.words (strContent instrText))-- in if hasCaptionStyle && (hasSimpleTableField || hasComplexTableField)- then return $ TblCaption parstyle parparts- else return $ Paragraph parstyle parparts-+ let parparts = parparts' ++ openFldCharsToParParts fldCharState+ case pHeading parstyle of+ Nothing | Just (numId, lvl) <- pNumInfo parstyle -> do+ mkListItem parstyle numId lvl parparts+ Just (parstylename, lev) -> do+ let (numId, lvl) = fromMaybe ("","") $ pNumInfo parstyle+ lvlInfo <- lookupLevel numId lvl <$> asks envNumbering+ return $ Heading lev parstylename parstyle numId lvl lvlInfo parparts+ Nothing -> return $ Paragraph parstyle parparts elemToBodyPart ns element | isElem ns "w" "tbl" element = do let tblProperties = findChildByName ns "w" "tblPr" element@@ -742,6 +935,9 @@ description = fromMaybe "" $ tblProperties >>= findChildByName ns "w" "tblDescription" >>= findAttrByName ns "w" "val"+ mbstyle = tblProperties+ >>= findChildByName ns "w" "tblStyle"+ >>= findAttrByName ns "w" "val" grid' = case findChildByName ns "w" "tblGrid" element of Just g -> elemToTblGrid ns g Nothing -> return []@@ -751,10 +947,16 @@ Just l -> elemToTblLook ns l Nothing -> return defaultTblLook - grid <- grid'+ grid'' <- grid' tblLook <- tblLook' rows <- mapD (elemToRow ns) (elChildren element)- return $ Tbl (caption <> description) grid tblLook rows+ let grid = if null grid''+ then let numcols = case rowsToRowspans rows of+ (cs@(_:_):_) -> sum (map fst cs)+ _ -> 0+ in replicate numcols 0.0+ else grid''+ return $ Tbl mbstyle (caption <> description) grid tblLook rows elemToBodyPart _ _ = throwError WrongElem lookupRelationship :: DocumentLocation -> RelId -> [Relationship] -> Maybe Target@@ -783,17 +985,30 @@ case target of Just filepath -> do media <- asks envMedia- let filepath' = case filepath of- ('/':rest) -> rest- _ -> "word/" ++ filepath+ -- the mediaName is the name we store it under in the mediabag.+ -- This is derived from the path, which might be absolute, e.g. /media/foo.jpg,+ -- or relative, media/foo.jpg (interpreted as /word/media/foo.jpg).+ -- The mediaName will strip off any leading `/` or `word/`.+ -- We assume here that the media will not be stored *both* in+ -- /media and in /word/media, which would lead to a name conflict+ -- given the scheme here for generating a mediaName.+ let (filepath', mediaName) =+ case filepath of+ ('/':rest) -- absolute path e.g. /media/foo.jpg+ -> (rest, case stripPrefix "word/" rest of+ Just rest' -> rest'+ Nothing -> rest)+ _ -- rel path to word, e.g. media/foo.jpg+ -> ("word/" ++ filepath, filepath) case lookup filepath' media of- Just bs -> return (filepath, bs)+ Just bs -> return (mediaName, bs) Nothing -> throwError DocxError Nothing -> throwError DocxError getTitleAndAlt :: NameSpaces -> Element -> (T.Text, T.Text) getTitleAndAlt ns element =- let mbDocPr = findChildByName ns "wp" "inline" element >>=+ let mbDocPr = (findChildByName ns "wp" "inline" element <|> -- Word+ findChildByName ns "wp" "anchor" element) >>= -- LibreOffice findChildByName ns "wp" "docPr" title = fromMaybe "" (mbDocPr >>= findAttrByName ns "" "title") alt = fromMaybe "" (mbDocPr >>= findAttrByName ns "" "descr")@@ -828,6 +1043,10 @@ <w:fldChar w:fldCharType="end"/> </w:r> +Note that there may be mulitple w:instrText elements in a row.+For example, you might first have ` XE "`, then `Kay, Alan`, then `"`.+The texts in all of them should be concatenated before it is processed!+ So we do this in a number of steps. If we encounter the fldchar begin tag, we start open a fldchar state variable (see state above). We add the instrtext to it as FieldInfo. Then we close that and start adding@@ -848,13 +1067,15 @@ _ | fldCharType == "begin" -> do modify $ \st -> st {stateFldCharState = FldCharOpen : fldCharState} return []- FldCharFieldInfo info : ancestors | fldCharType == "separate" -> do+ FldCharFieldInfo t : ancestors | fldCharType == "separate" -> do+ info <- eitherToD $ parseFieldInfo t modify $ \st -> st {stateFldCharState = FldCharContent info [] : ancestors} return []- -- Some fields have no content, since Pandoc doesn't understand any of those fields, we can just close it.- FldCharFieldInfo _ : ancestors | fldCharType == "end" -> do+ -- Some fields have no content, e.g. index XE:+ FldCharFieldInfo t : ancestors | fldCharType == "end" -> do modify $ \st -> st {stateFldCharState = ancestors}- return []+ info <- eitherToD $ parseFieldInfo t+ return [Field info []] [FldCharContent info children] | fldCharType == "end" -> do modify $ \st -> st {stateFldCharState = []} return [Field info $ reverse children]@@ -869,9 +1090,14 @@ fldCharState <- gets stateFldCharState case fldCharState of FldCharOpen : ancestors -> do- info <- eitherToD $ parseFieldInfo $ strContent instrText- modify $ \st -> st {stateFldCharState = FldCharFieldInfo info : ancestors}+ modify $ \st -> st {stateFldCharState =+ FldCharFieldInfo (strContent instrText) : ancestors} return []+ FldCharFieldInfo t : ancestors -> do+ modify $ \st -> st {stateFldCharState =+ FldCharFieldInfo (t <> strContent instrText) :+ ancestors}+ return [] _ -> return [] {- There is an open fldchar, so we calculate the element and add it to the@@ -894,13 +1120,12 @@ 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- a_ns = "http://schemas.openxmlformats.org/drawingml/2006/main" drawings = map (\el ->- ((findElement (QName "blip" (Just a_ns) (Just "a")) el- >>= findAttrByName ns "r" "embed"), el)) picElems+ ((findBlip el >>= findAttrByName ns "r" "embed"), el))+ picElems in mapM (\case (Just s, el) -> do (fp, bs) <- expandDrawingId s@@ -930,15 +1155,15 @@ elemToParPart' ns element | isElem ns "w" "r" element , Just drawingElem <- findChildByName ns "w" "drawing" element- , d_ns <- "http://schemas.openxmlformats.org/drawingml/2006/diagram"- , Just _ <- findElement (QName "relIds" (Just d_ns) (Just "dgm")) drawingElem+ , Just _ <- filterElementName+ (matchQName "drawingml" "diagram" (Just "dgm") "relIds") drawingElem = return [Diagram] -- Chart elemToParPart' ns element | isElem ns "w" "r" element , Just drawingElem <- findChildByName ns "w" "drawing" element- , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/chart"- , Just _ <- findElement (QName "chart" (Just c_ns) (Just "c")) drawingElem+ , Just _ <- filterElementName+ (matchQName "drawingml" "chart" (Just "c") "chart") drawingElem = return [Chart] elemToParPart' ns element | isElem ns "w" "r" element = do@@ -946,7 +1171,7 @@ return $ map PlainRun runs elemToParPart' ns element | Just change <- getTrackedChange ns element = do- runs <- mconcat <$> mapD (elemToRun ns) (elChildren element)+ runs <- mconcat <$> mapD (elemToParPart' ns) (elChildren element) return [ChangedRuns change runs] elemToParPart' ns element | isElem ns "w" "bookmarkStart" element@@ -985,6 +1210,9 @@ elemToParPart' ns element | isElem ns "m" "oMath" element = fmap (return . PlainOMath) (eitherToD $ readOMML $ showElement element)+elemToParPart' ns element+ | isElem ns "m" "oMathPara" element =+ fmap (return . OMathPara) (eitherToD $ readOMML $ showElement element) elemToParPart' _ _ = throwError WrongElem elemToCommentStart :: NameSpaces -> Element -> D [ParPart]@@ -1009,20 +1237,19 @@ (Just w, Just h) -> Just (w, h) _ -> Nothing where- getDim at = filterElementName (\n -> qName n `elem` ["extent", "ext"]) el+ getDim at = filterElementName (\n -> qName n == "extent") el >>= findAttr (QName at Nothing Nothing) >>= safeRead childElemToRun :: NameSpaces -> Element -> D [Run] childElemToRun ns element | isElem ns "w" "drawing" element- , pic_ns <- "http://schemas.openxmlformats.org/drawingml/2006/picture"- , picElems <- findElements (QName "pic" (Just pic_ns) (Just "pic")) element+ , picElems <- filterElementsName+ (matchQName "drawingml" "picture" (Just "pic") "pic") element = let (title, alt) = getTitleAndAlt ns element- a_ns = "http://schemas.openxmlformats.org/drawingml/2006/main" drawings = map (\el ->- ((findElement (QName "blip" (Just a_ns) (Just "a")) el- >>= findAttrByName ns "r" "embed"), el)) picElems+ ((findBlip el >>= findAttrByName ns "r" "embed"), el))+ picElems in mapM (\case (Just s, el) -> do (fp, bs) <- expandDrawingId s@@ -1032,13 +1259,13 @@ drawings childElemToRun ns element | isElem ns "w" "drawing" element- , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/chart"- , Just _ <- findElement (QName "chart" (Just c_ns) (Just "c")) element+ , Just _ <- filterElementName+ (matchQName "drawingml" "chart" (Just "c") "chart") element = return [InlineChart] childElemToRun ns element | isElem ns "w" "drawing" element- , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/diagram"- , Just _ <- findElement (QName "relIds" (Just c_ns) (Just "dgm")) element+ , Just _ <- filterElementName+ (matchQName "drawingml" "diagram" (Just "dgm") "relIds") element = return [InlineDiagram] childElemToRun ns element | isElem ns "w" "footnoteReference" element@@ -1061,15 +1288,6 @@ elemToRun :: NameSpaces -> Element -> D [Run] elemToRun ns element | isElem ns "w" "r" element- , Just altCont <- findChildByName ns "mc" "AlternateContent" element =- do let choices = findChildrenByName ns "mc" "Choice" altCont- choiceChildren = map head $ filter (not . null) $ map 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@@ -1115,15 +1333,30 @@ Just $ TrackedChange Deletion (ChangeInfo cId cAuthor mcDate) getTrackedChange _ _ = Nothing -elemToParagraphStyle :: NameSpaces -> Element -> ParStyleMap -> ParagraphStyle-elemToParagraphStyle ns element sty+elemToParagraphStyle :: NameSpaces -> Element+ -> ParStyleMap+ -> Numbering+ -> ParagraphStyle+elemToParagraphStyle ns element sty numbering | Just pPr <- findChildByName ns "w" "pPr" element = let style = mapMaybe (fmap ParaStyleId . findAttrByName ns "w" "val") (findChildrenByName ns "w" "pStyle" pPr)+ pStyle' = mapMaybe (`M.lookup` sty) style in ParagraphStyle- {pStyle = mapMaybe (`M.lookup` sty) style+ {pStyle = pStyle'+ , numbered = case getNumInfo ns element of+ Just (numId, lvl) -> isJust $ lookupLevel numId lvl numbering+ Nothing -> isJust $ getParStyleField numInfo pStyle'+ , justification =+ case findChildByName ns "w" "jc" pPr >>= findAttrByName ns "w" "val" of+ Nothing -> Nothing+ Just "both" -> Just JustifyBoth+ Just "center" -> Just JustifyCenter+ Just "left" -> Just JustifyLeft+ Just "right" -> Just JustifyRight+ _ -> Nothing , indentation = getIndentation ns element , dropCap =@@ -1142,8 +1375,9 @@ ) >>= getTrackedChange ns , pBidi = checkOnOff ns pPr (elemName ns "w" "bidi")+ , pKeepNext = isJust $ findChildByName ns "w" "keepNext" pPr }-elemToParagraphStyle _ _ _ = defaultParagraphStyle+ | otherwise = defaultParagraphStyle elemToRunStyleD :: NameSpaces -> Element -> D RunStyle elemToRunStyleD ns element@@ -1166,33 +1400,35 @@ case font of Nothing -> return $ TextRun str Just f -> return . TextRun $- T.map (\x -> fromMaybe x . getUnicode f . lowerFromPrivate $ x) str+ T.map (\c -> fromMaybe c (getFontChar f c)) str | isElem ns "w" "br" element = return LnBrk | isElem ns "w" "tab" element = return Tab | isElem ns "w" "softHyphen" element = return SoftHyphen | isElem ns "w" "noBreakHyphen" element = return NoBreakHyphen | isElem ns "w" "sym" element = return (getSymChar ns element) | otherwise = throwError WrongElem- where- lowerFromPrivate (ord -> c)- | c >= ord '\xF000' = chr $ c - ord '\xF000'- | otherwise = chr c -- The char attribute is a hex string getSymChar :: NameSpaces -> Element -> RunElem getSymChar ns element- | Just s <- lowerFromPrivate <$> getCodepoint+ | Just s <- getCodepoint , Just font <- getFont = case readLitChar ("\\x" ++ T.unpack s) of- [(char, _)] -> TextRun . maybe "" T.singleton $ getUnicode font char- _ -> TextRun ""+ [(ch, _)] ->+ TextRun $ T.singleton $ fromMaybe ch $ getFontChar font ch+ _ -> TextRun "" where getCodepoint = findAttrByName ns "w" "char" element- getFont = textToFont =<< findAttrByName ns "w" "font" element- lowerFromPrivate t | "F" `T.isPrefixOf` t = "0" <> T.drop 1 t- | otherwise = t+ getFont = findAttrByName ns "w" "font" element >>= textToFont getSymChar _ _ = TextRun "" +getFontChar :: Font -> Char -> Maybe Char+getFontChar font ch = chr <$> M.lookup (font, point) symbolMap+ where+ point -- sometimes F000 is added to put char in private range:+ | ch >= '\xF000' = ord ch - 0xF000+ | otherwise = ord ch+ elemToRunElems :: NameSpaces -> Element -> D [RunElem] elemToRunElems ns element | isElem ns "w" "r" element@@ -1200,11 +1436,67 @@ let qualName = elemName ns "w" let font = do fontElem <- findElement (qualName "rFonts") element- textToFont =<<- foldr ((<|>) . (flip findAttr fontElem . qualName))+ foldr ((<|>) . (flip findAttr fontElem . qualName)) Nothing ["ascii", "hAnsi"]+ >>= textToFont local (setFont font) (mapD (elemToRunElem ns) (elChildren element)) elemToRunElems _ _ = throwError WrongElem setFont :: Maybe Font -> ReaderEnv -> ReaderEnv setFont f s = s{envFont = f}++findBlip :: Element -> Maybe Element+findBlip el = do+ blip <- filterElementName (matchQName "drawingml" "main" (Just "a") "blip") el+ -- return svg if present:+ filterElementName (\(QName tag _ _) -> tag == "svgBlip") el `mplus` pure blip++-- | Checks if any style in the style hierarchy is a caption style.+hasCaptionStyle :: ParagraphStyle -> Bool+hasCaptionStyle =+ any (isCaptionStyleName . pStyleName) . concatMap nestedStyles . pStyle+ where -- note that these are case insensitive:+ isCaptionStyleName "caption" = True+ isCaptionStyleName "table caption" = True+ isCaptionStyleName "image caption" = True+ isCaptionStyleName _ = False++ -- Gets all the style names in the style hierarchy+ nestedStyles :: ParStyle -> [ParStyle]+ nestedStyles ps = ps : maybe [] nestedStyles (psParentStyle ps)++stripCaptionLabel :: [Element] -> [Element]+stripCaptionLabel els =+ if any isNumberElt els+ then dropWhile (not . isNumberElt) els+ else els+ where+ isNumberElt el@(Element name attribs _ _) =+ (qName name == "fldSimple" &&+ case lookupAttrBy ((== "instr") . qName) attribs of+ Nothing -> False+ Just instr -> "Table" `elem` T.words instr ||+ "Figure" `elem` T.words instr) ||+ (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'
@@ -111,6 +111,7 @@ , isStrike :: Maybe Bool , isRTL :: Maybe Bool , isForceCTL :: Maybe Bool+ , rHighlight :: Maybe Text , rVertAlign :: Maybe VertAlign , rUnderline :: Maybe Text , rParentStyle :: Maybe CharStyle@@ -140,6 +141,7 @@ , isStrike = Nothing , isRTL = Nothing , isForceCTL = Nothing+ , rHighlight = Nothing , rVertAlign = Nothing , rUnderline = Nothing , rParentStyle = Nothing@@ -237,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@@ -275,6 +277,9 @@ , isStrike = checkOnOff ns rPr (elemName ns "w" "strike") , isRTL = checkOnOff ns rPr (elemName ns "w" "rtl") , isForceCTL = checkOnOff ns rPr (elemName ns "w" "cs")+ , rHighlight =+ findChildByName ns "w" "highlight" rPr >>=+ findAttrByName ns "w" "val" , rVertAlign = findChildByName ns "w" "vertAlign" rPr >>= findAttrByName ns "w" "val" >>=
@@ -0,0 +1,1085 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.Docx.Symbols+ Copyright : © 2023 John MacFarlane <jgm@berkeley.edu>+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Symbol tables for MS symbol fonts. This is needed for w:sym.+-}+module Text.Pandoc.Readers.Docx.Symbols ( Font(..),+ textToFont,+ symbolMap ) where++import Data.Text (Text)+import qualified Data.Map as M++data Font = Symbol | Wingdings | Wingdings2 | Wingdings3 | Webdings+ deriving (Show, Ord, Eq)++textToFont :: Text -> Maybe Font+textToFont "Symbol" = Just Symbol+textToFont "Wingdings" = Just Wingdings+textToFont "Wingdings 2" = Just Wingdings2+textToFont "Wingdings 3" = Just Wingdings3+textToFont "Webdings" = Just Webdings+textToFont _ = Nothing++-- \ Maps font and internal character number to Unicode code point.+symbolMap :: M.Map (Font, Int) Int+symbolMap = M.fromList+ [((Wingdings, 0x21), 0x1F589)+ ,((Wingdings, 0x22), 0x2702)+ ,((Wingdings, 0x23), 0x2701)+ ,((Wingdings, 0x24), 0x1F453)+ ,((Wingdings, 0x25), 0x1F56D)+ ,((Wingdings, 0x26), 0x1F56E)+ ,((Wingdings, 0x27), 0x1F56F)+ ,((Wingdings, 0x28), 0x1F57F)+ ,((Wingdings, 0x29), 0x2706)+ ,((Wingdings, 0x2A), 0x1F582)+ ,((Wingdings, 0x2B), 0x1F583)+ ,((Wingdings, 0x2C), 0x1F4EA)+ ,((Wingdings, 0x2D), 0x1F4EB)+ ,((Wingdings, 0x2E), 0x1F4EC)+ ,((Wingdings, 0x2F), 0x1F4ED)+ ,((Wingdings, 0x30), 0x1F4C1)+ ,((Wingdings, 0x31), 0x1F4C2)+ ,((Wingdings, 0x32), 0x1F4C4)+ ,((Wingdings, 0x33), 0x1F5CF)+ ,((Wingdings, 0x34), 0x1F5D0)+ ,((Wingdings, 0x35), 0x1F5C4)+ ,((Wingdings, 0x36), 0x231B)+ ,((Wingdings, 0x37), 0x1F5AE)+ ,((Wingdings, 0x38), 0x1F5B0)+ ,((Wingdings, 0x39), 0x1F5B2)+ ,((Wingdings, 0x3A), 0x1F5B3)+ ,((Wingdings, 0x3B), 0x1F5B4)+ ,((Wingdings, 0x3C), 0x1F5AB)+ ,((Wingdings, 0x3D), 0x1F5AC)+ ,((Wingdings, 0x3E), 0x2707)+ ,((Wingdings, 0x3F), 0x270D)+ ,((Wingdings, 0x40), 0x1F58E)+ ,((Wingdings, 0x41), 0x270C)+ ,((Wingdings, 0x42), 0x1F44C)+ ,((Wingdings, 0x43), 0x1F44D)+ ,((Wingdings, 0x44), 0x1F44E)+ ,((Wingdings, 0x45), 0x261C)+ ,((Wingdings, 0x46), 0x261E)+ ,((Wingdings, 0x47), 0x261D)+ ,((Wingdings, 0x48), 0x261F)+ ,((Wingdings, 0x49), 0x1F590)+ ,((Wingdings, 0x4A), 0x263A)+ ,((Wingdings, 0x4B), 0x1F610)+ ,((Wingdings, 0x4C), 0x2639)+ ,((Wingdings, 0x4D), 0x1F4A3)+ ,((Wingdings, 0x4E), 0x2620)+ ,((Wingdings, 0x4F), 0x1F3F3)+ ,((Wingdings, 0x50), 0x1F3F1)+ ,((Wingdings, 0x51), 0x2708)+ ,((Wingdings, 0x52), 0x263C)+ ,((Wingdings, 0x53), 0x1F4A7)+ ,((Wingdings, 0x54), 0x2744)+ ,((Wingdings, 0x55), 0x1F546)+ ,((Wingdings, 0x56), 0x271E)+ ,((Wingdings, 0x57), 0x1F548)+ ,((Wingdings, 0x58), 0x2720)+ ,((Wingdings, 0x59), 0x2721)+ ,((Wingdings, 0x5A), 0x262A)+ ,((Wingdings, 0x5B), 0x262F)+ ,((Wingdings, 0x5C), 0x0950)+ ,((Wingdings, 0x5D), 0x2638)+ ,((Wingdings, 0x5E), 0x2648)+ ,((Wingdings, 0x5F), 0x2649)+ ,((Wingdings, 0x60), 0x264A)+ ,((Wingdings, 0x61), 0x264B)+ ,((Wingdings, 0x62), 0x264C)+ ,((Wingdings, 0x63), 0x264D)+ ,((Wingdings, 0x64), 0x264E)+ ,((Wingdings, 0x65), 0x264F)+ ,((Wingdings, 0x66), 0x2650)+ ,((Wingdings, 0x67), 0x2651)+ ,((Wingdings, 0x68), 0x2652)+ ,((Wingdings, 0x69), 0x2653)+ ,((Wingdings, 0x6A), 0x1F670)+ ,((Wingdings, 0x6B), 0x1F675)+ ,((Wingdings, 0x6C), 0x25CF)+ ,((Wingdings, 0x6D), 0x1F53E)+ ,((Wingdings, 0x6E), 0x25A0)+ ,((Wingdings, 0x6F), 0x25A1)+ ,((Wingdings, 0x70), 0x1F790)+ ,((Wingdings, 0x71), 0x2751)+ ,((Wingdings, 0x72), 0x2752)+ ,((Wingdings, 0x73), 0x2B27)+ ,((Wingdings, 0x74), 0x29EB)+ ,((Wingdings, 0x75), 0x25C6)+ ,((Wingdings, 0x76), 0x2756)+ ,((Wingdings, 0x77), 0x2B25)+ ,((Wingdings, 0x78), 0x2327)+ ,((Wingdings, 0x79), 0x2BB9)+ ,((Wingdings, 0x7A), 0x2318)+ ,((Wingdings, 0x7B), 0x1F3F5)+ ,((Wingdings, 0x7C), 0x1F3F6)+ ,((Wingdings, 0x7D), 0x1F676)+ ,((Wingdings, 0x7E), 0x1F677)+ ,((Wingdings, 0x80), 0x24EA)+ ,((Wingdings, 0x81), 0x2460)+ ,((Wingdings, 0x82), 0x2461)+ ,((Wingdings, 0x83), 0x2462)+ ,((Wingdings, 0x84), 0x2463)+ ,((Wingdings, 0x85), 0x2464)+ ,((Wingdings, 0x86), 0x2465)+ ,((Wingdings, 0x87), 0x2466)+ ,((Wingdings, 0x88), 0x2467)+ ,((Wingdings, 0x89), 0x2468)+ ,((Wingdings, 0x8A), 0x2469)+ ,((Wingdings, 0x8B), 0x24FF)+ ,((Wingdings, 0x8C), 0x2776)+ ,((Wingdings, 0x8D), 0x2777)+ ,((Wingdings, 0x8E), 0x2778)+ ,((Wingdings, 0x8F), 0x2779)+ ,((Wingdings, 0x90), 0x277A)+ ,((Wingdings, 0x91), 0x277B)+ ,((Wingdings, 0x92), 0x277C)+ ,((Wingdings, 0x93), 0x277D)+ ,((Wingdings, 0x94), 0x277E)+ ,((Wingdings, 0x95), 0x277F)+ ,((Wingdings, 0x96), 0x1F662)+ ,((Wingdings, 0x97), 0x1F660)+ ,((Wingdings, 0x98), 0x1F661)+ ,((Wingdings, 0x99), 0x1F663)+ ,((Wingdings, 0x9A), 0x1F65E)+ ,((Wingdings, 0x9B), 0x1F65C)+ ,((Wingdings, 0x9C), 0x1F65D)+ ,((Wingdings, 0x9D), 0x1F65F)+ ,((Wingdings, 0x9E), 0x00B7)+ ,((Wingdings, 0x9F), 0x2022)+ ,((Wingdings, 0xA1), 0x26AA)+ ,((Wingdings, 0xA2), 0x1F786)+ ,((Wingdings, 0xA3), 0x1F788)+ ,((Wingdings, 0xA4), 0x25C9)+ ,((Wingdings, 0xA5), 0x25CE)+ ,((Wingdings, 0xA6), 0x1F53F)+ ,((Wingdings, 0xA7), 0x25AA)+ ,((Wingdings, 0xA8), 0x25FB)+ ,((Wingdings, 0xA9), 0x1F7C2)+ ,((Wingdings, 0xAA), 0x2726)+ ,((Wingdings, 0xAB), 0x2605)+ ,((Wingdings, 0xAC), 0x2736)+ ,((Wingdings, 0xAD), 0x2734)+ ,((Wingdings, 0xAE), 0x2739)+ ,((Wingdings, 0xAF), 0x2735)+ ,((Wingdings, 0xB0), 0x2BD0)+ ,((Wingdings, 0xB1), 0x2316)+ ,((Wingdings, 0xB2), 0x27E1)+ ,((Wingdings, 0xB3), 0x2311)+ ,((Wingdings, 0xB4), 0x2BD1)+ ,((Wingdings, 0xB5), 0x272A)+ ,((Wingdings, 0xB6), 0x2730)+ ,((Wingdings, 0xB7), 0x1F550)+ ,((Wingdings, 0xB8), 0x1F551)+ ,((Wingdings, 0xB9), 0x1F552)+ ,((Wingdings, 0xBA), 0x1F553)+ ,((Wingdings, 0xBB), 0x1F554)+ ,((Wingdings, 0xBC), 0x1F555)+ ,((Wingdings, 0xBD), 0x1F556)+ ,((Wingdings, 0xBE), 0x1F557)+ ,((Wingdings, 0xBF), 0x1F558)+ ,((Wingdings, 0xC0), 0x1F559)+ ,((Wingdings, 0xC1), 0x1F55A)+ ,((Wingdings, 0xC2), 0x1F55B)+ ,((Wingdings, 0xC3), 0x2BB0)+ ,((Wingdings, 0xC4), 0x2BB1)+ ,((Wingdings, 0xC5), 0x2BB2)+ ,((Wingdings, 0xC6), 0x2BB3)+ ,((Wingdings, 0xC7), 0x2BB4)+ ,((Wingdings, 0xC8), 0x2BB5)+ ,((Wingdings, 0xC9), 0x2BB6)+ ,((Wingdings, 0xCA), 0x2BB7)+ ,((Wingdings, 0xCB), 0x1F66A)+ ,((Wingdings, 0xCC), 0x1F66B)+ ,((Wingdings, 0xCD), 0x1F655)+ ,((Wingdings, 0xCE), 0x1F654)+ ,((Wingdings, 0xCF), 0x1F657)+ ,((Wingdings, 0xD0), 0x1F656)+ ,((Wingdings, 0xD1), 0x1F650)+ ,((Wingdings, 0xD2), 0x1F651)+ ,((Wingdings, 0xD3), 0x1F652)+ ,((Wingdings, 0xD4), 0x1F653)+ ,((Wingdings, 0xD5), 0x232B)+ ,((Wingdings, 0xD6), 0x2326)+ ,((Wingdings, 0xD7), 0x2B98)+ ,((Wingdings, 0xD8), 0x2B9A)+ ,((Wingdings, 0xD9), 0x2B99)+ ,((Wingdings, 0xDA), 0x2B9B)+ ,((Wingdings, 0xDB), 0x2B88)+ ,((Wingdings, 0xDC), 0x2B8A)+ ,((Wingdings, 0xDD), 0x2B89)+ ,((Wingdings, 0xDE), 0x2B8B)+ ,((Wingdings, 0xDF), 0x1F868)+ ,((Wingdings, 0xE0), 0x1F86A)+ ,((Wingdings, 0xE1), 0x1F869)+ ,((Wingdings, 0xE2), 0x1F86B)+ ,((Wingdings, 0xE3), 0x1F86C)+ ,((Wingdings, 0xE4), 0x1F86D)+ ,((Wingdings, 0xE5), 0x1F86F)+ ,((Wingdings, 0xE6), 0x1F86E)+ ,((Wingdings, 0xE7), 0x1F878)+ ,((Wingdings, 0xE8), 0x1F87A)+ ,((Wingdings, 0xE9), 0x1F879)+ ,((Wingdings, 0xEA), 0x1F87B)+ ,((Wingdings, 0xEB), 0x1F87C)+ ,((Wingdings, 0xEC), 0x1F87D)+ ,((Wingdings, 0xED), 0x1F87F)+ ,((Wingdings, 0xEE), 0x1F87E)+ ,((Wingdings, 0xEF), 0x21E6)+ ,((Wingdings, 0xF0), 0x21E8)+ ,((Wingdings, 0xF1), 0x21E7)+ ,((Wingdings, 0xF2), 0x21E9)+ ,((Wingdings, 0xF3), 0x2B04)+ ,((Wingdings, 0xF4), 0x21F3)+ ,((Wingdings, 0xF5), 0x2B00)+ ,((Wingdings, 0xF6), 0x2B01)+ ,((Wingdings, 0xF7), 0x2B03)+ ,((Wingdings, 0xF8), 0x2B02)+ ,((Wingdings, 0xF9), 0x1F8AC)+ ,((Wingdings, 0xFA), 0x1F8AD)+ ,((Wingdings, 0xFB), 0x1F5F6)+ ,((Wingdings, 0xFC), 0x2714)+ ,((Wingdings, 0xFD), 0x1F5F7)+ ,((Wingdings, 0xFE), 0x1F5F9)+ ,((Wingdings2, 0x21), 0x1F58A)+ ,((Wingdings2, 0x22), 0x1F58B)+ ,((Wingdings2, 0x23), 0x1F58C)+ ,((Wingdings2, 0x24), 0x1F58D)+ ,((Wingdings2, 0x25), 0x2704)+ ,((Wingdings2, 0x26), 0x2700)+ ,((Wingdings2, 0x27), 0x1F57E)+ ,((Wingdings2, 0x28), 0x1F57D)+ ,((Wingdings2, 0x29), 0x1F5C5)+ ,((Wingdings2, 0x2A), 0x1F5C6)+ ,((Wingdings2, 0x2B), 0x1F5C7)+ ,((Wingdings2, 0x2C), 0x1F5C8)+ ,((Wingdings2, 0x2D), 0x1F5C9)+ ,((Wingdings2, 0x2E), 0x1F5CA)+ ,((Wingdings2, 0x2F), 0x1F5CB)+ ,((Wingdings2, 0x30), 0x1F5CC)+ ,((Wingdings2, 0x31), 0x1F5CD)+ ,((Wingdings2, 0x32), 0x1F4CB)+ ,((Wingdings2, 0x33), 0x1F5D1)+ ,((Wingdings2, 0x34), 0x1F5D4)+ ,((Wingdings2, 0x35), 0x1F5B5)+ ,((Wingdings2, 0x36), 0x1F5B6)+ ,((Wingdings2, 0x37), 0x1F5B7)+ ,((Wingdings2, 0x38), 0x1F5B8)+ ,((Wingdings2, 0x39), 0x1F5AD)+ ,((Wingdings2, 0x3A), 0x1F5AF)+ ,((Wingdings2, 0x3B), 0x1F5B1)+ ,((Wingdings2, 0x3C), 0x1F592)+ ,((Wingdings2, 0x3D), 0x1F593)+ ,((Wingdings2, 0x3E), 0x1F598)+ ,((Wingdings2, 0x3F), 0x1F599)+ ,((Wingdings2, 0x40), 0x1F59A)+ ,((Wingdings2, 0x41), 0x1F59B)+ ,((Wingdings2, 0x42), 0x1F448)+ ,((Wingdings2, 0x43), 0x1F449)+ ,((Wingdings2, 0x44), 0x1F59C)+ ,((Wingdings2, 0x45), 0x1F59D)+ ,((Wingdings2, 0x46), 0x1F59E)+ ,((Wingdings2, 0x47), 0x1F59F)+ ,((Wingdings2, 0x48), 0x1F5A0)+ ,((Wingdings2, 0x49), 0x1F5A1)+ ,((Wingdings2, 0x4A), 0x1F446)+ ,((Wingdings2, 0x4B), 0x1F447)+ ,((Wingdings2, 0x4C), 0x1F5A2)+ ,((Wingdings2, 0x4D), 0x1F5A3)+ ,((Wingdings2, 0x4E), 0x1F591)+ ,((Wingdings2, 0x4F), 0x1F5F4)+ ,((Wingdings2, 0x50), 0x2713)+ ,((Wingdings2, 0x51), 0x1F5F5)+ ,((Wingdings2, 0x52), 0x2611)+ ,((Wingdings2, 0x53), 0x2612)+ ,((Wingdings2, 0x54), 0x2612)+ ,((Wingdings2, 0x55), 0x2BBE)+ ,((Wingdings2, 0x56), 0x2BBF)+ ,((Wingdings2, 0x57), 0x29B8)+ ,((Wingdings2, 0x58), 0x29B8)+ ,((Wingdings2, 0x59), 0x1F671)+ ,((Wingdings2, 0x5A), 0x1F674)+ ,((Wingdings2, 0x5B), 0x1F672)+ ,((Wingdings2, 0x5C), 0x1F673)+ ,((Wingdings2, 0x5D), 0x203D)+ ,((Wingdings2, 0x5E), 0x1F679)+ ,((Wingdings2, 0x5F), 0x1F67A)+ ,((Wingdings2, 0x60), 0x1F67B)+ ,((Wingdings2, 0x61), 0x1F666)+ ,((Wingdings2, 0x62), 0x1F664)+ ,((Wingdings2, 0x63), 0x1F665)+ ,((Wingdings2, 0x64), 0x1F667)+ ,((Wingdings2, 0x65), 0x1F65A)+ ,((Wingdings2, 0x66), 0x1F658)+ ,((Wingdings2, 0x67), 0x1F659)+ ,((Wingdings2, 0x68), 0x1F65B)+ ,((Wingdings2, 0x69), 0x24EA)+ ,((Wingdings2, 0x6A), 0x2460)+ ,((Wingdings2, 0x6B), 0x2461)+ ,((Wingdings2, 0x6C), 0x2462)+ ,((Wingdings2, 0x6D), 0x2463)+ ,((Wingdings2, 0x6E), 0x2464)+ ,((Wingdings2, 0x6F), 0x2465)+ ,((Wingdings2, 0x70), 0x2466)+ ,((Wingdings2, 0x71), 0x2467)+ ,((Wingdings2, 0x72), 0x2468)+ ,((Wingdings2, 0x73), 0x2469)+ ,((Wingdings2, 0x74), 0x24FF)+ ,((Wingdings2, 0x75), 0x2776)+ ,((Wingdings2, 0x76), 0x2777)+ ,((Wingdings2, 0x77), 0x2778)+ ,((Wingdings2, 0x78), 0x2779)+ ,((Wingdings2, 0x79), 0x277A)+ ,((Wingdings2, 0x7A), 0x277B)+ ,((Wingdings2, 0x7B), 0x277C)+ ,((Wingdings2, 0x7C), 0x277D)+ ,((Wingdings2, 0x7D), 0x277E)+ ,((Wingdings2, 0x7E), 0x277F)+ ,((Wingdings2, 0x80), 0x2609)+ ,((Wingdings2, 0x81), 0x1F315)+ ,((Wingdings2, 0x82), 0x263D)+ ,((Wingdings2, 0x83), 0x263E)+ ,((Wingdings2, 0x84), 0x2E3F)+ ,((Wingdings2, 0x85), 0x271D)+ ,((Wingdings2, 0x86), 0x1F547)+ ,((Wingdings2, 0x87), 0x1F55C)+ ,((Wingdings2, 0x88), 0x1F55D)+ ,((Wingdings2, 0x89), 0x1F55E)+ ,((Wingdings2, 0x8A), 0x1F55F)+ ,((Wingdings2, 0x8B), 0x1F560)+ ,((Wingdings2, 0x8C), 0x1F561)+ ,((Wingdings2, 0x8D), 0x1F562)+ ,((Wingdings2, 0x8E), 0x1F563)+ ,((Wingdings2, 0x8F), 0x1F564)+ ,((Wingdings2, 0x90), 0x1F565)+ ,((Wingdings2, 0x91), 0x1F566)+ ,((Wingdings2, 0x92), 0x1F567)+ ,((Wingdings2, 0x93), 0x1F668)+ ,((Wingdings2, 0x94), 0x1F669)+ ,((Wingdings2, 0x95), 0x2022)+ ,((Wingdings2, 0x96), 0x25CF)+ ,((Wingdings2, 0x97), 0x26AB)+ ,((Wingdings2, 0x98), 0x2B24)+ ,((Wingdings2, 0x99), 0x1F785)+ ,((Wingdings2, 0x9A), 0x1F786)+ ,((Wingdings2, 0x9B), 0x1F787)+ ,((Wingdings2, 0x9C), 0x1F788)+ ,((Wingdings2, 0x9D), 0x1F78A)+ ,((Wingdings2, 0x9E), 0x29BF)+ ,((Wingdings2, 0x9F), 0x25FE)+ ,((Wingdings2, 0xA1), 0x25FC)+ ,((Wingdings2, 0xA2), 0x2B1B)+ ,((Wingdings2, 0xA3), 0x2B1C)+ ,((Wingdings2, 0xA4), 0x1F791)+ ,((Wingdings2, 0xA5), 0x1F792)+ ,((Wingdings2, 0xA6), 0x1F793)+ ,((Wingdings2, 0xA7), 0x1F794)+ ,((Wingdings2, 0xA8), 0x25A3)+ ,((Wingdings2, 0xA9), 0x1F795)+ ,((Wingdings2, 0xAA), 0x1F796)+ ,((Wingdings2, 0xAB), 0x1F797)+ ,((Wingdings2, 0xAC), 0x2B29)+ ,((Wingdings2, 0xAD), 0x2B25)+ ,((Wingdings2, 0xAE), 0x25C6)+ ,((Wingdings2, 0xAF), 0x25C7)+ ,((Wingdings2, 0xB0), 0x1F79A)+ ,((Wingdings2, 0xB1), 0x25C8)+ ,((Wingdings2, 0xB2), 0x1F79B)+ ,((Wingdings2, 0xB3), 0x1F79C)+ ,((Wingdings2, 0xB4), 0x1F79D)+ ,((Wingdings2, 0xB5), 0x2B2A)+ ,((Wingdings2, 0xB6), 0x2B27)+ ,((Wingdings2, 0xB7), 0x29EB)+ ,((Wingdings2, 0xB8), 0x25CA)+ ,((Wingdings2, 0xB9), 0x1F7A0)+ ,((Wingdings2, 0xBA), 0x25D6)+ ,((Wingdings2, 0xBB), 0x25D7)+ ,((Wingdings2, 0xBC), 0x2BCA)+ ,((Wingdings2, 0xBD), 0x2BCB)+ ,((Wingdings2, 0xBE), 0x25FC)+ ,((Wingdings2, 0xBF), 0x2B25)+ ,((Wingdings2, 0xC0), 0x2B1F)+ ,((Wingdings2, 0xC1), 0x2BC2)+ ,((Wingdings2, 0xC2), 0x2B23)+ ,((Wingdings2, 0xC3), 0x2B22)+ ,((Wingdings2, 0xC4), 0x2BC3)+ ,((Wingdings2, 0xC5), 0x2BC4)+ ,((Wingdings2, 0xC6), 0x1F7A1)+ ,((Wingdings2, 0xC7), 0x1F7A2)+ ,((Wingdings2, 0xC8), 0x1F7A3)+ ,((Wingdings2, 0xC9), 0x1F7A4)+ ,((Wingdings2, 0xCA), 0x1F7A5)+ ,((Wingdings2, 0xCB), 0x1F7A6)+ ,((Wingdings2, 0xCC), 0x1F7A7)+ ,((Wingdings2, 0xCD), 0x1F7A8)+ ,((Wingdings2, 0xCE), 0x1F7A9)+ ,((Wingdings2, 0xCF), 0x1F7AA)+ ,((Wingdings2, 0xD0), 0x1F7AB)+ ,((Wingdings2, 0xD1), 0x1F7AC)+ ,((Wingdings2, 0xD2), 0x1F7AD)+ ,((Wingdings2, 0xD3), 0x1F7AE)+ ,((Wingdings2, 0xD4), 0x1F7AF)+ ,((Wingdings2, 0xD5), 0x1F7B0)+ ,((Wingdings2, 0xD6), 0x1F7B1)+ ,((Wingdings2, 0xD7), 0x1F7B2)+ ,((Wingdings2, 0xD8), 0x1F7B3)+ ,((Wingdings2, 0xD9), 0x1F7B4)+ ,((Wingdings2, 0xDA), 0x1F7B5)+ ,((Wingdings2, 0xDB), 0x1F7B6)+ ,((Wingdings2, 0xDC), 0x1F7B7)+ ,((Wingdings2, 0xDD), 0x1F7B8)+ ,((Wingdings2, 0xDE), 0x1F7B9)+ ,((Wingdings2, 0xDF), 0x1F7BA)+ ,((Wingdings2, 0xE0), 0x1F7BB)+ ,((Wingdings2, 0xE1), 0x1F7BC)+ ,((Wingdings2, 0xE2), 0x1F7BD)+ ,((Wingdings2, 0xE3), 0x1F7BE)+ ,((Wingdings2, 0xE4), 0x1F7BF)+ ,((Wingdings2, 0xE5), 0x1F7C0)+ ,((Wingdings2, 0xE6), 0x1F7C2)+ ,((Wingdings2, 0xE7), 0x1F7C4)+ ,((Wingdings2, 0xE8), 0x2726)+ ,((Wingdings2, 0xE9), 0x1F7C9)+ ,((Wingdings2, 0xEA), 0x2605)+ ,((Wingdings2, 0xEB), 0x2736)+ ,((Wingdings2, 0xEC), 0x1F7CB)+ ,((Wingdings2, 0xED), 0x2737)+ ,((Wingdings2, 0xEE), 0x1F7CF)+ ,((Wingdings2, 0xEF), 0x1F7D2)+ ,((Wingdings2, 0xF0), 0x2739)+ ,((Wingdings2, 0xF1), 0x1F7C3)+ ,((Wingdings2, 0xF2), 0x1F7C7)+ ,((Wingdings2, 0xF3), 0x272F)+ ,((Wingdings2, 0xF4), 0x1F7CD)+ ,((Wingdings2, 0xF5), 0x1F7D4)+ ,((Wingdings2, 0xF6), 0x2BCC)+ ,((Wingdings2, 0xF7), 0x2BCD)+ ,((Wingdings2, 0xF8), 0x203B)+ ,((Wingdings2, 0xF9), 0x2042)+ ,((Wingdings3, 0x21), 0x2B60)+ ,((Wingdings3, 0x22), 0x2B62)+ ,((Wingdings3, 0x23), 0x2B61)+ ,((Wingdings3, 0x24), 0x2B63)+ ,((Wingdings3, 0x25), 0x2B66)+ ,((Wingdings3, 0x26), 0x2B67)+ ,((Wingdings3, 0x27), 0x2B69)+ ,((Wingdings3, 0x28), 0x2B68)+ ,((Wingdings3, 0x29), 0x2B70)+ ,((Wingdings3, 0x2A), 0x2B72)+ ,((Wingdings3, 0x2B), 0x2B71)+ ,((Wingdings3, 0x2C), 0x2B73)+ ,((Wingdings3, 0x2D), 0x2B76)+ ,((Wingdings3, 0x2E), 0x2B78)+ ,((Wingdings3, 0x2F), 0x2B7B)+ ,((Wingdings3, 0x30), 0x2B7D)+ ,((Wingdings3, 0x31), 0x2B64)+ ,((Wingdings3, 0x32), 0x2B65)+ ,((Wingdings3, 0x33), 0x2B6A)+ ,((Wingdings3, 0x34), 0x2B6C)+ ,((Wingdings3, 0x35), 0x2B6B)+ ,((Wingdings3, 0x36), 0x2B6D)+ ,((Wingdings3, 0x37), 0x2B4D)+ ,((Wingdings3, 0x38), 0x2BA0)+ ,((Wingdings3, 0x39), 0x2BA1)+ ,((Wingdings3, 0x3A), 0x2BA2)+ ,((Wingdings3, 0x3B), 0x2BA3)+ ,((Wingdings3, 0x3C), 0x2BA4)+ ,((Wingdings3, 0x3D), 0x2BA5)+ ,((Wingdings3, 0x3E), 0x2BA6)+ ,((Wingdings3, 0x3F), 0x2BA7)+ ,((Wingdings3, 0x40), 0x2B90)+ ,((Wingdings3, 0x41), 0x2B91)+ ,((Wingdings3, 0x42), 0x2B92)+ ,((Wingdings3, 0x43), 0x2B93)+ ,((Wingdings3, 0x44), 0x2B80)+ ,((Wingdings3, 0x45), 0x2B83)+ ,((Wingdings3, 0x46), 0x2B7E)+ ,((Wingdings3, 0x47), 0x2B7F)+ ,((Wingdings3, 0x48), 0x2B84)+ ,((Wingdings3, 0x49), 0x2B86)+ ,((Wingdings3, 0x4A), 0x2B85)+ ,((Wingdings3, 0x4B), 0x2B87)+ ,((Wingdings3, 0x4C), 0x2B8F)+ ,((Wingdings3, 0x4D), 0x2B8D)+ ,((Wingdings3, 0x4E), 0x2B8E)+ ,((Wingdings3, 0x4F), 0x2B8C)+ ,((Wingdings3, 0x50), 0x2B6E)+ ,((Wingdings3, 0x51), 0x2B6F)+ ,((Wingdings3, 0x52), 0x238B)+ ,((Wingdings3, 0x53), 0x2324)+ ,((Wingdings3, 0x54), 0x2303)+ ,((Wingdings3, 0x55), 0x2325)+ ,((Wingdings3, 0x56), 0x23B5)+ ,((Wingdings3, 0x57), 0x237D)+ ,((Wingdings3, 0x58), 0x21EA)+ ,((Wingdings3, 0x59), 0x2BB8)+ ,((Wingdings3, 0x5A), 0x1F8A0)+ ,((Wingdings3, 0x5B), 0x1F8A1)+ ,((Wingdings3, 0x5C), 0x1F8A2)+ ,((Wingdings3, 0x5D), 0x1F8A3)+ ,((Wingdings3, 0x5E), 0x1F8A4)+ ,((Wingdings3, 0x5F), 0x1F8A5)+ ,((Wingdings3, 0x60), 0x1F8A6)+ ,((Wingdings3, 0x61), 0x1F8A7)+ ,((Wingdings3, 0x62), 0x1F8A8)+ ,((Wingdings3, 0x63), 0x1F8A9)+ ,((Wingdings3, 0x64), 0x1F8AA)+ ,((Wingdings3, 0x65), 0x1F8AB)+ ,((Wingdings3, 0x66), 0x2190)+ ,((Wingdings3, 0x67), 0x2192)+ ,((Wingdings3, 0x68), 0x2191)+ ,((Wingdings3, 0x69), 0x2193)+ ,((Wingdings3, 0x6A), 0x2196)+ ,((Wingdings3, 0x6B), 0x2197)+ ,((Wingdings3, 0x6C), 0x2199)+ ,((Wingdings3, 0x6D), 0x2198)+ ,((Wingdings3, 0x6E), 0x1F858)+ ,((Wingdings3, 0x6F), 0x1F859)+ ,((Wingdings3, 0x70), 0x25B2)+ ,((Wingdings3, 0x71), 0x25BC)+ ,((Wingdings3, 0x72), 0x25B3)+ ,((Wingdings3, 0x73), 0x25BD)+ ,((Wingdings3, 0x74), 0x25C4)+ ,((Wingdings3, 0x75), 0x25BA)+ ,((Wingdings3, 0x76), 0x25C1)+ ,((Wingdings3, 0x77), 0x25B7)+ ,((Wingdings3, 0x78), 0x25E3)+ ,((Wingdings3, 0x79), 0x25E2)+ ,((Wingdings3, 0x7A), 0x25E4)+ ,((Wingdings3, 0x7B), 0x25E5)+ ,((Wingdings3, 0x7C), 0x1F780)+ ,((Wingdings3, 0x7D), 0x1F782)+ ,((Wingdings3, 0x7E), 0x1F781)+ ,((Wingdings3, 0x80), 0x1F783)+ ,((Wingdings3, 0x81), 0x25B2)+ ,((Wingdings3, 0x82), 0x25BC)+ ,((Wingdings3, 0x83), 0x25C0)+ ,((Wingdings3, 0x84), 0x25B6)+ ,((Wingdings3, 0x85), 0x2B9C)+ ,((Wingdings3, 0x86), 0x2B9E)+ ,((Wingdings3, 0x87), 0x2B9D)+ ,((Wingdings3, 0x88), 0x2B9F)+ ,((Wingdings3, 0x89), 0x1F810)+ ,((Wingdings3, 0x8A), 0x1F812)+ ,((Wingdings3, 0x8B), 0x1F811)+ ,((Wingdings3, 0x8C), 0x1F813)+ ,((Wingdings3, 0x8D), 0x1F814)+ ,((Wingdings3, 0x8E), 0x1F816)+ ,((Wingdings3, 0x8F), 0x1F815)+ ,((Wingdings3, 0x90), 0x1F817)+ ,((Wingdings3, 0x91), 0x1F818)+ ,((Wingdings3, 0x92), 0x1F81A)+ ,((Wingdings3, 0x93), 0x1F819)+ ,((Wingdings3, 0x94), 0x1F81B)+ ,((Wingdings3, 0x95), 0x1F81C)+ ,((Wingdings3, 0x96), 0x1F81E)+ ,((Wingdings3, 0x97), 0x1F81D)+ ,((Wingdings3, 0x98), 0x1F81F)+ ,((Wingdings3, 0x99), 0x1F800)+ ,((Wingdings3, 0x9A), 0x1F802)+ ,((Wingdings3, 0x9B), 0x1F801)+ ,((Wingdings3, 0x9C), 0x1F803)+ ,((Wingdings3, 0x9D), 0x1F804)+ ,((Wingdings3, 0x9E), 0x1F806)+ ,((Wingdings3, 0x9F), 0x1F805)+ ,((Wingdings3, 0xA1), 0x1F808)+ ,((Wingdings3, 0xA2), 0x1F80A)+ ,((Wingdings3, 0xA3), 0x1F809)+ ,((Wingdings3, 0xA4), 0x1F80B)+ ,((Wingdings3, 0xA5), 0x1F820)+ ,((Wingdings3, 0xA6), 0x1F822)+ ,((Wingdings3, 0xA7), 0x1F824)+ ,((Wingdings3, 0xA8), 0x1F826)+ ,((Wingdings3, 0xA9), 0x1F828)+ ,((Wingdings3, 0xAA), 0x1F82A)+ ,((Wingdings3, 0xAB), 0x1F82C)+ ,((Wingdings3, 0xAC), 0x1F89C)+ ,((Wingdings3, 0xAD), 0x1F89D)+ ,((Wingdings3, 0xAE), 0x1F89E)+ ,((Wingdings3, 0xAF), 0x1F89F)+ ,((Wingdings3, 0xB0), 0x1F82E)+ ,((Wingdings3, 0xB1), 0x1F830)+ ,((Wingdings3, 0xB2), 0x1F832)+ ,((Wingdings3, 0xB3), 0x1F834)+ ,((Wingdings3, 0xB4), 0x1F836)+ ,((Wingdings3, 0xB5), 0x1F838)+ ,((Wingdings3, 0xB6), 0x1F83A)+ ,((Wingdings3, 0xB7), 0x1F839)+ ,((Wingdings3, 0xB8), 0x1F83B)+ ,((Wingdings3, 0xB9), 0x1F898)+ ,((Wingdings3, 0xBA), 0x1F89A)+ ,((Wingdings3, 0xBB), 0x1F899)+ ,((Wingdings3, 0xBC), 0x1F89B)+ ,((Wingdings3, 0xBD), 0x1F83C)+ ,((Wingdings3, 0xBE), 0x1F83E)+ ,((Wingdings3, 0xBF), 0x1F83D)+ ,((Wingdings3, 0xC0), 0x1F83F)+ ,((Wingdings3, 0xC1), 0x1F840)+ ,((Wingdings3, 0xC2), 0x1F842)+ ,((Wingdings3, 0xC3), 0x1F841)+ ,((Wingdings3, 0xC4), 0x1F843)+ ,((Wingdings3, 0xC5), 0x1F844)+ ,((Wingdings3, 0xC6), 0x1F846)+ ,((Wingdings3, 0xC7), 0x1F845)+ ,((Wingdings3, 0xC8), 0x1F847)+ ,((Wingdings3, 0xC9), 0x2BA8)+ ,((Wingdings3, 0xCA), 0x2BA9)+ ,((Wingdings3, 0xCB), 0x2BAA)+ ,((Wingdings3, 0xCC), 0x2BAB)+ ,((Wingdings3, 0xCD), 0x2BAC)+ ,((Wingdings3, 0xCE), 0x2BAD)+ ,((Wingdings3, 0xCF), 0x2BAE)+ ,((Wingdings3, 0xD0), 0x2BAF)+ ,((Wingdings3, 0xD1), 0x1F860)+ ,((Wingdings3, 0xD2), 0x1F862)+ ,((Wingdings3, 0xD3), 0x1F861)+ ,((Wingdings3, 0xD4), 0x1F863)+ ,((Wingdings3, 0xD5), 0x1F864)+ ,((Wingdings3, 0xD6), 0x1F865)+ ,((Wingdings3, 0xD7), 0x1F867)+ ,((Wingdings3, 0xD8), 0x1F866)+ ,((Wingdings3, 0xD9), 0x1F870)+ ,((Wingdings3, 0xDA), 0x1F872)+ ,((Wingdings3, 0xDB), 0x1F871)+ ,((Wingdings3, 0xDC), 0x1F873)+ ,((Wingdings3, 0xDD), 0x1F874)+ ,((Wingdings3, 0xDE), 0x1F875)+ ,((Wingdings3, 0xDF), 0x1F877)+ ,((Wingdings3, 0xE0), 0x1F876)+ ,((Wingdings3, 0xE1), 0x1F880)+ ,((Wingdings3, 0xE2), 0x1F882)+ ,((Wingdings3, 0xE3), 0x1F881)+ ,((Wingdings3, 0xE4), 0x1F883)+ ,((Wingdings3, 0xE5), 0x1F884)+ ,((Wingdings3, 0xE6), 0x1F885)+ ,((Wingdings3, 0xE7), 0x1F887)+ ,((Wingdings3, 0xE8), 0x1F886)+ ,((Wingdings3, 0xE9), 0x1F890)+ ,((Wingdings3, 0xEA), 0x1F892)+ ,((Wingdings3, 0xEB), 0x1F891)+ ,((Wingdings3, 0xEC), 0x1F893)+ ,((Wingdings3, 0xED), 0x1F894)+ ,((Wingdings3, 0xEE), 0x1F896)+ ,((Wingdings3, 0xEF), 0x1F895)+ ,((Wingdings3, 0xF0), 0x1F897)+ ,((Webdings, 0x21), 0x1F577)+ ,((Webdings, 0x22), 0x1F578)+ ,((Webdings, 0x23), 0x1F572)+ ,((Webdings, 0x24), 0x1F576)+ ,((Webdings, 0x25), 0x1F3C6)+ ,((Webdings, 0x26), 0x1F396)+ ,((Webdings, 0x27), 0x1F587)+ ,((Webdings, 0x28), 0x1F5E8)+ ,((Webdings, 0x29), 0x1F5E9)+ ,((Webdings, 0x2A), 0x1F5F0)+ ,((Webdings, 0x2B), 0x1F5F1)+ ,((Webdings, 0x2C), 0x1F336)+ ,((Webdings, 0x2D), 0x1F397)+ ,((Webdings, 0x2E), 0x1F67E)+ ,((Webdings, 0x2F), 0x1F67C)+ ,((Webdings, 0x30), 0x1F5D5)+ ,((Webdings, 0x31), 0x1F5D6)+ ,((Webdings, 0x32), 0x1F5D7)+ ,((Webdings, 0x33), 0x23F4)+ ,((Webdings, 0x34), 0x23F5)+ ,((Webdings, 0x35), 0x23F6)+ ,((Webdings, 0x36), 0x23F7)+ ,((Webdings, 0x37), 0x23EA)+ ,((Webdings, 0x38), 0x23E9)+ ,((Webdings, 0x39), 0x23EE)+ ,((Webdings, 0x3A), 0x23ED)+ ,((Webdings, 0x3B), 0x23F8)+ ,((Webdings, 0x3C), 0x23F9)+ ,((Webdings, 0x3D), 0x23FA)+ ,((Webdings, 0x3E), 0x1F5DA)+ ,((Webdings, 0x3F), 0x1F5F3)+ ,((Webdings, 0x40), 0x1F6E0)+ ,((Webdings, 0x41), 0x1F3D7)+ ,((Webdings, 0x42), 0x1F3D8)+ ,((Webdings, 0x43), 0x1F3D9)+ ,((Webdings, 0x44), 0x1F3DA)+ ,((Webdings, 0x45), 0x1F3DC)+ ,((Webdings, 0x46), 0x1F3ED)+ ,((Webdings, 0x47), 0x1F3DB)+ ,((Webdings, 0x48), 0x1F3E0)+ ,((Webdings, 0x49), 0x1F3D6)+ ,((Webdings, 0x4A), 0x1F3DD)+ ,((Webdings, 0x4B), 0x1F6E3)+ ,((Webdings, 0x4C), 0x1F50D)+ ,((Webdings, 0x4D), 0x1F3D4)+ ,((Webdings, 0x4E), 0x1F441)+ ,((Webdings, 0x4F), 0x1F442)+ ,((Webdings, 0x50), 0x1F3DE)+ ,((Webdings, 0x51), 0x1F3D5)+ ,((Webdings, 0x52), 0x1F6E4)+ ,((Webdings, 0x53), 0x1F3DF)+ ,((Webdings, 0x54), 0x1F6F3)+ ,((Webdings, 0x55), 0x1F56C)+ ,((Webdings, 0x56), 0x1F56B)+ ,((Webdings, 0x57), 0x1F568)+ ,((Webdings, 0x58), 0x1F508)+ ,((Webdings, 0x59), 0x1F394)+ ,((Webdings, 0x5A), 0x1F395)+ ,((Webdings, 0x5B), 0x1F5EC)+ ,((Webdings, 0x5C), 0x1F67D)+ ,((Webdings, 0x5D), 0x1F5ED)+ ,((Webdings, 0x5E), 0x1F5EA)+ ,((Webdings, 0x5F), 0x1F5EB)+ ,((Webdings, 0x60), 0x2B94)+ ,((Webdings, 0x61), 0x2714)+ ,((Webdings, 0x62), 0x1F6B2)+ ,((Webdings, 0x63), 0x25A1)+ ,((Webdings, 0x64), 0x1F6E1)+ ,((Webdings, 0x65), 0x1F4E6)+ ,((Webdings, 0x66), 0x1F6F1)+ ,((Webdings, 0x67), 0x25A0)+ ,((Webdings, 0x68), 0x1F691)+ ,((Webdings, 0x69), 0x1F6C8)+ ,((Webdings, 0x6A), 0x1F6E9)+ ,((Webdings, 0x6B), 0x1F6F0)+ ,((Webdings, 0x6C), 0x1F7C8)+ ,((Webdings, 0x6D), 0x1F574)+ ,((Webdings, 0x6E), 0x26AB)+ ,((Webdings, 0x6F), 0x1F6E5)+ ,((Webdings, 0x70), 0x1F694)+ ,((Webdings, 0x71), 0x1F5D8)+ ,((Webdings, 0x72), 0x1F5D9)+ ,((Webdings, 0x73), 0x2753)+ ,((Webdings, 0x74), 0x1F6F2)+ ,((Webdings, 0x75), 0x1F687)+ ,((Webdings, 0x76), 0x1F68D)+ ,((Webdings, 0x77), 0x26F3)+ ,((Webdings, 0x78), 0x1F6C7)+ ,((Webdings, 0x79), 0x2296)+ ,((Webdings, 0x7A), 0x1F6AD)+ ,((Webdings, 0x7B), 0x1F5EE)+ ,((Webdings, 0x7C), 0x007C)+ ,((Webdings, 0x7D), 0x1F5EF)+ ,((Webdings, 0x7E), 0x1F5F2)+ ,((Webdings, 0x80), 0x1F6B9)+ ,((Webdings, 0x81), 0x1F6BA)+ ,((Webdings, 0x82), 0x1F6C9)+ ,((Webdings, 0x83), 0x1F6CA)+ ,((Webdings, 0x84), 0x1F6BC)+ ,((Webdings, 0x85), 0x1F47D)+ ,((Webdings, 0x86), 0x1F3CB)+ ,((Webdings, 0x87), 0x26F7)+ ,((Webdings, 0x88), 0x1F3C2)+ ,((Webdings, 0x89), 0x1F3CC)+ ,((Webdings, 0x8A), 0x1F3CA)+ ,((Webdings, 0x8B), 0x1F3C4)+ ,((Webdings, 0x8C), 0x1F3CD)+ ,((Webdings, 0x8D), 0x1F3CE)+ ,((Webdings, 0x8E), 0x1F698)+ ,((Webdings, 0x8F), 0x1F5E0)+ ,((Webdings, 0x90), 0x1F6E2)+ ,((Webdings, 0x91), 0x1F4B0)+ ,((Webdings, 0x92), 0x1F3F7)+ ,((Webdings, 0x93), 0x1F4B3)+ ,((Webdings, 0x94), 0x1F46A)+ ,((Webdings, 0x95), 0x1F5E1)+ ,((Webdings, 0x96), 0x1F5E2)+ ,((Webdings, 0x97), 0x1F5E3)+ ,((Webdings, 0x98), 0x272F)+ ,((Webdings, 0x99), 0x1F584)+ ,((Webdings, 0x9A), 0x1F585)+ ,((Webdings, 0x9B), 0x1F583)+ ,((Webdings, 0x9C), 0x1F586)+ ,((Webdings, 0x9D), 0x1F5B9)+ ,((Webdings, 0x9E), 0x1F5BA)+ ,((Webdings, 0x9F), 0x1F5BB)+ ,((Webdings, 0xA1), 0x1F570)+ ,((Webdings, 0xA2), 0x1F5BD)+ ,((Webdings, 0xA3), 0x1F5BE)+ ,((Webdings, 0xA4), 0x1F4CB)+ ,((Webdings, 0xA5), 0x1F5D2)+ ,((Webdings, 0xA6), 0x1F5D3)+ ,((Webdings, 0xA7), 0x1F4D6)+ ,((Webdings, 0xA8), 0x1F4DA)+ ,((Webdings, 0xA9), 0x1F5DE)+ ,((Webdings, 0xAA), 0x1F5DF)+ ,((Webdings, 0xAB), 0x1F5C3)+ ,((Webdings, 0xAC), 0x1F5C2)+ ,((Webdings, 0xAD), 0x1F5BC)+ ,((Webdings, 0xAE), 0x1F3AD)+ ,((Webdings, 0xAF), 0x1F39C)+ ,((Webdings, 0xB0), 0x1F398)+ ,((Webdings, 0xB1), 0x1F399)+ ,((Webdings, 0xB2), 0x1F3A7)+ ,((Webdings, 0xB3), 0x1F4BF)+ ,((Webdings, 0xB4), 0x1F39E)+ ,((Webdings, 0xB5), 0x1F4F7)+ ,((Webdings, 0xB6), 0x1F39F)+ ,((Webdings, 0xB7), 0x1F3AC)+ ,((Webdings, 0xB8), 0x1F4FD)+ ,((Webdings, 0xB9), 0x1F4F9)+ ,((Webdings, 0xBA), 0x1F4FE)+ ,((Webdings, 0xBB), 0x1F4FB)+ ,((Webdings, 0xBC), 0x1F39A)+ ,((Webdings, 0xBD), 0x1F39B)+ ,((Webdings, 0xBE), 0x1F4FA)+ ,((Webdings, 0xBF), 0x1F4BB)+ ,((Webdings, 0xC0), 0x1F5A5)+ ,((Webdings, 0xC1), 0x1F5A6)+ ,((Webdings, 0xC2), 0x1F5A7)+ ,((Webdings, 0xC3), 0x1F579)+ ,((Webdings, 0xC4), 0x1F3AE)+ ,((Webdings, 0xC5), 0x1F57B)+ ,((Webdings, 0xC6), 0x1F57C)+ ,((Webdings, 0xC7), 0x1F4DF)+ ,((Webdings, 0xC8), 0x1F581)+ ,((Webdings, 0xC9), 0x1F580)+ ,((Webdings, 0xCA), 0x1F5A8)+ ,((Webdings, 0xCB), 0x1F5A9)+ ,((Webdings, 0xCC), 0x1F5BF)+ ,((Webdings, 0xCD), 0x1F5AA)+ ,((Webdings, 0xCE), 0x1F5DC)+ ,((Webdings, 0xCF), 0x1F512)+ ,((Webdings, 0xD0), 0x1F513)+ ,((Webdings, 0xD1), 0x1F5DD)+ ,((Webdings, 0xD2), 0x1F4E5)+ ,((Webdings, 0xD3), 0x1F4E4)+ ,((Webdings, 0xD4), 0x1F573)+ ,((Webdings, 0xD5), 0x1F323)+ ,((Webdings, 0xD6), 0x1F324)+ ,((Webdings, 0xD7), 0x1F325)+ ,((Webdings, 0xD8), 0x1F326)+ ,((Webdings, 0xD9), 0x2601)+ ,((Webdings, 0xDA), 0x1F327)+ ,((Webdings, 0xDB), 0x1F328)+ ,((Webdings, 0xDC), 0x1F329)+ ,((Webdings, 0xDD), 0x1F32A)+ ,((Webdings, 0xDE), 0x1F32C)+ ,((Webdings, 0xDF), 0x1F32B)+ ,((Webdings, 0xE0), 0x1F31C)+ ,((Webdings, 0xE1), 0x1F321)+ ,((Webdings, 0xE2), 0x1F6CB)+ ,((Webdings, 0xE3), 0x1F6CF)+ ,((Webdings, 0xE4), 0x1F37D)+ ,((Webdings, 0xE5), 0x1F378)+ ,((Webdings, 0xE6), 0x1F6CE)+ ,((Webdings, 0xE7), 0x1F6CD)+ ,((Webdings, 0xE8), 0x24C5)+ ,((Webdings, 0xE9), 0x267F)+ ,((Webdings, 0xEA), 0x1F6C6)+ ,((Webdings, 0xEB), 0x1F588)+ ,((Webdings, 0xEC), 0x1F393)+ ,((Webdings, 0xED), 0x1F5E4)+ ,((Webdings, 0xEE), 0x1F5E5)+ ,((Webdings, 0xEF), 0x1F5E6)+ ,((Webdings, 0xF0), 0x1F5E7)+ ,((Webdings, 0xF1), 0x1F6EA)+ ,((Webdings, 0xF2), 0x1F43F)+ ,((Webdings, 0xF3), 0x1F426)+ ,((Webdings, 0xF4), 0x1F41F)+ ,((Webdings, 0xF5), 0x1F415)+ ,((Webdings, 0xF6), 0x1F408)+ ,((Webdings, 0xF7), 0x1F66C)+ ,((Webdings, 0xF8), 0x1F66E)+ ,((Webdings, 0xF9), 0x1F66D)+ ,((Webdings, 0xFA), 0x1F66F)+ ,((Webdings, 0xFB), 0x1F5FA)+ ,((Webdings, 0xFC), 0x1F30D)+ ,((Webdings, 0xFD), 0x1F30F)+ ,((Webdings, 0xFE), 0x1F30E)+ ,((Webdings, 0xFF), 0x1F54A)+ ,((Symbol,0x20), 0xA0)+ ,((Symbol,0x21), 0x21)+ ,((Symbol,0x22), 0x2200)+ ,((Symbol,0x23), 0x23)+ ,((Symbol,0x24), 0x2203)+ ,((Symbol,0x25), 0x25)+ ,((Symbol,0x26), 0x26)+ ,((Symbol,0x27), 0x220B)+ ,((Symbol,0x28), 0x28)+ ,((Symbol,0x29), 0x29)+ ,((Symbol,0x2A), 0x2217)+ ,((Symbol,0x2B), 0x2B)+ ,((Symbol,0x2C), 0x2C)+ ,((Symbol,0x2D), 0x2212)+ ,((Symbol,0x2E), 0x2E)+ ,((Symbol,0x2F), 0x2F)+ ,((Symbol,0x30), 0x30)+ ,((Symbol,0x31), 0x31)+ ,((Symbol,0x32), 0x32)+ ,((Symbol,0x33), 0x33)+ ,((Symbol,0x34), 0x34)+ ,((Symbol,0x35), 0x35)+ ,((Symbol,0x36), 0x36)+ ,((Symbol,0x37), 0x37)+ ,((Symbol,0x38), 0x38)+ ,((Symbol,0x39), 0x39)+ ,((Symbol,0x3A), 0x3A)+ ,((Symbol,0x3B), 0x3B)+ ,((Symbol,0x3C), 0x3C)+ ,((Symbol,0x3D), 0x3D)+ ,((Symbol,0x3E), 0x3E)+ ,((Symbol,0x3F), 0x3F)+ ,((Symbol,0x40), 0x2245)+ ,((Symbol,0x41), 0x391)+ ,((Symbol,0x42), 0x392)+ ,((Symbol,0x43), 0x3A7)+ ,((Symbol,0x44), 0x2206)+ ,((Symbol,0x45), 0x395)+ ,((Symbol,0x46), 0x3A6)+ ,((Symbol,0x47), 0x393)+ ,((Symbol,0x48), 0x397)+ ,((Symbol,0x49), 0x399)+ ,((Symbol,0x4A), 0x3D1)+ ,((Symbol,0x4B), 0x39A)+ ,((Symbol,0x4C), 0x39B)+ ,((Symbol,0x4D), 0x39C)+ ,((Symbol,0x4E), 0x39D)+ ,((Symbol,0x4F), 0x39F)+ ,((Symbol,0x50), 0x3A0)+ ,((Symbol,0x51), 0x398)+ ,((Symbol,0x52), 0x3A1)+ ,((Symbol,0x53), 0x3A3)+ ,((Symbol,0x54), 0x3A4)+ ,((Symbol,0x55), 0x3A5)+ ,((Symbol,0x56), 0x3C2)+ ,((Symbol,0x57), 0x2126)+ ,((Symbol,0x58), 0x39E)+ ,((Symbol,0x59), 0x3A8)+ ,((Symbol,0x5A), 0x396)+ ,((Symbol,0x5B), 0x5B)+ ,((Symbol,0x5C), 0x2234)+ ,((Symbol,0x5D), 0x5D)+ ,((Symbol,0x5E), 0x22A5)+ ,((Symbol,0x5F), 0x5F)+ ,((Symbol,0x60), 0xF8E5)+ ,((Symbol,0x61), 0x3B1)+ ,((Symbol,0x62), 0x3B2)+ ,((Symbol,0x63), 0x3C7)+ ,((Symbol,0x64), 0x3B4)+ ,((Symbol,0x65), 0x3B5)+ ,((Symbol,0x66), 0x3C6)+ ,((Symbol,0x67), 0x3B3)+ ,((Symbol,0x68), 0x3B7)+ ,((Symbol,0x69), 0x3B9)+ ,((Symbol,0x6A), 0x3D5)+ ,((Symbol,0x6B), 0x3BA)+ ,((Symbol,0x6C), 0x3BB)+ ,((Symbol,0x6D), 0x3BC)+ ,((Symbol,0x6E), 0x3BD)+ ,((Symbol,0x6F), 0x3BF)+ ,((Symbol,0x70), 0x3C0)+ ,((Symbol,0x71), 0x3B8)+ ,((Symbol,0x72), 0x3C1)+ ,((Symbol,0x73), 0x3C3)+ ,((Symbol,0x74), 0x3C4)+ ,((Symbol,0x75), 0x3C5)+ ,((Symbol,0x76), 0x3D6)+ ,((Symbol,0x77), 0x3C9)+ ,((Symbol,0x78), 0x3BE)+ ,((Symbol,0x79), 0x3C8)+ ,((Symbol,0x7A), 0x3B6)+ ,((Symbol,0x7B), 0x7B)+ ,((Symbol,0x7C), 0x7C)+ ,((Symbol,0x7D), 0x7D)+ ,((Symbol,0x7E), 0x223C)+ ,((Symbol,0xA0), 0x20AC)+ ,((Symbol,0xA1), 0x3D2)+ ,((Symbol,0xA2), 0x2032)+ ,((Symbol,0xA3), 0x2264)+ ,((Symbol,0xA4), 0x2215)+ ,((Symbol,0xA5), 0x221E)+ ,((Symbol,0xA6), 0x192)+ ,((Symbol,0xA7), 0x2663)+ ,((Symbol,0xA8), 0x2666)+ ,((Symbol,0xA9), 0x2665)+ ,((Symbol,0xAA), 0x2660)+ ,((Symbol,0xAB), 0x2194)+ ,((Symbol,0xAC), 0x2190)+ ,((Symbol,0xAD), 0x2191)+ ,((Symbol,0xAE), 0x2192)+ ,((Symbol,0xAF), 0x2193)+ ,((Symbol,0xB0), 0xB0)+ ,((Symbol,0xB1), 0xB1)+ ,((Symbol,0xB2), 0x2033)+ ,((Symbol,0xB3), 0x2265)+ ,((Symbol,0xB4), 0xD7)+ ,((Symbol,0xB5), 0x221D)+ ,((Symbol,0xB6), 0x2202)+ ,((Symbol,0xB7), 0x2022)+ ,((Symbol,0xB8), 0xF7)+ ,((Symbol,0xB9), 0x2260)+ ,((Symbol,0xBA), 0x2261)+ ,((Symbol,0xBB), 0x2248)+ ,((Symbol,0xBC), 0x2026)+ ,((Symbol,0xBD), 0xF8E6)+ ,((Symbol,0xBE), 0xF8E7)+ ,((Symbol,0xBF), 0x21B5)+ ,((Symbol,0xC0), 0x2135)+ ,((Symbol,0xC1), 0x2111)+ ,((Symbol,0xC2), 0x211C)+ ,((Symbol,0xC3), 0x2118)+ ,((Symbol,0xC4), 0x2297)+ ,((Symbol,0xC5), 0x2295)+ ,((Symbol,0xC6), 0x2205)+ ,((Symbol,0xC7), 0x2229)+ ,((Symbol,0xC8), 0x222A)+ ,((Symbol,0xC9), 0x2283)+ ,((Symbol,0xCA), 0x2287)+ ,((Symbol,0xCB), 0x2284)+ ,((Symbol,0xCC), 0x2282)+ ,((Symbol,0xCD), 0x2286)+ ,((Symbol,0xCE), 0x2208)+ ,((Symbol,0xCF), 0x2209)+ ,((Symbol,0xD0), 0x2220)+ ,((Symbol,0xD1), 0x2207)+ ,((Symbol,0xD2), 0xF6DA)+ ,((Symbol,0xD3), 0xF6D9)+ ,((Symbol,0xD4), 0xF6DB)+ ,((Symbol,0xD5), 0x220F)+ ,((Symbol,0xD6), 0x221A)+ ,((Symbol,0xD7), 0x22C5)+ ,((Symbol,0xD8), 0xAC)+ ,((Symbol,0xD9), 0x2227)+ ,((Symbol,0xDA), 0x2228)+ ,((Symbol,0xDB), 0x21D4)+ ,((Symbol,0xDC), 0x21D0)+ ,((Symbol,0xDD), 0x21D1)+ ,((Symbol,0xDE), 0x21D2)+ ,((Symbol,0xDF), 0x21D3)+ ,((Symbol,0xE0), 0x25CA)+ ,((Symbol,0xE1), 0x2329)+ ,((Symbol,0xE2), 0xF8E8)+ ,((Symbol,0xE3), 0xF8E9)+ ,((Symbol,0xE4), 0xF8EA)+ ,((Symbol,0xE5), 0x2211)+ ,((Symbol,0xE6), 0xF8EB)+ ,((Symbol,0xE7), 0xF8EC)+ ,((Symbol,0xE8), 0xF8ED)+ ,((Symbol,0xE9), 0xF8EE)+ ,((Symbol,0xEA), 0xF8EF)+ ,((Symbol,0xEB), 0xF8F0)+ ,((Symbol,0xEC), 0xF8F1)+ ,((Symbol,0xED), 0xF8F2)+ ,((Symbol,0xEE), 0xF8F3)+ ,((Symbol,0xEF), 0xF8F4)+ ,((Symbol,0xF1), 0x232A)+ ,((Symbol,0xF2), 0x222B)+ ,((Symbol,0xF3), 0x2320)+ ,((Symbol,0xF4), 0xF8F5)+ ,((Symbol,0xF5), 0x2321)+ ,((Symbol,0xF6), 0xF8F6)+ ,((Symbol,0xF7), 0xF8F7)+ ,((Symbol,0xF8), 0xF8F8)+ ,((Symbol,0xF9), 0xF8F9)+ ,((Symbol,0xFA), 0xF8FA)+ ,((Symbol,0xFB), 0xF8FB)+ ,((Symbol,0xFC), 0xF8FC)+ ,((Symbol,0xFD), 0xF8FD)+ ,((Symbol,0xFE), 0xF8FE)+ ]
@@ -1,8 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} {- |- Module : Text.Pandoc.Readers.Docx.StyleMaps+ Module : Text.Pandoc.Readers.Docx.Util Copyright : © 2014-2020 Jesse Rosenthal <jrosenthal@jhu.edu>,- 2014-2022 John MacFarlane <jgm@berkeley.edu>,+ 2014-2024 John MacFarlane <jgm@berkeley.edu>, 2015 Nikolay Yakimov <root@livid.pp.ru> License : GNU GPL, version 2 or above @@ -21,50 +21,25 @@ , findChildrenByName , findElementByName , findAttrByName+ , extractChildren ) where -import qualified Data.Text as T-import Data.Text (Text)+import Data.List (partition) import Text.Pandoc.XML.Light-import qualified Data.Map as M+import Text.Pandoc.Readers.OOXML.Shared+ (NameSpaces, elemName, isElem, elemToNameSpaces,+ findChildByName, findChildrenByName, findElementByName, findAttrByName) -type NameSpaces = M.Map Text Text -elemToNameSpaces :: Element -> NameSpaces-elemToNameSpaces = foldr (\(Attr qn val) ->- case qn of- QName s _ (Just "xmlns") -> M.insert s val- _ -> id) mempty . elAttribs--elemName :: NameSpaces -> Text -> Text -> QName-elemName ns prefix name =- QName name (M.lookup prefix ns)- (if T.null prefix then Nothing else Just prefix)--isElem :: NameSpaces -> Text -> Text -> Element -> Bool-isElem ns prefix name element =- let ns' = ns <> elemToNameSpaces element- in qName (elName element) == name &&- qURI (elName element) == M.lookup prefix ns'--findChildByName :: NameSpaces -> Text -> Text -> Element -> Maybe Element-findChildByName ns pref name el =- let ns' = ns <> elemToNameSpaces el- in findChild (elemName ns' pref name) el--findChildrenByName :: NameSpaces -> Text -> Text -> Element -> [Element]-findChildrenByName ns pref name el =- let ns' = ns <> elemToNameSpaces el- in findChildren (elemName ns' pref name) el---- | Like 'findChildrenByName', but searches descendants.-findElementByName :: NameSpaces -> Text -> Text -> Element -> Maybe Element-findElementByName ns pref name el =- let ns' = ns <> elemToNameSpaces el- in findElement (elemName ns' pref name) el--findAttrByName :: NameSpaces -> Text -> Text -> Element -> Maybe Text-findAttrByName ns pref name el =- let ns' = ns <> elemToNameSpaces el- in findAttr (elemName ns' pref name) el+-- | Removes child elements that satisfy a given condition.+-- Returns the modified element and the list of removed children.+extractChildren :: Element -> (Element -> Bool) -> Maybe (Element, [Element])+extractChildren el condition+ | null removedChildren = Nothing -- No children removed, return Nothing+ | otherwise = Just (modifiedElement, removedChildren) -- Children removed, return Just+ where+ -- Separate the children based on the condition+ (removedChildren, keptChildren) = partition condition (onlyElems $ elContent el) + -- Reconstruct the element with the kept children+ modifiedElement = el { elContent = map Elem keptChildren }
@@ -26,11 +26,10 @@ import qualified Text.Pandoc.Builder as B import Text.Pandoc.Class.PandocMonad (PandocMonad (..)) import Text.Pandoc.Definition-import Text.Pandoc.Error (PandocError (PandocParsecError)) import Text.Pandoc.Options-import Text.Pandoc.Parsing hiding (enclosed, nested)+import Text.Pandoc.Parsing hiding (enclosed) import Text.Pandoc.Shared (trim, stringify, tshow)-import Data.List (isPrefixOf, isSuffixOf)+import Data.List (isPrefixOf, isSuffixOf, groupBy) import qualified Safe -- | Read DokuWiki from an input string and return a Pandoc document.@@ -43,26 +42,17 @@ res <- runParserT parseDokuWiki def {stateOptions = opts } (initialSourceName sources) sources case res of- Left e -> throwError $ PandocParsecError sources e+ Left e -> throwError $ fromParsecError sources e Right d -> return d -type DWParser = ParserT Sources ParserState+type DWParser = ParsecT Sources ParserState -- * Utility functions -- | Parse end-of-line, which can be either a newline or end-of-file.-eol :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m ()+eol :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m () eol = void newline <|> eof -nested :: PandocMonad m => DWParser m a -> DWParser m a-nested p = do- nestlevel <- stateMaxNestingLevel <$> getState- guard $ nestlevel > 0- updateState $ \st -> st{ stateMaxNestingLevel = stateMaxNestingLevel st - 1 }- res <- p- updateState $ \st -> st{ stateMaxNestingLevel = nestlevel }- return res- guardColumnOne :: PandocMonad m => DWParser m () guardColumnOne = getPosition >>= \pos -> guard (sourceColumn pos == 1) @@ -115,14 +105,13 @@ <|> superscript <|> deleted <|> footnote- <|> inlineCode- <|> inlineFile <|> inlineRaw <|> math <|> autoLink <|> autoEmail <|> notoc <|> nocache+ <|> smartPunctuation inline <|> str <|> symbol <?> "inline"@@ -164,7 +153,7 @@ nestedInlines end = innerSpace <|> nestedInline where innerSpace = try $ whitespace <* notFollowedBy end- nestedInline = notFollowedBy whitespace >> nested inline+ nestedInline = notFollowedBy whitespace >> inline bold :: PandocMonad m => DWParser m B.Inlines bold = try $ B.strong <$> enclosed (string "**") nestedInlines@@ -203,12 +192,6 @@ footnote :: PandocMonad m => DWParser m B.Inlines footnote = try $ B.note . B.para <$> between (string "((") (try $ string "))") nestedInlines -inlineCode :: PandocMonad m => DWParser m B.Inlines-inlineCode = codeTag B.codeWith "code"--inlineFile :: PandocMonad m => DWParser m B.Inlines-inlineFile = codeTag B.codeWith "file"- inlineRaw :: PandocMonad m => DWParser m B.Inlines inlineRaw = try $ do char '<'@@ -240,6 +223,7 @@ state <- getState guard $ stateAllowLinks state (text, url) <- uri+ guard $ not $ T.isInfixOf "%%//%%" text -- see #9153 guard $ checkLink (T.last url) return $ makeLink (text, url) where@@ -254,10 +238,10 @@ nocache = try $ mempty <$ string "~~NOCACHE~~" str :: PandocMonad m => DWParser m B.Inlines-str = B.str <$> (many1Char alphaNum <|> countChar 1 characterReference)+str = B.str <$> (many1Char alphaNum <|> characterReference) symbol :: PandocMonad m => DWParser m B.Inlines-symbol = B.str <$> countChar 1 nonspaceChar+symbol = B.str <$> (notFollowedBy' blockCode *> countChar 1 nonspaceChar) link :: PandocMonad m => DWParser m B.Inlines link = try $ do@@ -317,8 +301,11 @@ parseLink f l r = f <$ textStr l <*> many1TillChar anyChar (lookAhead (void (char '|') <|> try (void $ textStr r)))- <*> optionMaybe (B.trimInlines . mconcat <$> (char '|' *> manyTill inline (try $ lookAhead $ textStr r)))- <* textStr r+ <*> ( (char '|' *> optionMaybe (B.trimInlines . B.text . T.pack <$>+ many1Till anyChar (lookAhead (try (textStr r)))))+ <|> pure Nothing+ )+ <* textStr r -- | Split Interwiki link into left and right part -- | Return Nothing if it is not Interwiki link@@ -399,7 +386,11 @@ parameterList = T.splitOn "&" $ T.drop 1 parameters linkOnly = "linkonly" `elem` parameterList (width, height) = maybe (Nothing, Nothing) parseWidthHeight (F.find isWidthHeightParameter parameterList)- attributes = catMaybes [fmap ("width",) width, fmap ("height",) height]+ attributes = catMaybes [+ fmap ("width",) width,+ fmap ("height",) height,+ fmap ("query",) (if T.null parameters then Nothing else Just parameters)+ ] defaultDescription = B.str $ urlToText path' -- * Block parsers@@ -420,7 +411,6 @@ <|> indentedCode <|> quote <|> blockCode- <|> blockFile <|> blockRaw <|> table @@ -454,23 +444,49 @@ many1 ((<>) <$> item <*> fmap mconcat (many continuation)) where continuation = try $ list (" " <> prefix)- item = try $ textStr prefix *> char marker *> char ' ' *> itemContents- itemContents = B.plain . mconcat <$> many1Till inline' eol+ item = try $ textStr prefix *>+ optional (char ' ') *> -- see #8863+ char marker *> char ' ' *>+ (mconcat <$> many1 itemContents <* eol)+ itemContents = (B.plain . mconcat <$> many1 inline') <|>+ blockCode indentedCode :: PandocMonad m => DWParser m B.Blocks indentedCode = try $ B.codeBlock . T.unlines <$> many1 indentedLine where indentedLine = try $ string " " *> manyTillChar anyChar eol +-- Note that block quotes in dokuwiki parse as lists of hard-break+-- separated lines; see #6461. quote :: PandocMonad m => DWParser m B.Blocks-quote = try $ nestedQuote 0- where- prefix level = count level (char '>')- contents level = nestedQuote level <|> quoteLine- quoteLine = try $ B.plain . B.trimInlines . mconcat <$> many1Till inline' eol- quoteContents level = (<>) <$> contents level <*> quoteContinuation level- quoteContinuation level = mconcat <$> many (try $ prefix level *> contents level)- nestedQuote level = B.blockQuote <$ char '>' <*> quoteContents (level + 1 :: Int)+quote = go <$> many1 blockQuoteLine+ where+ blockQuoteLine = try $ do+ lev <- length <$> many1 (char '>')+ skipMany spaceChar+ contents <- (blockCode <* skipMany spaceChar <* optional eol) <|>+ (B.plain . B.trimInlines . mconcat <$> many1Till inline' eol)+ pure (lev, contents)+ go [] = mempty+ go xs = mconcat $ map go' (groupBy (\(x,_) (y,_) -> (x == 0 && y == 0) ||+ (x > 0 && y > 0)) xs)+ go' [] = mempty+ go' xs@((0,_):_) =+ let (lns, bls) = F.foldl' consolidatePlains (mempty,mempty) (map snd xs)+ in bls <> if lns == mempty+ then mempty+ else B.plain lns+ go' xs = B.blockQuote (go $ map (\(x,y) -> (x - 1, y)) xs)+ consolidatePlains (lns, bls) b =+ case B.toList b of+ [Plain ils] -> ((if lns == mempty+ then B.fromList ils+ else lns <> B.linebreak <> B.fromList ils), bls)+ _ -> (mempty, bls <>+ (if lns == lns+ then mempty+ else B.plain lns)+ <> b) blockRaw :: PandocMonad m => DWParser m B.Blocks blockRaw = try $ do@@ -492,7 +508,7 @@ rows <- tableRows let firstRow = fromMaybe [] . Safe.headMay $ rows let (headerRow, body) = if firstSeparator == '^'- then (firstRow, tail rows)+ then (firstRow, drop 1 rows) else ([], rows) -- Since Pandoc only has column level alignment, we have to make an arbitrary -- choice of how to reconcile potentially different alignments in the row.@@ -539,10 +555,8 @@ blockCode :: PandocMonad m => DWParser m B.Blocks-blockCode = codeTag B.codeBlockWith "code"--blockFile :: PandocMonad m => DWParser m B.Blocks-blockFile = codeTag B.codeBlockWith "file"+blockCode = codeTag B.codeBlockWith "code" <|>+ codeTag B.codeBlockWith "file" para :: PandocMonad m => DWParser m B.Blocks para = result . mconcat <$> many1Till inline endOfParaElement@@ -550,7 +564,8 @@ endOfParaElement = lookAhead $ endOfInput <|> endOfPara <|> newBlockElement endOfInput = try $ skipMany blankline >> skipSpaces >> eof endOfPara = try $ blankline >> skipMany1 blankline- newBlockElement = try $ blankline >> void blockElements+ newBlockElement = try (blankline >> void blockElements)+ <|> lookAhead (void blockCode) result content = if F.all (==Space) content then mempty else B.para $ B.trimInlines content
@@ -29,7 +29,7 @@ import Data.Maybe (mapMaybe) import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Encoding as TL-import Network.URI (unEscapeString)+import Network.URI (unEscapeString, parseRelativeReference, URI(..)) import System.FilePath (dropFileName, dropFileName, normalise, splitFileName, takeFileName, (</>)) import qualified Text.Pandoc.Builder as B@@ -40,7 +40,8 @@ import Text.Pandoc.MIME (MimeType) import Text.Pandoc.Options (ReaderOptions (..)) import Text.Pandoc.Readers.HTML (readHtml)-import Text.Pandoc.Shared (addMetaField, collapseFilePath, escapeURI, tshow)+import Text.Pandoc.Shared (addMetaField, collapseFilePath, tshow)+import Text.Pandoc.URI (escapeURI) import qualified Text.Pandoc.UTF8 as UTF8 (toTextLazy) import Text.Pandoc.Walk (query, walk) import Text.Pandoc.XML.Light@@ -50,7 +51,8 @@ readEPUB :: PandocMonad m => ReaderOptions -> BL.ByteString -> m Pandoc readEPUB opts bytes = case toArchiveOrFail bytes of Right archive -> archiveToEPUB opts archive- Left _ -> throwError $ PandocParseError "Couldn't extract ePub file"+ Left e -> throwError $ PandocParseError $+ "Couldn't extract ePub file: " <> T.pack e -- runEPUB :: Except PandocError a -> Either PandocError a -- runEPUB = runExcept@@ -209,10 +211,17 @@ Span (fixAttrs s as) v fixInlineIRs s (Code as code) = Code (fixAttrs s as) code-fixInlineIRs s (Link as is (T.uncons -> Just ('#', url), tit)) =- Link (fixAttrs s as) is (addHash s url, tit)-fixInlineIRs s (Link as is t) =- Link (fixAttrs s as) is t+fixInlineIRs s (Link as is (url, tit)) =+ case parseRelativeReference (T.unpack url) of+ Just URI{ uriScheme = ""+ , uriAuthority = Nothing+ , uriPath = upath+ , uriQuery = ""+ , uriFragment = '#':ufrag } ->+ Link (fixAttrs s as) is (addHash (if null upath+ then s+ else upath) (T.pack ufrag), tit)+ _ -> Link (fixAttrs s as) is (url, tit) fixInlineIRs _ v = v prependHash :: [Text] -> Inline -> Inline@@ -237,7 +246,7 @@ addHash :: FilePath -> Text -> Text addHash _ "" = ""-addHash s ident = T.pack (takeFileName s) <> "#" <> ident+addHash s ident = T.pack (takeFileName s) <> "_" <> ident removeEPUBAttrs :: [(Text, Text)] -> [(Text, Text)] removeEPUBAttrs kvs = filter (not . isEPUBAttr) kvs
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.EndNote- Copyright : Copyright (C) 2022 John MacFarlane+ Copyright : Copyright (C) 2022-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -30,7 +30,7 @@ import Text.Pandoc.Class (PandocMonad) import Text.Pandoc.Citeproc.MetaValue (referenceToMetaValue) import Text.Pandoc.Sources (Sources(..), ToSources(..), sourcesToText)-import Text.Pandoc.Citeproc.BibTeX (toName)+import Text.Pandoc.Citeproc.Name (toName, NameOpts(..)) import Control.Applicative ((<|>)) import Control.Monad.Except (throwError) import Control.Monad (mzero, unless)@@ -72,15 +72,18 @@ B.doc mempty readEndNoteXMLCitation :: PandocMonad m- => Sources -> m (Citeproc.Citation Text)-readEndNoteXMLCitation sources = do- tree <- either (throwError . PandocXMLError "") return $- parseXMLElement (TL.fromStrict . sourcesToText $ sources)+ => Text -> m (Citeproc.Citation Text)+readEndNoteXMLCitation xml = do+ tree <- either (throwError . PandocXMLError "EndNote references") return $+ parseXMLElement (TL.fromStrict xml) unless (qName (elName tree) == "EndNote") $- throwError $ PandocXMLError "" "Expected EndNote element"+ throwError $ PandocXMLError "EndNote references" "Expected EndNote element" let items = map toCitationItem $ filterElementsName (name "Cite") tree return $ Citeproc.Citation{ Citeproc.citationId = Nothing+ , Citeproc.citationResetPosition = False+ , Citeproc.citationPrefix = Nothing+ , Citeproc.citationSuffix = Nothing , Citeproc.citationNoteNumber = Nothing , Citeproc.citationItems = items }@@ -88,7 +91,7 @@ readEndNoteXMLReferences :: PandocMonad m => Sources -> m [Reference Text] readEndNoteXMLReferences sources = do- tree <- either (throwError . PandocXMLError "") return $+ tree <- either (throwError . PandocXMLError "EndNote references") return $ parseXMLElement (TL.fromStrict . sourcesToText $ sources) let records = filterElementsName (name "record") tree return $ map recordToReference records@@ -140,7 +143,9 @@ filterChildrenName (name "contributors") e >>= filterChildrenName (name "authors") >>= filterChildrenName (name "author") >>=- toName [] . B.toList . B.text . T.strip . getText+ toName NameOpts{ nameOptsPrefixIsNonDroppingParticle = False+ , nameOptsUseJuniorComma = False }+ . B.toList . B.text . T.strip . getText titles = do x <- filterChildrenName (name "titles") e (key, name') <- [("title", "title"),
@@ -25,7 +25,7 @@ module Text.Pandoc.Readers.FB2 ( readFB2 ) where import Control.Monad.Except (throwError) import Control.Monad.State.Strict-import Data.ByteString.Lazy.Base64+import Data.ByteString.Base64.Lazy import Data.Functor import Data.List (intersperse) import qualified Data.Map as M@@ -34,7 +34,7 @@ import qualified Data.Text.Lazy as TL import Data.Default import Data.Maybe-import Text.HTML.TagSoup.Entity (lookupEntity)+import Text.Pandoc.XML (lookupEntity) import Text.Pandoc.Builder import Text.Pandoc.Class.PandocMonad (PandocMonad, insertMedia, report) import Text.Pandoc.Error@@ -88,7 +88,7 @@ _ -> t convertEntity :: Text -> Text-convertEntity e = maybe (T.toUpper e) T.pack $ lookupEntity (T.unpack e)+convertEntity e = fromMaybe (T.toUpper e) $ lookupEntity e parseInline :: PandocMonad m => Content -> FB2 m Inlines parseInline (Elem e) =@@ -202,7 +202,7 @@ report $ IgnoredElement "binary without content-type attribute" (Just filename, contentType) -> insertMedia (T.unpack filename) contentType- (decodeBase64Lenient+ (decodeLenient (UTF8.fromTextLazy . TL.fromStrict . strContent $ e)) -- * Type parsers
@@ -5,7 +5,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Readers.HTML- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -21,20 +21,21 @@ , isBlockTag , isTextTag , isCommentTag+ , toAttr ) where import Control.Applicative ((<|>))-import Control.Monad (guard, msum, mzero, unless, void)+import Control.Monad (guard, mzero, unless, void) import Control.Monad.Except (throwError, catchError) import Control.Monad.Reader (ask, asks, lift, local, runReaderT)-import Data.Text.Encoding.Base64 (encodeBase64)+import Data.ByteString.Base64 (encode) import Data.Char (isAlphaNum, isLetter) import Data.Default (Default (..), def) import Data.Foldable (for_) import Data.List.Split (splitWhen)-import Data.List (foldl')+import qualified Data.List as L import qualified Data.Map as M-import Data.Maybe (fromMaybe, isJust, isNothing)+import Data.Either (partitionEithers) import Data.Monoid (First (..)) import qualified Data.Set as Set import Data.Text (Text)@@ -62,11 +63,13 @@ extensionEnabled) import Text.Pandoc.Parsing hiding ((<|>)) import Text.Pandoc.Shared (- addMetaField, blocksToInlines', escapeURI, extractSpaces,- htmlSpanLikeElements, renderTags', safeRead, tshow, formatCode)+ addMetaField, extractSpaces, htmlSpanLikeElements, renderTags',+ safeRead, tshow, formatCode)+import Text.Pandoc.URI (escapeURI) import Text.Pandoc.Walk-import Text.Parsec.Error import Text.TeXMath (readMathML, writeTeX)+import qualified Data.Sequence as Seq+import Data.Maybe (fromMaybe, isJust) -- | Convert HTML-formatted string to 'Pandoc' document. readHtml :: (PandocMonad m, ToSources a)@@ -82,7 +85,7 @@ meta <- stateMeta . parserState <$> getState bs' <- replaceNotes (B.toList blocks) reportLogMessages- return $ Pandoc meta bs'+ return $ Pandoc meta $ extractMain bs' getError (errorMessages -> ms) = case ms of [] -> "" (m:_) -> messageString m@@ -95,6 +98,20 @@ Right doc -> return doc Left err -> throwError $ PandocParseError $ T.pack $ getError err +-- Extract contents of main element if exactly one is present; otherwise+-- return all blocks.+extractMain :: [Block] -> [Block]+extractMain bs =+ case query getMain bs of+ [] -> bs+ [Div ("",[],_) bs'] -> bs'+ bs' -> bs'+ where+ getMain :: Block -> [Block]+ getMain b@(Div (_,_,kvs) _)+ | Just "main" <- lookup "role" kvs = [b]+ getMain _ = []+ -- Strip namespace prefixes on tags (not attributes) stripPrefixes :: [Tag Text] -> [Tag Text] stripPrefixes = map stripPrefix@@ -126,6 +143,10 @@ setInPlain :: PandocMonad m => HTMLParser m s a -> HTMLParser m s a setInPlain = local (\s -> s {inPlain = True}) +-- Some items should be handled differently when in a list item tag, e.g. checkbox+setInListItem :: PandocMonad m => HTMLParser m s a -> HTMLParser m s a+setInListItem = local (\s -> s {inListItem = True})+ pHtml :: PandocMonad m => TagParser m Blocks pHtml = do (TagOpen "html" attr) <- lookAhead pAny@@ -171,6 +192,7 @@ TagOpen name attr -> let type' = fromMaybe "" $ lookup "type" attr <|> lookup "epub:type" attr+ role = fromMaybe "" $ lookup "role" attr epubExts = extensionEnabled Ext_epub_html_exts exts in case name of@@ -190,6 +212,8 @@ _ | "titlepage" `T.isInfixOf` type' , name `elem` ("section" : groupingContent) -> mempty <$ eTitlePage+ _ | role == "doc-endnotes"+ -> eFootnotes "p" -> pPara "h1" -> pHeader "h2" -> pHeader@@ -213,6 +237,7 @@ -> pLineBlock | otherwise -> pDiv+ "aside" -> pDiv "section" -> pDiv "header" -> pDiv "main" -> pDiv@@ -260,14 +285,14 @@ eFootnote :: PandocMonad m => TagParser m () eFootnote = do- guardEnabled Ext_epub_html_exts+ inNotes <- inFootnotes <$> getState TagOpen tag attr' <- lookAhead $ pSatisfy (\case TagOpen _ attr' -> case lookup "type" attr' <|> lookup "epub:type" attr' of Just "footnote" -> True Just "rearnote" -> True- _ -> False+ _ -> inNotes _ -> False) let attr = toStringAttr attr' let ident = fromMaybe "" (lookup "id" attr)@@ -278,11 +303,12 @@ eFootnotes :: PandocMonad m => TagParser m Blocks eFootnotes = try $ do let notes = ["footnotes", "rearnotes"]- guardEnabled Ext_epub_html_exts (TagOpen tag attr') <- lookAhead pAny let attr = toStringAttr attr'- guard $ maybe False (`elem` notes)- (lookup "type" attr <|> lookup "epub:type" attr)+ guard (lookup "role" attr == Just "doc-endnotes") <|>+ (guardEnabled Ext_epub_html_exts >>+ guard (maybe False (`elem` notes)+ (lookup "type" attr <|> lookup "epub:type" attr))) updateState $ \s -> s{ inFootnotes = True } result <- pInTags tag block updateState $ \s -> s{ inFootnotes = False }@@ -295,12 +321,12 @@ eNoteref :: PandocMonad m => TagParser m Inlines eNoteref = try $ do- guardEnabled Ext_epub_html_exts TagOpen tag attr <- pSatisfy (\case TagOpen _ as -> (lookup "type" as <|> lookup "epub:type" as)- == Just "noteref"+ == Just "noteref" ||+ lookup "role" as == Just "doc-noteref" _ -> False) ident <- case lookup "href" attr >>= T.uncons of Just ('#', rest) -> return rest@@ -321,32 +347,44 @@ pBulletList :: PandocMonad m => TagParser m Blocks pBulletList = try $ do pSatisfy (matchTagOpen "ul" [])- let nonItem = pSatisfy (\t ->- not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) &&- not (matchTagClose "ul" t)) -- note: if they have an <ol> or <ul> not in scope of a <li>, -- treat it as a list item, though it's not valid xhtml...- skipMany nonItem- items <- manyTill (pListItem' nonItem) (pCloses "ul")- return $ B.bulletList $ map (fixPlains True) items+ skipMany pBlank+ orphans <- many (do notFollowedBy (pSatisfy (matchTagOpen "li" []))+ notFollowedBy (pSatisfy isTagClose)+ block) -- e.g. <ul>, see #9187+ items <- manyTill pListItem (pCloses "ul")+ let items' = case orphans of+ [] -> items+ xs -> mconcat xs : items+ return $ B.bulletList $ map (fixPlains True) items' pListItem :: PandocMonad m => TagParser m Blocks-pListItem = do+pListItem = setInListItem $ do TagOpen _ attr' <- lookAhead $ pSatisfy (matchTagOpen "li" []) let attr = toStringAttr attr' let addId ident bs = case B.toList bs of (Plain ils:xs) -> B.fromList (Plain [Span (ident, [], []) ils] : xs) _ -> B.divWith (ident, [], []) bs- maybe id addId (lookup "id" attr) <$>- pInTags "li" block+ item <- pInTags "li" block+ skipMany pBlank+ orphans <- many (do notFollowedBy (pSatisfy (matchTagOpen "li" []))+ notFollowedBy (pSatisfy isTagClose)+ block) -- e.g. <ul>, see #9187+ skipMany pBlank+ return $ maybe id addId (lookup "id" attr) $ item <> mconcat orphans --- | Parses a list item just like 'pListItem', but allows sublists outside of--- @li@ tags to be treated as items.-pListItem' :: PandocMonad m => TagParser m a -> TagParser m Blocks-pListItem' nonItem = (pListItem <|> pBulletList <|> pOrderedList)- <* skipMany nonItem+pCheckbox :: PandocMonad m => TagParser m Inlines+pCheckbox = do+ TagOpen _ attr' <- pSatisfy $ matchTagOpen "input" [("type","checkbox")]+ TagClose _ <- pSatisfy (matchTagClose "input")+ let attr = toStringAttr attr'+ let isChecked = isJust $ lookup "checked" attr+ let escapeSequence = B.str $ if isChecked then "\9746" else "\9744"+ return $ escapeSequence <> B.space + parseListStyleType :: Text -> ListNumberStyle parseListStyleType "lower-roman" = LowerRoman parseListStyleType "upper-roman" = UpperRoman@@ -376,20 +414,23 @@ where pickListStyle = pickStyleAttrProps ["list-style-type", "list-style"] - let nonItem = pSatisfy (\t ->- not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) &&- not (matchTagClose "ol" t)) -- note: if they have an <ol> or <ul> not in scope of a <li>, -- treat it as a list item, though it's not valid xhtml...- skipMany nonItem+ skipMany pBlank+ orphans <- many (do notFollowedBy (pSatisfy (matchTagOpen "li" []))+ notFollowedBy (pSatisfy isTagClose)+ block) -- e.g. <ul>, see #9187 if isNoteList then do _ <- manyTill (eFootnote <|> pBlank) (pCloses "ol") return mempty else do- items <- manyTill (pListItem' nonItem) (pCloses "ol")+ items <- manyTill pListItem (pCloses "ol")+ let items' = case orphans of+ [] -> items+ xs -> mconcat xs : items return $ B.orderedListWith (start, style, DefaultDelim) $- map (fixPlains True) items+ map (fixPlains True) items' pDefinitionList :: PandocMonad m => TagParser m Blocks pDefinitionList = try $ do@@ -404,9 +445,9 @@ terms <- many1 (try $ skipMany nonItem >> pInTags "dt" inline) defs <- many1 (try $ skipMany nonItem >> pInTags "dd" block) skipMany nonItem- let term = foldl' (\x y -> if null x- then trimInlines y- else x <> B.linebreak <> trimInlines y)+ let term = L.foldl' (\x y -> if null x+ then trimInlines y+ else x <> B.linebreak <> trimInlines y) mempty terms return (term, map (fixPlains True) defs) @@ -449,6 +490,7 @@ isDivLike "section" = True isDivLike "header" = True isDivLike "main" = True+isDivLike "aside" = True isDivLike _ = False pDiv :: PandocMonad m => TagParser m Blocks@@ -457,28 +499,42 @@ TagOpen tag attr' <- lookAhead $ pSatisfy $ tagOpen isDivLike (const True) let (ident, classes, kvs) = toAttr attr' contents <- pInTags tag block- let classes' = if tag == "section"- then "section":classes- else classes- kvs' = if tag == "main" && isNothing (lookup "role" kvs)- then ("role", "main"):kvs- else kvs- return $ B.divWith (ident, classes', kvs') contents+ let contents' = case B.unMany contents of+ Header lev (hident,hclasses,hkvs) ils Seq.:<| rest+ | hident == ident ->+ B.Many $ Header lev ("",hclasses,hkvs) ils Seq.<| rest+ _ -> contents+ let (classes', kvs') =+ case tag of+ "section" -> ("section":classes, kvs)+ "aside" -> ("aside":classes, kvs)+ "header" -> ("header":classes, kvs)+ "main" | Nothing <- lookup "role" kvs -> (classes, ("role", "main"):kvs)+ _ -> (classes, kvs)+ return $ B.divWith (ident, classes', kvs') contents' pIframe :: PandocMonad m => TagParser m Blocks pIframe = try $ do guardDisabled Ext_raw_html tag <- pSatisfy (tagOpen (=="iframe") (isJust . lookup "src"))+ skipMany pBlank pCloses "iframe" <|> eof url <- canonicalizeUrl $ fromAttrib "src" tag if T.null url then ignore $ renderTags' [tag, TagClose "iframe"] else catchError- (do (bs, _) <- openURL url- let inp = UTF8.toText bs- opts <- readerOpts <$> getState- Pandoc _ contents <- readHtml opts inp- return $ B.divWith ("",["iframe"],[]) $ B.fromList contents)+ (do (bs, mbMime) <- openURL url+ case mbMime of+ Just mt+ | "text/html" `T.isPrefixOf` mt -> do+ let inp = UTF8.toText bs+ opts <- readerOpts <$> getState+ Pandoc _ contents <- readHtml opts inp+ return $ B.divWith ("",["iframe"],[]) $ B.fromList contents+ | "image/" `T.isPrefixOf` mt -> do+ return $ B.divWith ("",["iframe"],[]) $+ B.plain $ B.image url "" mempty+ _ -> return $ B.divWith ("",["iframe"],[("src", url)]) mempty) (\e -> do logMessage $ CouldNotFetchResource url (renderError e) ignore $ renderTags' [tag, TagClose "iframe"])@@ -580,24 +636,15 @@ <|> return (B.para contents) pFigure :: PandocMonad m => TagParser m Blocks-pFigure = try $ do- TagOpen _ _ <- pSatisfy (matchTagOpen "figure" [])- skipMany pBlank- let pImg = (\x -> (Just x, Nothing)) <$>- (pInTag TagsOmittable "p" pImage <* skipMany pBlank)- pCapt = (\x -> (Nothing, Just x)) <$> do- bs <- pInTags "figcaption" block- return $ blocksToInlines' $ B.toList bs- pSkip = (Nothing, Nothing) <$ pSatisfy (not . matchTagClose "figure")- res <- many (pImg <|> pCapt <|> pSkip)- let mbimg = msum $ map fst res- let mbcap = msum $ map snd res- TagClose _ <- pSatisfy (matchTagClose "figure")- let caption = fromMaybe mempty mbcap- case B.toList <$> mbimg of- Just [Image attr _ (url, tit)] ->- return $ B.simpleFigureWith attr caption url tit- _ -> mzero+pFigure = do+ TagOpen tag attrList <- pSatisfy $ matchTagOpen "figure" []+ let parser = Left <$> pInTags "figcaption" block <|>+ (Right <$> block)+ (captions, rest) <- partitionEithers <$> manyTill parser (pCloses tag <|> eof)+ -- Concatenate all captions together+ return $ B.figureWith (toAttr attrList)+ (B.simpleCaption (mconcat captions))+ (mconcat rest) pCodeBlock :: PandocMonad m => TagParser m Blocks pCodeBlock = try $ do@@ -616,14 +663,10 @@ else v ] contents <- manyTill pAny (pCloses "pre" <|> eof) let rawText = T.concat $ map tagToText contents- -- drop leading newline if any- let result' = case T.uncons rawText of- Just ('\n', xs) -> xs- _ -> rawText -- drop trailing newline if any- let result = case T.unsnoc result' of+ let result = case T.unsnoc rawText of Just (result'', '\n') -> result''- _ -> result'+ _ -> rawText return $ B.codeBlockWith attr result tagToText :: Tag Text -> Text@@ -642,6 +685,9 @@ , Just "noteref" <- lookup "type" attr <|> lookup "epub:type" attr , Just ('#',_) <- lookup "href" attr >>= T.uncons -> eNoteref+ | Just "doc-noteref" <- lookup "role" attr+ , Just ('#',_) <- lookup "href" attr >>= T.uncons+ -> eNoteref | otherwise -> pLink "switch" -> eSwitch id inline "q" -> pQ@@ -661,11 +707,16 @@ "img" -> pImage "svg" -> pSvg "bdo" -> pBdo+ "tt" -> pCode "code" -> pCode "samp" -> pCodeWithClass "samp" "sample" "var" -> pCodeWithClass "var" "variable" "span" -> pSpan "math" -> pMath False+ "input"+ | lookup "type" attr == Just "checkbox"+ -> asks inListItem >>= guard >> pCheckbox+ "style" -> B.rawInline "html" <$> pHtmlBlock "style" "script" | Just x <- lookup "type" attr , "math/tex" `T.isPrefixOf` x -> pScriptMath@@ -785,8 +836,12 @@ contents <- many (notFollowedBy (pCloses "svg") >> pAny) closet <- TagClose "svg" <$ (pCloses "svg" <|> eof) let rawText = T.strip $ renderTags' (opent : contents ++ [closet])- let svgData = "data:image/svg+xml;base64," <> encodeBase64 rawText- return $ B.imageWith (ident,cls,[]) svgData mempty mempty+ let svgData = "data:image/svg+xml;base64," <>+ UTF8.toText (encode $ UTF8.fromText rawText)+ let kvs = [("width", "1em") | "fa-w-14" `elem` cls ||+ "fa-w-16" `elem` cls ||+ "fa-fw" `elem` cls] -- #10134+ return $ B.imageWith (ident,cls,kvs) svgData mempty mempty pCodeWithClass :: PandocMonad m => Text -> Text -> TagParser m Inlines pCodeWithClass name class' = try $ do@@ -819,18 +874,33 @@ Nothing -> contents pSpan :: PandocMonad m => TagParser m Inlines-pSpan = try $ do- guardEnabled Ext_native_spans- TagOpen _ attr' <- lookAhead $ pSatisfy $ tagOpen (=="span") (const True)+pSpan = do+ (TagOpen _ attr') <- lookAhead (pSatisfy $ tagOpen (=="span") (const True))+ exts <- getOption readerExtensions let attr = toAttr attr'- contents <- pInTags "span" inline- let isSmallCaps = fontVariant == "small-caps" || "smallcaps" `elem` classes- where styleAttr = fromMaybe "" $ lookup "style" attr'- fontVariant = fromMaybe "" $ pickStyleAttrProps ["font-variant"] styleAttr- classes = maybe []- T.words $ lookup "class" attr'- let tag = if isSmallCaps then B.smallcaps else B.spanWith attr- return $ tag contents+ case attr of+ (_,cls,_) -- skip MathJaX-generated HTML; see #10673+ | "mjx-chtml" `elem` cls -> mempty <$ pInTags "span" inline+ | "MathJax_CHTML" `elem` cls -> mempty <$ pInTags "span" inline+ | "MathJax_Preview" `elem` cls -> mempty <$ pInTags "span" inline+ | "MJX_Assistive_MathML" `elem` cls -> pInTags "span" inline+ (_,["katex-html"],_) -> mempty <$ pInTags "span" inline+ -- skip HTML generated by KaTeX, since we get+ -- the math by parsing mathml (#9971)+ _ | extensionEnabled Ext_native_spans exts -> do+ contents <- pInTags "span" inline+ let classes = maybe [] T.words $ lookup "class" attr'+ let styleAttr = fromMaybe "" $ lookup "style" attr'+ let fontVariant = fromMaybe "" $+ pickStyleAttrProps ["font-variant"] styleAttr+ let isSmallCaps = fontVariant == "small-caps" ||+ "smallcaps" `elem` classes+ let tag = if isSmallCaps then B.smallcaps else B.spanWith attr+ return $ tag contents+ | extensionEnabled Ext_raw_html exts -> do+ tag <- pSatisfy $ tagOpen (=="span") (const True)+ return $ B.rawInline "html" $ renderTags' [tag]+ | otherwise -> pInTags "span" inline -- just contents pRawHtmlInline :: PandocMonad m => TagParser m Inlines pRawHtmlInline = do@@ -866,16 +936,30 @@ let attr = toStringAttr attr' unless inCase $ guard (maybe True (== mathMLNamespace) (lookup "xmlns" attr))+ let constructor = case lookup "display" attr of+ Just "block" -> B.displayMath+ _ -> B.math contents <- manyTill pAny (pSatisfy (matchTagClose "math"))- case mathMLToTeXMath (renderTags $- [open] <> contents <> [TagClose "math"]) of- Left _ -> return $ B.spanWith ("",["math"],attr) $ B.text $- innerText contents- Right "" -> return mempty- Right x -> return $ case lookup "display" attr of- Just "block" -> B.displayMath x- _ -> B.math x+ -- KaTeX and others include original TeX in annotation tag;+ -- just use this if present rather than parsing MathML:+ case extractTeXAnnotation contents of+ Just x -> return $ constructor x+ Nothing ->+ case mathMLToTeXMath (renderTags $+ [open] <> contents <> [TagClose "math"]) of+ Left _ -> return $ B.spanWith ("",["math"],attr) $ B.text $+ innerText contents+ Right "" -> return mempty+ Right x -> return $ constructor x +extractTeXAnnotation :: [Tag Text] -> Maybe Text+extractTeXAnnotation [] = Nothing+extractTeXAnnotation (TagOpen "annotation" [("encoding","application/x-tex")]+ : ts) =+ Just $ innerText $ takeWhile (~/= TagClose ("annotation" :: Text)) ts+extractTeXAnnotation (_:ts) = extractTeXAnnotation ts++ pInlinesInTags :: PandocMonad m => Text -> (Inlines -> Inlines) -> TagParser m Inlines pInlinesInTags tagtype f = extractSpaces f <$> pInTags tagtype inline@@ -997,6 +1081,8 @@ isInlineTag t = isCommentTag t || case t of TagOpen "script" _ -> "math/tex" `T.isPrefixOf` fromAttrib "type" t TagClose "script" -> True+ TagOpen "style" _ -> True -- see #10643, invalid but it happens+ TagClose "style" -> True TagOpen name _ -> isInlineTagName name TagClose name -> isInlineTagName name _ -> False@@ -1026,7 +1112,7 @@ -- | Matches a stretch of HTML in balanced tags. htmlInBalanced :: Monad m => (Tag Text -> Bool)- -> ParserT Sources st m Text+ -> ParsecT Sources st m Text htmlInBalanced f = try $ do lookAhead (char '<') sources <- getInput@@ -1075,7 +1161,7 @@ -- | Matches a tag meeting a certain condition. htmlTag :: (HasReaderOptions st, Monad m) => (Tag Text -> Bool)- -> ParserT Sources st m (Tag Text, Text)+ -> ParsecT Sources st m (Tag Text, Text) htmlTag f = try $ do lookAhead (char '<') startpos <- getPosition@@ -1147,8 +1233,10 @@ -- | Adjusts a url according to the document's base URL. canonicalizeUrl :: PandocMonad m => Text -> TagParser m Text-canonicalizeUrl url = do- mbBaseHref <- baseHref <$> getState- return $ case (parseURIReference (T.unpack url), mbBaseHref) of- (Just rel, Just bs) -> tshow (rel `nonStrictRelativeTo` bs)- _ -> url+canonicalizeUrl url+ | "data:" `T.isPrefixOf` url = return url+ | otherwise = do+ mbBaseHref <- baseHref <$> getState+ return $ case (parseURIReference (T.unpack url), mbBaseHref) of+ (Just rel, Just bs) -> tshow (rel `nonStrictRelativeTo` bs)+ _ -> url
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.HTML.Parsing- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -104,6 +104,8 @@ t <- lookAhead $ pSatisfy $ \tag -> isTagClose tag || isTagOpen tag case t of (TagClose t') | t' == tagtype -> void pAny+ (TagClose "th") | tagtype == "td" -> void pAny -- see #9090+ (TagClose "td") | tagtype == "th" -> void pAny (TagOpen t' _) | t' `closes` tagtype -> return () (TagClose "ul") | tagtype == "li" -> return () (TagClose "ol") | tagtype == "li" -> return ()
@@ -3,11 +3,11 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Readers.HTML.Table- Copyright : © 2006-2022 John MacFarlane,- 2020-2022 Albert Krewinkel+ Copyright : © 2006-2024 John MacFarlane,+ 2020-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -15,10 +15,12 @@ -} module Text.Pandoc.Readers.HTML.Table (pTable) where +import qualified Data.Vector as V import Control.Applicative ((<|>)) import Data.Maybe (fromMaybe, isJust) import Data.Either (lefts, rights) import Data.List.NonEmpty (nonEmpty)+import qualified Data.List as L import Data.Text (Text) import Text.HTML.TagSoup import Text.Pandoc.Builder (Blocks)@@ -123,19 +125,18 @@ toStyleString :: [(Text, Text)] -> Text toStyleString = T.intercalate "; " . map (\(k, v) -> k <> ": " <> v) --- | Parses a normal table row; returns the row together with the number--- of header cells at the beginning of the row.+-- | Parses a normal table row; returns the row and the number+-- of cells at the beginning that are header cells. pRow :: PandocMonad m => TagParser m Blocks- -> TagParser m (RowHeadColumns, B.Row)+ -> TagParser m (Int, B.Row) pRow block = try $ do skipMany pBlank TagOpen _ attribs <- pSatisfy (matchTagOpen "tr" []) <* skipMany pBlank cells <- many (pCell block BodyCell <|> pCell block HeaderCell) TagClose _ <- pSatisfy (matchTagClose "tr")- return ( RowHeadColumns $ length (takeWhile ((== HeaderCell) . fst) cells)- , Row (toAttr attribs) $ map snd cells- )+ let numheadcells = length $ takeWhile (\(ct,_) -> ct == HeaderCell) cells+ return (numheadcells, Row (toAttr attribs) $ map snd cells) -- | Parses a header row, i.e., a row which containing nothing but -- @<th>@ elements.@@ -144,7 +145,7 @@ -> TagParser m B.Row pHeaderRow block = try $ do skipMany pBlank- let pThs = map snd <$> many (pCell block HeaderCell)+ let pThs = many (snd <$> pCell block HeaderCell) let mkRow (attribs, cells) = Row (toAttr attribs) cells mkRow <$> pInTagWithAttribs TagsRequired "tr" pThs @@ -174,7 +175,7 @@ pTableFoot block = try $ do skipMany pBlank TagOpen _ attribs <- pSatisfy (matchTagOpen "tfoot" []) <* skipMany pBlank- rows <- many (fmap snd $ pRow block <* skipMany pBlank)+ rows <- many $ snd <$> (pRow block <* skipMany pBlank) optional $ pSatisfy (matchTagClose "tfoot") return $ TableFoot (toAttr attribs) rows @@ -187,11 +188,31 @@ mbattribs <- option Nothing $ Just . getAttribs <$> pSatisfy (matchTagOpen "tbody" []) <* skipMany pBlank bodyheads <- many (pHeaderRow block)- (rowheads, rows) <- unzip <$> many (pRow block <* skipMany pBlank)+ rows <- many (pRow block <* skipMany pBlank) optional $ pSatisfy (matchTagClose "tbody") guard $ isJust mbattribs || not (null bodyheads && null rows) let attribs = fromMaybe [] mbattribs- return $ TableBody (toAttr attribs) (foldr max 0 rowheads) bodyheads rows+ -- we only set row head columns if all rows agree;+ -- if some rows have headings but others not, we use 0; see #8984, #8634:+ let numrows = length rows+ let adjustRowHeadColsForCell currentrow headcolsv+ (Cell _ _ (RowSpan rowspan) (ColSpan colspan) _) =+ V.imap (\i x -> if i >= currentrow &&+ i < currentrow + rowspan+ then x + colspan+ else x) headcolsv+ let adjustRowHeadCols+ headcolsv+ (currentrow, (numheads, Row _ cells)) =+ L.foldl' (adjustRowHeadColsForCell currentrow) headcolsv+ (take numheads cells)+ let headcols = L.foldl' adjustRowHeadCols+ (V.replicate numrows (0 :: Int))+ (zip [(0 :: Int)..] rows)+ let rowHeadCols = case V.uncons headcols of+ Just (x, v) | all (== x) v -> RowHeadColumns x+ _ -> RowHeadColumns 0+ return $ TableBody (toAttr attribs) rowHeadCols bodyheads (map snd rows) where getAttribs (TagOpen _ attribs) = attribs getAttribs _ = []
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.HTML.TagCategories- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -28,7 +28,7 @@ eitherBlockOrInline = fromList ["audio", "applet", "button", "iframe", "embed", "del", "ins", "progress", "map", "area", "noscript", "script",- "object", "svg", "video", "source"]+ "object", "svg", "video", "source", "track"] blockHtmlTags :: Set Text blockHtmlTags = fromList
@@ -2,7 +2,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} {- | Module : Text.Pandoc.Readers.HTML.Types- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -33,12 +33,12 @@ import Text.Pandoc.Parsing ( HasIdentifierList (..), HasLastStrPosition (..), HasLogMessages (..) , HasMacros (..), HasQuoteContext (..), HasReaderOptions (..)- , ParserT, ParserState, QuoteContext (NoQuote)+ , ParsecT, ParserState, QuoteContext (NoQuote) )-import Text.Pandoc.Readers.LaTeX.Types (Macro)+import Text.Pandoc.TeX (Macro) -- | HTML parser type-type HTMLParser m s = ParserT s HTMLState (ReaderT HTMLLocal m)+type HTMLParser m s = ParsecT s HTMLState (ReaderT HTMLLocal m) -- | HTML parser, expecting @Tag Text@ as tokens. type TagParser m = HTMLParser m [Tag Text]@@ -60,6 +60,7 @@ { quoteContext :: QuoteContext , inChapter :: Bool -- ^ Set if in chapter section , inPlain :: Bool -- ^ Set if in pPlain+ , inListItem :: Bool -- ^ Set if in <li> tag } @@ -91,7 +92,7 @@ deleteMeta s st = st {parserState = deleteMeta s $ parserState st} instance Default HTMLLocal where- def = HTMLLocal NoQuote False False+ def = HTMLLocal NoQuote False False False instance HasLastStrPosition HTMLState where setLastStrPos s st = st {parserState = setLastStrPos s (parserState st)}
@@ -101,10 +101,9 @@ toRow = Row nullAttr . map B.simpleCell toHeaderRow l = [toRow l | not (null l)] (header, body) =- if null headerRows- then ([], map toCells bodyRows)- else (toCells (head headerRows),- map toCells (tail headerRows ++ bodyRows))+ case headerRows of+ [] -> ([], map toCells bodyRows)+ (x:xs) -> (toCells x, map toCells (xs ++ bodyRows)) colspecs = replicate (maybe 0 maximum (nonEmpty (map length body))) (AlignDefault, ColWidthDefault) in B.table B.emptyCaption
@@ -4,7 +4,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Text.Pandoc.Readers.Ipynb- Copyright : Copyright (C) 2019-2022 John MacFarlane+ Copyright : Copyright (C) 2019-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -15,9 +15,9 @@ -} module Text.Pandoc.Readers.Ipynb ( readIpynb ) where+import Crypto.Hash (hashWith, SHA1(SHA1)) import Data.Char (isDigit) import Data.Maybe (fromMaybe)-import Data.Digest.Pure.SHA (sha1, showDigest) import Text.Pandoc.Options import Control.Applicative ((<|>)) import qualified Data.Scientific as Scientific@@ -81,13 +81,13 @@ Nothing -> mempty Just (MimeAttachments m) -> M.toList m let ident = fromMaybe mempty $ cellId c- mapM_ addAttachment attachments+ mapM_ (addAttachment (cellId c)) attachments case cellType c of Ipynb.Markdown -> do bs <- if isEnabled Ext_raw_markdown opts then return [RawBlock (Format "markdown") source] else do- Pandoc _ bs <- walk fixImage <$> readMarkdown opts source+ Pandoc _ bs <- walk (fixImage (cellId c)) <$> readMarkdown opts source return bs return $ B.divWith (ident,["cell","markdown"],kvs) $ B.fromList bs@@ -121,14 +121,17 @@ <> outputBlocks -- Remove attachment: prefix from images...-fixImage :: Inline -> Inline-fixImage (Image attr lab (src,tit))- | "attachment:" `T.isPrefixOf` src = Image attr lab (T.drop 11 src, tit)-fixImage x = x+fixImage :: Maybe Text -> Inline -> Inline+fixImage mbident (Image attr lab (src,tit))+ | "attachment:" `T.isPrefixOf` src =+ let src' = T.drop 11 src+ qualifiedSrc = maybe src' (<> ("-" <> src')) mbident+ in Image attr lab (qualifiedSrc, tit)+fixImage _ x = x -addAttachment :: PandocMonad m => (Text, MimeBundle) -> m ()-addAttachment (fname, mimeBundle) = do- let fp = T.unpack fname+addAttachment :: PandocMonad m => Maybe Text -> (Text, MimeBundle) -> m ()+addAttachment mbident (fname, mimeBundle) = do+ let fp = T.unpack $ maybe fname (<> ("-" <> fname)) mbident case M.toList (unMimeBundle mimeBundle) of (mimeType, BinaryData bs):_ -> insertMedia fp (Just mimeType) (BL.fromStrict bs)@@ -183,16 +186,16 @@ Error _ -> mempty _ -> mempty let metaPairs = jsonMetaToPairs meta- let bl = case d of- BinaryData bs -> BL.fromStrict bs- TextualData t -> BL.fromStrict $ UTF8.fromText t- JsonData v -> encode v+ let bs = case d of+ BinaryData bs' -> bs'+ TextualData t -> UTF8.fromText t+ JsonData v -> BL.toStrict $ encode v -- SHA1 hash for filename- let fname = T.pack (showDigest (sha1 bl)) <>+ let fname = T.pack (show (hashWith SHA1 bs)) <> case extensionFromMimeType mt of Nothing -> "" Just ext -> "." <> ext- insertMedia (T.unpack fname) (Just mt) bl+ insertMedia (T.unpack fname) (Just mt) (BL.fromStrict bs) return $ B.para $ B.imageWith ("",[],metaPairs) fname "" mempty dataBlock ("text/html", TextualData t)
@@ -14,30 +14,32 @@ -} module Text.Pandoc.Readers.JATS ( readJATS ) where-import Control.Monad.State.Strict+import Control.Monad.State.Strict ( StateT(runStateT), gets, modify )+import Control.Monad (forM_, when, unless) import Control.Monad.Except (throwError) import Text.Pandoc.Error (PandocError(..)) import Data.Char (isDigit, isSpace) import Data.Default import Data.Generics-import Data.List (foldl', intersperse)+import qualified Data.List as L import qualified Data.Map as Map import Data.Maybe (maybeToList, fromMaybe, catMaybes) import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Lazy as TL-import Text.HTML.TagSoup.Entity (lookupEntity)+import Text.Pandoc.XML (lookupEntity) import Text.Pandoc.Builder import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Options-import Text.Pandoc.Shared (safeRead, extractSpaces)+import Text.Pandoc.Shared (safeRead) import Text.Pandoc.Walk (walk) import Text.Pandoc.XML.Light import Text.TeXMath (readMathML, writeTeX) import qualified Data.Set as S (fromList, member) import Data.Set ((\\)) import Text.Pandoc.Sources (ToSources(..), sourcesToText)-import qualified Data.Foldable as DF+import Safe (headMay)+import Text.Printf (printf) type JATS m = StateT JATSState m @@ -47,6 +49,7 @@ , jatsBook :: Bool , jatsFootnotes :: Map.Map Text Blocks , jatsContent :: [Content]+ , jatsInFigure :: Bool } deriving Show instance Default JATSState where@@ -55,7 +58,8 @@ , jatsMeta = mempty , jatsBook = False , jatsFootnotes = mempty- , jatsContent = [] }+ , jatsContent = []+ , jatsInFigure = False } readJATS :: (PandocMonad m, ToSources a)@@ -102,31 +106,30 @@ deleteMeta field s = s {jatsMeta = deleteMeta field (jatsMeta s)} isBlockElement :: Content -> Bool-isBlockElement (Elem e) = qName (elName e) `S.member` blocktags- where blocktags = S.fromList (paragraphLevel ++ lists ++ mathML ++ other) \\ S.fromList inlinetags- paragraphLevel = ["address", "array", "boxed-text", "chem-struct-wrap",- "code", "fig", "fig-group", "graphic", "media", "preformat",+isBlockElement (Elem e) = case qName (elName e) of+ "disp-formula" -> if onlyOneChild e+ then if hasFormulaChild e+ then False+ else case filterChild (named "alternatives") e of+ Just a -> if hasFormulaChild a then False else True+ Nothing -> True+ else True+ "alternatives" -> if hasFormulaChild e then False else True+ _ -> qName (elName e) `S.member` blocktags++ where blocktags = S.fromList (paragraphLevel ++ lists ++ formulae ++ other) \\ S.fromList canBeInline+ paragraphLevel = ["address", "answer", "answer-set", "array", "boxed-text", "chem-struct-wrap",+ "code", "explanation", "fig", "fig-group", "graphic", "media", "preformat", "question", "question-wrap", "question-wrap-group", "supplementary-material", "table-wrap", "table-wrap-group", "alternatives", "disp-formula", "disp-formula-group"] lists = ["def-list", "list"]- mathML = ["tex-math", "mml:math"]+ formulae = ["tex-math", "mml:math"] other = ["p", "related-article", "related-object", "ack", "disp-quote", "speech", "statement", "verse-group", "x"]- inlinetags = ["email", "ext-link", "uri", "inline-supplementary-material",- "related-article", "related-object", "hr", "bold", "fixed-case",- "italic", "monospace", "overline", "overline-start", "overline-end",- "roman", "sans-serif", "sc", "strike", "underline", "underline-start",- "underline-end", "ruby", "alternatives", "inline-graphic", "private-char",- "chem-struct", "inline-formula", "tex-math", "mml:math", "abbrev",- "milestone-end", "milestone-start", "named-content", "styled-content",- "fn", "target", "xref", "sub", "sup", "x", "address", "array",- "boxed-text", "chem-struct-wrap", "code", "fig", "fig-group", "graphic",- "media", "preformat", "supplementary-material", "table-wrap",- "table-wrap-group", "disp-formula", "disp-formula-group",- "citation-alternatives", "element-citation", "mixed-citation",- "nlm-citation", "award-id", "funding-source", "open-access",- "def-list", "list", "ack", "disp-quote", "speech", "statement",- "verse-group"]+ canBeInline = ["tex-math", "mml:math", "related-object", "x"]+ onlyOneChild x = length (allChildren x) == 1+ allChildren x = filterChildren (const True) x+ isBlockElement _ = False -- Trim leading and trailing newline characters@@ -135,18 +138,16 @@ -- function that is used by both graphic (in parseBlock) -- and inline-graphic (in parseInline)-getGraphic :: PandocMonad m- => Maybe (Inlines, Text) -> Element -> JATS m Inlines-getGraphic mbfigdata e = do+getGraphic :: PandocMonad m => Element -> JATS m Inlines+getGraphic e = do let atVal a = attrValue a e- (ident, title, capt) =- case mbfigdata of- Just (capt', i) -> (i, "fig:" <> atVal "title", capt')- Nothing -> (atVal "id", atVal "title",- text (atVal "alt-text"))+ let altText = case filterElement (named "alt-text") e of+ Just alt -> textContent alt+ Nothing -> mempty+ (ident, title, altText') = (atVal "id", atVal "title", text altText) attr = (ident, T.words $ atVal "role", []) imageUrl = atVal "href"- return $ imageWith attr imageUrl title capt+ return $ imageWith attr imageUrl title altText' getBlocks :: PandocMonad m => Element -> JATS m Blocks getBlocks e = mconcat <$>@@ -159,27 +160,50 @@ then return mempty else return $ plain $ trimInlines $ text s parseBlock (CRef x) = return $ plain $ str $ T.toUpper x-parseBlock (Elem e) =+parseBlock (Elem e) = do+ sectionLevel <- gets jatsSectionLevel+ let parseBlockWithHeader = wrapWithHeader (sectionLevel+1) (getBlocks e)+ case qName (elName e) of+ "book" -> parseBook+ "book-part-wrapper" -> parseBook "p" -> parseMixed para (elContent e) "code" -> codeBlockWithLang "preformat" -> codeBlockWithLang- "disp-quote" -> parseBlockquote- "list" -> case attrValue "list-type" e of- "bullet" -> bulletList <$> listitems- listType -> do- let start = fromMaybe 1 $- (filterElement (named "list-item") e- >>= filterElement (named "label"))- >>= safeRead . textContent- orderedListWith (start, parseListStyleType listType, DefaultDelim)- <$> listitems- "def-list" -> definitionList <$> deflistitems- "sec" -> gets jatsSectionLevel >>= sect . (+1)- "graphic" -> para <$> getGraphic Nothing e+ "disp-quote" -> wrapWithHeader (sectionLevel+1) parseBlockquote+ "list" -> wrapWithHeader (sectionLevel+1) parseList+ "def-list" -> wrapWithHeader (sectionLevel+1) (definitionList <$> deflistitems)+ "sec" -> parseBlockWithHeader+ "abstract" -> parseBlockWithHeader+ "ack" -> parseBlockWithHeader+ "answer" -> parseBlockWithHeader+ "answer-set" -> parseBlockWithHeader+ "app" -> parseBlockWithHeader+ "app-group" -> parseBlockWithHeader+ "author-comment" -> parseBlockWithHeader+ "author-notes" -> parseBlockWithHeader+ "back" -> parseBlockWithHeader+ "bio" -> parseBlockWithHeader+ "explanation" -> parseBlockWithHeader+ "glossary" -> parseBlockWithHeader+ "kwd-group" -> parseBlockWithHeader+ "list-item" -> parseBlockWithHeader+ "notes" -> parseBlockWithHeader+ "option" -> parseBlockWithHeader+ "question" -> parseBlockWithHeader+ "question-preamble" -> parseBlockWithHeader+ "question-wrap-group" -> parseBlockWithHeader+ "statement" -> parseBlockWithHeader+ "supplement" -> parseBlockWithHeader+ "table-wrap-foot" -> parseBlockWithHeader+ "trans-abstract" -> parseBlockWithHeader+ "verse-group" -> parseBlockWithHeader+ "graphic" -> para <$> getGraphic e "journal-meta" -> parseMetadata e "article-meta" -> parseMetadata e "custom-meta" -> parseMetadata e+ "processing-meta" -> return mempty+ "book-meta" -> parseMetadata e "title" -> return mempty -- processed by header "label" -> return mempty -- processed by header "table" -> parseTable@@ -188,9 +212,33 @@ <$> getBlocks e "table-wrap" -> divWith (attrValue "id" e, ["table-wrap"], []) <$> getBlocks e- "caption" -> divWith (attrValue "id" e, ["caption"], []) <$> sect 6+ "caption" -> do+ inFigure <- gets jatsInFigure+ if inFigure -- handled by parseFigure+ then return mempty+ else divWith (attrValue "id" e, ["caption"], []) <$> wrapWithHeader 6 (getBlocks e) "fn-group" -> parseFootnoteGroup "ref-list" -> parseRefList e+ "alternatives" -> if hasFormulaChild e+ then blockFormula displayMath e+ else getBlocks e+ "disp-formula" -> if hasFormulaChild e+ then blockFormula displayMath e+ else divWith (attrValue "id" e, ["disp-formula"], [])+ <$> getBlocks e+ "index" -> parseBlockWithHeader+ "index-div" -> parseBlockWithHeader+ "index-group" -> parseBlockWithHeader+ "index-title-group" -> return mempty -- handled by index and index-div+ "toc" -> parseBlockWithHeader+ "toc-div" -> parseBlockWithHeader+ "toc-entry" -> parseBlockWithHeader+ "toc-group" -> parseBlockWithHeader+ "toc-title-group" -> return mempty -- handled by toc+ "legend" -> parseBlockWithHeader+ "dedication" -> parseBlockWithHeader+ "foreword" -> parseBlockWithHeader+ "preface" -> parseBlockWithHeader "?xml" -> return mempty _ -> getBlocks e where parseMixed container conts = do@@ -210,13 +258,25 @@ return $ codeBlockWith (attrValue "id" e, classes', []) $ trimNl $ strContentRecursive e parseBlockquote = do- attrib <- case filterChild (named "attribution") e of+ attrib <- case filterChild (named "attrib") e of Nothing -> return mempty Just z -> para . (str "— " <>) . mconcat <$> mapM parseInline (elContent z) contents <- getBlocks e return $ blockQuote (contents <> attrib)+ parseList = do+ case attrValue "list-type" e of+ "bullet" -> bulletList <$> listitems+ listType -> do+ let start =+ fromMaybe 1 $+ ( filterElement (named "list-item") e+ >>= filterElement (named "label")+ )+ >>= safeRead . textContent+ orderedListWith (start, parseListStyleType listType, DefaultDelim)+ <$> listitems parseListStyleType "roman-lower" = LowerRoman parseListStyleType "roman-upper" = UpperRoman parseListStyleType "alpha-lower" = LowerAlpha@@ -230,30 +290,19 @@ let items = filterChildren (named "def") e' terms' <- mapM getInlines terms items' <- mapM getBlocks items- return (mconcat $ intersperse (str "; ") terms', items')- parseFigure =- -- if a simple caption and single graphic, we emit a standard- -- implicit figure. otherwise, we emit a div with the contents- case filterChildren (named "graphic") e of- [g] -> do- capt <- case filterChild (named "caption") e of- Just t -> mconcat .- intersperse linebreak <$>- mapM getInlines- (filterChildren (const True) t)- Nothing -> return mempty-- let figAttributes = DF.toList $- ("alt", ) . strContent <$>- filterChild (named "alt-text") e-- return $ simpleFigureWith- (attrValue "id" e, [], figAttributes)- capt- (attrValue "href" g)- (attrValue "title" g)-- _ -> divWith (attrValue "id" e, ["fig"], []) <$> getBlocks e+ return (mconcat $ L.intersperse (str "; ") terms', items')+ parseFigure = do+ modify $ \st -> st{ jatsInFigure = True }+ capt <- case filterChild (named "caption") e of+ Just t -> mconcat . L.intersperse linebreak <$>+ mapM getInlines (filterChildren (const True) t)+ Nothing -> return mempty+ contents <- getBlocks e+ modify $ \st -> st{ jatsInFigure = False }+ return $ figureWith+ (attrValue "id" e, [], [])+ (simpleCaption $ plain capt)+ contents parseFootnoteGroup = do forM_ (filterChildren (named "fn") e) $ \fn -> do let id' = attrValue "id" fn@@ -273,26 +322,35 @@ Just c -> filterChildren isColspec c _ -> filterChildren isColspec e' 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 x- Nothing -> return []- Nothing -> return []- bodyrows <- case filterChild (named "tbody") e' of- Just b -> mapM parseRow- $ filterChildren isRow b- Nothing -> mapM parseRow- $ filterChildren isRow e'++ let parseRows elementWithRows =+ map parseElement $ filterChildren isRow elementWithRows++ -- list of list of body cell elements+ let multipleBodyRowElements =+ map parseRows $ filterChildren (named "tbody") e'++ -- list of list header cell elements+ let headRowElements = maybe [] parseRows (filterChild (named "thead") e')++ -- list of foot cell elements+ let footRowElements = maybe [] parseRows (filterChild (named "tfoot") e')+ let toAlignment c = case findAttr (unqual "align") c of Just "left" -> AlignLeft Just "right" -> AlignRight Just "center" -> AlignCenter _ -> AlignDefault+ let toColSpan element = fromMaybe 1 $+ findAttr (unqual "colspan") element >>= safeRead+ let toRowSpan element = fromMaybe 1 $+ findAttr (unqual "rowspan") element >>= safeRead let toWidth c = do w <- findAttr (unqual "colwidth") c n <- safeRead $ "0" <> T.filter (\x -> isDigit x || x == '.') w if n > 0 then Just n else Nothing- let numrows = foldl' max 0 $ map length bodyrows+ let firstBody = fromMaybe [] (headMay multipleBodyRowElements)+ let numrows = L.foldl' max 0 $ map length firstBody let aligns = case colspecs of [] -> replicate numrows AlignDefault cs -> map toAlignment cs@@ -303,33 +361,58 @@ Just ws' -> let tot = sum ws' in ColWidth . (/ tot) <$> ws' Nothing -> replicate numrows ColWidthDefault- let toRow = Row nullAttr . map simpleCell- toHeaderRow l = [toRow l | not (null l)]+ let parseCell = parseMixed plain . elContent+ let elementToCell element = cell+ (toAlignment element)+ (RowSpan $ toRowSpan element)+ (ColSpan $ toColSpan element)+ <$> (parseCell element)+ let rowElementsToCells elements = mapM elementToCell elements+ let toRow = fmap (Row nullAttr) . rowElementsToCells+ toRows elements = mapM toRow elements++ headerRows <- toRows headRowElements+ footerRows <- toRows footRowElements+ bodyRows <- mapM toRows multipleBodyRowElements+ return $ table (simpleCaption $ plain capt) (zip aligns widths)- (TableHead nullAttr $ toHeaderRow headrows)- [TableBody nullAttr 0 [] $ map toRow bodyrows]- (TableFoot nullAttr [])+ (TableHead nullAttr headerRows)+ (map (TableBody nullAttr 0 []) bodyRows)+ (TableFoot nullAttr footerRows) isEntry x = named "entry" x || named "td" x || named "th" x- parseRow = mapM (parseMixed plain . elContent) . filterChildren isEntry- sect n = do isbook <- gets jatsBook- let n' = if isbook || n == 0 then n + 1 else n- labelText <- case filterChild (named "label") e of- Just t -> (<> ("." <> space)) <$>- getInlines t- Nothing -> return mempty- headerText <- case filterChild (named "title") e `mplus`- (filterChild (named "info") e >>=- filterChild (named "title")) of- Just t -> (labelText <>) <$>- getInlines t- Nothing -> return mempty- oldN <- gets jatsSectionLevel- modify $ \st -> st{ jatsSectionLevel = n }- b <- getBlocks e- let ident = attrValue "id" e- modify $ \st -> st{ jatsSectionLevel = oldN }- return $ headerWith (ident,[],[]) n' headerText <> b+ parseElement = filterChildren isEntry+ wrapWithHeader n mBlocks = do+ isBook <- gets jatsBook+ let n' = case (filterChild (named "title") e >>= maybeAttrValue "display-as") of+ Just t -> read $ T.unpack t+ Nothing -> if isBook || n == 0 then n + 1 else n+ headerText <- case filterChild (named "title") e of+ Just t -> case maybeAttrValue "suppress" t of+ Just s -> if s == "no"+ then getInlines t+ else return mempty+ Nothing -> getInlines t+ Nothing -> do+ let name = qName (elName e)+ if (name == "dedication" || name == "foreword" || name == "preface")+ then return $ str $ T.toTitle name+ else case filterChild (named "index-title-group") e >>= filterChild (named "title") of+ Just i -> getInlines i+ Nothing -> case filterChild (named "toc-title-group") e >>= filterChild (named "title") of+ Just t -> getInlines t+ Nothing -> return mempty+ oldN <- gets jatsSectionLevel+ modify $ \st -> st{ jatsSectionLevel = n }+ blocks <- mBlocks+ let ident = attrValue "id" e+ modify $ \st -> st{ jatsSectionLevel = oldN }+ return $ (if headerText == mempty+ then mempty+ else headerWith (ident,[],[]) n' headerText) <> blocks+ parseBook = do+ modify $ \st -> st{ jatsBook = True }+ getBlocks e getInlines :: PandocMonad m => Element -> JATS m Inlines getInlines e' = trimInlines . mconcat <$>@@ -337,15 +420,17 @@ parseMetadata :: PandocMonad m => Element -> JATS m Blocks parseMetadata e = do- getTitle e- getAuthors e+ isBook <- gets jatsBook+ if isBook then getBookTitle e else getArticleTitle e+ if isBook then getBookAuthors e else getArticleAuthors e getAffiliations e getAbstract e getPubDate e+ getPermissions e return mempty -getTitle :: PandocMonad m => Element -> JATS m ()-getTitle e = do+getArticleTitle :: PandocMonad m => Element -> JATS m ()+getArticleTitle e = do tit <- case filterElement (named "article-title") e of Just s -> getInlines s Nothing -> return mempty@@ -356,8 +441,21 @@ when (tit /= mempty) $ addMeta "title" tit when (subtit /= mempty) $ addMeta "subtitle" subtit -getAuthors :: PandocMonad m => Element -> JATS m ()-getAuthors e = do++getBookTitle :: PandocMonad m => Element -> JATS m ()+getBookTitle e = do+ tit <- case (filterElement (named "book-title-group") e >>= filterElement (named "book-title")) of+ Just s -> getInlines s+ Nothing -> return mempty+ subtit <- case (filterElement (named "book-title-group") e >>= filterElement (named "subtitle")) of+ Just s -> (text ": " <>) <$>+ getInlines s+ Nothing -> return mempty+ when (tit /= mempty) $ addMeta "title" tit+ when (subtit /= mempty) $ addMeta "subtitle" subtit++getArticleAuthors :: PandocMonad m => Element -> JATS m ()+getArticleAuthors e = do authors <- mapM getContrib $ filterElements (\x -> named "contrib" x && attrValue "contrib-type" x == "author") e@@ -368,6 +466,18 @@ (a:as, ns) -> reverse as ++ [a <> mconcat ns] unless (null authors) $ addMeta "author" authors' +getBookAuthors :: PandocMonad m => Element -> JATS m ()+getBookAuthors e = do+ authors <- mapM getContrib $ filterElements (\x -> named "contrib-group" x) e+ >>= filterElements (\x -> named "contrib" x &&+ attrValue "contrib-type" x == "author")+ authorNotes <- mapM getInlines $ filterElements (named "author-notes") e+ let authors' = case (reverse authors, authorNotes) of+ ([], _) -> []+ (_, []) -> authors+ (a:as, ns) -> reverse as ++ [a <> mconcat ns]+ unless (null authors) $ addMeta "author" authors'+ getAffiliations :: PandocMonad m => Element -> JATS m () getAffiliations x = do affs <- mapM getInlines $ filterChildren (named "aff") x@@ -384,16 +494,69 @@ getPubDate :: PandocMonad m => Element -> JATS m () getPubDate e = case filterElement (named "pub-date") e of- Just d -> do- case maybeAttrValue "iso-8601-date" d of- Just isod -> addMeta "date" (text isod)- Nothing -> do- let yr = strContent <$> filterElement (named "year") d- let mon = strContent <$> filterElement (named "month") d- let day = strContent <$> filterElement (named "day") d- addMeta "date" $ text $ T.intercalate "-" $ catMaybes [yr, mon, day]+ Just d -> getDate d >>= addMeta "date" . text Nothing -> pure () +-- extract a structured date and create an ISO-8901 string date from it+getDate :: PandocMonad m => Element -> JATS m Text+getDate e =+ case maybeAttrValue "iso-8601-date" e of+ Just isod -> pure isod+ Nothing -> do+ let extractDate :: Element -> Maybe Int+ extractDate = safeRead . strContent+ let yr = filterElement (named "year") e >>= extractDate+ let mon = filterElement (named "month") e >>= extractDate+ let day = filterElement (named "day") e >>= extractDate+ let stringDate = strContent <$> filterElement (named "string-date") e+ pure $+ case (yr, mon, day) of+ (Just y, Just m, Just d) -> T.pack $ printf "%04d-%02d-%02d" y m d+ (Just y, Just m, Nothing) -> T.pack $ printf "%04d-%02d" y m+ (Just y, Nothing, Nothing) -> T.pack $ printf "%04d" y+ _ -> fromMaybe mempty stringDate++getPermissions :: PandocMonad m => Element -> JATS m ()+getPermissions e = do+ copyright <- getCopyright e+ license <- case filterElement (named "license") e of+ Just s -> getLicense s+ Nothing -> return mempty+ when (copyright /= mempty) $ addMeta "copyright" copyright+ when (license /= mempty) $ addMeta "license" license++getCopyright :: PandocMonad m => Element -> JATS m (Map.Map Text MetaValue)+getCopyright e = do+ let holder = metaElement e "copyright-holder" "holder"+ let statement = metaElement e "copyright-statement" "statement"+ let year = metaElement e "copyright-year" "year"+ return $ Map.fromList (catMaybes $ [holder, statement, year])++getLicense :: PandocMonad m => Element -> JATS m (Map.Map Text MetaValue)+getLicense e = do+ let licenseType = metaAttribute e "license-type" "type"+ let licenseLink = metaElementAliRef e "link"+ let licenseText = metaElement e "license-p" "text"+ return $ Map.fromList (catMaybes $ [licenseType, licenseLink, licenseText])++metaElement :: Element -> Text -> Text -> Maybe (Text, MetaValue)+metaElement e child key =+ case filterElement (named child) e of+ Just content -> Just (key, toMetaValue $ strContent content)+ Nothing -> Nothing++metaElementAliRef :: Element -> Text -> Maybe (Text, MetaValue)+metaElementAliRef e key =+ case filterElement isAliLicenseRef e of+ Just content -> Just (key, toMetaValue $ strContent content)+ Nothing -> Nothing++metaAttribute :: Element -> Text -> Text -> Maybe (Text, MetaValue)+metaAttribute e attr key =+ case maybeAttrValue attr e of+ Just content -> Just (key, toMetaValue content)+ Nothing -> Nothing+ getContrib :: PandocMonad m => Element -> JATS m Inlines getContrib x = do given <- maybe (return mempty) getInlines@@ -409,8 +572,12 @@ parseRefList :: PandocMonad m => Element -> JATS m Blocks parseRefList e = do refs <- mapM parseRef $ filterChildren (named "ref") e+ let mbtitle = filterChild (named "title") e+ title <- case mbtitle of+ Nothing -> pure mempty+ Just te -> header 1 <$> parseInline (Elem te) addMeta "references" refs- return mempty+ return $ title <> divWith ("refs",[],[]) mempty parseRef :: PandocMonad m => Element -> JATS m (Map.Map Text MetaValue)@@ -444,6 +611,7 @@ "issue" -> Just . ("issue",) . toMetaValue <$> getInlines el "isbn" -> Just . ("ISBN",) . toMetaValue <$> getInlines el "issn" -> Just . ("ISSN",) . toMetaValue <$> getInlines el+ "uri" -> Just . ("url",) . toMetaValue <$> getInlines el "fpage" -> case filterChild (named "lpage") c of Just lp -> Just . ("page",) . toMetaValue <$>@@ -494,8 +662,8 @@ parseInline :: PandocMonad m => Content -> JATS m Inlines parseInline (Text (CData _ s _)) = return $ text s-parseInline (CRef ref) = return $ maybe (text $ T.toUpper ref) (text . T.pack)- $ lookupEntity (T.unpack ref)+parseInline (CRef ref) = return $ maybe (text $ T.toUpper ref) text+ $ lookupEntity ref parseInline (Elem e) = case qName (elName e) of "italic" -> innerInlines emph@@ -510,7 +678,7 @@ "code" -> codeWithLang "monospace" -> codeWithLang - "inline-graphic" -> getGraphic Nothing e+ "inline-graphic" -> getGraphic e "disp-quote" -> do qt <- gets jatsQuoteType let qt' = if qt == SingleQuote then DoubleQuote else SingleQuote@@ -550,8 +718,11 @@ let attr = (attrValue "id" e, [], []) return $ linkWith attr href title ils' - "disp-formula" -> formula displayMath- "inline-formula" -> formula math+ "alternatives" -> if hasFormulaChild e+ then inlineFormula math e+ else innerInlines id+ "disp-formula" -> inlineFormula displayMath e+ "inline-formula" -> inlineFormula math e "math" | qURI (elName e) == Just "http://www.w3.org/1998/Math/MathML" -> return . math $ mathML e "tex-math" -> return . math $ textContent e@@ -562,13 +733,15 @@ "fn" -> note . mconcat <$> mapM parseBlock (elContent e) _ -> innerInlines id- where innerInlines f = extractSpaces f . mconcat <$>- mapM parseInline (elContent e)- mathML x =- case readMathML . showElement $ everywhere (mkT removePrefix) x of- Left _ -> mempty- Right m -> writeTeX m- formula constructor = do+ where innerInlines f = f . mconcat <$> mapM parseInline (elContent e)+ codeWithLang = do+ let classes' = case attrValue "language" e of+ "" -> []+ l -> [l]+ return $ codeWith (attrValue "id" e,classes',[]) $ strContentRecursive e++inlineFormula :: PandocMonad m => (Text->Inlines) -> Element -> JATS m Inlines+inlineFormula constructor e = do let whereToLook = fromMaybe e $ filterElement (named "alternatives") e texMaths = map textContent $ filterChildren (named "tex-math") whereToLook@@ -576,12 +749,36 @@ filterChildren isMathML whereToLook return . mconcat . take 1 . map constructor $ texMaths ++ mathMLs - isMathML x = qName (elName x) == "math" &&+blockFormula :: PandocMonad m => (Text->Inlines) -> Element -> JATS m Blocks+blockFormula constructor e = do+ let whereToLook = fromMaybe e $ filterElement (named "alternatives") e+ texMaths = map textContent $+ filterChildren (named "tex-math") whereToLook+ mathMLs = map mathML $+ filterChildren isMathML whereToLook+ case texMaths ++ mathMLs of+ [] -> return mempty+ (m:_) -> return $ para (constructor m)++mathML :: Element -> Text+mathML x =+ case readMathML . showElement $ everywhere (mkT removePrefix) x of+ Left _ -> mempty+ Right m -> writeTeX m+ where removePrefix elname = elname { qPrefix = Nothing }++isMathML :: Element -> Bool+isMathML x = qName (elName x) == "math" && qURI (elName x) == Just "http://www.w3.org/1998/Math/MathML"- removePrefix elname = elname { qPrefix = Nothing }- codeWithLang = do- let classes' = case attrValue "language" e of- "" -> []- l -> [l]- return $ codeWith (attrValue "id" e,classes',[]) $ strContentRecursive e++formulaChildren :: Element -> [Element]+formulaChildren x = filterChildren isMathML x ++ filterChildren (named "tex-math") x++hasFormulaChild :: Element -> Bool+hasFormulaChild x = length (formulaChildren x) > 0++isAliLicenseRef :: Element -> Bool+isAliLicenseRef x = qName (elName x) == "license_ref" &&+ qURI (elName x) ==+ Just "http://www.niso.org/schemas/ali/1.0/"
@@ -1,19 +1,20 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {- |- Module : Text.Pandoc.Readers.Org- Copyright : © 2019-2022 Albert Krewinkel- License : GNU GPL, version 2 or above+ Module : Text.Pandoc.Readers.Jira+ Copyright : © 2019-2024 Albert Krewinkel+ License : GPL-2.0-or-later - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Conversion of jira wiki formatted plain text to 'Pandoc' document. -} module Text.Pandoc.Readers.Jira ( readJira ) where import Control.Monad.Except (throwError)-import Data.Text (Text, append, pack, singleton, unpack)-import Text.HTML.TagSoup.Entity (lookupEntity)+import Data.List (partition)+import Data.Text (Text, append, pack, singleton)+import Text.Pandoc.XML (lookupEntity) import Text.Jira.Parser (parse) import Text.Pandoc.Class.PandocMonad (PandocMonad (..)) import Text.Pandoc.Builder hiding (cell)@@ -76,7 +77,16 @@ -- | Create a pandoc @'Div'@ from a panel. toPandocDiv :: [Jira.Parameter] -> [Jira.Block] -> Blocks toPandocDiv params =- divWith ("", ["panel"], map paramToPair params) . foldMap jiraToPandocBlocks+ let (titles, params') = partition ((== "title") . Jira.parameterKey) params+ addTitle = case titles of+ [] ->+ id+ (title:_) -> \blks ->+ (divWith ("", ["panelheader"], []) . plain . strong $+ text (Jira.parameterValue title)) <> blks+ in divWith ("", ["panel"], map paramToPair params')+ . addTitle+ . foldMap jiraToPandocBlocks paramToPair :: Jira.Parameter -> (Text, Text) paramToPair (Jira.Parameter key value) = (key, value)@@ -137,9 +147,9 @@ Jira.Styled style inlns -> fromStyle style $ fromInlines inlns where fromInlines = foldMap jiraToPandocInlines- fromEntity e = case lookupEntity (unpack e ++ ";") of+ fromEntity e = case lookupEntity (e <> ";") of Nothing -> "&" `append` e `append` ";"- Just cs -> pack cs+ Just t ->t fromStyle = \case Jira.Emphasis -> emph
@@ -4,7 +4,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Readers.LaTeX- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -24,6 +24,7 @@ import Control.Applicative (many, optional, (<|>)) import Control.Monad import Control.Monad.Except (throwError)+import Data.Containers.ListUtils (nubOrd) import Data.Char (isDigit, isLetter, isAlphaNum, toUpper, chr) import Data.Default import Data.List (intercalate)@@ -32,6 +33,7 @@ import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T+import Data.Either (partitionEithers) import Skylighting (defaultSyntaxMap) import System.FilePath (addExtension, replaceExtension, takeExtension) import Text.Collate.Lang (renderLang)@@ -40,18 +42,18 @@ readFileFromDirs, report, setResourcePath, getZonedTime) import Data.Time (ZonedTime(..), LocalTime(..), showGregorian)-import Text.Pandoc.Error (PandocError (PandocParseError, PandocParsecError))+import Text.Pandoc.Error (PandocError (PandocParseError)) import Text.Pandoc.Highlighting (languagesByExtension) import Text.Pandoc.ImageSize (numUnit, showFl) import Text.Pandoc.Logging import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (blankline, many, mathDisplay, mathInline, optional, space, spaces, withRaw, (<|>))-import Text.Pandoc.Readers.LaTeX.Types (Tok (..), TokType (..))+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)@@ -59,11 +61,13 @@ import Text.Pandoc.Readers.LaTeX.Macro (macroDef) import Text.Pandoc.Readers.LaTeX.Lang (inlineLanguageCommands, enquoteCommands,- babelLangToBCP47, setDefaultLanguage)+ babelLangToBCP47,+ setDefaultLanguage) import Text.Pandoc.Readers.LaTeX.SIunitx (siunitxCommands) import Text.Pandoc.Readers.LaTeX.Inline (acronymCommands, refCommands, nameCommands, charCommands, accentCommands,+ miscCommands, biblatexInlineCommands, verbCommands, rawInlineOr, listingsLanguage)@@ -87,7 +91,7 @@ (TokStream False (tokenizeSources sources)) case parsed of Right result -> return result- Left e -> throwError $ PandocParsecError sources e+ Left e -> throwError $ fromParsecError sources e parseLaTeX :: PandocMonad m => LP m Pandoc parseLaTeX = do@@ -106,21 +110,34 @@ (if bottomLevel < 1 then walk (adjustHeaders (1 - bottomLevel)) else id) $+ walk (resolveFootnoteMarks (sFootnoteTexts st)) $ walk (resolveRefs (sLabels st)) doc' return $ Pandoc meta bs' resolveRefs :: M.Map Text [Inline] -> Inline -> Inline resolveRefs labels x@(Link (ident,classes,kvs) _ _) =- case (lookup "reference-type" kvs,+ case (T.takeWhile (/='+') <$> lookup "reference-type" kvs, lookup "reference" kvs) of- (Just "ref", Just lab) ->+ (Just "ref", Just lab) -> -- TODO special treatment of ref+label case M.lookup lab labels of Just txt -> Link (ident,classes,kvs) txt ("#" <> lab, "") Nothing -> x _ -> x resolveRefs _ x = x +-- | Resolve footnote marks (\footnotemark) to actual notes using+-- the footnote texts collected from \footnotetext commands.+resolveFootnoteMarks :: M.Map Int Blocks -> Inline -> Inline+resolveFootnoteMarks fnTexts (Span (_, classes, kvs) _)+ | "footnote-mark" `elem` classes+ , Just numText <- lookup "note-num" kvs+ , [(n, "")] <- reads (T.unpack numText)+ = case M.lookup n fnTexts of+ Just contents -> Note (toList contents)+ Nothing -> Str "" -- No matching footnotetext found+resolveFootnoteMarks _ x = x + -- testParser :: LP PandocIO a -> Text -> IO a -- testParser p t = do -- res <- runIOorExplode (runParserT p defaultLaTeXState{@@ -134,22 +151,34 @@ rawLaTeXBlock :: (PandocMonad m, HasMacros s, HasReaderOptions s)- => ParserT Sources s m Text+ => ParsecT Sources s m Text rawLaTeXBlock = do lookAhead (try (char '\\' >> letter)) toks <- getInputTokens snd <$> ( rawLaTeXParser toks- (macroDef (const mempty) <|>+ (makeAtLetterSection <|>+ macroDef (const mempty) <|> do choice (map controlSeq ["include", "input", "subfile", "usepackage"]) skipMany opt braced return mempty) blocks <|> rawLaTeXParser toks- (environment <|> blockCommand)+ (void (environment <|> blockCommand)) (mconcat <$> many (block <|> beginOrEndCommand))) +makeAtLetterSection :: PandocMonad m => LP m ()+makeAtLetterSection = try $ do+ controlSeq "makeatletter"+ void $ manyTill+ ( whitespace+ <|> newlineTok+ <|> macroDef (const ())+ <|> void environment+ <|> void blockCommand+ ) (controlSeq "makeatother")+ -- See #4667 for motivation; sometimes people write macros -- that just evaluate to a begin or end command, which blockCommand -- won't accept.@@ -165,7 +194,7 @@ (txt <> untokenize rawargs) rawLaTeXInline :: (PandocMonad m, HasMacros s, HasReaderOptions s)- => ParserT Sources s m Text+ => ParsecT Sources s m Text rawLaTeXInline = do lookAhead (try (char '\\' >> letter)) toks <- getInputTokens@@ -173,17 +202,16 @@ ( rawLaTeXParser toks (mempty <$ (controlSeq "input" >> skipMany rawopt >> braced)) inlines- <|> rawLaTeXParser toks (inlineEnvironment <|> inlineCommand')- inlines+ <|> rawLaTeXParser toks (void inline) inlines ) finalbraces <- mconcat <$> many (try (string "{}")) -- see #5439 return $ raw <> T.pack finalbraces -inlineCommand :: PandocMonad m => ParserT Sources ParserState m Inlines+inlineCommand :: PandocMonad m => ParsecT Sources ParserState m Inlines inlineCommand = do lookAhead (try (char '\\' >> letter)) toks <- getInputTokens- fst <$> rawLaTeXParser toks (inlineEnvironment <|> inlineCommand')+ fst <$> rawLaTeXParser toks (void (inlineEnvironment <|> inlineCommand')) inlines -- inline elements:@@ -204,14 +232,16 @@ mkImage :: PandocMonad m => [(Text, Text)] -> Text -> LP m Inlines mkImage options (T.unpack -> src) = do- let replaceTextwidth (k,v) =+ let replaceRelative (k,v) = case numUnit v of Just (num, "\\textwidth") -> (k, showFl (num * 100) <> "%")+ Just (num, "\\linewidth") -> (k, showFl (num * 100) <> "%")+ Just (num, "\\textheight") -> (k, showFl (num * 100) <> "%") _ -> (k, v)- let kvs = map replaceTextwidth+ let kvs = map replaceRelative $ filter (\(k,_) -> k `elem` ["width", "height"]) options let attr = ("",[], kvs)- let alt = str "image"+ let alt = maybe (str "image") str $ lookup "alt" options defaultExt <- getOption readerDefaultImageExtension let exts' = [".pdf", ".png", ".jpg", ".mps", ".jpeg", ".jbig2", ".jb2"] let exts = exts' ++ map (map toUpper) exts'@@ -301,7 +331,7 @@ else pure "" overlay <- option "" overlaySpecification let name' = name <> star <> overlay- let names = ordNub [name', name] -- check non-starred as fallback+ let names = nubOrd [name', name] -- check non-starred as fallback let raw = do guard $ isInlineCommand name || not (isBlockCommand name) rawcommand <- getRawCommand name (cmd <> star)@@ -315,7 +345,7 @@ unescapeURL :: Text -> Text unescapeURL = T.concat . go . T.splitOn "\\" where- isEscapable c = c `elemText` "#$%&~_^\\{}"+ isEscapable c = T.any (== c) "#$%&~_^\\{}" go (x:xs) = x : map unescapeInterior xs go [] = [] unescapeInterior t@@ -326,6 +356,7 @@ inlineCommands :: PandocMonad m => M.Map Text (LP m Inlines) inlineCommands = M.unions [ accentCommands tok+ , miscCommands , citationCommands inline , siunitxCommands tok , acronymCommands@@ -338,6 +369,12 @@ , biblatexInlineCommands tok , rest ] where+ disableLigatures p = do+ oldLigatures <- sLigatures <$> getState+ updateState (\s -> s{ sLigatures = False })+ res <- p+ updateState (\s -> s{ sLigatures = oldLigatures })+ pure res rest = M.fromList [ ("emph", extractSpaces emph <$> tok) , ("textit", extractSpaces emph <$> tok)@@ -347,8 +384,7 @@ , ("textmd", extractSpaces (spanWith ("",["medium"],[])) <$> tok) , ("textrm", extractSpaces (spanWith ("",["roman"],[])) <$> tok) , ("textup", extractSpaces (spanWith ("",["upright"],[])) <$> tok)- , ("texttt", formatCode nullAttr <$> tok)- , ("sout", extractSpaces strikeout <$> tok)+ , ("texttt", formatCode nullAttr <$> disableLigatures tok) , ("alert", skipopts >> spanWith ("",["alert"],[]) <$> tok) -- beamer , ("textsuperscript", extractSpaces superscript <$> tok) , ("textsubscript", extractSpaces subscript <$> tok)@@ -359,9 +395,11 @@ , ("hbox", rawInlineOr "hbox" $ processHBox <$> tok) , ("vbox", rawInlineOr "vbox" tok) , ("lettrine", rawInlineOr "lettrine" lettrine)- , ("(", mathInline . untokenize <$> manyTill anyTok (controlSeq ")"))- , ("[", mathDisplay . untokenize <$> manyTill anyTok (controlSeq "]"))- , ("ensuremath", mathInline . untokenize <$> braced)+ , ("(", withMathMode+ (mathInline . untokenize <$> manyTill anyTok (controlSeq ")")))+ , ("[", withMathMode+ (mathDisplay . untokenize <$> manyTill anyTok (controlSeq "]")))+ , ("ensuremath", withMathMode (mathInline . untokenize <$> braced)) , ("texorpdfstring", const <$> tok <*> tok) -- old TeX commands , ("em", extractSpaces emph <$> inlines)@@ -382,20 +420,19 @@ , ("lowercase", makeLowercase <$> tok) , ("thanks", skipopts >> note <$> grouped block) , ("footnote", skipopts >> footnote)+ , ("footnotemark", footnotemark)+ , ("footnotetext", footnotetext)+ , ("newline", pure B.linebreak) , ("passthrough", fixPassthroughEscapes <$> tok) -- \passthrough macro used by latex writer -- for listings , ("includegraphics", do options <- option [] keyvals- src <- braced- mkImage options .- unescapeURL .- removeDoubleQuotes $ untokenize src)+ src <- bracedFilename+ mkImage options . unescapeURL $ src) -- svg , ("includesvg", do options <- option [] keyvals- src <- braced- mkImage options .- unescapeURL .- removeDoubleQuotes $ untokenize src)+ src <- bracedFilename+ mkImage options . unescapeURL $ src) -- hyperref , ("url", (\url -> linkWith ("",["uri"],[]) url "" (str url)) . unescapeURL . untokenize <$> bracedUrl)@@ -414,7 +451,6 @@ , ("textcolor", coloredInline "color") , ("colorbox", coloredInline "background-color") -- etoolbox- , ("ifstrequal", ifstrequal) , ("newtoggle", braced >>= newToggle) , ("toggletrue", braced >>= setToggle True) , ("togglefalse", braced >>= setToggle False)@@ -422,15 +458,29 @@ -- include , ("input", rawInlineOr "input" $ include "input") -- soul package+ , ("st", extractSpaces strikeout <$> tok) , ("ul", underline <$> tok)+ , ("hl", extractSpaces (spanWith ("",["mark"],[])) <$> tok) -- ulem package+ , ("sout", extractSpaces strikeout <$> tok) , ("uline", underline <$> tok) -- plain tex stuff that should just be passed through as raw tex , ("ifdim", ifdim) -- generally only used in \date , ("today", today)+ -- this is used internally by pandoc but the definition is too complicated+ -- for pandoc to handle (see #11140):+ , ("pandocbounded", tok) ] +bracedFilename :: PandocMonad m => LP m Text+bracedFilename =+ removeDoubleQuotes . T.strip . untokenize . filter (not . isComment) <$> braced++isComment :: Tok -> Bool+isComment (Tok _ Comment _) = True+isComment _ = False+ today :: PandocMonad m => LP m Inlines today = text . T.pack . showGregorian . localDay . zonedTimeToLocalTime@@ -442,6 +492,39 @@ contents <- grouped block >>= walkM resolveNoteLabel return $ note contents +-- | Parse \footnotemark[n]. If n is not given, increment the counter.+-- Returns a span marker that will be resolved to a Note later.+footnotemark :: PandocMonad m => LP m Inlines+footnotemark = do+ mbNum <- optionalFootnoteNum+ noteNum <- case mbNum of+ Just n -> return n+ Nothing -> do+ updateState $ \st -> st{ sLastNoteNum = sLastNoteNum st + 1 }+ sLastNoteNum <$> getState+ return $ B.spanWith ("", ["footnote-mark"], [("note-num", tshow noteNum)]) mempty++-- | Parse \footnotetext[n]{text}. If n is not given, use current counter.+-- Stores the text in state to be resolved later.+footnotetext :: PandocMonad m => LP m Inlines+footnotetext = do+ mbNum <- optionalFootnoteNum+ noteNum <- case mbNum of+ Just n -> return n+ Nothing -> sLastNoteNum <$> getState+ contents <- grouped block >>= walkM resolveNoteLabel+ updateState $ \st -> st{+ sFootnoteTexts = M.insert noteNum contents (sFootnoteTexts st) }+ return mempty++-- | Parse optional footnote number argument [n]+optionalFootnoteNum :: PandocMonad m => LP m (Maybe Int)+optionalFootnoteNum = option Nothing $ do+ t <- bracketedToks+ case reads (T.unpack $ untokenize t) of+ [(n, "")] -> return $ Just n+ _ -> return Nothing+ resolveNoteLabel :: PandocMonad m => Inline -> LP m Inline resolveNoteLabel (Span (_,cls,kvs) _) | Just lab <- lookup "label" kvs = do@@ -526,9 +609,9 @@ ifToggle = do name <- braced spaces- yes <- braced+ yes <- withVerbatimMode braced spaces- no <- braced+ no <- withVerbatimMode braced toggles <- sToggles <$> getState TokStream _ inp <- getInput let name' = untokenize name@@ -540,18 +623,6 @@ report $ UndefinedToggle name' pos return () -ifstrequal :: (PandocMonad m, Monoid a) => LP m a-ifstrequal = do- str1 <- tok- str2 <- tok- ifequal <- braced- ifnotequal <- braced- TokStream _ ts <- getInput- if str1 == str2- then setInput $ TokStream False (ifequal ++ ts)- else setInput $ TokStream False (ifnotequal ++ ts)- return mempty- coloredInline :: PandocMonad m => Text -> LP m Inlines coloredInline stylename = do skipopts@@ -621,6 +692,7 @@ do eatOneToken report $ ParsingUnescaped t pos return $ str t+ ligatures <- sLigatures <$> getState case toktype of Comment -> mempty <$ eatOneToken Spaces -> space <$ eatOneToken@@ -628,14 +700,19 @@ Word -> str t <$ eatOneToken Symbol -> case t of- "-" -> eatOneToken *>+ "-" | ligatures+ -> eatOneToken *> option (str "-") (symbol '-' *> option (str "–") (str "—" <$ symbol '-')) "'" -> eatOneToken *>- option (str "’") (str "”" <$ symbol '\'')+ option (str "’") (str "”" <$ (guard ligatures *> symbol '\'')) "~" -> str "\160" <$ eatOneToken- "`" -> doubleQuote <|> singleQuote <|> symbolAsString- "\"" -> doubleQuote <|> singleQuote <|> symbolAsString+ "`" | ligatures+ -> doubleQuote <|> singleQuote <|> (str "‘" <$ symbol '`')+ | otherwise+ -> str "‘" <$ symbol '`'+ "\"" | ligatures+ -> doubleQuote <|> singleQuote <|> symbolAsString "“" -> doubleQuote <|> symbolAsString "‘" -> singleQuote <|> symbolAsString "$" -> dollarsMath <|> unescapedSymbolAsString@@ -669,7 +746,7 @@ (TokStream False toks) case parsed of Right result -> return result- Left e -> throwError $ PandocParsecError (toSources toks) e+ Left e -> throwError $ fromParsecError (toSources toks) e -- block elements: @@ -712,7 +789,7 @@ doSubfile :: PandocMonad m => LP m Blocks doSubfile = do skipMany opt- f <- T.unpack . removeDoubleQuotes . T.strip . untokenize <$> braced+ f <- T.unpack <$> bracedFilename oldToks <- getInput setInput $ TokStream False [] insertIncluded (ensureExtension (/= "") ".tex" f)@@ -730,7 +807,7 @@ _ -> const False skipMany opt fs <- map (T.unpack . removeDoubleQuotes . T.strip) . T.splitOn "," .- untokenize <$> braced+ untokenize . filter (not . isComment) <$> braced mapM_ (insertIncluded . ensureExtension isAllowed ".tex") fs return mempty @@ -738,7 +815,7 @@ usepackage = do skipMany opt fs <- map (T.unpack . removeDoubleQuotes . T.strip) . T.splitOn "," .- untokenize <$> braced+ untokenize . filter (not . isComment) <$> braced let parsePackage f = do TokStream _ ts <- getIncludedToks (ensureExtension (== ".sty") ".sty" f) parseFromToks (do _ <- blocks@@ -755,8 +832,11 @@ case M.lookup (T.pack fp) fileContentsMap of Just t -> return (Just t) Nothing -> do- dirs <- map T.unpack . splitTextBy (==':') . fromMaybe "."- <$> lookupEnv "TEXINPUTS"+ dirs <- map (\t -> if T.null t+ then "."+ else T.unpack t)+ . T.split (==':') . fromMaybe ""+ <$> lookupEnv "TEXINPUTS" readFileFromDirs dirs fp ensureExtension :: (FilePath -> Bool) -> FilePath -> FilePath -> FilePath@@ -840,7 +920,7 @@ guard $ name /= "begin" && name /= "end" && name /= "and" star <- option "" ("*" <$ symbol '*' <* sp) let name' = name <> star- let names = ordNub [name', name]+ let names = nubOrd [name', name] let rawDefiniteBlock = do guard $ isBlockCommand name rawcontents <- getRawCommand name (txt <> star)@@ -905,7 +985,7 @@ , ("address", mempty <$ (skipopts *> tok >>= addMeta "address")) , ("signature", mempty <$ (skipopts *> authors)) , ("date", mempty <$ (skipopts *> tok >>= addMeta "date"))- , ("newtheorem", newtheorem inline)+ , ("newtheorem", newtheorem) , ("theoremstyle", theoremstyle) -- KOMA-Script metadata commands , ("extratitle", mempty <$ (skipopts *> tok >>= addMeta "extratitle"))@@ -918,7 +998,7 @@ , ("dedication", mempty <$ (skipopts *> tok >>= addMeta "dedication")) -- sectioning , ("part", section nullAttr (-1))- , ("part*", section nullAttr (-1))+ , ("part*", section ("",["unnumbered"],[]) (-1)) , ("chapter", section nullAttr 0) , ("chapter*", section ("",["unnumbered"],[]) 0) , ("section", section nullAttr 1)@@ -931,6 +1011,7 @@ , ("paragraph*", section ("",["unnumbered"],[]) 4) , ("subparagraph", section nullAttr 5) , ("subparagraph*", section ("",["unnumbered"],[]) 5)+ , ("minisec", section ("",["unnumbered","unlisted"],[]) 6) -- from KOMA -- beamer slides , ("frametitle", section nullAttr 3) , ("framesubtitle", section nullAttr 4)@@ -989,6 +1070,11 @@ , ("epigraph", epigraph) -- alignment , ("raggedright", pure mempty)+ -- etoolbox+ , ("newtoggle", braced >>= newToggle)+ , ("toggletrue", braced >>= setToggle True)+ , ("togglefalse", braced >>= setToggle False)+ , ("iftoggle", try $ ifToggle >> block) ] skipSameFileToks :: PandocMonad m => LP m ()@@ -997,16 +1083,17 @@ skipMany $ infile (sourceName pos) environments :: PandocMonad m => M.Map Text (LP m Blocks)-environments = M.union (tableEnvironments blocks inline) $+environments = M.union (tableEnvironments block inline) $ M.fromList [ ("document", env "document" blocks <* skipMany anyTok) , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract")) , ("sloppypar", env "sloppypar" blocks) , ("letter", env "letter" letterContents)- , ("minipage", env "minipage" $- skipopts *> spaces *> optional braced *> spaces *> blocks)- , ("figure", env "figure" $ skipopts *> figure)- , ("subfigure", env "subfigure" $ skipopts *> tok *> figure)+ , ("minipage", divWith ("",["minipage"],[]) <$>+ env "minipage" (skipopts *> spaces *> optional braced *> spaces *> blocks))+ , ("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) , ("quotation", blockQuote <$> env "quotation" blocks)@@ -1031,15 +1118,26 @@ , ("ly", rawVerbEnv "ly") -- amsthm , ("proof", proof blocks opt)- -- etoolbox- , ("ifstrequal", ifstrequal)- , ("newtoggle", braced >>= newToggle)- , ("toggletrue", braced >>= setToggle True)- , ("togglefalse", braced >>= setToggle False)- , ("iftoggle", try $ ifToggle >> block)+ -- other , ("CSLReferences", braced >> braced >> env "CSLReferences" blocks)+ , ("otherlanguage", env "otherlanguage" otherlanguageEnv) ] +otherlanguageEnv :: PandocMonad m => LP m Blocks+otherlanguageEnv = do+ skipopts+ babelLang <- untokenize <$> braced+ case babelLangToBCP47 babelLang of+ Just lang -> divWith ("", [], [("lang", renderLang lang)]) <$> blocks+ Nothing -> blocks++langEnvironment :: PandocMonad m => Text -> LP m Blocks+langEnvironment name =+ case babelLangToBCP47 name of+ Just lang ->+ env name (divWith ("", [], [("lang", renderLang lang)]) <$> blocks)+ Nothing -> mzero -- fall through to raw environment+ filecontents :: PandocMonad m => LP m Blocks filecontents = try $ do controlSeq "begin"@@ -1057,7 +1155,8 @@ controlSeq "begin" name <- untokenize <$> braced M.findWithDefault mzero name environments <|>- theoremEnvironment blocks opt name <|>+ langEnvironment name <|>+ theoremEnvironment blocks inlines opt name <|> if M.member name (inlineEnvironments :: M.Map Text (LP PandocPure Inlines)) then mzero@@ -1158,36 +1257,34 @@ _ -> mempty return $ addr <> bs -- sig added by \closing -figure :: PandocMonad m => LP m Blocks-figure = try $ do+figure' :: PandocMonad m => LP m Blocks+figure' = try $ do+ sp+ poshint <- option "" $ untokenize <$> bracketedToks+ sp resetCaption- blocks >>= addImageCaption--addImageCaption :: PandocMonad m => Blocks -> LP m Blocks-addImageCaption = walkM go- where go p@(Para [Image attr@(_, cls, kvs) _ (src, tit)])- | not ("fig:" `T.isPrefixOf` tit) = do- st <- getState- case sCaption st of- Nothing -> return p- Just figureCaption -> do- let mblabel = sLastLabel st- let attr' = case mblabel of- Just lab -> (lab, cls, kvs)- Nothing -> attr- case attr' of- ("", _, _) -> return ()- (ident, _, _) -> do- num <- getNextNumber sLastFigureNum- setState- st{ sLastFigureNum = num- , sLabels = M.insert ident- [Str (renderDottedNum num)] (sLabels st) }+ 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 kvs = [("latex-placement", poshint) | not (T.null poshint)]+ let ident = fromMaybe "" mblabel+ let attr = (ident, [], kvs)+ case mblabel of+ Nothing -> pure ()+ Just lab -> do+ num <- getNextNumber sLastFigureNum+ setState+ st { sLastFigureNum = num+ , sLabels = M.insert lab [Str (renderDottedNum num)] (sLabels st)+ }+ return $ B.figureWith attr caption' content - return $ SimpleFigure attr'- (maybe id removeLabel mblabel (B.toList figureCaption))- (src, tit)- go x = return x+ where+ -- Remove the `Image` caption b.c. it's on the `Figure`+ go (Para [Image attr [Str "image"] target]) = Plain [Image attr [] target]+ go x = x coloredBlock :: PandocMonad m => Text -> LP m Blocks coloredBlock stylename = try $ do@@ -1324,4 +1421,3 @@ blocks :: PandocMonad m => LP m Blocks blocks = mconcat <$> many block-
@@ -15,7 +15,6 @@ import Control.Monad (mzero) import Control.Monad.Trans (lift) import Control.Monad.Except (throwError)-import Text.Pandoc.Error (PandocError(PandocParsecError)) import Text.Pandoc.Parsing hiding (blankline, many, mathDisplay, mathInline, optional, space, spaces, withRaw, (<|>)) @@ -121,7 +120,7 @@ (TokStream False toks) case parsed of Right result -> return result- Left e -> throwError $ PandocParsecError (toSources toks) e+ Left e -> throwError $ fromParsecError (toSources toks) e @@ -208,4 +207,3 @@ inNote :: Inlines -> Inlines inNote ils = note $ para $ ils <> str "."-
@@ -2,7 +2,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Readers.LaTeX.Inline- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -14,6 +14,7 @@ , verbCommands , charCommands , accentCommands+ , miscCommands , nameCommands , biblatexInlineCommands , refCommands@@ -27,10 +28,11 @@ import qualified Data.Text as T import Text.Pandoc.Builder import Text.Pandoc.Shared (toRomanNumeral, safeRead)-import Text.Pandoc.Readers.LaTeX.Types (Tok (..), TokType (..))+import Text.Pandoc.TeX (Tok (..), TokType (..)) import Control.Applicative (optional, (<|>)) import Control.Monad (guard, mzero, mplus, unless)-import Text.Pandoc.Class.PandocMonad (PandocMonad (..), translateTerm)+import Text.Pandoc.Class.PandocMonad (PandocMonad (..))+import Text.Pandoc.Translations (translateTerm) import Text.Pandoc.Readers.LaTeX.Parsing import Text.Pandoc.Extensions (extensionEnabled, Extension(..)) import Text.Pandoc.Parsing (getOption, updateState, getState, notFollowedBy,@@ -182,6 +184,43 @@ , ("Verb", doverb) ] +miscCommands :: PandocMonad m => M.Map Text (LP m Inlines)+miscCommands =+ M.fromList+ [ ("pounds", lit "£")+ , ("euro", lit "€")+ , ("copyright", lit "©")+ , ("textasciicircum", lit "^")+ , ("textasciitilde", lit "~")+ , ("textbaht", lit "฿")+ , ("textblank", lit "␢")+ , ("textbigcircle", lit "○")+ , ("textbrokenbar", lit "¦")+ , ("textbullet", lit "•")+ , ("textcentoldstyle", lit "¢")+ , ("textcopyright", lit "©")+ , ("textdagger", lit "†")+ , ("textdegree", lit "°")+ , ("textdollar", lit "$")+ , ("textdong", lit "₫")+ , ("textlira", lit "₤")+ , ("textmu", lit "μ")+ , ("textmusicalnote", lit "♪")+ , ("textonehalf", lit "½")+ , ("textonequarter", lit "¼")+ , ("textparagraph", lit "¶")+ , ("textpertenthousand", lit "‱")+ , ("textpeso", lit "₱")+ , ("textquotesingle", lit "'")+ , ("textregistered", lit "®")+ , ("textsection", lit "§")+ , ("textsterling", lit "£")+ , ("textthreequarters", lit "¾")+ , ("textthreesuperior", lit "³")+ , ("texttwosuperior", lit "²")+ , ("textyen", lit "¥")+ ]+ accentCommands :: PandocMonad m => LP m Inlines -> M.Map Text (LP m Inlines) accentCommands tok = let accent = accentWith tok@@ -197,11 +236,6 @@ , ("AE", lit "Æ") , ("oe", lit "œ") , ("OE", lit "Œ")- , ("pounds", lit "£")- , ("euro", lit "€")- , ("copyright", lit "©")- , ("textasciicircum", lit "^")- , ("textasciitilde", lit "~") , ("H", accent '\779' Nothing) -- hungarumlaut , ("`", accent '\768' (Just '`')) -- grave , ("'", accent '\769' (Just '\'')) -- acute@@ -247,6 +281,7 @@ , ("_", lit "_") , ("{", lit "{") , ("}", lit "}")+ , ("-", lit "\x00ad") -- soft hyphen , ("qed", lit "\a0\x25FB") , ("lq", return (str "‘")) , ("rq", return (str "’"))@@ -280,6 +315,26 @@ , ("dothyp", lit ".\173") , ("colonhyp", lit ":\173") , ("hyp", lit "-")+ -- ngerman (babel)+ , ("glq", lit "‚")+ , ("grq", lit "‘")+ , ("glqq", lit "„")+ , ("grqq", lit "“")+ , ("flq", lit "‹")+ , ("frq", lit "›")+ , ("flqq", lit "«")+ , ("frqq", lit "»")+ , ("dq", lit "\"")+ -- fontspec+ , ("guillemetleft", lit "«")+ , ("guillemotleft", lit "«")+ , ("guillemetright", lit "»")+ , ("guillemotright", lit "»")+ , ("guilsinglleft", lit "‹")+ , ("guilsinglright", lit "›")+ , ("quotedblbase", lit "„")+ , ("quotesinglbase", lit ",")+ , ("textquotedbl", lit "\"") ] biblatexInlineCommands :: PandocMonad m@@ -336,10 +391,11 @@ refCommands = M.fromList [ ("label", rawInlineOr "label" dolabel) , ("ref", rawInlineOr "ref" $ doref "ref")- , ("cref", rawInlineOr "cref" $ doref "ref") -- from cleveref.sty- , ("vref", rawInlineOr "vref" $ doref "ref+page") -- from varioref.sty+ , ("cref", rawInlineOr "cref" $ doref "ref+label") -- from cleveref.sty+ , ("Cref", rawInlineOr "Cref" $ doref "ref+Label") -- from cleveref.sty+ , ("vref", rawInlineOr "vref" $ doref "ref") -- from varioref.sty , ("eqref", rawInlineOr "eqref" $ doref "eqref") -- from amsmath.sty- , ("autoref", rawInlineOr "autoref" $ doref "autoref") -- from hyperref.sty+ , ("autoref", rawInlineOr "autoref" $ doref "ref+label") -- from hyperref.sty ] acronymCommands :: PandocMonad m => M.Map Text (LP m Inlines)@@ -394,5 +450,3 @@ return . mconcat $ [spanWith ("",[],[("acronym-label", untokenize acro), ("acronym-form", "plural+" <> form)]) $ mconcat [str $ untokenize acro, plural]]--
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.LaTeX.Lang- Copyright : Copyright (C) 2018-2022 John MacFarlane+ Copyright : Copyright (C) 2018-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -24,7 +24,8 @@ import qualified Data.Text as T import Text.Pandoc.Shared (extractSpaces) import Text.Collate.Lang (Lang(..), renderLang)-import Text.Pandoc.Class (PandocMonad(..), setTranslations)+import Text.Pandoc.Class (PandocMonad(..))+import Text.Pandoc.Translations (setTranslations) import Text.Pandoc.Readers.LaTeX.Parsing import Text.Pandoc.Parsing (updateState, option, getState, QuoteContext(..), withQuoteContext)@@ -170,7 +171,7 @@ , ("indonesian", \_ -> simpleLang "id") , ("icelandic", \_ -> simpleLang "is") , ("italian", \_ -> simpleLang "it")- , ("japanese", \_ -> simpleLang "jp")+ , ("japanese", \_ -> simpleLang "ja") , ("khmer", \_ -> simpleLang "km") , ("kurmanji", \_ -> simpleLang "kmr") , ("kannada", \_ -> simpleLang "kn")@@ -225,6 +226,7 @@ "ngerman" -> Just $ Lang "de" Nothing (Just "DE") [] [] [] "lowersorbian" -> Just $ Lang "dsb" Nothing Nothing [] [] [] "uppersorbian" -> Just $ Lang "hsb" Nothing Nothing [] [] []+ "polytonicgreek" -> Just $ Lang "el" Nothing Nothing ["polyton"] [] [] "polutonikogreek" -> Just $ Lang "el" Nothing Nothing ["polyton"] [] [] "slovene" -> Just $ simpleLang "sl" "australian" -> Just $ Lang "en" Nothing (Just "AU") [] [] []
@@ -6,7 +6,7 @@ import Text.Pandoc.Extensions (Extension(..)) import Text.Pandoc.Logging (LogMessage(MacroAlreadyDefined)) import Text.Pandoc.Readers.LaTeX.Parsing-import Text.Pandoc.Readers.LaTeX.Types+import Text.Pandoc.TeX import Text.Pandoc.Class import Text.Pandoc.Shared (safeRead) import Text.Pandoc.Parsing hiding (blankline, mathDisplay, mathInline,
@@ -1,7 +1,9 @@ {-# LANGUAGE OverloadedStrings #-} module Text.Pandoc.Readers.LaTeX.Math- ( dollarsMath+ ( withMathMode+ , dollarsMath , inlineEnvironments+ , inlineEnvironmentNames , inlineEnvironment , mathInline , mathDisplay@@ -11,14 +13,15 @@ , proof ) where-import Data.Maybe (fromMaybe)+import Data.Maybe (fromMaybe, mapMaybe, listToMaybe)+import qualified Data.List as L import Text.Pandoc.Walk (walk) import Text.Pandoc.Builder as B import qualified Data.Sequence as Seq import Text.Pandoc.Readers.LaTeX.Parsing-import Text.Pandoc.Readers.LaTeX.Types+import Text.Pandoc.TeX import Text.Pandoc.Class-import Text.Pandoc.Shared (trimMath, stripTrailingNewlines)+import Text.Pandoc.Shared (trimMath, trimr) import Text.Pandoc.Parsing hiding (blankline, mathDisplay, mathInline, optional, space, spaces, withRaw, (<|>)) import Control.Applicative ((<|>), optional)@@ -26,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)@@ -68,11 +79,10 @@ "\n\\end{" <> y <> "}" mathEnv :: PandocMonad m => Text -> LP m Text-mathEnv name = do- skipopts+mathEnv name = withMathMode $ do optional blankline res <- manyTill anyTok (end_ name)- return $ stripTrailingNewlines $ untokenize res+ return $ trimr $ untokenize res inlineEnvironment :: PandocMonad m => LP m Inlines inlineEnvironment = try $ do@@ -80,22 +90,29 @@ name <- untokenize <$> braced M.findWithDefault mzero name inlineEnvironments +inlineEnvironmentNames :: [Text]+inlineEnvironmentNames =+ M.keys (inlineEnvironments :: M.Map Text (LP PandocPure Inlines))+ inlineEnvironments :: PandocMonad m => M.Map Text (LP m Inlines) 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*")+ , ("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")@@ -118,14 +135,14 @@ Just sty -> updateState $ \s -> s{ sLastTheoremStyle = sty } return mempty -newtheorem :: PandocMonad m => LP m Inlines -> LP m Blocks-newtheorem inline = do+newtheorem :: PandocMonad m => LP m Blocks+newtheorem = do number <- option True (False <$ symbol '*' <* sp) name <- untokenize <$> braced sp series <- option Nothing $ Just . untokenize <$> bracketedToks sp- showName <- tokWith inline+ showName <- braced <|> ((:[]) <$> anyTok) sp syncTo <- option Nothing $ Just . untokenize <$> bracketedToks sty <- sLastTheoremStyle <$> getState@@ -140,9 +157,23 @@ M.insert name spec tmap } return mempty +extractLabelFromBlock :: Block -> Maybe Text+extractLabelFromBlock (Para inlines) = extractLabel Nothing inlines+ where+ extractLabel = L.foldl' go+ go :: Maybe Text -> Inline -> Maybe Text+ go (Just t) _ = Just t+ go Nothing (Span (_, _, attrs) _) = lookup "label" attrs+ go Nothing _ = Nothing+extractLabelFromBlock _ = Nothing+ theoremEnvironment :: PandocMonad m- => LP m Blocks -> LP m Inlines -> Text -> LP m Blocks-theoremEnvironment blocks opt name = do+ => LP m Blocks+ -> LP m Inlines+ -> LP m Inlines+ -> Text+ -> LP m Blocks+theoremEnvironment blocks inlines opt name = do resetCaption tmap <- sTheoremMap <$> getState case M.lookup name tmap of@@ -150,7 +181,7 @@ Just tspec -> do optTitle <- option mempty $ (\x -> space <> "(" <> x <> ")") <$> opt bs <- env name blocks- mblabel <- sLastLabel <$> getState+ let mblabel = listToMaybe $ mapMaybe extractLabelFromBlock (toList bs) number <- if theoremNumber tspec@@ -179,7 +210,8 @@ PlainStyle -> B.strong DefinitionStyle -> B.strong RemarkStyle -> B.emph- let title = titleEmph (theoremName tspec <> number)+ tname <- parseFromToks inlines (theoremName tspec)+ let title = titleEmph (tname <> number) <> optTitle <> "." <> space return $ divWith (fromMaybe "" mblabel, [name], []) $ addTitle title@@ -214,9 +246,8 @@ qedSign = B.str "\xa0\x25FB" italicize :: Block -> Block-italicize x@(Para [Image{}]) = x -- see #6925+italicize x@(Para [Image{}]) = x -- see #6925+italicize x@(Plain [Image{}]) = x -- ditto italicize (Para ils) = Para [Emph ils] italicize (Plain ils) = Plain [Emph ils] italicize x = x--
@@ -7,7 +7,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Text.Pandoc.Readers.LaTeX.Parsing- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -34,7 +34,6 @@ , getInputTokens , untokenize , untoken- , toksToString , satisfyTok , peekTok , parseFromToks@@ -118,11 +117,9 @@ import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (blankline, many, mathDisplay, mathInline, space, spaces, withRaw, (<|>))-import Text.Pandoc.Readers.LaTeX.Types (ExpansionPoint (..), Macro (..),+import Text.Pandoc.TeX (ExpansionPoint (..), Macro (..), ArgSpec (..), Tok (..), TokType (..)) import Text.Pandoc.Shared-import Text.Parsec.Pos-import Text.Parsec (Stream(uncons)) import Text.Pandoc.Walk newtype DottedNum = DottedNum [Int]@@ -144,7 +141,7 @@ data TheoremSpec = TheoremSpec- { theoremName :: Inlines+ { theoremName :: [Tok] , theoremStyle :: TheoremStyle , theoremSeries :: Maybe Text , theoremSyncTo :: Maybe Text@@ -160,13 +157,15 @@ , sLogMessages :: [LogMessage] , sIdentifiers :: Set.Set Text , sVerbatimMode :: Bool- , sCaption :: Maybe Inlines+ , sMathMode :: Bool+ , sCaption :: Maybe Caption , sInListItem :: Bool , sInTableCell :: Bool , sLastHeaderNum :: DottedNum , sLastFigureNum :: DottedNum , sLastTableNum :: DottedNum , sLastNoteNum :: Int+ , sFootnoteTexts :: M.Map Int Blocks , sTheoremMap :: M.Map Text TheoremSpec , sLastTheoremStyle :: TheoremStyle , sLastLabel :: Maybe Text@@ -176,6 +175,7 @@ , sFileContents :: M.Map Text Text , sEnableWithRaw :: Bool , sRawTokens :: IntMap.IntMap [Tok]+ , sLigatures :: Bool } deriving Show @@ -188,6 +188,7 @@ , sLogMessages = [] , sIdentifiers = Set.empty , sVerbatimMode = False+ , sMathMode = False , sCaption = Nothing , sInListItem = False , sInTableCell = False@@ -195,6 +196,7 @@ , sLastFigureNum = DottedNum [] , sLastTableNum = DottedNum [] , sLastNoteNum = 0+ , sFootnoteTexts = M.empty , sTheoremMap = M.empty , sLastTheoremStyle = PlainStyle , sLastLabel = Nothing@@ -204,6 +206,7 @@ , sFileContents = M.empty , sEnableWithRaw = True , sRawTokens = IntMap.empty+ , sLigatures = True } instance PandocMonad m => HasQuoteContext LaTeXState m where@@ -264,7 +267,7 @@ uncons (TokStream _ []) = return Nothing uncons (TokStream _ (t:ts)) = return $ Just (t, TokStream False ts) -type LP m = ParserT TokStream LaTeXState m+type LP m = ParsecT TokStream LaTeXState m withVerbatimMode :: PandocMonad m => LP m a -> LP m a withVerbatimMode parser = do@@ -278,8 +281,8 @@ return result rawLaTeXParser :: (PandocMonad m, HasMacros s, HasReaderOptions s, Show a)- => [Tok] -> LP m a -> LP m a- -> ParserT Sources s m (a, Text)+ => [Tok] -> LP m () -> LP m a+ -> ParsecT Sources s m (a, Text) rawLaTeXParser toks parser valParser = do pstate <- getState let lstate = def{ sOptions = extractReaderOptions pstate }@@ -300,14 +303,14 @@ Left _ -> mzero Right ((val, raw), st) -> do updateState (updateMacros ((NonEmpty.head (sMacros st)) <>))- let skipTilPos stopPos = do- anyChar+ let rawChar = do pos <- getPosition- if pos >= stopPos- then return ()- else skipTilPos stopPos- skipTilPos endpos- let result = untokenize raw+ if pos >= endpos+ then mzero+ else anyChar+ result <- (guardEnabled Ext_latex_macros+ >> (untokenize raw <$ skipMany rawChar))+ <|> T.pack <$> many rawChar -- ensure we end with space if input did, see #4442 let result' = case reverse toks' of@@ -319,7 +322,7 @@ return (val, result') applyMacros :: (PandocMonad m, HasMacros s, HasReaderOptions s)- => Text -> ParserT Sources s m Text+ => Text -> ParsecT Sources s m Text applyMacros s = (guardDisabled Ext_latex_macros >> return s) <|> do let retokenize = untokenize <$> many anyTok pstate <- getState@@ -347,7 +350,7 @@ -- Return tokens from input sources. Ensure that starting position is -- correct.-getInputTokens :: PandocMonad m => ParserT Sources s m [Tok]+getInputTokens :: PandocMonad m => ParsecT Sources s m [Tok] getInputTokens = do pos <- getPosition ss <- getInput@@ -357,41 +360,41 @@ Sources ((_,t):rest) -> tokenizeSources $ Sources ((pos,t):rest) tokenize :: SourcePos -> Text -> [Tok]-tokenize = totoks+tokenize = totoks False where- totoks pos t =+ totoks atIsLetter pos t = case T.uncons t of Nothing -> [] Just (c, rest) | c == '\n' -> Tok pos Newline "\n"- : totoks (setSourceColumn (incSourceLine pos 1) 1) rest+ : totoks atIsLetter (setSourceColumn (incSourceLine pos 1) 1) rest | isSpaceOrTab c -> let (sps, rest') = T.span isSpaceOrTab t in Tok pos Spaces sps- : totoks (incSourceColumn pos (T.length sps))+ : totoks atIsLetter (incSourceColumn pos (T.length sps)) rest' | isAlphaNum c -> let (ws, rest') = T.span isAlphaNum t in Tok pos Word ws- : totoks (incSourceColumn pos (T.length ws)) rest'+ : totoks atIsLetter (incSourceColumn pos (T.length ws)) rest' | c == '%' -> let (cs, rest') = T.break (== '\n') rest in Tok pos Comment ("%" <> cs)- : totoks (incSourceColumn pos (1 + T.length cs)) rest'+ : totoks atIsLetter (incSourceColumn pos (1 + T.length cs)) rest' | c == '\\' -> case T.uncons rest of Nothing -> [Tok pos (CtrlSeq " ") "\\"] Just (d, rest')- | isLetterOrAt d ->- -- \makeatletter is common in macro defs;- -- ideally we should make tokenization sensitive- -- to \makeatletter and \makeatother, but this is- -- probably best for now- let (ws, rest'') = T.span isLetterOrAt rest+ | isLetter' atIsLetter d ->+ let (ws, rest'') = T.span (isLetter' atIsLetter) rest (ss, rest''') = T.span isSpaceOrTab rest''+ atIsLetter' = case ws of+ "makeatletter" -> True+ "makeatother" -> False+ _ -> atIsLetter in Tok pos (CtrlSeq ws) ("\\" <> ws <> ss)- : totoks (incSourceColumn pos+ : totoks atIsLetter' (incSourceColumn pos (1 + T.length ws + T.length ss)) rest''' | isSpaceOrTab d || d == '\n' -> let (w1, r1) = T.span isSpaceOrTab rest@@ -404,24 +407,36 @@ in case T.uncons r3 of Just ('\n', _) -> Tok pos (CtrlSeq " ") ("\\" <> w1)- : totoks (incSourceColumn pos (T.length ws))- r1+ : totoks atIsLetter+ (incSourceColumn pos (T.length ws)) r1 _ -> Tok pos (CtrlSeq " ") ws- : totoks (incSourceColumn pos (T.length ws))- r3+ : totoks atIsLetter+ (incSourceColumn pos (T.length ws)) r3 | otherwise -> Tok pos (CtrlSeq (T.singleton d)) (T.pack [c,d])- : totoks (incSourceColumn pos 2) rest'+ : totoks atIsLetter (incSourceColumn pos 2) rest' | c == '#' ->- let (t1, t2) = T.span (\d -> d >= '0' && d <= '9') rest- in case safeRead t1 of- Just i ->- Tok pos (Arg i) ("#" <> t1)- : totoks (incSourceColumn pos (1 + T.length t1)) t2- Nothing ->- Tok pos Symbol "#"- : totoks (incSourceColumn pos 1) t2+ case T.uncons rest of+ Just ('#', t3) ->+ let (t1, t2) = T.span (\d -> d >= '0' && d <= '9') t3+ in case safeRead t1 of+ Just i ->+ Tok pos (DeferredArg i) ("##" <> t1)+ : totoks atIsLetter+ (incSourceColumn pos (2 + T.length t1)) t2+ Nothing -> Tok pos Symbol "#"+ : Tok (incSourceColumn pos 1) Symbol "#"+ : totoks atIsLetter (incSourceColumn pos 1) t3+ _ ->+ let (t1, t2) = T.span (\d -> d >= '0' && d <= '9') rest+ in case safeRead t1 of+ Just i ->+ Tok pos (Arg i) ("#" <> t1)+ : totoks atIsLetter+ (incSourceColumn pos (1 + T.length t1)) t2+ Nothing -> Tok pos Symbol "#"+ : totoks atIsLetter (incSourceColumn pos 1) rest | c == '^' -> case T.uncons rest of Just ('^', rest') ->@@ -431,26 +446,35 @@ case T.uncons rest'' of Just (e, rest''') | isLowerHex e -> Tok pos Esc2 (T.pack ['^','^',d,e])- : totoks (incSourceColumn pos 4) rest'''+ : totoks atIsLetter+ (incSourceColumn pos 4) rest''' _ -> Tok pos Esc1 (T.pack ['^','^',d])- : totoks (incSourceColumn pos 3) rest''+ : totoks atIsLetter+ (incSourceColumn pos 3) rest'' | d < '\128' -> Tok pos Esc1 (T.pack ['^','^',d])- : totoks (incSourceColumn pos 3) rest''+ : totoks atIsLetter+ (incSourceColumn pos 3) rest'' _ -> Tok pos Symbol "^" : Tok (incSourceColumn pos 1) Symbol "^" :- totoks (incSourceColumn pos 2) rest'+ totoks atIsLetter (incSourceColumn pos 2) rest' _ -> Tok pos Symbol "^"- : totoks (incSourceColumn pos 1) rest+ : totoks atIsLetter (incSourceColumn pos 1) rest | otherwise ->- Tok pos Symbol (T.singleton c) : totoks (incSourceColumn pos 1) rest+ Tok pos Symbol (T.singleton c) :+ totoks atIsLetter (incSourceColumn pos 1) rest isSpaceOrTab :: Char -> Bool isSpaceOrTab ' ' = True isSpaceOrTab '\t' = True isSpaceOrTab _ = False +-- First parameter is True if @ is letter+isLetter' :: Bool -> Char -> Bool+isLetter' True '@' = True+isLetter' _ c = isLetter c+ isLetterOrAt :: Char -> Bool isLetterOrAt '@' = True isLetterOrAt c = isLetter c@@ -475,9 +499,6 @@ untoken :: Tok -> Text untoken t = untokenAccum t mempty -toksToString :: [Tok] -> String-toksToString = T.unpack . untokenize- parseFromToks :: PandocMonad m => LP m a -> [Tok] -> LP m a parseFromToks parser toks = do oldInput <- getInput@@ -486,7 +507,11 @@ case toks of Tok pos _ _ : _ -> setPosition pos _ -> return ()- result <- disablingWithRaw parser+ -- we ignore existing raw tokens maps (see #9517)+ oldRawTokens <- sRawTokens <$> getState+ updateState $ \st -> st{ sRawTokens = mempty }+ result <- parser+ updateState $ \st -> st{ sRawTokens = oldRawTokens } setInput oldInput setPosition oldpos return result@@ -571,6 +596,8 @@ x <- try $ spaces >> bracedOrToken getargs (M.insert i x argmap) rest + addTok False _args spos (Tok _ (DeferredArg i) txt) acc =+ Tok spos (Arg i) txt : acc addTok False args spos (Tok _ (Arg i) _) acc = case M.lookup i args of Nothing -> mzero@@ -625,13 +652,30 @@ Tok pos Word t : _ | startsWithAlphaNum t -> return $ Tok pos Spaces " " : ts' _ -> return ts'-trySpecialMacro "iftrue" ts = handleIf True ts-trySpecialMacro "iffalse" ts = handleIf False ts+trySpecialMacro "iftrue" ts = handleIf (ifParser True) ts+trySpecialMacro "iffalse" ts = handleIf (ifParser False) ts+trySpecialMacro "ifmmode" ts = do+ mathMode <- sMathMode <$> getState+ handleIf (ifParser mathMode) ts+trySpecialMacro "ifstrequal" ts = do+ handleIf ifStrequalParser ts trySpecialMacro _ _ = mzero -handleIf :: PandocMonad m => Bool -> [Tok] -> LP m [Tok]-handleIf b ts = do- res' <- lift $ runParserT (ifParser b) defaultLaTeXState "tokens"+ifStrequalParser :: PandocMonad m => LP m [Tok]+ifStrequalParser = do+ str1 <- braced <|> count 1 anyTok+ str2 <- braced <|> count 1 anyTok+ ifequal <- withVerbatimMode (braced <|> count 1 anyTok)+ ifnotequal <- withVerbatimMode (braced <|> count 1 anyTok)+ TokStream _ ts <- getInput+ return $+ if untokenize str1 == untokenize str2+ then ifequal ++ ts+ else ifnotequal ++ ts++handleIf :: PandocMonad m => LP m [Tok] -> [Tok] -> LP m [Tok]+handleIf parser ts = do+ res' <- lift $ runParserT parser defaultLaTeXState "tokens" $ TokStream False ts case res' of Left _ -> Prelude.fail "Could not parse conditional"@@ -864,7 +908,12 @@ optional sp ch <- option False $ True <$ symbol '=' minus <- option "" $ "-" <$ symbol '-'- Tok _ _ s1 <- satisfyTok isWordTok+ s1 <- option ""+ (do Tok _ _ s1 <- satisfyTok isWordTok+ guard (case T.uncons s1 of+ Just (c,_) -> isDigit c+ Nothing -> False)+ pure s1) s2 <- option "" $ try $ do symbol '.' Tok _ _ t <- satisfyTok isWordTok@@ -872,10 +921,14 @@ let s = s1 <> s2 let (num, rest) = T.span (\c -> isDigit c || c == '.') s guard $ T.length num > 0- guard $ rest `elem` ["", "pt","pc","in","bp","cm","mm","dd","cc","sp"]+ guard $ rest `elem`+ ["", "pt","pc","in","bp","cm","mm","dd","cc","sp","ex","em",+ "mu", -- "mu" in math mode only+ "px" -- "px" with pdftex and luatex only+ ] return $ T.pack ['=' | ch] <> minus <> s -ignore :: (Monoid a, PandocMonad m) => Text -> ParserT s u m a+ignore :: (Monoid a, PandocMonad m) => Text -> ParsecT s u m a ignore raw = do pos <- getPosition report $ SkippedContent raw pos@@ -904,6 +957,7 @@ keyval :: PandocMonad m => LP m (Text, Text) keyval = try $ do+ sp key <- untokenize <$> many1 (notFollowedBy (symbol '=') >> (symbol '-' <|> symbol '_' <|> satisfyTok isWordTok)) sp@@ -922,6 +976,7 @@ Tok _ Symbol "{" -> False Tok _ Symbol "}" -> False _ -> True)))))+ sp optional (symbol ',') sp return (key, T.strip val)@@ -977,6 +1032,18 @@ void (manyTill anyTok braced) <|> void (satisfyTok isPreTok) -- see #7531 _ | isFontSizeCommand name -> return ()+ | name `elem` ["hfil", "hfill", "vfil", "vfill",+ "hfilneg", "vfilneg"] -> return ()+ | name `elem` ["hskip", "vskip", "mskip"] -> do+ dimenarg+ skipMany $ try $ do+ sp+ satisfyTok $+ \case+ Tok _ Word "plus" -> True+ Tok _ Word "minus" -> True+ _ -> False+ dimenarg | otherwise -> do skipopts option "" (try dimenarg)@@ -1066,10 +1133,11 @@ setCaption :: PandocMonad m => LP m Inlines -> LP m () setCaption inline = try $ do- skipopts+ mbshort <- Just . toList <$> bracketed inline <|> pure Nothing ils <- tokWith inline optional $ try $ spaces *> label- updateState $ \st -> st{ sCaption = Just ils }+ updateState $ \st -> st{ sCaption = Just $+ Caption mbshort [Plain $ toList ils] } resetCaption :: PandocMonad m => LP m () resetCaption = updateState $ \st -> st{ sCaption = Nothing
@@ -28,7 +28,7 @@ symbol, untokenize, LP )-import Text.Pandoc.Readers.LaTeX.Types+import Text.Pandoc.TeX ( Tok(Tok), TokType(Word, CtrlSeq) ) import Text.Pandoc.Class.PandocMonad ( PandocMonad ) import Text.Pandoc.Parsing@@ -43,7 +43,7 @@ try, skipMany1, runParser,- Parser )+ Parsec ) import Control.Applicative ((<|>)) import Control.Monad (void) import qualified Data.Map as M@@ -122,7 +122,7 @@ mconcat (intersperse (str "," <> space) (init xs)) <> text ", & " <> last xs -parseNum :: Parser Text () Inlines+parseNum :: Parsec Text () Inlines parseNum = (mconcat <$> many parseNumPart) <* eof minus :: Text@@ -132,7 +132,7 @@ hyphenToMinus (Str t) = Str (T.replace "-" minus t) hyphenToMinus x = x -parseNumPart :: Parser Text () Inlines+parseNumPart :: Parsec Text () Inlines parseNumPart = parseDecimalNum <|> parseComma <|>@@ -145,7 +145,7 @@ where parseDecimalNum, parsePlusMinus, parsePM, parseComma, parseI, parseX,- parseExp, parseSpace :: Parser Text () Inlines+ parseExp, parseSpace :: Parsec Text () Inlines parseDecimalNum = try $ do pref <- option mempty $ (mempty <$ char '+') <|> (minus <$ char '-') basenum' <- many1 (satisfy (\c -> isDigit c || c == '.'))@@ -409,7 +409,7 @@ , ("arcmin", str "′") , ("arcminute", str "′") , ("arcsecond", str "″")- , ("astronomicalunit", str "ua")+ , ("astronomicalunit", str "au") , ("atomicmassunit", str "u") , ("bar", str "bar") , ("barn", str "b")@@ -469,5 +469,3 @@ , ("watt", str "W") , ("weber", str "Wb") ]--
@@ -7,7 +7,7 @@ import Data.Functor (($>)) import Text.Pandoc.Class import Text.Pandoc.Readers.LaTeX.Parsing-import Text.Pandoc.Readers.LaTeX.Types+import Text.Pandoc.TeX import Text.Pandoc.Builder as B import qualified Data.Map as M import Data.Text (Text)@@ -25,36 +25,41 @@ => LP m Blocks -> LP m Inlines -> M.Map Text (LP m Blocks)-tableEnvironments blocks inline =+tableEnvironments block inline = M.fromList [ ("longtable", env "longtable" $ resetCaption *>- simpTable blocks inline "longtable" False >>= addTableCaption)+ simpTable block inline "longtable" False >>= addTableCaption) , ("table", env "table" $ skipopts *> resetCaption *> blocks >>= addTableCaption)- , ("tabular*", env "tabular*" $ simpTable blocks inline "tabular*" True)- , ("tabularx", env "tabularx" $ simpTable blocks inline "tabularx" True)- , ("tabular", env "tabular" $ simpTable blocks inline "tabular" False)+ , ("tabular*", env "tabular*" $ simpTable block inline "tabular*" True)+ , ("tabularx", env "tabularx" $ simpTable block inline "tabularx" True)+ , ("tabular", env "tabular" $ simpTable block inline "tabular" False)+ , ("supertabular", env "supertabular" $ simpTable block inline "supertabular" False)+ , ("supertabular*", env "supertabular*" $ simpTable block inline "supertabular*" False) ]+ where+ blocks = mconcat <$> many block hline :: PandocMonad m => LP m () hline = try $ do spaces- controlSeq "hline" <|>- (controlSeq "cline" <* braced) <|>- -- booktabs rules:- controlSeq "toprule" <|>- controlSeq "bottomrule" <|>- controlSeq "midrule" <|>- controlSeq "endhead" <|>- controlSeq "endfirsthead"- spaces+ hasParenArg <-+ (False <$ controlSeq "hline") <|>+ (False <$ controlSeq "cline") <|>+ (True <$ controlSeq "cmidrule") <|>+ -- booktabs rules:+ (True <$ controlSeq "toprule") <|>+ (True <$ controlSeq "bottomrule") <|>+ (True <$ controlSeq "midrule") <|>+ (True <$ controlSeq "endhead") <|>+ (True <$ controlSeq "endfirsthead") optional rawopt- return ()+ when hasParenArg $ void $ optional (parenWrapped (() <$ singleChar)) lbreak :: PandocMonad m => LP m Tok lbreak = (controlSeq "\\" <|> controlSeq "tabularnewline")- <* skipopts <* spaces+ <* optional (void rawopt) <* spaces amp :: PandocMonad m => LP m Tok amp = symbol '&'@@ -86,11 +91,12 @@ let alignPrefix = symbol '>' >> braced let alignSuffix = symbol '<' >> braced let colWidth = try $ do- symbol '{'- ds <- trim . untokenize <$> manyTill anyTok (controlSeq "linewidth")- spaces- symbol '}'- return $ safeRead ds+ ts <- braced+ let isLinewidth (Tok _ (CtrlSeq "linewidth") _) = True+ isLinewidth _ = False+ case break isLinewidth ts of+ (ds, _:_) -> return $ safeRead $ trim $ untokenize ds+ _ -> return Nothing let alignSpec = do pref <- option [] alignPrefix spaces@@ -105,9 +111,9 @@ let starAlign = do -- '*{2}{r}' == 'rr', we just expand like a macro symbol '*' spaces- ds <- trim . untokenize <$> braced+ ds <- trim . untokenize <$> bracedOrToken spaces- spec <- braced+ spec <- bracedOrToken case safeRead ds of Just n -> do TokStream _ ts <- getInput@@ -135,7 +141,7 @@ -> Text -- ^ table environment name -> [([Tok], [Tok])] -- ^ pref/suffixes -> LP m Row-parseTableRow blocks inline envname prefsufs = do+parseTableRow block inline envname prefsufs = do notFollowedBy (spaces *> end_ envname) -- contexts that can contain & that is not colsep: let canContainAmp (Tok _ (CtrlSeq "begin") _) = True@@ -148,10 +154,13 @@ contents <- mconcat <$> many ( snd <$> withRaw ((lookAhead (controlSeq "parbox") >>- void blocks) -- #5711+ void block) -- #5711 <|> (lookAhead (satisfyTok canContainAmp) >> void inline) <|>+ (lookAhead (controlSeq "begin") >>+ void block) -- #4746+ <|> (lookAhead (symbol '$') >> void inline)) <|> (do notFollowedBy@@ -162,16 +171,16 @@ option [] (count 1 amp) return $ map (setpos prefpos) pref ++ contents ++ map (setpos suffpos) suff rawcells <- mapM celltoks prefsufs- cells <- mapM (parseFromToks (parseTableCell blocks)) rawcells+ cells <- mapM (parseFromToks (parseTableCell block)) rawcells spaces return $ Row nullAttr cells parseTableCell :: PandocMonad m => LP m Blocks -> LP m Cell-parseTableCell blocks = do+parseTableCell block = do spaces updateState $ \st -> st{ sInTableCell = True }- cell' <- multicolumnCell blocks- <|> multirowCell blocks+ cell' <- multicolumnCell block+ <|> multirowCell block <|> parseSimpleCell <|> parseEmptyCell updateState $ \st -> st{ sInTableCell = False }@@ -181,14 +190,14 @@ -- The parsing of empty cells is important in LaTeX, especially when dealing -- with multirow/multicolumn. See #6603. parseEmptyCell = spaces $> emptyCell- parseSimpleCell = simpleCell <$> (plainify <$> blocks)+ parseSimpleCell = simpleCell <$> (plainify . mconcat <$> many block) cellAlignment :: PandocMonad m => LP m Alignment cellAlignment = skipMany (symbol '|') *> alignment <* skipMany (symbol '|') where alignment = do- c <- untoken <$> singleChar+ c <- untoken <$> singleChar <* optional braced -- ignore args return $ case c of "l" -> AlignLeft "r" -> AlignRight@@ -202,7 +211,7 @@ _ -> bs multirowCell :: PandocMonad m => LP m Blocks -> LP m Cell-multirowCell blocks = controlSeq "multirow" >> do+multirowCell block = controlSeq "multirow" >> do -- Full prototype for \multirow macro is: -- \multirow[vpos]{nrows}[bigstruts]{width}[vmove]{text} -- However, everything except `nrows` and `text` make@@ -212,16 +221,16 @@ _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']') -- bigstrut-related _ <- symbol '{' *> manyTill anyTok (symbol '}') -- Cell width _ <- optional $ symbol '[' *> manyTill anyTok (symbol ']') -- Length used for fine-tuning- content <- symbol '{' *> (plainify <$> blocks) <* symbol '}'+ content <- symbol '{' *> (plainify . mconcat <$> many block) <* symbol '}' return $ cell AlignDefault (RowSpan nrows) (ColSpan 1) content multicolumnCell :: PandocMonad m => LP m Blocks -> LP m Cell-multicolumnCell blocks = controlSeq "multicolumn" >> do+multicolumnCell block = controlSeq "multicolumn" >> do span' <- fmap (fromMaybe 1 . safeRead . untokenize) braced alignment <- symbol '{' *> cellAlignment <* symbol '}' let singleCell = do- content <- plainify <$> blocks+ content <- plainify . mconcat <$> many block return $ cell alignment (RowSpan 1) (ColSpan span') content -- Two possible contents: either a \multirow cell, or content.@@ -229,7 +238,7 @@ -- Note that a \multirow cell can be nested in a \multicolumn, -- but not the other way around. See #6603 let nestedCell = do- (Cell _ _ (RowSpan rs) _ bs) <- multirowCell blocks+ (Cell _ _ (RowSpan rs) _ bs) <- multirowCell block return $ cell alignment (RowSpan rs)@@ -318,7 +327,7 @@ -> Text -> Bool -> LP m Blocks-simpTable blocks inline envname hasWidthParameter = try $ do+simpTable block inline envname hasWidthParameter = try $ do when hasWidthParameter $ () <$ tokWith inline skipopts colspecs <- parseAligns@@ -332,10 +341,10 @@ skipMany hline spaces header' <- option [] . try . fmap (:[]) $- parseTableRow blocks inline envname prefsufs <*+ parseTableRow block inline envname prefsufs <* lbreak <* many1 hline spaces- rows <- sepEndBy (parseTableRow blocks inline envname prefsufs)+ rows <- sepEndBy (parseTableRow block inline envname prefsufs) (lbreak <* optional (skipMany hline)) spaces optional $ controlSeq "caption" *> setCaption inline@@ -354,30 +363,22 @@ addTableCaption = walkM go where go (Table attr c spec th tb tf) = do st <- getState+ let capt = fromMaybe c $ sCaption st let mblabel = sLastLabel st- capt <- case (sCaption st, mblabel) of- (Just ils, Nothing) -> return $ caption Nothing (plain ils)- (Just ils, Just lab) -> do+ case mblabel of+ Nothing -> return ()+ Just lab -> do num <- getNextNumber sLastTableNum setState st{ sLastTableNum = num , sLabels = M.insert lab [Str (renderDottedNum num)] (sLabels st) }- return $ caption Nothing (plain ils) -- add number??- (Nothing, _) -> return c+ -- add num to caption? let attr' = case (attr, mblabel) of ((_,classes,kvs), Just ident) -> (ident,classes,kvs) _ -> attr- return $ addAttrDiv attr'- $ maybe id removeLabel mblabel- $ Table nullAttr capt spec th tb tf+ return $ maybe id removeLabel mblabel+ $ Table attr' capt spec th tb tf go x = return x---- TODO: For now we add a Div to contain table attributes, since--- most writers don't do anything yet with attributes on Table.--- This can be removed when that changes.-addAttrDiv :: Attr -> Block -> Block-addAttrDiv ("",[],[]) b = b-addAttrDiv attr b = Div attr [b]
@@ -1,54 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{- |- Module : Text.Pandoc.Readers.LaTeX.Types- Copyright : Copyright (C) 2017-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Types for LaTeX tokens and macros.--}-module Text.Pandoc.Readers.LaTeX.Types ( Tok(..)- , TokType(..)- , Macro(..)- , ArgSpec(..)- , ExpansionPoint(..)- , MacroScope(..)- , SourcePos- )-where-import Data.Text (Text)-import Text.Parsec.Pos (SourcePos, sourceName)-import Text.Pandoc.Sources-import Data.List (groupBy)--data TokType = CtrlSeq Text | Spaces | Newline | Symbol | Word | Comment |- Esc1 | Esc2 | Arg Int- deriving (Eq, Ord, Show)--data Tok = Tok SourcePos TokType Text- deriving (Eq, Ord, Show)--instance ToSources [Tok] where- toSources = Sources- . map (\ts -> case ts of- Tok p _ _ : _ -> (p, mconcat $ map tokToText ts)- _ -> error "toSources [Tok] encountered empty group")- . groupBy (\(Tok p1 _ _) (Tok p2 _ _) -> sourceName p1 == sourceName p2)--tokToText :: Tok -> Text-tokToText (Tok _ _ t) = t--data ExpansionPoint = ExpandWhenDefined | ExpandWhenUsed- deriving (Eq, Ord, Show)--data MacroScope = GlobalScope | GroupScope- deriving (Eq, Ord, Show)--data Macro = Macro MacroScope ExpansionPoint [ArgSpec] (Maybe [Tok]) [Tok]- deriving Show--data ArgSpec = ArgNum Int | Pattern [Tok]- deriving Show
@@ -16,7 +16,7 @@ import Data.Char (toLower) import Data.Default (Default)-import Control.Monad (liftM, mzero, guard, void)+import Control.Monad (mzero, guard, void) import Control.Monad.Trans (lift) import Control.Monad.Except (throwError) import Data.Maybe (catMaybes, isJust)@@ -24,30 +24,45 @@ import qualified Data.Text as T import Text.Pandoc.Builder as B import Text.Pandoc.Class.PandocMonad (PandocMonad(..), report)-import Text.Pandoc.Error (PandocError (PandocParsecError)) import Text.Pandoc.Logging (LogMessage(..)) import Text.Pandoc.Options+import Text.Pandoc.Parsing.Capabilities import Text.Pandoc.Parsing import Text.Pandoc.Walk (query)-import Text.Pandoc.Shared (mapLeft) import Text.Pandoc.Readers.Roff -- TODO explicit imports-import qualified Text.Parsec as Parsec-import Text.Parsec.Pos (updatePosString)+import qualified Text.Pandoc.Parsing as P import qualified Data.Foldable as Foldable+import qualified Data.Set as Set+import Text.Pandoc.Shared (extractSpaces) data ManState = ManState { readerOptions :: ReaderOptions+ , manLogMessages :: []LogMessage+ , manIdentifiers :: Set.Set T.Text , metadata :: Meta , tableCellsPlain :: Bool } deriving Show instance Default ManState where def = ManState { readerOptions = def+ , manLogMessages = []+ , manIdentifiers = Set.empty , metadata = nullMeta , tableCellsPlain = True } -type ManParser m = ParserT [RoffToken] ManState m+instance HasReaderOptions ManState where+ extractReaderOptions = readerOptions +instance HasLogMessages ManState where+ addLogMessage msg st = st{ manLogMessages = msg : manLogMessages st }+ getLogMessages st = reverse $ manLogMessages st +instance HasIdentifierList ManState where+ extractIdentifierList = manIdentifiers+ updateIdentifierList f st = st{ manIdentifiers = f $ manIdentifiers st }++type ManParser m = P.ParsecT [RoffToken] ManState m++ -- | Read man (troff) from an input string and return a Pandoc document. readMan :: (PandocMonad m, ToSources a) => ReaderOptions@@ -57,21 +72,18 @@ let Sources inps = toSources s tokenz <- mconcat <$> mapM (uncurry lexRoff) inps let state = def {readerOptions = opts} :: ManState- let fixError (PandocParsecError _ e) = PandocParsecError (Sources inps) e- fixError e = e eitherdoc <- readWithMTokens parseMan state (Foldable.toList . unRoffTokens $ tokenz)- either (throwError . fixError) return eitherdoc+ either (throwError . fromParsecError (Sources inps)) return eitherdoc readWithMTokens :: PandocMonad m- => ParserT [RoffToken] ManState m a -- ^ parser+ => ParsecT [RoffToken] ManState m a -- ^ parser -> ManState -- ^ initial state -> [RoffToken] -- ^ input- -> m (Either PandocError a)+ -> m (Either ParseError a) readWithMTokens parser state input =- let leftF = PandocParsecError mempty- in mapLeft leftF `liftM` runParserT parser state "source" input+ runParserT parser state "source" input parseMan :: PandocMonad m => ManParser m Pandoc@@ -79,6 +91,7 @@ bs <- many parseBlock <* eof meta <- metadata <$> getState let (Pandoc _ blocks) = doc $ mconcat bs+ reportLogMessages return $ Pandoc meta blocks parseBlock :: PandocMonad m => ManParser m Blocks@@ -180,14 +193,16 @@ -- Parser: [RoffToken] -> Pandoc -- -msatisfy :: Monad m => (RoffToken -> Bool) -> ParserT [RoffToken] st m RoffToken-msatisfy predic = tokenPrim show nextPos testTok+msatisfy :: Monad m+ => (RoffToken -> Bool) -> P.ParsecT [RoffToken] st m RoffToken+msatisfy predic = P.tokenPrim show nextPos testTok where testTok t = if predic t then Just t else Nothing nextPos _pos _x (ControlLine _ _ pos':_) = pos'- nextPos pos _x _xs = updatePosString- (setSourceColumn- (setSourceLine pos $ sourceLine pos + 1) 1) ""+ nextPos pos _x _xs = P.updatePosString+ (P.setSourceColumn+ (P.setSourceLine pos $+ P.sourceLine pos + 1) 1) "" mtoken :: PandocMonad m => ManParser m RoffToken mtoken = msatisfy (const True)@@ -203,9 +218,11 @@ isEmptyLine _ = False mmacro :: PandocMonad m => T.Text -> ManParser m RoffToken-mmacro mk = msatisfy isControlLine where- isControlLine (ControlLine mk' _ _) | mk == mk' = True- | otherwise = False+mmacro mk = mmacroMatching (== mk)++mmacroMatching :: PandocMonad m => (T.Text -> Bool) -> ManParser m RoffToken+mmacroMatching f = msatisfy isControlLine where+ isControlLine (ControlLine mk _ _) = f mk isControlLine _ = False mmacroAny :: PandocMonad m => ManParser m RoffToken@@ -222,8 +239,17 @@ (ControlLine _ args _) <- mmacro "TH" let adjustMeta = case args of- (x:y:z:_) -> setMeta "title" (linePartsToInlines x) .+ (x:y:z:a:b:_) -> setMeta "title" (linePartsToInlines x) .+ setMeta "section" (linePartsToInlines y) .+ setMeta "date" (linePartsToInlines z) .+ setMeta "footer" (linePartsToInlines a) .+ setMeta "header" (linePartsToInlines b)+ [x,y,z,a] -> setMeta "title" (linePartsToInlines x) . setMeta "section" (linePartsToInlines y) .+ setMeta "date" (linePartsToInlines z) .+ setMeta "footer" (linePartsToInlines a)+ [x,y,z] -> setMeta "title" (linePartsToInlines x) .+ setMeta "section" (linePartsToInlines y) . setMeta "date" (linePartsToInlines z) [x,y] -> setMeta "title" (linePartsToInlines x) . setMeta "section" (linePartsToInlines y)@@ -245,12 +271,12 @@ | otherwise = text s <> go mono xs go mono (Font fs: xs) | litals > 0 && litals >= lbolds && litals >= lmonos- = emph (go mono (Font fs{ fontItalic = False } :+ = extractSpaces emph (go mono (Font fs{ fontItalic = False } : map (adjustFontSpec (\s -> s{ fontItalic = False })) itals)) <> go mono italsrest | lbolds > 0 && lbolds >= lmonos- = strong (go mono (Font fs{ fontBold = False } :+ = extractSpaces strong (go mono (Font fs{ fontBold = False } : map (adjustFontSpec (\s -> s{ fontBold = False })) bolds)) <> go mono boldsrest@@ -309,12 +335,12 @@ "RI" -> parseAlternatingFonts [id, emph] args "BR" -> parseAlternatingFonts [strong, id] args "RB" -> parseAlternatingFonts [id, strong] args- "SY" -> return $ strong $ mconcat $ intersperse B.space+ "SY" -> return $ extractSpaces strong $ mconcat $ intersperse B.space $ map linePartsToInlines args "YS" -> return mempty "OP" -> case args of (x:ys) -> return $ B.space <> str "[" <> B.space <>- mconcat (strong (linePartsToInlines x) :+ mconcat (extractSpaces strong (linePartsToInlines x) : map ((B.space <>) . linePartsToInlines) ys) <> B.space <> str "]" [] -> return mempty@@ -323,16 +349,18 @@ parseBold :: PandocMonad m => [Arg] -> ManParser m Inlines parseBold [] = do TextLine lparts <- mline- return $ strong $ linePartsToInlines lparts+ return $ extractSpaces strong $ linePartsToInlines lparts parseBold args = return $- strong $ mconcat $ intersperse B.space $ map linePartsToInlines args+ extractSpaces strong $+ mconcat $ intersperse B.space $ map linePartsToInlines args parseItalic :: PandocMonad m => [Arg] -> ManParser m Inlines parseItalic [] = do TextLine lparts <- mline- return $ emph $ linePartsToInlines lparts+ return $ extractSpaces emph $ linePartsToInlines lparts parseItalic args = return $- emph $ mconcat $ intersperse B.space $ map linePartsToInlines args+ extractSpaces emph $+ mconcat $ intersperse B.space $ map linePartsToInlines args parseAlternatingFonts :: [Inlines -> Inlines] -> [Arg]@@ -407,10 +435,21 @@ else return $ mconcat $ intersperse B.space $ map linePartsToInlines args let lvl = if name == "SH" then 1 else 2- return $ header lvl contents+ attr <- registerHeader nullAttr contents + return $ B.headerWith attr lvl contents+ parseBlockQuote :: PandocMonad m => ManParser m Blocks-parseBlockQuote = blockQuote <$> continuation+parseBlockQuote = blockQuote <$>+ ( (mmacro "RS" *> (mconcat <$> manyTill parseBlock (endmacro "RE")))+ <|> parseIndentedParagraphs+ )+ where+ parseIndentedParagraphs = try $ do+ bareIP+ first <- parsePara <|> parseCodeBlock+ rest <- many $ try (memptyLine *> (parsePara <|> parseCodeBlock))+ pure (first <> mconcat rest) data ListType = Ordered ListAttributes | Bullet@@ -431,7 +470,7 @@ (arg1 : _) -> do let cs = linePartsToText arg1 let cs' = if not (T.any (== '.') cs || T.any (== ')') cs) then cs <> "." else cs- let lt = case Parsec.runParser anyOrderedListMarker defaultParserState+ let lt = case P.runParser anyOrderedListMarker defaultParserState "list marker" cs' of Right (start, listtype, listdelim) | cs == cs' -> Ordered (start, listtype, listdelim)@@ -461,10 +500,13 @@ continuation :: PandocMonad m => ManParser m Blocks continuation =- mconcat <$> (mmacro "RS" *> manyTill parseBlock (endmacro "RE"))- <|> mconcat <$> many1 ( try (bareIP *> parsePara)- <|> try (bareIP *> parseCodeBlock)- )+ (mmacro "RS" *> (mconcat <$> manyTill parseBlock (endmacro "RE")))+ <|> (bareIP *> parsePara)+ <|> (notFollowedBy (mmacroMatching+ (`elem` ["TP","IP","LP","P","PP","HP",+ "RE","RS","SH","SS","SV","YS","TH",+ "TQ","YS","AT","DT","OP","PD","UC"]))+ *> parseBlock) definitionListItem :: PandocMonad m => ManParser m (Inlines, [Blocks])@@ -477,11 +519,10 @@ mmacro "TQ" parseInline skipMany memptyLine- inls <- option mempty parseInlines- skipMany memptyLine- continuations <- mconcat <$> many continuation+ firstBlock <- parseBlock+ otherBlocks <- mconcat <$> many continuation return ( mconcat (intersperse B.linebreak (term:moreterms))- , [para inls <> continuations])+ , [firstBlock <> otherBlocks]) parseDefinitionList :: PandocMonad m => ManParser m Blocks parseDefinitionList = definitionList <$> many1 definitionListItem
@@ -6,7 +6,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Readers.Markdown- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -22,40 +22,42 @@ import Control.Monad import Control.Monad.Except (throwError)-import Data.Bifunctor (second)+import qualified Data.Bifunctor as Bifunctor import Data.Char (isAlphaNum, isPunctuation, isSpace)-import Text.DocLayout (realLength)-import Data.List (transpose, elemIndex, sortOn, foldl')+import Data.List (transpose, elemIndex, sortOn)+import qualified Data.List as L import qualified Data.Map as M import Data.Maybe import qualified Data.Set as Set+import qualified Data.Attoparsec.Text as A import Data.Text (Text) import qualified Data.Text as T import qualified Data.ByteString as BS import System.FilePath (addExtension, takeExtension, takeDirectory) import qualified System.FilePath.Windows as Windows import qualified System.FilePath.Posix as Posix+import Text.DocLayout (realLength) import Text.HTML.TagSoup hiding (Row) import Text.Pandoc.Builder (Blocks, Inlines) import qualified Text.Pandoc.Builder as B import Text.Pandoc.Class.PandocMonad (PandocMonad (..), report) import Text.Pandoc.Definition as Pandoc import Text.Pandoc.Emoji (emojiToInline)-import Text.Pandoc.Error import Safe.Foldable (maximumBounded) import Text.Pandoc.Logging import Text.Pandoc.Options import Text.Pandoc.Walk (walk) import Text.Pandoc.Parsing hiding (tableCaption) import Text.Pandoc.Readers.HTML (htmlInBalanced, htmlTag, isBlockTag,- isCommentTag, isInlineTag, isTextTag)+ isInlineTag, isTextTag) import Text.Pandoc.Readers.LaTeX (applyMacros, rawLaTeXBlock, rawLaTeXInline) import Text.Pandoc.Shared+import Text.Pandoc.URI (escapeURI, isURI, pBase64DataURI) import Text.Pandoc.XML (fromEntities) import Text.Pandoc.Readers.Metadata (yamlBsToMeta, yamlBsToRefs, yamlMetaBlock) -- import Debug.Trace (traceShowId) -type MarkdownParser m = ParserT Sources ParserState m+type MarkdownParser m = ParsecT Sources ParserState m type F = Future ParserState @@ -141,12 +143,6 @@ setextHChars :: [Char] setextHChars = "=-" -isBlank :: Char -> Bool-isBlank ' ' = True-isBlank '\t' = True-isBlank '\n' = True-isBlank _ = False- -- -- auxiliary functions --@@ -157,14 +153,14 @@ ctx <- stateParserContext <$> getState guard (ctx == ListItemState) -spnl :: PandocMonad m => ParserT Sources st m ()+spnl :: PandocMonad m => ParsecT Sources st m () spnl = try $ do skipSpaces optional newline skipSpaces notFollowedBy (char '\n') -spnl' :: PandocMonad m => ParserT Sources st m Text+spnl' :: PandocMonad m => ParsecT Sources st m Text spnl' = try $ do xs <- many spaceChar ys <- option "" $ try $ (:) <$> newline@@ -188,18 +184,43 @@ tabStop <- getOption readerTabStop gobbleAtMostSpaces (tabStop - 1) <* notFollowedBy spaceChar -litChar :: PandocMonad m => MarkdownParser m Char-litChar = escapedChar'+litChar :: PandocMonad m => MarkdownParser m Text+litChar = T.singleton <$> escapedChar' <|> characterReference- <|> noneOf "\n"- <|> try (newline >> notFollowedBy blankline >> return ' ')+ <|> T.singleton <$> noneOf "\n"+ <|> try (newline >> notFollowedBy blankline >> return " ") --- | Parse a sequence of inline elements between square brackets,--- including inlines between balanced pairs of square brackets.-inlinesInBalancedBrackets :: PandocMonad m => MarkdownParser m (F Inlines)-inlinesInBalancedBrackets =+litBetween :: PandocMonad m => Char -> Char -> MarkdownParser m Text+litBetween op cl = try $ do+ char op+ mconcat <$> (manyTill litChar (char cl))++litCharNoSpace :: PandocMonad m => MarkdownParser m Text+litCharNoSpace = T.singleton <$> escapedChar''+ <|> characterReference+ <|> (snd <$> withRaw attributes)+ <|> T.singleton <$> noneOf "\n \r\t"+ where+ escapedChar'' = do+ c <- escapedChar'+ pure $ case c of+ ' ' -> '\160'+ _ -> c++litBetweenNoSpace :: PandocMonad m => Char -> Char -> MarkdownParser m Text+litBetweenNoSpace op cl = try $ do+ char op+ mconcat <$> (manyTill litCharNoSpace (char cl))++-- | Parse a sequence of elements between square brackets,+-- including between balanced pairs of square brackets.+-- Skip brackets in standard inline escapes, code, raw HTML or LaTeX.+inBalancedBrackets :: PandocMonad m+ => MarkdownParser m (F a)+ -> MarkdownParser m (F a)+inBalancedBrackets innerParser = try $ char '[' >> withRaw (go 1) >>=- parseFromString inlines . stripBracket . snd+ parseFromString innerParser . stripBracket . snd where stripBracket t = case T.unsnoc t of Just (t', ']') -> t' _ -> t@@ -331,13 +352,9 @@ checkNotes = do st <- getState let notesUsed = stateNoteRefs st- let notesDefined = M.keys (stateNotes' st)- mapM_ (\n -> unless (n `Set.member` notesUsed) $- case M.lookup n (stateNotes' st) of- Just (pos, _) -> report (NoteDefinedButNotUsed n pos)- Nothing -> throwError $- PandocShouldNeverHappenError "note not found")- notesDefined+ forM_ (M.toList (stateNotes' st)) $ \(n, (pos, _)) ->+ unless (n `Set.member` notesUsed) $+ report (NoteDefinedButNotUsed n pos) referenceKey :: PandocMonad m => MarkdownParser m (F Blocks)@@ -351,15 +368,15 @@ let sourceURL = fmap T.unwords $ many $ try $ do skipMany spaceChar notFollowedBy' referenceTitle- notFollowedBy' $ guardEnabled Ext_link_attributes >> attributes+ notFollowedBy' $ guardEnabled Ext_link_attributes >>+ attributes notFollowedBy' $ guardEnabled Ext_mmd_link_attributes >> try (spnl <* keyValAttr) notFollowedBy' (() <$ reference)- many1Char $ notFollowedBy space >> litChar- let betweenAngles = try $ char '<' >> manyTillChar litChar (char '>')+ mconcat <$> many1 (notFollowedBy space *> litChar) rebase <- option False (True <$ guardEnabled Ext_rebase_relative_paths) src <- (if rebase then rebasePath pos else id) <$>- (try betweenAngles <|> sourceURL)+ (try (litBetween '<' '>') <|> sourceURL) tit <- option "" referenceTitle attr <- option nullAttr $ try $ do guardEnabled Ext_link_attributes@@ -368,7 +385,7 @@ addKvs <- option [] $ guardEnabled Ext_mmd_link_attributes >> many (try $ spnl >> keyValAttr) blanklines- let attr' = extractIdClass $ foldl' (\x f -> f x) attr addKvs+ let attr' = extractIdClass $ L.foldl' (\x f -> f x) attr addKvs target = (escapeURI $ trimr src, tit) st <- getState let oldkeys = stateKeys st@@ -394,8 +411,8 @@ char c notFollowedBy spaces let pEnder = try $ char c >> notFollowedBy (satisfy isAlphaNum)- let regChunk = many1Char (noneOf ['\\','\n','&',c]) <|> countChar 1 litChar- let nestedChunk = (\x -> T.singleton c <> x <> T.singleton c) <$> quotedTitle c+ let regChunk = many1Char (noneOf ['\\','\n','&',c]) <|> litChar+ let nestedChunk = (\x -> (c `T.cons` x) `T.snoc` c) <$> quotedTitle c T.unwords . T.words . T.concat <$> manyTill (nestedChunk <|> regChunk) pEnder -- | PHP Markdown Extra style abbreviation key. Currently@@ -413,11 +430,14 @@ return $ return mempty noteMarker :: PandocMonad m => MarkdownParser m Text-noteMarker = string "[^" >> many1TillChar (satisfy $ not . isBlank) (char ']')+noteMarker = string "[^" >>+ many1TillChar (satisfy (`notElem` ['\r','\n','\t',' ','^','[',']']))+ (char ']') rawLine :: PandocMonad m => MarkdownParser m Text rawLine = try $ do notFollowedBy blankline+ notFollowedByDivCloser notFollowedBy' $ try $ skipNonindentSpaces >> noteMarker optional indentSpaces anyLine@@ -582,15 +602,16 @@ | T.null raw = return () | otherwise = do let key = toKey $ "[" <> raw <> "]"- updateState $ \s ->- s { stateHeaderKeys = M.insert key (("#" <> ident,""), attr)+ updateState $ \s -> -- don't override existing headers+ s { stateHeaderKeys = M.insertWith (\_new old -> old)+ key (("#" <> ident,""), attr) (stateHeaderKeys s) } -- -- hrule block -- -hrule :: PandocMonad m => ParserT Sources st m (F Blocks)+hrule :: PandocMonad m => ParsecT Sources st m (F Blocks) hrule = try $ do skipSpaces start <- satisfy isHruleChar@@ -610,7 +631,7 @@ blockDelimiter :: PandocMonad m => (Char -> Bool) -> Maybe Int- -> ParserT Sources ParserState m Int+ -> ParsecT Sources ParserState m Int blockDelimiter f len = try $ do skipNonindentSpaces c <- lookAhead (satisfy f)@@ -624,7 +645,7 @@ spnl attrs <- many (attribute <* spnl) char '}'- return $ foldl' (\x f -> f x) nullAttr attrs+ return $ L.foldl' (\x f -> f x) nullAttr attrs attribute :: PandocMonad m => MarkdownParser m (Attr -> Attr) attribute = identifierAttr <|> classAttr <|> keyValAttr <|> specialAttr@@ -651,8 +672,8 @@ keyValAttr = try $ do key <- identifier char '='- val <- T.pack <$> enclosed (char '"') (char '"') litChar- <|> T.pack <$> enclosed (char '\'') (char '\'') litChar+ val <- mconcat <$> enclosed (char '"') (char '"') litChar+ <|> mconcat <$> enclosed (char '\'') (char '\'') litChar <|> ("" <$ try (string "\"\"")) <|> ("" <$ try (string "''")) <|> manyChar (escapedChar' <|> noneOf " \t\n\r}")@@ -688,9 +709,17 @@ rawattr <- (Left <$> (guardEnabled Ext_raw_attribute >> try rawAttribute)) <|>- (Right <$> option ("",[],[])- ((guardEnabled Ext_fenced_code_attributes >> try attributes)- <|> ((\x -> ("",[toLanguageId x],[])) <$> many1Char nonspaceChar)))+ (Right <$> do+ let pLangId = many1Char . satisfy $ \x ->+ x `notElem` ['`', '{', '}'] && not (isSpace x)+ mbLanguageId <- optionMaybe (toLanguageId <$> pLangId)+ skipMany spaceChar+ mbAttr <- optionMaybe+ (guardEnabled Ext_fenced_code_attributes *> try attributes)+ return $ case mbAttr of+ Nothing -> ("", maybeToList mbLanguageId, [])+ Just (elementId, classes, attrs) ->+ (elementId, (maybe id (:) mbLanguageId) classes, attrs)) blankline contents <- T.intercalate "\n" <$> manyTill (gobbleAtMostSpaces indentLevel >> anyLine)@@ -748,13 +777,13 @@ when (sourceColumn pos /= 1) $ Prelude.fail "Not in first column" lns <- many1 $ birdTrackLine c -- if (as is normal) there is always a space after >, drop it- let lns' = if all (\ln -> T.null ln || T.take 1 ln == " ") lns+ let lns' = if all (\ln -> T.null ln || T.head ln == ' ') lns then map (T.drop 1) lns else lns blanklines return $ T.intercalate "\n" lns' -birdTrackLine :: PandocMonad m => Char -> ParserT Sources st m Text+birdTrackLine :: PandocMonad m => Char -> ParsecT Sources st m Text birdTrackLine c = try $ do char c -- allow html tags on left margin:@@ -785,9 +814,28 @@ blockQuote :: PandocMonad m => MarkdownParser m (F Blocks) blockQuote = do raw <- emailBlockQuote+ (mbAlert, raw') <-+ (do guardEnabled Ext_alerts+ case raw of+ (t:ts) | "[!" `T.isPrefixOf` t ->+ case T.strip t of+ "[!TIP]" -> pure (Just "tip", ts)+ "[!WARNING]" -> pure (Just "warning", ts)+ "[!IMPORTANT]" -> pure (Just "important", ts)+ "[!CAUTION]" -> pure (Just "caution", ts)+ "[!NOTE]" -> pure (Just "note", ts)+ _ -> pure (Nothing, raw)+ _ -> pure (Nothing, raw))+ <|> pure (Nothing, raw) -- parse the extracted block, which may contain various block elements:- contents <- parseFromString' parseBlocks $ T.intercalate "\n" raw <> "\n\n"- return $ B.blockQuote <$> contents+ contents <- parseFromString' parseBlocks $ T.intercalate "\n" raw' <> "\n\n"+ return $+ case mbAlert of+ Nothing -> B.blockQuote <$> contents+ Just alert ->+ (B.divWith ("", [alert], [])+ . (B.divWith ("", ["title"], []) (B.para (B.str (T.toTitle alert))) <>))+ <$> contents -- -- list blocks@@ -832,7 +880,9 @@ return (num, style, delim)) listStart :: PandocMonad m => MarkdownParser m ()-listStart = bulletListStart <|> Control.Monad.void (orderedListStart Nothing)+listStart = bulletListStart+ <|> Control.Monad.void (orderedListStart Nothing)+ <|> defListStart listLine :: PandocMonad m => Int -> MarkdownParser m Text listLine continuationIndent = try $ do@@ -842,15 +892,7 @@ notFollowedByHtmlCloser notFollowedByDivCloser optional (() <$ gobbleSpaces continuationIndent)- listLineCommon--listLineCommon :: PandocMonad m => MarkdownParser m Text-listLineCommon = T.concat <$> manyTill- ( many1Char (satisfy $ \c -> c `notElem` ['\n', '<', '`'])- <|> fmap snd (withRaw code)- <|> fmap (renderTags . (:[]) . fst) (htmlTag isCommentTag)- <|> countChar 1 anyChar- ) newline+ anyLine -- parse raw text for one list item, excluding start marker and continuations rawListItem :: PandocMonad m@@ -864,7 +906,7 @@ let continuationIndent = if fourSpaceRule then 4 else sourceColumn pos2 - sourceColumn pos1- first <- listLineCommon+ first <- anyLine rest <- many (do notFollowedBy listStart notFollowedBy (() <$ codeBlockFenced) notFollowedBy blankline@@ -962,67 +1004,39 @@ -- definition lists -defListMarker :: PandocMonad m => MarkdownParser m ()-defListMarker = do- sps <- nonindentSpaces+defListStart :: PandocMonad m => MarkdownParser m ()+defListStart = do+ nonindentSpaces char ':' <|> char '~'- tabStop <- getOption readerTabStop- let remaining = tabStop - (T.length sps + 1)- if remaining > 0- then try (count remaining (char ' ')) <|> string "\t" <|> many1 spaceChar- else mzero- return ()+ gobbleSpaces 1 <|> () <$ lookAhead newline+ try (gobbleAtMostSpaces 3 >> notFollowedBy spaceChar) <|> return () -definitionListItem :: PandocMonad m => Bool -> MarkdownParser m (F (Inlines, [Blocks]))-definitionListItem compact = try $ do+definitionListItem :: PandocMonad m => MarkdownParser m (F (Inlines, [Blocks]))+definitionListItem = try $ do rawLine' <- anyLine- raw <- many1 $ defRawBlock compact term <- parseFromString' (trimInlinesF <$> inlines) rawLine'- contents <- mapM (parseFromString' parseBlocks . (<> "\n")) raw+ isTight <- (False <$ blanklines) <|> pure True+ fourSpaceRule <- (True <$ guardEnabled Ext_four_space_rule) <|> pure False+ contents <- many1 $ listItem fourSpaceRule defListStart optional blanklines- return $ liftM2 (,) term (sequence contents)+ return $ liftM2 (,)+ term+ ((if isTight+ then fmap (fmap (fmap paraToPlain))+ else id) (sequence contents)) -defRawBlock :: PandocMonad m => Bool -> MarkdownParser m Text-defRawBlock compact = try $ do- hasBlank <- option False $ blankline >> return True- defListMarker- firstline <- anyLineNewline- let dline = try- ( do notFollowedBy blankline- notFollowedByHtmlCloser- notFollowedByDivCloser- if compact -- laziness not compatible with compact- then () <$ indentSpaces- else (() <$ indentSpaces)- <|> notFollowedBy defListMarker- anyLine )- rawlines <- many dline- cont <- fmap T.concat $ many $ try $ do- trailing <- option "" blanklines- ln <- indentSpaces >> notFollowedBy blankline >> anyLine- lns <- many dline- return $ trailing <> T.unlines (ln:lns)- return $ trimr (firstline <> T.unlines rawlines <> cont) <>- if hasBlank || not (T.null cont) then "\n\n" else ""+paraToPlain :: Block -> Block+paraToPlain (Para ils) = Plain ils+paraToPlain x = x definitionList :: PandocMonad m => MarkdownParser m (F Blocks) definitionList = try $ do+ guardEnabled Ext_definition_lists lookAhead (anyLine >> optional (blankline >> notFollowedBy (Control.Monad.void table)) >> -- don't capture table caption as def list!- defListMarker)- compactDefinitionList <|> normalDefinitionList--compactDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)-compactDefinitionList = do- guardEnabled Ext_compact_definition_lists- items <- fmap sequence $ many1 $ definitionListItem True- return $ B.definitionList <$> fmap compactifyDL items--normalDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)-normalDefinitionList = do- guardEnabled Ext_definition_lists- items <- fmap sequence $ many1 $ definitionListItem False+ defListStart)+ items <- fmap sequence $ many1 definitionListItem return $ B.definitionList <$> items --@@ -1039,7 +1053,7 @@ [Image attr figCaption (src, tit)] | extensionEnabled Ext_implicit_figures exts , not (null figCaption) -> do- B.simpleFigureWith attr (B.fromList figCaption) src tit+ implicitFigure attr (B.fromList figCaption) src tit _ -> constr inlns @@ -1047,19 +1061,21 @@ $ try $ do newline (mempty <$ blanklines)- <|> (guardDisabled Ext_blank_before_blockquote >> () <$ lookAhead blockQuote)- <|> (guardEnabled Ext_backtick_code_blocks >> () <$ lookAhead codeBlockFenced)- <|> (guardDisabled Ext_blank_before_header >> () <$ lookAhead header)- <|> (guardEnabled Ext_lists_without_preceding_blankline >>- -- Avoid creating a paragraph in a nested list.- notFollowedBy' inList >>- () <$ lookAhead listStart)+ <|> (guardDisabled Ext_blank_before_blockquote+ <* lookAhead blockQuote)+ <|> (guardEnabled Ext_backtick_code_blocks+ <* lookAhead codeBlockFenced)+ <|> (guardDisabled Ext_blank_before_header+ <* lookAhead header)+ <|> (guardEnabled Ext_lists_without_preceding_blankline+ -- Avoid creating a paragraph in a nested list.+ <* notFollowedBy' (inList <* listStart)) <|> do guardEnabled Ext_native_divs inHtmlBlock <- stateInHtmlBlock <$> getState case inHtmlBlock of- Just "div" -> () <$- lookAhead (htmlTag (~== TagClose ("div" :: Text)))- _ -> mzero+ Just "div" -> () <$+ lookAhead (htmlTag (~== TagClose ("div" :: Text)))+ _ -> mzero <|> do guardEnabled Ext_fenced_divs divLevel <- stateFencedDivLevel <$> getState if divLevel > 0@@ -1070,6 +1086,21 @@ plain :: PandocMonad m => MarkdownParser m (F Blocks) plain = fmap B.plain . trimInlinesF <$> inlines1 +implicitFigure :: Attr -> Inlines -> Text -> Text -> Blocks+implicitFigure (ident, classes, attribs) capt url title =+ let alt = case "alt" `lookup` attribs of+ Just alt' -> B.text alt'+ _ -> capt+ 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+ -- -- raw html --@@ -1132,7 +1163,7 @@ many1 ((<>) <$> rawLaTeXBlock <*> spnl')) return $ case B.toList result of [RawBlock _ cs]- | T.all (`elem` [' ','\t','\n']) cs -> return mempty+ | T.all (\c -> c == ' ' || c == '\t' || c == '\n') cs -> return mempty -- don't create a raw block for suppressed macro defs _ -> return result @@ -1168,7 +1199,9 @@ return (return (B.rawBlock "html" $ stripMarkdownAttribute raw) <> contents <> return (B.rawBlock "html" rawcloser)))- <|> return (return (B.rawBlock "html" raw) <> contents)+ <|> if T.all isSpace raw+ then return mempty+ else return (return (B.rawBlock "html" raw) <> contents) updateState $ \st -> st{ stateInHtmlBlock = oldInHtmlBlock } return result @@ -1199,7 +1232,7 @@ -- and the length including trailing space. dashedLine :: PandocMonad m => Char- -> ParserT Sources st m (Int, Int)+ -> ParsecT Sources st m (Int, Int) dashedLine ch = do dashes <- many1 (char ch) sp <- many spaceChar@@ -1211,7 +1244,7 @@ -- one (or zero) line of text. simpleTableHeader :: PandocMonad m => Bool -- ^ Headerless table- -> MarkdownParser m (F [Blocks], [Alignment], [Int])+ -> MarkdownParser m (F [[Blocks]], [Alignment], [Int]) simpleTableHeader headless = try $ do rawContent <- if headless then return ""@@ -1222,7 +1255,7 @@ let (lengths, lines') = unzip dashes let indices = scanl (+) (T.length initSp) lines' -- If no header, calculate alignment on basis of first row of text- rawHeads <- fmap (tail . splitTextByIndices (init indices)) $+ rawHeads <- fmap (drop 1 . splitTextByIndices (init indices)) $ if headless then lookAhead anyLine else return rawContent@@ -1233,7 +1266,7 @@ heads <- fmap sequence $ mapM (parseFromString' (mconcat <$> many plain).trim) rawHeads'- return (heads, aligns, indices)+ return (fmap (:[]) heads, aligns, indices) -- Returns an alignment type for a table, based on a list of strings -- (the rows of the column header) and a number (the length of the@@ -1246,7 +1279,7 @@ let nonempties = filter (not . T.null) $ map trimr strLst (leftSpace, rightSpace) = case sortOn T.length nonempties of- (x:_) -> (T.head x `elem` [' ', '\t'], T.length x < len)+ (x:_) -> (T.head x `elem` [' ', '\t'], realLength x < len) [] -> (False, False) in case (leftSpace, rightSpace) of (True, False) -> AlignRight@@ -1269,8 +1302,7 @@ rawTableLine indices = do notFollowedBy' (blanklines' <|> tableFooter) line <- anyLine- return $ map trim $ tail $- splitTextByIndices (init indices) line+ return $ map trim $ drop 1 $ splitTextByIndices (init indices) line -- Parse a table line and return a list of lists of blocks (columns). tableLine :: PandocMonad m@@ -1290,13 +1322,19 @@ -- Parses a table caption: inlines beginning with 'Table:' -- and followed by blank lines.-tableCaption :: PandocMonad m => MarkdownParser m (F Inlines)+tableCaption :: PandocMonad m => MarkdownParser m (F Inlines, Attr) tableCaption = do guardEnabled Ext_table_captions try $ do skipNonindentSpaces- (string ":" <* notFollowedBy (satisfy isPunctuation)) <|> string "Table:"- trimInlinesF <$> inlines1 <* blanklines+ (string ":" <* notFollowedBy (satisfy isPunctuation)) <|>+ (oneOf ['T','t'] >> string "able:")+ let attributes' = guardEnabled Ext_table_attributes *> attributes+ ils <- trimInlinesF . mconcat <$>+ many (notFollowedBy (attributes' *> blanklines) *> inline)+ attr <- option nullAttr attributes'+ blanklines+ pure (ils, attr) -- Parse a simple table with '---' header and one line per row. simpleTable :: PandocMonad m@@ -1310,7 +1348,8 @@ (if headless then tableFooter else tableFooter <|> blanklines') -- All columns in simple tables have default widths. let useDefaultColumnWidths tc =- let cs' = map (second (const ColWidthDefault)) $ tableColSpecs tc+ let cs' = map (Bifunctor.second (const ColWidthDefault)) $+ tableColSpecs tc in tc {tableColSpecs = cs'} return $ useDefaultColumnWidths <$> tableComponents @@ -1327,7 +1366,7 @@ multilineTableHeader :: PandocMonad m => Bool -- ^ Headerless table- -> MarkdownParser m (F [Blocks], [Alignment], [Int])+ -> MarkdownParser m (F [[Blocks]], [Alignment], [Int]) multilineTableHeader headless = try $ do unless headless $ tableSep >> notFollowedBy blankline@@ -1345,10 +1384,10 @@ [] -> [] (x:xs) -> reverse (x+1:xs) rawHeadsList <- if headless- then fmap (map (:[]) . tail .- splitTextByIndices (init indices')) $ lookAhead anyLine+ then map (:[]) . drop 1 . splitTextByIndices (init indices')+ <$> lookAhead anyLine else return $ transpose $ map- (tail . splitTextByIndices (init indices'))+ (drop 1 . splitTextByIndices (init indices')) rawContent let aligns = zipWith alignType rawHeadsList lengths let rawHeads = if headless@@ -1356,7 +1395,7 @@ else map (T.unlines . map trim) rawHeadsList heads <- fmap sequence $ mapM (parseFromString' (mconcat <$> many plain).trim) rawHeads- return (heads, aligns, indices')+ return (fmap (:[]) heads, aligns, indices') -- Parse a grid table: starts with row of '-' on top, then header -- (which may be grid), then the rows,@@ -1364,7 +1403,20 @@ -- ending with a footer (dashed line followed by blank line). gridTable :: PandocMonad m => MarkdownParser m (F TableComponents)-gridTable = gridTableWith' NormalizeHeader parseBlocks+gridTable = try $ do+ -- Like other block-level constructs, a grid table may be indented by+ -- up to three spaces. The underlying grid-table parser expects the+ -- table to begin at the left margin, so strip a uniform indentation+ -- from every line before handing it off.+ indent <- T.length <$> lookAhead nonindentSpaces+ if indent == 0+ then gridTableWith' NormalizeHeader parseBlocks+ else do+ let gridLine = try $ count indent (char ' ')+ *> lookAhead (oneOf "+|")+ *> anyLineNewline+ rawTable <- T.concat <$> many1 gridLine+ parseFromString' (gridTableWith' NormalizeHeader parseBlocks) rawTable pipeBreak :: PandocMonad m => MarkdownParser m ([Alignment], [Int]) pipeBreak = try $ do@@ -1391,15 +1443,17 @@ let lineWidths = map (sum . map realLength) (heads' : lines'') columns <- getOption readerColumns -- add numcols + 1 for the pipes themselves- let widths = if maximumBounded (sum seplengths : lineWidths) + (numcols + 1) > columns+ let widths = if maximumBounded (sum seplengths : lineWidths) + (numcols + 1)+ > columns then map (\len -> fromIntegral len / fromIntegral (sum seplengths)) seplengths else replicate (length aligns) 0.0 (headCells :: F [Blocks]) <- sequence <$> mapM cellContents heads'- (rows :: F [[Blocks]]) <- sequence <$> mapM (fmap sequence . mapM cellContents) lines''+ (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@@ -1413,7 +1467,8 @@ skipMany spaceChar openPipe <- (True <$ char '|') <|> return False -- split into cells- let chunk = void (code <|> math <|> rawHtmlInline <|> escapedChar <|> rawLaTeXInline')+ let chunk = void (code <|> math <|> rawHtmlInline <|>+ escapedChar <|> rawLaTeXInline') <|> void (noneOf "|\n\r") cells <- (snd <$> withRaw (many chunk)) `sepBy1` char '|' closePipe <- (True <$ char '|') <|> return False@@ -1428,7 +1483,7 @@ return $ B.plain <$> result) <|> return mempty -pipeTableHeaderPart :: PandocMonad m => ParserT Sources st m (Alignment, Int)+pipeTableHeaderPart :: PandocMonad m => ParsecT Sources st m (Alignment, Int) pipeTableHeaderPart = try $ do skipMany spaceChar left <- optionMaybe (char ':')@@ -1444,7 +1499,7 @@ (Just _,Just _) -> AlignCenter, len) -- Succeed only if current line contains a pipe.-scanForPipe :: PandocMonad m => ParserT Sources st m ()+scanForPipe :: PandocMonad m => ParsecT Sources st m () scanForPipe = do Sources inps <- getInput let ln = case inps of@@ -1457,7 +1512,8 @@ table :: PandocMonad m => MarkdownParser m (F Blocks) table = try $ do- frontCaption <- option Nothing (Just <$> tableCaption)+ (frontCaption, frontAttr) <- option (Nothing, nullAttr)+ (Bifunctor.first Just <$> tableCaption) tableComponents <- (guardEnabled Ext_pipe_tables >> try (scanForPipe >> pipeTable)) <|> (guardEnabled Ext_multiline_tables >> try (multilineTable False)) <|>@@ -1468,13 +1524,14 @@ (guardEnabled Ext_grid_tables >> try gridTable) <?> "table" optional blanklines- caption <- case frontCaption of- Nothing -> option (return mempty) tableCaption- Just c -> return c+ (caption, attr) <- case frontCaption of+ Nothing -> option (return mempty, nullAttr) tableCaption+ Just c -> return (c, frontAttr) return $ do caption' <- caption (TableComponents _attr _capt colspecs th tb tf) <- tableComponents- return $ B.table (B.simpleCaption $ B.plain caption') colspecs th tb tf+ return $ B.tableWith attr+ (B.simpleCaption $ B.plain caption') colspecs th tb tf -- -- inline@@ -1496,11 +1553,12 @@ '`' -> code '_' -> strongOrEmph '*' -> strongOrEmph- '^' -> superscript <|> inlineNote -- in this order bc ^[link](/foo)^- '[' -> note <|> cite <|> bracketedSpan <|> link+ '^' -> inlineNote <|> superscript+ '[' -> note <|> cite <|> bracketedSpan <|> wikilink B.linkWith <|> link '!' -> image '$' -> math '~' -> strikeout <|> subscript+ '=' -> mark '<' -> autoLink <|> spanHtml <|> rawHtmlInline <|> ltSign '\\' -> math <|> escapedNewline <|> escapedChar <|> rawLaTeXInline' '@' -> cite <|> exampleRef@@ -1510,7 +1568,7 @@ '\145' -> smart '\8220' -> smart '\147' -> smart- '-' -> smart+ '-' -> cite <|> smart '.' -> smart '&' -> return . B.singleton <$> charRef ':' -> emoji@@ -1522,10 +1580,11 @@ escapedChar' :: PandocMonad m => MarkdownParser m Char escapedChar' = try $ do char '\\'- (guardEnabled Ext_all_symbols_escapable >> satisfy (not . isAlphaNum))+ (guardEnabled Ext_all_symbols_escapable >>+ satisfy (\c -> c /= '\n' && c /= '\r' && not (isAlphaNum c))) <|> (guardEnabled Ext_angle_brackets_escapable >> oneOf "\\`*_{}[]()>#+-.!~\"<>")- <|> oneOf "\\`*_{}[]()>#+-.!~\""+ <|> oneOf "\\`*_{}[]()>#+-.!" escapedNewline :: PandocMonad m => MarkdownParser m (F Inlines) escapedNewline = do@@ -1559,7 +1618,7 @@ guardEnabled Ext_example_lists try $ do char '@'- lab <- mconcat . map T.pack <$>+ lab <- T.pack . concat <$> many (many1 alphaNum <|> try (do c <- char '_' <|> char '-' cs <- many1 alphaNum@@ -1576,7 +1635,7 @@ <|> try (do lookAhead $ char '\\' notFollowedBy' (() <$ rawTeXBlock) char '\\')- return $ return $ B.str $ T.singleton result+ return $ return $ B.str $! T.singleton result -- parses inline code, between n `s and n `s code :: PandocMonad m => MarkdownParser m (F Inlines)@@ -1601,8 +1660,8 @@ (guardEnabled Ext_inline_code_attributes >> try attributes)) return $ return $ case rawattr of- Left syn -> B.rawInline syn result- Right attr -> B.codeWith attr result+ Left syn -> B.rawInline syn $! result+ Right attr -> B.codeWith attr $! result math :: PandocMonad m => MarkdownParser m (F Inlines) math = (return . B.displayMath <$> (mathDisplay >>= applyMacros))@@ -1680,7 +1739,8 @@ -> MarkdownParser m (F Inlines) inlinesBetween start end = trimInlinesF . mconcat <$> try (start >> many1Till inner end)- where inner = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline)+ where inner = innerSpace <|>+ (notFollowedBy' (() <$ whitespace) >> inline) innerSpace = try $ whitespace <* notFollowedBy' end strikeout :: PandocMonad m => MarkdownParser m (F Inlines)@@ -1690,38 +1750,46 @@ >> notFollowedBy (char '~') strikeEnd = try $ string "~~" +mark :: PandocMonad m => MarkdownParser m (F Inlines)+mark = fmap (B.spanWith ("",["mark"],[])) <$>+ (guardEnabled Ext_mark >> inlinesBetween markStart markEnd)+ where markStart = string "==" >> lookAhead nonspaceChar+ >> notFollowedBy (char '=')+ markEnd = try $ string "=="+ superscript :: PandocMonad m => MarkdownParser m (F Inlines) superscript = do- fmap B.superscript <$> try (do- char '^'- mconcat <$> (try regularSuperscript <|> try mmdShortSuperscript))- where regularSuperscript = many1Till (do guardEnabled Ext_superscript- notFollowedBy spaceChar- notFollowedBy newline- inline) (char '^')- mmdShortSuperscript = do guardEnabled Ext_short_subsuperscripts- result <- T.pack <$> many1 alphaNum- return $ return $ return $ B.str result+ fmap B.superscript <$> (regularSuperscript <|> mmdShortSuperscript)+ where+ regularSuperscript = do+ guardEnabled Ext_superscript+ litBetweenNoSpace '^' '^' >>= parseFromString inlines+ mmdShortSuperscript = try $ do+ guardEnabled Ext_short_subsuperscripts+ char '^'+ result <- T.pack <$> many1 alphaNum+ return $ return $ B.str result subscript :: PandocMonad m => MarkdownParser m (F Inlines) subscript = do- fmap B.subscript <$> try (do- char '~'- mconcat <$> (try regularSubscript <|> mmdShortSubscript))- where regularSubscript = many1Till (do guardEnabled Ext_subscript- notFollowedBy spaceChar- notFollowedBy newline- inline) (char '~')- mmdShortSubscript = do guardEnabled Ext_short_subsuperscripts- result <- T.pack <$> many1 alphaNum- return $ return $ return $ B.str result+ fmap B.subscript <$> (regularSubscript <|> mmdShortSubscript)+ where+ regularSubscript = do+ guardEnabled Ext_subscript+ litBetweenNoSpace '~' '~' >>= parseFromString inlines+ mmdShortSubscript = try $ do+ guardEnabled Ext_short_subsuperscripts+ char '~'+ result <- T.pack <$> many1 alphaNum+ return $ return $ B.str result whitespace :: PandocMonad m => MarkdownParser m (F Inlines) whitespace = spaceChar >> return <$> (lb <|> regsp) <?> "whitespace"- where lb = spaceChar >> skipMany spaceChar >> option B.space (endline >> return B.linebreak)+ where lb = spaceChar >> skipMany spaceChar+ >> option B.space (endline >> return B.linebreak) regsp = skipMany spaceChar >> return B.space -nonEndline :: PandocMonad m => ParserT Sources st m Char+nonEndline :: PandocMonad m => ParsecT Sources st m Char nonEndline = satisfy (/='\n') str :: PandocMonad m => MarkdownParser m (F Inlines)@@ -1775,35 +1843,64 @@ -- a reference label for a link reference :: PandocMonad m => MarkdownParser m (F Inlines, Text) reference = do- guardDisabled Ext_footnotes <|> notFollowedBy' (string "[^")- withRaw $ trimInlinesF <$> inlinesInBalancedBrackets--parenthesizedChars :: PandocMonad m => MarkdownParser m Text-parenthesizedChars = do- result <- charsInBalanced '(' ')' litChar- return $ "(" <> result <> ")"+ guardDisabled Ext_footnotes <|> notFollowedBy' noteMarker+ withRaw $ trimInlinesF <$> inBalancedBrackets inlines -- source for a link, with optional title source :: PandocMonad m => MarkdownParser m (Text, Text) source = do char '(' skipSpaces- let urlChunk =- try parenthesizedChars- <|> (notFollowedBy (oneOf " )") >> countChar 1 litChar)- <|> try (many1Char spaceChar <* notFollowedBy (oneOf "\"')"))+ let parenthesizedChars = do+ result <- charsInBalanced '(' ')' litChar+ return $ "(" <> result <> ")"+ let linkTitle' = try $ spnl >> linkTitle+ let urlChunk = do+ try parenthesizedChars+ <|> (notFollowedBy (oneOf "\n\r )") >> litChar)+ <|> (lookAhead (oneOf "\n\r") >> notFollowedBy linkTitle' >> litChar)+ <|> try (many1Char spaceChar <* notFollowedBy (oneOf "\"')")) let sourceURL = T.unwords . T.words . T.concat <$> many urlChunk- let betweenAngles = try $- char '<' >> manyTillChar litChar (char '>')- src <- try betweenAngles <|> sourceURL- tit <- option "" $ try $ spnl >> linkTitle+ src <- try (litBetween '<' '>') <|> try base64DataURI <|> sourceURL+ tit <- option "" linkTitle' skipSpaces char ')' return (escapeURI $ trimr src, tit) +base64DataURI :: PandocMonad m => ParsecT Sources s m Text+base64DataURI = do+ Sources ((pos, txt):rest) <- getInput+ let r = A.parse (fst <$> A.match pBase64DataURI) txt+ case r of+ A.Done remaining consumed -> do+ let pos' = incSourceColumn pos (T.length consumed)+ setInput $ Sources ((pos', remaining):rest)+ return consumed+ _ -> mzero+ linkTitle :: PandocMonad m => MarkdownParser m Text linkTitle = quotedTitle '"' <|> quotedTitle '\'' +wikilink :: PandocMonad m+ => (Attr -> Text -> Text -> Inlines -> Inlines)+ -> MarkdownParser m (F Inlines)+wikilink constructor = do+ let attr = (mempty, ["wikilink"], mempty)+ titleAfter <-+ (True <$ guardEnabled Ext_wikilinks_title_after_pipe) <|>+ (False <$ guardEnabled Ext_wikilinks_title_before_pipe)+ try $ do+ string "[[" *> notFollowedBy' (char '[')+ raw <- many1TillChar anyChar (try $ string "]]")+ let (title, url) = case T.break (== '|') raw of+ (before, "") -> (before, before)+ (before, after)+ | titleAfter -> (T.drop 1 after, before)+ | otherwise -> (before, T.drop 1 after)+ guard $ T.all (\c -> c /= '\n' && c /= '\r' && c /= '\f' && c /= '\t') url+ return . pure . constructor attr url "" $+ B.text $ fromEntities title+ link :: PandocMonad m => MarkdownParser m (F Inlines) link = try $ do st <- getState@@ -1845,7 +1942,7 @@ isSmallCapsFontVariant :: Text -> Bool isSmallCapsFontVariant s =- T.toLower (T.filter (`notElem` [' ', '\t', ';']) s) ==+ T.toLower (T.filter (\c -> c /= ' ' && c /= '\t' && c /= ';') s) == "font-variant:small-caps" regLink :: PandocMonad m@@ -1853,12 +1950,11 @@ -> F Inlines -> MarkdownParser m (F Inlines) regLink constructor lab = try $ do- (src, tit) <- source+ (!src, !tit) <- source rebase <- option False (True <$ guardEnabled Ext_rebase_relative_paths) pos <- getPosition- let src' = if rebase then rebasePath pos src else src- attr <- option nullAttr $- guardEnabled Ext_link_attributes >> attributes+ let !src' = if rebase then rebasePath pos src else src+ !attr <- option nullAttr $ guardEnabled Ext_link_attributes >> attributes return $ constructor attr src' tit <$> lab -- a link like [this][ref] or [this][] or [this]@@ -1868,7 +1964,7 @@ -> MarkdownParser m (F Inlines) referenceLink constructor (lab, raw) = do sp <- (True <$ lookAhead (char ' ')) <|> return False- (_,raw') <- option (mempty, "") $+ (_,!raw') <- option (mempty, "") $ lookAhead (try (do guardEnabled Ext_citations guardDisabled Ext_spaced_reference_links <|> spnl normalCite@@ -1876,16 +1972,25 @@ <|> try ((guardDisabled Ext_spaced_reference_links <|> spnl) >> reference) when (raw' == "") $ guardEnabled Ext_shortcut_reference_links- let labIsRef = raw' == "" || raw' == "[]"- let key = toKey $ if labIsRef then raw else raw'+ !attr <- option nullAttr $ guardEnabled Ext_link_attributes >> attributes+ let !labIsRef = raw' == "" || raw' == "[]"+ let (exclam, rawsuffix) =+ case T.uncons raw of+ Just ('!', rest) -> (True, rest)+ _ -> (False, raw)+ let !key = toKey $ if labIsRef then rawsuffix else raw' parsedRaw <- parseFromString' inlines raw'- fallback <- parseFromString' inlines $ dropBrackets raw+ fallback <- parseFromString' inlines $ if exclam+ then rawsuffix+ else dropBrackets rawsuffix implicitHeaderRefs <- option False $ True <$ guardEnabled Ext_implicit_header_references let makeFallback = do parsedRaw' <- parsedRaw fallback' <- fallback- return $ B.str "[" <> fallback' <> B.str "]" <>+ return $ (if exclam+ then "!" <> fallback'+ else B.str "[" <> fallback' <> B.str "]") <> (if sp && not (T.null raw) then B.space else mempty) <> parsedRaw' return $ do@@ -1896,11 +2001,11 @@ then do headerKeys <- asksF stateHeaderKeys case M.lookup key headerKeys of- Just ((src, tit), _) -> constructor nullAttr src tit <$> lab+ Just ((src, tit), _) -> constructor attr src tit <$> lab Nothing -> makeFallback else makeFallback- Just ((src,tit), attr) ->- constructor attr src tit <$> lab+ Just ((src,tit), defattr) ->+ constructor (combineAttr attr defattr) src tit <$> lab dropBrackets :: Text -> Text dropBrackets = dropRB . dropLB@@ -1953,14 +2058,17 @@ image :: PandocMonad m => MarkdownParser m (F Inlines) image = try $ do char '!'- (lab,raw) <- reference- defaultExt <- getOption readerDefaultImageExtension- let constructor attr' src =- case takeExtension (T.unpack src) of- "" -> B.imageWith attr' (T.pack $ addExtension (T.unpack src)- $ T.unpack defaultExt)- _ -> B.imageWith attr' src- regLink constructor lab <|> referenceLink constructor (lab,raw)+ wikilink B.imageWith <|>+ do (lab,raw) <- reference+ defaultExt <- getOption readerDefaultImageExtension+ let constructor attr' src+ | "data:" `T.isPrefixOf` src = B.imageWith attr' src -- see #9118+ | otherwise =+ case takeExtension (T.unpack src) of+ "" -> B.imageWith attr' (T.pack $ addExtension (T.unpack src)+ $ T.unpack defaultExt)+ _ -> B.imageWith attr' src+ regLink constructor lab <|> referenceLink constructor (lab, "!" <> raw) note :: PandocMonad m => MarkdownParser m (F Inlines) note = try $ do@@ -1993,7 +2101,9 @@ char '^' updateState $ \st -> st{ stateInNote = True , stateNoteNumber = stateNoteNumber st + 1 }- contents <- inlinesInBalancedBrackets+ contents <- withQuoteContext NoQuote $ inBalancedBrackets inlines+ notFollowedBy (char '(' <|> char '[' <|> ('{' <$ attributes))+ -- ^[link](foo)^ is superscript updateState $ \st -> st{ stateInNote = False } return $ B.note . B.para <$> contents @@ -2001,25 +2111,24 @@ rawLaTeXInline' = do guardEnabled Ext_raw_tex notFollowedBy' rawConTeXtEnvironment- try $ do- s <- rawLaTeXInline- return $ return $ B.rawInline "tex" s -- "tex" because it might be context+ !s <- rawLaTeXInline+ return $ return $ B.rawInline "tex" s -- "tex" because it might be context -rawConTeXtEnvironment :: PandocMonad m => ParserT Sources st m Text+rawConTeXtEnvironment :: PandocMonad m => ParsecT Sources st m Text rawConTeXtEnvironment = try $ do string "\\start" completion <- inBrackets (letter <|> digit <|> spaceChar) <|> many1Char letter- contents <- manyTill (rawConTeXtEnvironment <|> countChar 1 anyChar)+ !contents <- manyTill (rawConTeXtEnvironment <|> countChar 1 anyChar) (try $ string "\\stop" >> textStr completion)- return $ "\\start" <> completion <> T.concat contents <> "\\stop" <> completion+ return $! "\\start" <> completion <> T.concat contents <> "\\stop" <> completion -inBrackets :: PandocMonad m => ParserT Sources st m Char -> ParserT Sources st m Text+inBrackets :: PandocMonad m => ParsecT Sources st m Char -> ParsecT Sources st m Text inBrackets parser = do char '[' contents <- manyChar parser char ']'- return $ "[" <> contents <> "]"+ return $! "[" <> contents <> "]" spanHtml :: PandocMonad m => MarkdownParser m (F Inlines) spanHtml = do@@ -2036,29 +2145,29 @@ divHtml = do guardEnabled Ext_native_divs try $ do- (TagOpen _ attrs, rawtag) <- htmlTag (~== TagOpen ("div" :: Text) [])+ openpos <- getPosition+ (TagOpen _ attrs, _) <- htmlTag (~== TagOpen ("div" :: Text) []) -- we set stateInHtmlBlock so that closing tags that can be either block -- or inline will not be parsed as inline tags oldInHtmlBlock <- stateInHtmlBlock <$> getState updateState $ \st -> st{ stateInHtmlBlock = Just "div" }- bls <- option "" (blankline >> option "" blanklines)+ optional blanklines contents <- mconcat <$>- many (notFollowedBy' (htmlTag (~== TagClose ("div" :: Text))) >> block)- closed <- option False (True <$ htmlTag (~== TagClose ("div" :: Text)))- if closed- then do- updateState $ \st -> st{ stateInHtmlBlock = oldInHtmlBlock }- let ident = fromMaybe "" $ lookup "id" attrs- let classes = maybe [] T.words $ lookup "class" attrs- let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]- return $ B.divWith (ident, classes, keyvals) <$> contents- else -- avoid backtracing- return $ return (B.rawBlock "html" (rawtag <> bls)) <> contents+ many (notFollowedBy' (htmlTag (~== TagClose ("div" :: Text)))+ >> block)+ void (htmlTag (~== TagClose ("div" :: Text))) <|>+ (getPosition >>= report . UnclosedDiv openpos)+ let ident = fromMaybe "" $ lookup "id" attrs+ let classes = maybe [] T.words $ lookup "class" attrs+ let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]+ updateState $ \st -> st{ stateInHtmlBlock = oldInHtmlBlock }+ return $ B.divWith (ident, classes, keyvals) <$> contents divFenced :: PandocMonad m => MarkdownParser m (F Blocks) divFenced = do guardEnabled Ext_fenced_divs try $ do+ openpos <- getPosition string ":::" skipMany (char ':') skipMany spaceChar@@ -2068,7 +2177,8 @@ blankline updateState $ \st -> st{ stateFencedDivLevel = stateFencedDivLevel st + 1 }- bs <- mconcat <$> manyTill block divFenceEnd+ bs <- mconcat <$> many (notFollowedBy divFenceEnd >> block)+ divFenceEnd <|> (getPosition >>= report . UnclosedDiv openpos) updateState $ \st -> st{ stateFencedDivLevel = stateFencedDivLevel st - 1 } return $ B.divWith attribs <$> bs@@ -2095,19 +2205,18 @@ then (\x -> isInlineTag x && not (isCloseBlockTag x)) else not . isTextTag- return $ return $ B.rawInline "html" result+ return $ if T.all isSpace result+ then return mempty+ else return $ B.rawInline "html" result -- Emoji -emojiChars :: [Char]-emojiChars = ['a'..'z'] ++ ['0'..'9'] ++ ['_','+','-']- emoji :: PandocMonad m => MarkdownParser m (F Inlines) emoji = do guardEnabled Ext_emoji try $ do char ':'- emojikey <- many1Char (oneOf emojiChars)+ emojikey <- many1Char (alphaNum <|> oneOf "_+-") char ':' case emojiToInline emojikey of Just i -> return (return $ B.singleton i)@@ -2181,7 +2290,7 @@ rest <- option (return []) $ try $ char ';' >> spnl >> citeList spnl char ']'- notFollowedBy $ oneOf "[("+ notFollowedBy $ oneOf "[({" return $ do suff' <- suff rest' <- rest@@ -2194,15 +2303,19 @@ citations <- citeList spnl char ']'- notFollowedBy (oneOf "{([") -- not a link or a bracketed span+ -- not a link or a bracketed span+ notFollowedBy (try (void source) <|>+ (guardEnabled Ext_bracketed_spans *> void attributes) <|>+ void reference) return citations suffix :: PandocMonad m => MarkdownParser m (F Inlines) suffix = try $ do hasSpace <- option False (notFollowedBy nonspaceChar >> return True) spnl- rest <- trimInlinesF . mconcat <$> many (notFollowedBy (oneOf ";]") >> inline)- return $ if hasSpace+ ils <- many (notFollowedBy (oneOf ";]") >> inline)+ let rest = trimInlinesF (mconcat ils)+ return $ if hasSpace && not (null ils) then (B.space <>) <$> rest else rest
@@ -0,0 +1,1469 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ViewPatterns #-}+{- |+ Module : Text.Pandoc.Readers.Mdoc+ Copyright : © 2024 Evan Silberman+ License : GNU GPL, version 2 or above++ Maintainer : Evan Silberman <evan@jklol.net>+ Stability : WIP+ Portability : portable++Conversion of mdoc to 'Pandoc' document.+-}+module Text.Pandoc.Readers.Mdoc (readMdoc) where++import Data.Char (isAsciiLower, toUpper)+import Data.Default (Default)+import Data.Either (fromRight)+import Data.Functor (($>))+import Data.Maybe (catMaybes)+import Control.Monad (mplus, guard, void, when, unless)+import Control.Monad.Except (throwError)+#if MIN_VERSION_base(4,19,0)+import Data.List (intersperse, unsnoc)+#else+import Data.List (intersperse)+#endif+import qualified Data.Map.Strict as M+import qualified Data.Text as T+import Text.Pandoc.Definition (Pandoc(Pandoc), Meta)+import Text.Pandoc.Builder (Blocks, Inlines)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class.PandocMonad (PandocMonad(..))+import Text.Pandoc.Options+import Text.Pandoc.Parsing hiding (uncons)+import Text.Pandoc.Logging+import Text.Pandoc.Readers.Mdoc.Lex+import Text.Pandoc.Readers.Mdoc.Standards+import Text.Parsec (modifyState)+import qualified Text.Pandoc.Parsing as P+import qualified Data.Foldable as Foldable+import Text.Pandoc.Shared (stringify)++#if !MIN_VERSION_base(4,19,0)+unsnoc :: [a] -> Maybe ([a], a)+unsnoc = foldr (\x -> Just . maybe ([], x) (\(~(a, b)) -> (x : a, b))) Nothing+#endif++ {- As a general principle, if mandoc -T lint issues a WARNING admonition+ or worse about a construct, I consider it fair game for this reader to+ do something different than what mandoc does with it, including bailing+ out instead of recovering. -}++data MdocSection+ = ShName+ | ShSynopsis+ | ShAuthors+ | ShSeeAlso+ | ShOther+ deriving (Show, Eq)++-- Declaration order is important: this is the order fields of a reference+-- are printed by mandoc+data ReferenceField =+ Author+ | ArticleTitle+ | BookTitle+ | Publisher+ | Journal+ | TechReportTitle+ | IssueNumber+ | VolumeNumber+ | Url+ | Pages+ | Institution+ | PubLocation+ | PubDate+ | Optional+ deriving (Show, Eq, Ord, Enum)++-- mandoc allows specifying multiple of _any_ reference field, and just+-- prints them all out in document order, even though authors are the only+-- field where this is the documented behavior. There's no lint warning+-- about this either. I'd prefer to do last-one-wins for the non-author+-- fields, which would presumably make it easier to transform the+-- bibliographic data into something else, but for now all I'm doing is+-- printing the references out the same way mandoc does.+type MdocReference = M.Map ReferenceField [T.Text]++data MdocState = MdocState+ { readerOptions :: ReaderOptions+ , metadata :: Meta+ , tableCellsPlain :: Bool+ , spacingMode :: Bool+ , authorNameSplit :: Bool+ , inLineEnclosure :: Bool+ , progName :: Maybe T.Text+ , currentSection :: MdocSection+ , currentReference :: MdocReference+ , logMessages :: [LogMessage]+ }+ deriving (Show)++instance Default MdocState where+ def =+ MdocState+ { readerOptions = def+ , metadata = B.nullMeta+ , tableCellsPlain = True+ , spacingMode = True+ , authorNameSplit = False+ , inLineEnclosure = False+ , currentSection = ShOther+ , currentReference = M.empty+ , progName = Nothing+ , logMessages = []+ }++instance HasLogMessages MdocState where+ addLogMessage msg st = st{ logMessages = msg : logMessages st }+ getLogMessages st = reverse $ logMessages st++type MdocParser m = P.ParsecT [MdocToken] MdocState m+++-- | Read mdoc from an input string and return a Pandoc document.+readMdoc :: (PandocMonad m, ToSources a)+ => ReaderOptions+ -> a+ -> m Pandoc+readMdoc opts s = do+ let Sources inps = toSources s+ tokenz <- mconcat <$> mapM (uncurry lexMdoc) inps+ let state = def {readerOptions = opts} :: MdocState+ eitherdoc <- readWithMTokens parseMdoc state+ (Foldable.toList . unMdocTokens $ tokenz)+ either (throwError . fromParsecError (Sources inps)) return eitherdoc+++readWithMTokens :: PandocMonad m+ => ParsecT [MdocToken] MdocState m a -- ^ parser+ -> MdocState -- ^ initial state+ -> [MdocToken] -- ^ input+ -> m (Either ParseError a)+readWithMTokens parser state input =+ runParserT parser state "source" input+++parseMdoc :: PandocMonad m => MdocParser m Pandoc+parseMdoc = do+ optional parsePrologue+ bs <- many parseBlock <* eof+ meta <- metadata <$> getState+ let (Pandoc _ blocks) = B.doc $ mconcat bs+ reportLogMessages+ return $ Pandoc meta blocks++msatisfy :: Monad m+ => (MdocToken -> Bool) -> P.ParsecT [MdocToken] st m MdocToken+msatisfy predic = P.tokenPrim show nextPos testTok+ where+ testTok t = if predic t then Just t else Nothing+ nextPos _ _ (Macro _ pos':_) = pos'+ nextPos _ _ (Lit _ pos':_) = pos'+ nextPos _ _ (Str _ pos':_) = pos'+ nextPos _ _ (Delim _ _ pos':_) = pos'+ nextPos _ _ (Blank pos':_) = pos'+ nextPos a _ (Eol{}:x:xs) = nextPos a x xs+ nextPos pos _ [Eol] = pos+ nextPos pos _ [] = pos++macro :: PandocMonad m => T.Text -> MdocParser m MdocToken+macro name = msatisfy t where+ t (Macro n _) = n == name+ t _ = False++anyMacro :: PandocMonad m => MdocParser m MdocToken+anyMacro = msatisfy t where+ t (Macro _ _) = True+ t _ = False++emptyMacro :: PandocMonad m => T.Text -> MdocParser m MdocToken+emptyMacro n = macro n <* eol++delim :: PandocMonad m => DelimSide -> MdocParser m MdocToken+delim side = msatisfy t where+ t (Delim s _ _) = side == s+ t _ = False++str :: PandocMonad m => MdocParser m MdocToken+str = msatisfy t where+ t Str{} = True+ t _ = False++lit :: PandocMonad m => MdocParser m MdocToken+lit = msatisfy t where+ t Lit{} = True+ t _ = False++arg :: PandocMonad m => MdocParser m MdocToken+arg = msatisfy t where+ t Lit{} = True+ t Macro{} = True+ t _ = False++literal :: PandocMonad m => T.Text -> MdocParser m MdocToken+literal n = msatisfy t where+ t (Lit n' _) = n == n'+ t _ = False++blank :: PandocMonad m => MdocParser m MdocToken+blank = msatisfy t where+ t Blank{} = True+ t _ = False++eol :: PandocMonad m => MdocParser m ()+eol = void $ msatisfy t where+ t Eol{} = True+ t _ = False++newControlContext :: MdocToken -> Bool+newControlContext Eol{} = True+newControlContext Macro{} = True+newControlContext Str{} = True+newControlContext Blank{} = True+newControlContext Lit{} = False+newControlContext Delim{} = False+++inlineContextEnd :: PandocMonad m => MdocParser m ()+inlineContextEnd = eof <|> (void . lookAhead $ msatisfy newControlContext)++sectionEnd :: PandocMonad m => MdocParser m ()+sectionEnd = eof <|> (void . lookAhead $ macro "Sh")++argsToInlines :: PandocMonad m => MdocParser m Inlines+argsToInlines = do+ ls <- manyTill arg eol+ let strs = map (B.str . toString) ls+ spacify strs++parsePrologue :: PandocMonad m => MdocParser m ()+parsePrologue = do+ macro "Dd"+ date <- argsToInlines+ macro "Dt"+ (Lit title _) <- lit+ (Lit section _) <- lit+ arch <- optionMaybe (toString <$> lit)+ eol+ emptyMacro "Os"+ let adjust = B.setMeta "title" (B.str title)+ . B.setMeta "date" date+ . B.setMeta "section" (B.str section)+ . maybe id (B.setMeta "architecture" . B.str) arch+ modifyState $ \s -> s{metadata = adjust $ metadata s}++shToSectionMode :: T.Text -> MdocSection+shToSectionMode "NAME" = ShName+shToSectionMode "SYNOPSIS" = ShSynopsis+shToSectionMode "AUTHORS" = ShAuthors+shToSectionMode "SEE ALSO" = ShSeeAlso+shToSectionMode _ = ShOther++parseHeader :: PandocMonad m => MdocParser m Blocks+parseHeader = do+ (Macro m _) <- lookAhead $ macro "Sh" <|> macro "Ss"+ txt <- lineEnclosure m id+ let lvl = if m == "Sh" then 1 else 2+ when (lvl == 1) $ modifyState $ \s -> s{currentSection = (shToSectionMode . stringify) txt}+ return $ B.header lvl txt++parseNameSection :: PandocMonad m => MdocParser m Blocks+parseNameSection = do+ sec <- currentSection <$> getState+ guard $ sec == ShName+ nms <- mconcat . intersperse B.space <$> many nameNm+ macro "Nd"+ desc <- argsToInlines+ return $ B.para $ nms <> B.space <> "—" <> B.space <> desc+ where+ nameNm = do+ macro "Nm"+ nms <- many1 aNm+ eol+ return $ mconcat $ intersperse B.space nms+ comma = msatisfy $ \case+ (Delim _ "," _) -> True+ _ -> False+ aNm = do+ nm <- toString <$> lit+ c <- option mempty (toString <$> comma)+ modifyState $ \s -> s{progName = mplus (progName s) (Just nm)}+ return $ B.code nm <> B.str c++parseSynopsisSection :: PandocMonad m => MdocParser m Blocks+parseSynopsisSection = do+ sec <- currentSection <$> getState+ guard $ sec == ShSynopsis+ parseSynopsis sectionEnd++parseMiniSynopsis :: PandocMonad m => MdocParser m Blocks+parseMiniSynopsis = do+ macro "nr"+ literal "nS"+ literal "1"+ eol+ parseSynopsis (sectionEnd <|> end)+ where+ end = do+ macro "nr"+ literal "nS"+ literal "0"+ eol+ return ()++parseSynopsis :: PandocMonad m => MdocParser m () -> MdocParser m Blocks+parseSynopsis end = do+ bs <- manyTill synopsisBlock end+ return $ mconcat bs+ where+ synopsisGroup p = B.lineBlock <$> many1 p <* optional (emptyMacro "Pp")+ synopsisBlock = synopsisGroup parseInvocation+ <|> synopsisGroup (parseCd <* optional eol)+ <|> synopsisGroup (parseIn <* optional eol)+ <|> synopsisGroup (parseFd <* optional eol)+ <|> synopsisGroup (parseVt <* optional eol)+ <|> try parseSignature+ <|> parseWeirdSignature+ <|> parseRegularBlock+ parseInvocation = do+ nm <- parseNm+ optional eol+ rest <- many synopsisInline+ spacify (nm:rest)+ parseSignature = do+ ft <- parseFt <* optional eol+ sig <- (parseFn <|> parseFo) <* optional eol+ return $ B.lineBlock [ft, sig <> ";"]+ -- e.g. OpenBSD MB_CUR_MAX(3), mild abuse of notation for Ft+ parseWeirdSignature = do+ ft <- parseFt <* optional eol+ rest <- many synopsisInline+ line <- spacify (ft:rest)+ return $ B.lineBlock [line]+ synopsisInline = parseSmToggle <|> parseStrs <|> (controlLine >>= spacify) <?> "synopsis inlines"+ safeEol = do+ amNested <- inLineEnclosure <$> getState+ unless amNested $ optional eol+ controlLine = many1 ((choice otherInlineMacros <|> litsAndDelimsToInlines) <* safeEol)++parseSeeAlsoSection :: PandocMonad m => MdocParser m Blocks+parseSeeAlsoSection = do+ sec <- currentSection <$> getState+ guard $ sec == ShSeeAlso+ blocks <- many1Till parseSeeAlsoBlock sectionEnd+ return $ mconcat blocks+ where+ parseSeeAlsoBlock = parseRegularBlock <|> (B.para <$> parseRs)++-- roff(7) says "In text lines, whitespace is preserved within a line." I+-- considered following this rule but it really cuts against the grain of what+-- Pandoc writers want to work with, for no clear benefit. This isn't wholly+-- inconsistent with mandoc, because it makes no effort to render multiple+-- consecutive spaces from the source document in HTML. Hence I call B.text+-- instead of B.str+parseStr :: PandocMonad m => MdocParser m Inlines+parseStr = do+ (Str txt _) <- str+ return $ B.text txt++-- It's unclear whether consecutive text lines ought to be affected by the+-- spacing mode. mdoc(7) claims that:+--+-- > By default, spacing is on. When switched off, no white space is+-- > inserted between macro arguments and between the output generated from+-- > adjacent macros, but text lines still get normal spacing between words+-- > **and sentences.**+--+-- (emphasis added)+-- This implied to me that while spacing is off, consecutive text lines+-- would have spacing between them as normal. In fact, in mandoc's+-- implementation, they do not:+--+-- text+-- .Sm off+-- text.+-- text+-- .Sm on+-- text+--+-- renders as+--+-- text text.text text+--+-- (The "." is in there since the allusion in the documentation to+-- sentences made me wonder if that made a difference; it doesn't.)+--+-- I've chosen to adopt my interpretation of the documented behavior, rather+-- than mandoc's implementation. Multiple consecutive strs within a block get+-- spaces between them and then packed up together, and text lines are not+-- affected by the spacing mode.+--+-- Reported at https://inbox.vuxu.org/mandoc-discuss/369KFE6SHMXSE.3PS4387AYEFB5@silby.fyi/T/+parseStrs :: PandocMonad m => MdocParser m Inlines+parseStrs = do+ txt <- many1 parseStr+ return $ mconcat $ intersperse B.space txt++parseDelim :: PandocMonad m => DelimSide -> MdocParser m Inlines+parseDelim pos = do+ (Delim _ txt _) <- delim pos+ return $ B.str txt++litsToText :: PandocMonad m => MdocParser m [T.Text]+litsToText = do+ ls <- many1 lit+ return $ map toString ls++litsToInlines :: PandocMonad m => MdocParser m Inlines+litsToInlines = do+ ls <- many1 lit+ let strs = map (B.str . toString) ls+ spacify strs++litsAndDelimsToInlines :: PandocMonad m => MdocParser m Inlines+litsAndDelimsToInlines = do+ (o, ls, c) <- delimitedArgs $ many lit+ guard $ not (null o && null ls && null c)+ strs <- spacify $ map (B.str . toString) ls+ return $ o <> strs <> c++openingDelimiters :: PandocMonad m => MdocParser m Inlines+openingDelimiters = do+ openDelim <- mconcat <$> many (parseDelim Open)+ omids <- pipes+ addSpace <- spacingMode <$> getState+ let omid | null omids = mempty+ | addSpace = omids <> B.space+ | otherwise = omids+ return $ openDelim <> omid++pipes :: PandocMonad m => MdocParser m Inlines+pipes = many (parseDelim Middle) >>= spacify++closingDelimiters :: PandocMonad m => MdocParser m Inlines+closingDelimiters = do+ cmids <- pipes+ addSpace <- spacingMode <$> getState+ let cmid | null cmids = mempty+ | addSpace = B.space <> cmids+ | otherwise = cmids+ closeDelim <- mconcat <$> many (parseDelim Close)+ return $ cmid <> closeDelim++delimitedArgs :: PandocMonad m => MdocParser m x -> MdocParser m (Inlines, x, Inlines)+delimitedArgs p = do+ openDelim <- openingDelimiters+ inlines <- p+ closeDelim <- closingDelimiters+ return (openDelim, inlines, closeDelim)++simpleInline :: PandocMonad m => T.Text -> (Inlines -> Inlines) -> MdocParser m Inlines+simpleInline nm xform = do+ macro nm+ segs <- manyTill segment inlineContextEnd+ spacify segs+ where+ segment = do+ (openDelim, inlines, closeDelim) <- delimitedArgs $ option mempty litsToInlines+ return $ openDelim <> xform inlines <> closeDelim++codeLikeInline' :: PandocMonad m => T.Text -> T.Text -> MdocParser m Inlines+codeLikeInline' nm cl = simpleInline nm (eliminateEmpty (B.codeWith (cls cl) . stringify))++codeLikeInline :: PandocMonad m => T.Text -> MdocParser m Inlines+codeLikeInline nm = codeLikeInline' nm nm++spanLikeInline :: PandocMonad m => T.Text -> MdocParser m Inlines+spanLikeInline nm = simpleInline nm (eliminateEmpty (B.spanWith (cls nm)))++-- One-line enclosures need a little bit of state so that we don't parse+-- the closing delimiters that follow nested one-line or multiline+-- enclosures; the closing delimiters are meant to go after the close of+-- the outermost enclosure. Hence we respect and set inLineEnclosure.+lineEnclosure :: PandocMonad m => T.Text -> (Inlines -> Inlines) -> MdocParser m Inlines+lineEnclosure nm xform = do+ macro nm+ amNested <- inLineEnclosure <$> getState+ modifyState $ \s -> s{inLineEnclosure = True}+ first <- openingDelimiters+ further <-+ (manyTill+ (parseInlineMacro+ <|> (try (litsAndDelimsToInlines <* notFollowedBy eol))+ <|> litsToInlines+ <|> openingDelimiters)+ lineEnclosureContextEnd)+ further' <- spacify further+ finally <- if amNested then mempty else closingDelimiters <* optional eol+ modifyState $ \s -> s{inLineEnclosure = amNested}+ return $ first <> xform further' <> finally+ where+ lineEnclosureContextEnd =+ try $+ void (lookAhead (macro "Ta"))+ <|> lookAhead (many (macro "Ns" <|> delim Close) *> eol)+++-- The Ns, Ap, and Sm macros affect the automatic insertion of spaces between+-- macro arguments that occurs by default. We parse these macros to RawInlines+-- that we then eliminate in foldNoSpaces. If any of these macros end up+-- in the final AST returned by readMdoc, it's a bug.++noSpace :: Inlines+noSpace = B.rawInline "mdoc" "Ns"++apMacro :: Inlines+apMacro = B.rawInline "mdoc" "Ap"++smOff :: Inlines+smOff = B.rawInline "mdoc" "Sm off"++smOn :: Inlines+smOn = B.rawInline "mdoc" "Sm on"++-- Accumulator for eliminating of Ns, Ap, and Sm macros from a list of 'Inlines'+data SpacifyState = SpacifyState+ { accum :: [Inlines], -- already-folded 'Inlines'+ prev :: Inlines, -- content we might be appending further content to+ ns :: Bool, -- True when we've read an Ns and are waiting to concatenate content to prev+ sm :: Bool -- True when spacing mode is on+ }++instance Default SpacifyState where+ def = SpacifyState [] mempty False True++-- Given a list of 'Inlines'es, concatenate consecutive elements that shouldn't+-- have a 'Space' inserted between them based on changes to the spacing mode,+-- Ap macros, and Ns macros.+foldNoSpaces :: [Inlines] -> [Inlines]+foldNoSpaces xs = (finalize . foldl go def) xs+ where+ go :: SpacifyState -> Inlines -> SpacifyState+ go s x+ | ns s && x == noSpace = s+ | x == apMacro = s{prev = prev s <> "'", ns = True}+ | x == noSpace = s{ns = True}+ | x == smOn = s{sm = True}+ | sm s && x == smOff = s{accum = accum s <> [prev s], prev = mempty, sm = False}+ | ns s = s{prev = prev s <> x, ns = False}+ | not (sm s) = s{prev = prev s <> x}+ | null (prev s) = s{prev = x}+ | otherwise = s{accum = accum s <> [prev s], prev = x}+ finalize s+ | null (prev s) = accum s+ | otherwise = accum s <> [prev s]++-- Add any necessary spaces between individual 'Inlines' in a list.+-- Respects the spacing mode status. This should more or less+-- always get applied to any list of 'Inlines' before doing anything+-- else with it.+spacify :: PandocMonad m => [Inlines] -> MdocParser m Inlines+spacify x = do+ mode <- spacingMode <$> getState+ return (go mode x)+ where+ go True = mconcat . intersperse B.space . foldNoSpaces+ go False = mconcat . foldNoSpaces++-- Compatibility note: mandoc permits, and doesn't warn on, "vertical" macros+-- (Pp, Bl/El, Bd/Ed) inside of "horizontal" block partial-explicit quotations+-- like Do/Dc. However there are no OpenBSD manual pages that employ such markup+-- and it doesn't look right when rendered. We don't attempt to consume anything+-- but pandoc inlines inside of these multiline enclosures.+multilineEnclosure :: PandocMonad m => T.Text -> T.Text -> (Inlines -> Inlines) -> MdocParser m Inlines+multilineEnclosure op cl xform = do+ macro op+ amNested <- inLineEnclosure <$> getState+ -- we're now "protected" from any outer enclosure or .It+ modifyState $ \s -> s{inLineEnclosure = False}+ openDelim <- mconcat <$> many (parseDelim Open)+ optional eol+ contents <- parseInlines+ (macro cl <?> show cl)+ closeDelim <-+ if amNested+ then mempty+ else mconcat <$> many (parseDelim Close) <* optional eol+ modifyState $ \s -> s{inLineEnclosure = amNested}+ return $ openDelim <> xform contents <> closeDelim++parseEo :: PandocMonad m => MdocParser m Inlines+parseEo = do+ macro "Eo"+ odel <- del+ optional eol+ inner <- parseInlines+ macro "Ec"+ cdel <- del+ optional eol+ return $ odel <> inner <> cdel+ where+ del = B.str . toString <$> (arg <|> delim Open <|> delim Middle <|> delim Close)++eliminateEmpty :: (Inlines -> Inlines) -> Inlines -> Inlines+eliminateEmpty x y = if null y then mempty else x y++cls :: T.Text -> B.Attr+cls x = (mempty, [x], mempty)++-- mandoc -T html formats Sy with a <b> tag, since it's not really+-- semantically <strong>, but Strong is our best option in Pandoc+parseSy :: PandocMonad m => MdocParser m Inlines+parseSy = simpleInline "Sy" (eliminateEmpty B.strong)++parseEm :: PandocMonad m => MdocParser m Inlines+parseEm = simpleInline "Em" (eliminateEmpty B.emph)++parseNo :: PandocMonad m => MdocParser m Inlines+parseNo = simpleInline "No" (eliminateEmpty id)++-- Deprecated, mandoc doesn't style this at all+parseTn :: PandocMonad m => MdocParser m Inlines+parseTn = simpleInline "Tn" (eliminateEmpty id)++parseLi :: PandocMonad m => MdocParser m Inlines+parseLi = codeLikeInline "Li"++parseEv :: PandocMonad m => MdocParser m Inlines+parseEv = codeLikeInline "Ev"++parseDv :: PandocMonad m => MdocParser m Inlines+parseDv = codeLikeInline "Dv"++parseAd :: PandocMonad m => MdocParser m Inlines+parseAd = spanLikeInline "Ad"++parseVa :: PandocMonad m => MdocParser m Inlines+parseVa = codeLikeInline' "Va" "variable"++parseVt :: PandocMonad m => MdocParser m Inlines+parseVt = codeLikeInline' "Vt" "variable"++parseAn :: PandocMonad m => MdocParser m Inlines+parseAn = try anSplit <|> anRegular+ where+ anSplit = do+ macro "An"+ mode <- literal "-split" $> True <|> literal "-nosplit" $> False+ modifyState $ \s -> s{authorNameSplit = mode}+ return mempty+ anRegular = do+ an <- spanLikeInline "An"+ spl <- authorNameSplit <$> getState+ return $ (if spl then B.linebreak else mempty) <> an++parseMs :: PandocMonad m => MdocParser m Inlines+parseMs = spanLikeInline "Ms"++-- TODO implement internal reference links+parseSx :: PandocMonad m => MdocParser m Inlines+parseSx = spanLikeInline "Sx"++-- I'm not sure why mandoc inserts a ~ when Mt is missing an argument,+-- but it does, and it doesn't issue a warning, so that quirk is+-- retained.+parseMt :: PandocMonad m => MdocParser m Inlines+parseMt = simpleInline "Mt" mailto+ where mailto x | null x = B.link ("mailto:~") "" "~"+ | otherwise = B.link ("mailto:" <> stringify x) "" x++parsePa :: PandocMonad m => MdocParser m Inlines+parsePa = simpleInline "Pa" p+ where p x | null x = B.spanWith (cls "Pa") "~"+ | otherwise = B.spanWith (cls "Pa") x++-- There's a number of unique-looking cases for Fl parsing so I am just+-- handling them very explicitly instead of trying to generalize anything+-- enough to handle it. Could conceivably be better.+parseFl :: PandocMonad m => MdocParser m Inlines+parseFl = do+ macro "Fl"+ start <- option mempty (emptyWithDelim <|> flfl <|> emptyWithMacro <|> emptyEmpty)+ segs <- manyTill segment inlineContextEnd+ spacify ([start] <> segs)+ where+ emptyWithDelim = do+ lookAhead $ many1 (delim Middle <|> delim Close)+ ds <- closingDelimiters+ return $ fl "-" <> ds+ flfl = do+ lookAhead (macro "Fl")+ x:xs <- B.toList <$> parseFl+ let xx = B.codeWith (cls "Fl") $ "-" <> stringify x+ return $ xx <> B.fromList xs+ emptyWithMacro = do+ lookAhead anyMacro+ rest <- parseInline+ return $ fl "-" <> rest+ emptyEmpty = lookAhead eol $> fl "-"+ segment = do+ (openDelim, inlines, closeDelim) <- delimitedArgs $ option mempty litsToText+ inner <- (spacify . (map fl) . flags) inlines+ return $ openDelim <> inner <> closeDelim+ fl = B.codeWith (cls "Fl")+ flags [] = ["-"]+ flags xs = map ("-" <>) xs++parseAr :: PandocMonad m => MdocParser m Inlines+parseAr = simpleInline "Ar" ar+ where ar x | null x = B.codeWith (cls "variable") "file ..."+ | otherwise = B.codeWith (cls "variable") $ stringify x+++parseCm :: PandocMonad m => MdocParser m Inlines+parseCm = codeLikeInline "Cm"++parseIc :: PandocMonad m => MdocParser m Inlines+parseIc = codeLikeInline "Ic"++parseEr :: PandocMonad m => MdocParser m Inlines+parseEr = codeLikeInline "Er"++parseCd :: PandocMonad m => MdocParser m Inlines+parseCd = codeLikeInline "Cd"++parseQl :: PandocMonad m => MdocParser m Inlines+parseQl = lineEnclosure "Ql" $ B.codeWith (cls "Ql") . stringify++parseDq :: PandocMonad m => MdocParser m Inlines+parseDq = lineEnclosure "Dq" B.doubleQuoted++parseDo :: PandocMonad m => MdocParser m Inlines+parseDo = multilineEnclosure "Do" "Dc" B.doubleQuoted++parseSq :: PandocMonad m => MdocParser m Inlines+parseSq = lineEnclosure "Sq" B.singleQuoted++parseSo :: PandocMonad m => MdocParser m Inlines+parseSo = multilineEnclosure "So" "Sc" B.singleQuoted++parseQq :: PandocMonad m => MdocParser m Inlines+parseQq = lineEnclosure "Qq" $ \x -> "\"" <> x <> "\""++parseQo :: PandocMonad m => MdocParser m Inlines+parseQo = multilineEnclosure "Qo" "Qc" $ \x -> "\"" <> x <> "\""++parsePq :: PandocMonad m => MdocParser m Inlines+parsePq = lineEnclosure "Pq" $ \x -> "(" <> x <> ")"++parsePo :: PandocMonad m => MdocParser m Inlines+parsePo = multilineEnclosure "Po" "Pc" $ \x -> "(" <> x <> ")"++parseBq :: PandocMonad m => MdocParser m Inlines+parseBq = lineEnclosure "Bq" $ \x -> "[" <> x <> "]"++parseBo :: PandocMonad m => MdocParser m Inlines+parseBo = multilineEnclosure "Bo" "Bc" $ \x -> "[" <> x <> "]"++-- For our purposes this probably behaves identically to Bq+-- in most circumstances but I might need to do something+-- special with it in SYNOPSIS+parseOp :: PandocMonad m => MdocParser m Inlines+parseOp = lineEnclosure "Op" $ \x -> "[" <> x <> "]"++parseOo :: PandocMonad m => MdocParser m Inlines+parseOo = multilineEnclosure "Oo" "Oc" $ \x -> "[" <> x <> "]"++parseBrq :: PandocMonad m => MdocParser m Inlines+parseBrq = lineEnclosure "Brq" $ \x -> "{" <> x <> "}"++parseBro :: PandocMonad m => MdocParser m Inlines+parseBro = multilineEnclosure "Bro" "Brc" $ \x -> "{" <> x <> "}"++parseAq :: PandocMonad m => MdocParser m Inlines+parseAq = lineEnclosure "Aq" $ \x -> "⟨" <> x <> "⟩"++parseAo :: PandocMonad m => MdocParser m Inlines+parseAo = multilineEnclosure "Ao" "Ac" $ \x -> "⟨" <> x <> "⟩"++parseDl :: PandocMonad m => MdocParser m Blocks+parseDl = do+ inner <- lineEnclosure "Dl" id+ return $ B.codeBlock (stringify inner)++parseD1 :: PandocMonad m => MdocParser m Blocks+parseD1 = do+ inner <- lineEnclosure "D1" id+ return $ B.divWith (cls "display") $ B.plain inner++parseNm :: PandocMonad m => MdocParser m Inlines+parseNm = do+ macro "Nm"+ mnm <- (progName <$> getState)+ (op, rg, cl) <- delimitedArgs $ option mempty litsToInlines+ return $ case (mnm, rg) of+ (Just nm, x) | null x ->+ op <> ok nm <> cl+ (_, x) ->+ op <> (ok . stringify) x <> cl+ where+ ok = B.codeWith (cls "Nm")+++parseXr :: PandocMonad m => MdocParser m Inlines+parseXr = do+ macro "Xr"+ (open, (name, section), close) <- delimitedArgs f+ let ref = name <> "(" <> section <> ")"+ return $ open <> B.spanWith (cls "Xr") (B.str ref) <> close+ where+ f = do+ n <- lit <?> "Xr manual name"+ s <- lit <?> "Xr manual section"+ return (toString n, toString s)++parseIn :: PandocMonad m => MdocParser m Inlines+parseIn = do+ macro "In"+ openClose <- closingDelimiters+ openOpen <- openingDelimiters+ header <- toString <$> lit+ close <- closingDelimiters+ return $ open openClose openOpen <> B.codeWith (cls "In") ("<" <> header <> ">") <> close+ where+ open a b+ | null a = b+ | null b = a+ | otherwise = a <> B.space <> b++parseFd :: PandocMonad m => MdocParser m Inlines+parseFd = codeLikeInline "Fd"++parseFt :: PandocMonad m => MdocParser m Inlines+parseFt = codeLikeInline' "Ft" "variable"++-- The output here is comparable to mandoc's HTML output, which doesn't tag+-- the commas/parentheses. Is this questionable from a pandoc POV?+formatFunction :: T.Text -> [Inlines] -> Inlines+formatFunction nm args = B.codeWith (cls "Fn") nm <> "(" <> args' <> ")"+ where+ args' = mconcat $ intersperse (", ") args++parseFn :: PandocMonad m => MdocParser m Inlines+parseFn = do+ macro "Fn"+ (op, (nm, args), cl) <- delimitedArgs f+ return $ op <> formatFunction nm (fmap (B.codeWith (cls "variable")) args) <> cl+ where+ f = do+ nm <- toString <$> lit+ args <- option [] litsToText+ return (nm, args)++parseFa :: PandocMonad m => MdocParser m Inlines+parseFa = codeLikeInline' "Fa" "variable"++parseFo :: PandocMonad m => MdocParser m Inlines+parseFo = do+ macro "Fo"+ nm <- toString <$> lit+ eol+ args <- many (parseFa <* eol)+ macro "Fc"+ return $ formatFunction nm args++parseLk :: PandocMonad m => MdocParser m Inlines+parseLk = do+ macro "Lk"+ openClose <- closingDelimiters+ openOpen <- openingDelimiters+ url <- toString <$> lit+ inner <- many segment >>= spacify+ close <- closingDelimiters+ let label | null inner = B.str url+ | otherwise = inner+ return $ open openClose openOpen <> B.link url "" label <> close+ where+ open a b+ | null a = b+ | null b = a+ | otherwise = a <> B.space <> b+ end = msatisfy newControlContext+ segment = do+ a <- openingDelimiters+ m <- option mempty litsToInlines+ z <-+ try (closingDelimiters <* notFollowedBy end)+ <|> option mempty pipes+ guard $ not $ all null [a, m, z]+ return $ a <> m <> z++-- This is a raw roff request but it appears sometimes in mdoc+-- manuals and is easy enough to handle+parsebr :: PandocMonad m => MdocParser m Inlines+parsebr = emptyMacro "br" >> return B.linebreak++parseNs :: PandocMonad m => MdocParser m Inlines+parseNs = macro "Ns" >> return noSpace++-- Per mdoc(7), Pf prefix macro [argument ...] is equivalent to+-- No \&prefix Ns macro [argument ...] and because of the way+-- spacify works, the easiest thing to do is just push an Ns onto+-- the input+parsePf :: PandocMonad m => MdocParser m Inlines+parsePf = do+ macro "Pf"+ t <- toString <$> anyToken+ rest <- getInput+ pos <- getPosition+ setInput $ (Macro "Ns" pos):rest+ return $ B.str t++parseAp :: PandocMonad m => MdocParser m Inlines+parseAp = macro "Ap" >> return apMacro++parseEx :: PandocMonad m => MdocParser m Inlines+parseEx = do+ macro "Ex"+ literal "-std"+ args <- fmap toString <$> many lit+ pn <- progName <$> getState+ eol+ return $ "The"+ <> B.space+ <> utils pn args+ <> B.space+ <> "0 on success, and >0 if an error occurs."+ where+ nm = B.codeWith (cls "Nm")+ sing = "utility exits"+ plur = "utilities exit"+ utils (Just x) [] = nm x <> B.space <> sing+ utils _ [x] = nm x <> B.space <> sing+ utils _ [x,y] = nm x <> B.space <> "and" <> B.space <> nm y <> B.space <> plur+ utils pn xs =+ case (pn, unsnoc xs) of+ (Nothing, Nothing) -> sing+ (_, Just (hd, end)) -> mconcat ((intersperse (", ") . fmap nm) hd) <> ", and " <> nm end <> B.space <> plur+ (Just p, Nothing) -> nm p <> B.space <> sing+++parseRv :: (PandocMonad m) => MdocParser m Inlines+parseRv = do+ macro "Rv"+ literal "-std"+ args <- fmap toString <$> many lit+ pn <- progName <$> getState+ eol+ return $ go pn args+ where+ nm a = B.codeWith (cls "Fn") a <> "()"+ nothing = "Upon successful completion, the value 0 is returned;"+ sing = "function returns"+ plur = "functions return"+ success = "the value 0 if successful;"+ errno =+ "otherwise the value -1 is returned and the global variable"+ <> B.codeWith (cls "variable") "errno"+ <> "is set to indicate the error."+ message conj =+ "The"+ <> B.space+ <> conj+ <> B.space+ <> success+ <> B.space+ <> errno+ go (Just x) [] = message (nm x <> B.space <> sing)+ go _ [x] = message (nm x <> B.space <> sing)+ go _ [x, y] = message (nm x <> B.space <> "and" <> B.space <> nm y <> B.space <> plur)+ go pn xs =+ case (pn, unsnoc xs) of+ (Nothing, Nothing) -> nothing <> B.space <> errno+ (_, Just (hd, end)) -> message (mconcat ((intersperse (", ") . fmap nm) hd) <> ", and " <> nm end <> B.space <> plur)+ (Just p, Nothing) -> message (nm p <> B.space <> sing)++parseSt :: PandocMonad m => MdocParser m Inlines+parseSt = do+ macro "St"+ (Lit std pos) <- lit+ case standard std of+ Nothing -> do+ logMessage $ SkippedContent ("unrecognized argument to St: " <> std) pos+ return mempty+ Just t -> return $ B.text t++-- TODO incorporate well-known library description and linker options+-- from mandoc lib.in expected in FreeBSD LIBRARY section, at minimum.+parseLb :: PandocMonad m => MdocParser m Inlines+parseLb = do+ macro "Lb"+ library <- toString <$> lit+ return $ "library" <> B.space <> B.doubleQuoted (B.str library)++unixVersion :: PandocMonad m => T.Text -> T.Text -> MdocParser m Inlines+unixVersion m s = do+ macro m+ (o, v, c) <- delimitedArgs (option mempty (toString <$> lit))+ return $ o <> B.str s <> f v <> c+ where+ f v | T.null v = mempty+ | otherwise = B.space <> B.str v++parseAt :: PandocMonad m => MdocParser m Inlines+parseAt = do+ macro "At"+ (o, v, c) <- delimitedArgs (optionMaybe (toString <$> lit))+ let v' = maybe "AT&T UNIX" attVer v+ return $ o <> B.text v' <> c+ where+ isVersion x = x `elem` ["1", "2", "3", "4", "5", "6", "7"]+ isRelease x = x `elem` ["1", "2", "3", "4"]+ attVer (T.stripPrefix "v" -> Just ver)+ | isVersion ver = "Version " <> ver <> " AT&T UNIX"+ attVer "32v" = "Version 7 AT&T UNIX/32V"+ attVer "III" = "AT&T System III UNIX"+ attVer (T.stripPrefix "V." -> Just release)+ | isRelease release = "AT&T System V Release " <> release <> " UNIX"+ attVer "V" = "AT&T System V UNIX"+ attVer x = "AT&T UNIX " <> x++parseBsx :: PandocMonad m => MdocParser m Inlines+parseBsx = unixVersion "Bsx" "BSD/OS"++parseBx :: PandocMonad m => MdocParser m Inlines+parseBx = do+ macro "Bx"+ (o, v, c) <- delimitedArgs zeroToTwoLits+ return $ o <> bsd v <> c+ where+ zeroToTwoLits = do+ toks <- try (count 2 lit) <|> count 1 lit <|> count 0 lit+ return $ toString <$> toks+ bsd [] = B.str "BSD"+ bsd [x] = B.str $ x <> "BSD"+ bsd (x:y:_) = B.str (x <> "BSD" <> "-" <> T.toTitle y)++parseDx :: PandocMonad m => MdocParser m Inlines+parseDx = unixVersion "Dx" "DragonFly"++parseFx :: PandocMonad m => MdocParser m Inlines+parseFx = unixVersion "Fx" "FreeBSD"++-- This dance to capitalize a letter at the end of a NetBSD+-- version matches what mandoc does to the argument of .Nx.+-- See mandoc mdoc_validate.c r1.350+-- Curiously, there's little easy-to-find evidence of what+-- these lettered releases actually are, other than+-- references in man page history sections to 0.9A etc.+parseNx :: PandocMonad m => MdocParser m Inlines+parseNx = do+ macro "Nx"+ (o, v, c) <- delimitedArgs (option mempty (toString <$> lit))+ return $ o <> "NetBSD" <> f v <> c+ where+ f v | T.null v = mempty+ | otherwise = B.space <> B.str (fromRight v $ readWith earlyNetBSDVersion () v)+ earlyNetBSDVersion = do+ major <- oneOf "01"+ dot <- char '.'+ minor <- digit+ ltr <- satisfy isAsciiLower+ return $ T.pack [major, dot, minor, toUpper ltr]++parseOx :: PandocMonad m => MdocParser m Inlines+parseOx = unixVersion "Ox" "OpenBSD"++parseUx :: PandocMonad m => MdocParser m Inlines+parseUx = macro "Ux" >> return (B.str "UNIX")++parseInlineMacro :: PandocMonad m => MdocParser m Inlines+parseInlineMacro = choice (synopsisTopicMacros <> otherInlineMacros) <?> "inline macro"++-- These macros always start a new line in SYNOPSIS+synopsisTopicMacros :: PandocMonad m => [MdocParser m Inlines]+synopsisTopicMacros =+ [parseNm, parseCd, parseFd, parseFn, parseFo, parseIn, parseVt, parseFt]++otherInlineMacros :: PandocMonad m => [MdocParser m Inlines]+otherInlineMacros =+ [ parseSy,+ parseEm,+ parseLk,+ parseLi,+ parseEv,+ parseDv,+ parseMt,+ parsePa,+ parseFl,+ parseCm,+ parseIc,+ parseEr,+ parseAd,+ parseVa,+ parseAn,+ parseMs,+ parseSx,+ parseAr,+ parseFa,+ parseNo,+ parseTn,+ parseXr,+ parseQl,+ parseOp,+ parseSq,+ parseDq,+ parseQq,+ parsePq,+ parseBq,+ parseBrq,+ parseAq,+ parseEo,+ parseSo,+ parseDo,+ parseQo,+ parsePo,+ parseBo,+ parseBro,+ parseAo,+ parseOo,+ parseBf,+ parseRsInline,+ parseEx,+ parseRv,+ parseSt,+ parseLb,+ parseAt,+ parseBsx,+ parseBx,+ parseDx,+ parseFx,+ parseNx,+ parseOx,+ parseUx,+ parsebr,+ parseAp,+ parsePf,+ parseNs,+ skipUnsupportedInlines+ ]++parseInline :: PandocMonad m => MdocParser m Inlines+parseInline = parseStrs <|> (controlLine >>= spacify) <?> "text lines or inline macros"+ where+ safeEol = do+ amNested <- inLineEnclosure <$> getState+ unless amNested $ optional eol+ controlLine = many1 ((parseInlineMacro <|> litsAndDelimsToInlines) <* safeEol)++parseInlines :: PandocMonad m => MdocParser m Inlines+parseInlines = many1 (parseSmToggle <|> parseInline) >>= spacify++-- Lp is a deprecated synonym for Pp+parsePara :: PandocMonad m => MdocParser m Blocks+parsePara = B.para . B.trimInlines <$> parseInlines <*+ optional (emptyMacro "Pp" <|> emptyMacro "Lp")++-- Indented display blocks are visually similar to block quotes+-- but rarely carry those semantics. I'm just putting things in+-- divs. Centered is discouraged and rarely seen.+parseDisplay :: PandocMonad m => MdocParser m Blocks+parseDisplay = do+ literal "-filled" <|> literal "-ragged" <|> literal "-centered"+ many $ (literal "-offset" *> lit) <|> (literal "-compact")+ eol+ B.divWith (cls "display") . mconcat <$> many parseRegularBlock++-- This is something of a best-effort interpretation of the -unfilled+-- display block type. The main difference with mandoc is probably+-- that newlines inside of multiline enclosures won't be preserved.+parseUnfilled :: PandocMonad m => MdocParser m Blocks+parseUnfilled = do+ literal "-unfilled"+ many $ (literal "-offset" *> lit) <|> (literal "-compact")+ eol+ lns <- many $ Just <$> parseStrPreserveSpace+ <|> Nothing <$ parseSmToggle+ <|> Just <$> parseInline+ <|> Just "" <$ emptyMacro "Pp"+ return $ B.lineBlock (catMaybes lns)+ where+ parseStrPreserveSpace = (B.str . toString) <$> str <|> (blank *> mempty)++parseCodeBlock :: PandocMonad m => MdocParser m Blocks+parseCodeBlock = do+ literal "-literal"+ many $ (literal "-offset" *> lit) <|> (literal "-compact")+ eol+ lns <- many $ Just . toString <$> (str <|> blank)+ <|> Nothing <$ parseSmToggle+ <|> Just . stringify <$> parseInline+ <|> Just "" <$ emptyMacro "Pp"+ return $ B.codeBlock (T.unlines (catMaybes lns))++parseBd :: PandocMonad m => MdocParser m Blocks+parseBd = do+ macro "Bd"+ blk <- parseCodeBlock <|> parseDisplay <|> parseUnfilled+ emptyMacro "Ed"+ return blk++-- This is a bit of a best effort version. Hypothetically multiple blocks+-- could occur inside a Bf and this should be a stateful thing but I don't+-- know if that's observed in the wild.+parseBf :: PandocMonad m => MdocParser m Inlines+parseBf = do+ macro "Bf"+ xform <- B.strong <$ (literal "Sy" <|> literal "-symbolic")+ <|> B.emph <$ (literal "Em" <|> literal "-emphasis")+ <|> code <$ (literal "Li" <|> literal "-literal")+ eol+ ins <- parseInlines+ emptyMacro "Ef"+ return $ xform ins+ where+ code = B.code . stringify++skipListArgument :: (PandocMonad m) => MdocParser m ()+skipListArgument =+ void $ choice+ [ literal "-width" *> lit,+ literal "-offset" *> lit,+ literal "-compact"+ ]++parseItemList :: PandocMonad m => MdocParser m Blocks+parseItemList = do+ f <- (choice (map literal ["-bullet", "-dash", "-hyphen", "-item"]) $> B.bulletList)+ <|> literal "-enum" $> B.orderedList+ many skipListArgument+ eol+ items <- many bulletItem+ return $ f items+ where+ bulletItem = do+ emptyMacro "It"+ mconcat <$> many parseRegularBlock++-- Despite some ambiguous documentation to the contrary the Xo/Xc macros+-- only seem genuinely useful in an .It head, and it's not clear what if+-- anything it means to use them somewhere else in a contemporary mdoc manual.+-- See https://inbox.vuxu.org/mandoc-discuss/2UKLZW0DL8BSM.2IIO9W4HSUSRR@silby.fyi/T/+-- for more blathering.+parseDefinitionList :: PandocMonad m => MdocParser m Blocks+parseDefinitionList = do+ headParser <- (choice . map literal) ["-hang", "-inset", "-ohang", "-tag"] $> parsedHead <|> literal "-diag" $> diagHead+ many skipListArgument+ eol+ items <- many (parseSmToggle *> mempty <|> dlItem headParser)+ return $ B.definitionList items+ where+ parsedHead = try xoListHead <|> eolListHead+ eolListHead = do+ modifyState $ \s -> s{inLineEnclosure = True}+ inner <- parseInlines+ eol+ modifyState $ \s -> s{inLineEnclosure = False}+ return inner+ diagHead = argsToInlines+ dlItem hed = do+ -- Some manuals have an evidently useless .Pp before .It+ -- e.g. OpenBSD ld(1), just deal with it.+ many ((void . emptyMacro) "Pp" <|> skipUnsupportedMacro "Tg")+ macro "It"+ dt <- hed+ dd <- mconcat <$> many parseRegularBlock+ return (dt, [dd])+ xoListHead = do+ before <- option mempty parseInline+ macro "Xo"+ optional eol+ after <- many1Till parseInlines (emptyMacro "Xc")+ spacify (before:after)++-- TODO support implicit rows:+-- If the first line of the body of a -column list is not an It macro line,+-- It contexts spanning one input line each are implied until an It macro+-- line is encountered+-- and support literal tabs+parseColumnList :: PandocMonad m => MdocParser m Blocks+parseColumnList = do+ literal "-column"+ many skipListArgument+ many $ arg <|> delim Open <|> delim Middle <|> delim Close+ eol+ rows <- many listRow+ return $ B.simpleTable [] rows+ where+ listRow = do+ optional (emptyMacro "Pp")+ macro "It"+ fmap B.plain <$> sepBy (parseInlines <|> pure mempty) (macro "Ta" <* optional eol)++parseBl :: PandocMonad m => MdocParser m Blocks+parseBl = do+ macro "Bl"+ blk <- parseItemList <|> parseDefinitionList <|> parseColumnList+ emptyMacro "El"+ return blk++referenceField :: PandocMonad m => T.Text -> ReferenceField -> MdocParser m ()+referenceField m field = do+ macro m+ reference <- currentReference <$> getState+ contents <- stringify <$> litsAndDelimsToInlines+ eol+ modifyState $ \s -> s{currentReference = M.insertWith (++) field [contents] reference}+ return ()++parsePercentA :: PandocMonad m => MdocParser m ()+parsePercentA = referenceField "%A" Author++parsePercentB :: PandocMonad m => MdocParser m ()+parsePercentB = referenceField "%B" BookTitle++parsePercentC :: PandocMonad m => MdocParser m ()+parsePercentC = referenceField "%C" PubLocation++parsePercentD :: PandocMonad m => MdocParser m ()+parsePercentD = referenceField "%D" PubDate++parsePercentI :: PandocMonad m => MdocParser m ()+parsePercentI = referenceField "%I" Publisher++parsePercentJ :: PandocMonad m => MdocParser m ()+parsePercentJ = referenceField "%J" Journal++parsePercentN :: PandocMonad m => MdocParser m ()+parsePercentN = referenceField "%N" IssueNumber++parsePercentO :: PandocMonad m => MdocParser m ()+parsePercentO = referenceField "%O" Optional++parsePercentP :: PandocMonad m => MdocParser m ()+parsePercentP = referenceField "%P" Pages++parsePercentQ :: PandocMonad m => MdocParser m ()+parsePercentQ = referenceField "%Q" Institution++parsePercentR :: PandocMonad m => MdocParser m ()+parsePercentR = referenceField "%R" TechReportTitle++parsePercentT :: PandocMonad m => MdocParser m ()+parsePercentT = referenceField "%T" ArticleTitle++parsePercentU :: PandocMonad m => MdocParser m ()+parsePercentU = referenceField "%U" Url++parsePercentV :: PandocMonad m => MdocParser m ()+parsePercentV = referenceField "%V" VolumeNumber++parseReferenceField :: PandocMonad m => MdocParser m ()+parseReferenceField =+ choice [+ parsePercentA,+ parsePercentB,+ parsePercentC,+ parsePercentD,+ parsePercentI,+ parsePercentJ,+ parsePercentN,+ parsePercentO,+ parsePercentP,+ parsePercentQ,+ parsePercentR,+ parsePercentT,+ parsePercentU,+ parsePercentV+ ]++parseRsInline :: PandocMonad m => MdocParser m Inlines+parseRsInline = do+ sec <- currentSection <$> getState+ guard $ sec /= ShSeeAlso+ parseRs++parseRs :: PandocMonad m => MdocParser m Inlines+parseRs = do+ emptyMacro "Rs"+ modifyState $ \s -> s{currentReference = M.empty}+ many1 parseReferenceField+ emptyMacro "Re"+ ref <- currentReference <$> getState+ -- TODO formatting fields correctly+ return $ B.text $ (M.foldl f mempty ref) <> "."+ where join v = T.concat (intersperse ", " v)+ f a v | T.null a = join v+ | otherwise = a <> ", " <> join v++-- mandoc's roff(7) says "Blank text lines, which may include whitespace,+-- are only permitted within literal contexts." mandoc -T lint warns about+-- blank lines and inserts a roff `sp` request, which is handled+-- differently depending on the output format. My read is that mandoc+-- considers the handling of a blank line in non-literal context in mdoc(7)+-- to be undefined. The Mdoc reader thus ignores blank input lines outside+-- of -literal and -unfilled displays.+skipBlanks :: PandocMonad m => MdocParser m Blocks+skipBlanks = many1 blank *> mempty++-- By default, mdoc is in "spacing mode", where horizontal space is added+-- between macro contents. The Sm macro turns it off and on. When we encounter+-- the Sm macro, we both modify the parser state and we emit a sentinel value+-- that spacify/foldNoSpaces uses to handle cases where spacing mode gets+-- turned off and on within a stretch of inlines.+parseSmToggle :: PandocMonad m => MdocParser m Inlines+parseSmToggle = do+ macro "Sm"+ cur <- spacingMode <$> getState+ mode <- optionMaybe (literal "on" $> True <|> literal "off" $> False)+ eol+ let newMode = update mode cur+ modifyState $ \s -> s{spacingMode = newMode}+ return $ if newMode then smOn else smOff+ where+ update = \case+ Nothing -> not+ Just x -> const x++skipUnsupportedMacro :: PandocMonad m => T.Text -> MdocParser m ()+skipUnsupportedMacro nm = do+ (Macro _ pos) <- macro nm+ manyTill anyToken eol+ logMessage $ SkippedContent ("unsupported macro: " <> nm) pos+++skipUnsupportedInlines :: PandocMonad m => MdocParser m Inlines+skipUnsupportedInlines = choice+ [ skipUnsupportedMacro "Tg",+ skipUnsupportedMacro "Bk",+ skipUnsupportedMacro "Ek"+ ] *> mempty++skipUnknownMacro :: PandocMonad m => MdocParser m Blocks+skipUnknownMacro = do+ pos <- getPosition+ m <- anyMacro+ manyTill anyToken eol+ logMessage $ SkippedContent ("unsupported macro: " <> toString m) pos+ return mempty+++parseRegularBlock :: PandocMonad m => MdocParser m Blocks+parseRegularBlock =+ choice+ [ parseDl+ , parseD1+ , parsePara+ , emptyMacro "Pp" *> mempty+ , parseBd+ , parseBl+ , skipBlanks+ ]++parseBlock :: (PandocMonad m) => MdocParser m Blocks+parseBlock =+ choice+ [ parseHeader+ , parseNameSection+ , parseSynopsisSection+ , parseSeeAlsoSection+ , parseMiniSynopsis+ , parseRegularBlock+ , skipUnknownMacro+ ]
@@ -0,0 +1,225 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}+{- |+ Module : Text.Pandoc.Readers.Mdoc.Lex+ Copyright : Copyright (C) 2024 Evan Silberman+ License : GNU GPL, version 2 or above++ Maintainer : Evan Silberman <evan@jklol.net>+ Stability : WIP+ Portability : portable++Tokenizer for mdoc+-}+module Text.Pandoc.Readers.Mdoc.Lex+ ( MdocToken(..)+ , MdocTokens(..)+ , DelimSide(..)+ , lexMdoc+ , toString+ )+where++import Control.Monad (void, guard, when)+import Control.Monad.Except (throwError)+import Text.Pandoc.Class.PandocMonad (PandocMonad(..))+import Data.Char (isAlphaNum)+import Data.Maybe (isJust)+import qualified Data.Text as T+import Text.Pandoc.Options+import Text.Pandoc.Parsing+import Text.Pandoc.Readers.Roff.Escape+import Text.Pandoc.Readers.Mdoc.Macros+import qualified Data.Sequence as Seq++-- As a higher level language with a wealth of semantic macros, mdoc+-- discourages authors from falling back to low-level roff features like font+-- selection, custom macros, defined strings, etc. Pandoc's mdoc reader is+-- accordingly implemented as a high-level interpreter of mdoc's semantic macros+-- and almost no raw roff requests are supported.+--+-- tbl(7) and eqn(7) macros are rare but not completely unseen in mdoc manuals.+-- they are not yet implemented. most use of tbl macros in mdoc could probably+-- be replaced with .Bl -column++data DelimSide = Open | Middle | Close deriving (Show, Eq)++-- | Tokens for Mdoc documents+data MdocToken = Str T.Text SourcePos -- ^ The contents of a text line+ | Macro T.Text SourcePos -- ^ A macro to be processed+ | Lit T.Text SourcePos -- ^ Literal text on a control line+ | Blank SourcePos -- ^ A blank line+ | Delim DelimSide T.Text SourcePos -- ^ A delimiter character+ | Eol -- ^ The end of a control line+ deriving Show++toString :: MdocToken -> T.Text+toString (Str x _) = x+toString (Macro x _) = x+toString (Lit x _) = x+toString (Delim _ x _) = x+toString Blank{} = mempty+toString Eol = mempty++newtype MdocTokens = MdocTokens { unMdocTokens :: Seq.Seq MdocToken }+ deriving (Show, Semigroup, Monoid)++singleTok :: MdocToken -> MdocTokens+singleTok t = MdocTokens (Seq.singleton t)++type Lexer m = ParsecT Sources () m++instance RoffLikeLexer MdocTokens where+ -- This is a bit confusing. We're lexing to MdocTokens, but for escaping+ -- purposes we just want Texts.+ type Token MdocTokens = T.Text+ -- We don't need a state+ type State MdocTokens = ()+ -- We don't support predefined string expansion+ expandString = return ()+ escString = return mempty+ -- what token type the unescaped text gets wrapped in is decided by other+ -- parts of the lexer.+ emit = id+ -- All escapes are resolved in the lexer and we never need to emit anything,+ -- vs. the roff lexer which has to push the backlashes to the output while+ -- in copy mode.+ backslash = (mempty <* char '\\') <|> (mempty <* string "\\E")+ -- We don't support macro definition and we don't output anything for \A+ checkDefined = const mempty+ -- We don't support copy mode and \E is treated as backslash+ escE = return mempty+ -- We don't support low-level font selection+ escFont = escIgnore 'f' [escapeArg, countChar 1 (satisfy (/='\n'))]++eofline :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s u m MdocToken+eofline = do+ void newline <|> eof+ return Eol++lexComment :: PandocMonad m => Lexer m MdocTokens+lexComment = do+ try $ string ".\\\""+ skipMany $ noneOf "\n"+ eofline+ return mempty++argText :: PandocMonad m => Lexer m T.Text+argText = do+ beg <- escape <|> regularText+ end <- mconcat <$> many (escape <|> regularText <|> quoteChar)+ return $ beg <> end++spaceTabChar :: PandocMonad m => Lexer m T.Text+spaceTabChar = T.singleton <$> spaceChar++quotedArg :: PandocMonad m => Lexer m T.Text+quotedArg = do+ quoteChar+ t <- mconcat <$> many (try innerQuote <|> escape <|> regularText <|> spaceTabChar)+ quoteChar+ notFollowedBy quoteChar+ return t+ where+ innerQuote = do+ string "\"\""+ return "\""++anyText :: PandocMonad m => Lexer m T.Text+anyText = escape <|> regularText <|> quoteChar <|> spaceTabChar++regularText :: PandocMonad m => Lexer m T.Text+regularText = many1Char $ noneOf "\n\r\t \\\""++quoteChar :: PandocMonad m => Lexer m T.Text+quoteChar = T.singleton <$> char '"'++mdocToken :: PandocMonad m => Lexer m MdocTokens+mdocToken = lexComment <|> lexControlLine <|> lexTextLine++lexMacroName :: PandocMonad m => Lexer m T.Text+lexMacroName = many1Char (satisfy isMacroChar)+ where+ isMacroChar '%' = True+ isMacroChar x = isAlphaNum x++lexMacro :: PandocMonad m => Lexer m MdocToken+lexMacro = do+ pos <- getPosition+ name <- lexMacroName+ eof <|> void (lookAhead (spaceChar <|> newline))+ skipSpaces+ return $ Macro name pos++lexCallableMacro :: PandocMonad m => Lexer m MdocToken+lexCallableMacro = do+ pos <- getPosition+ q <- optionMaybe quoteChar+ name <- lexMacroName+ when (isJust q) (void quoteChar)+ eof <|> void (lookAhead (spaceChar <|> newline))+ skipSpaces+ guard $ isCallableMacro name+ return $ Macro name pos++lexDelim :: (PandocMonad m) => Lexer m MdocToken+lexDelim = do+ pos <- getPosition+ q <- optionMaybe quoteChar+ t <-+ Delim Open <$> oneOfStrings ["(", "["]+ <|> Delim Close <$> oneOfStrings [".", ",", ":", ";", ")", "]", "?", "!"]+ <|> Delim Middle <$> textStr "|"+ when (isJust q) (void quoteChar)+ eof <|> void (lookAhead (spaceChar <|> newline))+ skipSpaces+ return $ t pos++lexLit :: PandocMonad m => Lexer m MdocToken+lexLit = do+ pos <- getPosition+ t <- argText <|> quotedArg+ skipSpaces+ return $ Lit t pos++lexTextLine :: PandocMonad m => Lexer m MdocTokens+lexTextLine = do+ pos <- getPosition+ guard $ sourceColumn pos == 1+ t <- mconcat <$> many anyText+ eofline+ if T.null $ T.strip t+ then return $ singleTok $ Blank pos+ else return $ singleTok $ Str t pos++lexControlLine :: PandocMonad m => Lexer m MdocTokens+lexControlLine = do+ pos <- getPosition+ guard $ sourceColumn pos == 1+ char '.'+ eofline *> mempty <|> do+ m@(Macro name _) <- lexMacro+ -- .Ns macros at the start of a line are ignored. We'd have to look behind+ -- to keep track of the "start of the line" in the parser, so we'll drop+ -- those macros in lexing.+ let start | name == "Ns" = []+ | otherwise = [m]+ let parsed = isParsedMacro name+ (wds, e) <- manyUntil (l parsed) eofline+ return $ MdocTokens $ Seq.fromList $ start <> wds <> [e]+ where+ l True = try lexDelim <|> try lexCallableMacro <|> lexLit+ l False = try lexDelim <|> lexLit++-- | Tokenize a string as a sequence of mdoc tokens.+lexMdoc :: PandocMonad m => SourcePos -> T.Text -> m MdocTokens+lexMdoc pos txt = do+ eithertokens <- readWithM (do setPosition pos+ mconcat <$> manyTill mdocToken eof) def txt+ case eithertokens of+ Left e -> throwError e+ Right tokenz -> return tokenz
@@ -0,0 +1,183 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.Mdoc.Macros+ Copyright : © 2024 Evan Silberman+ License : GNU GPL, version 2 or above++ Maintainer : Evan Silberman <evan@jklol.net>+ Stability : WIP+ Portability : portable++-}+module Text.Pandoc.Readers.Mdoc.Macros (isParsedMacro, isCallableMacro) where++import Data.Set (member, fromList, Set)+import Data.Text++isParsedMacro :: Text -> Bool+isParsedMacro a = member a parsedMacros++isCallableMacro :: Text -> Bool+isCallableMacro a = member a callableMacros++parsedMacros :: Set Text+parsedMacros = fromList [+ "Ac",+ "Ad",+ "An",+ "Ao",+ "Ap",+ "Aq",+ "Ar",+ "At",+ "Bc",+ "Bo",+ "Bq",+ "Brc",+ "Bro",+ "Brq",+ "Bsx",+ "Bx",+ "Cd",+ "Cm",+ "D1",+ "Dc",+ "Dl",+ "Do",+ "Dq",+ "Dv",+ "Dx",+ "Ec",+ "Em",+ "En",+ "Eo",+ "Er",+ "Es",+ "Ev",+ "Fa",+ "Fc",+ "Fl",+ "Fn",+ "Fr",+ "Ft",+ "Fx",+ "Ic",+ "In",+ "It",+ "Li",+ "Lk",+ "Ms",+ "Mt",+ "Nm",+ "No",+ "Ns",+ "Nx",+ "Oc",+ "Oo",+ "Op",+ "Ot",+ "Ox",+ "Pa",+ "Pc",+ "Pf",+ "Po",+ "Pq",+ "Qc",+ "Ql",+ "Qo",+ "Qq",+ "Sc",+ "Sh",+ "So",+ "Sq",+ "Ss",+ "St",+ "Sx",+ "Sy",+ "Ta",+ "Tn",+ "Ux",+ "Va",+ "Vt",+ "Xc",+ "Xo",+ "Xr"]++callableMacros :: Set Text+callableMacros = fromList [+ "Ac",+ "Ad",+ "An",+ "Ao",+ "Ap",+ "Aq",+ "Ar",+ "At",+ "Bc",+ "Bo",+ "Bq",+ "Brc",+ "Bro",+ "Brq",+ "Bsx",+ "Bx",+ "Cd",+ "Cm",+ "Dc",+ "Do",+ "Dq",+ "Dv",+ "Dx",+ "Ec",+ "Em",+ "En",+ "Eo",+ "Er",+ "Es",+ "Ev",+ "Fa",+ "Fc",+ "Fl",+ "Fn",+ "Fo",+ "Fr",+ "Ft",+ "Fx",+ "Ic",+ "In",+ "Li",+ "Lk",+ "Ms",+ "Mt",+ "Nm",+ "No",+ "Ns",+ "Nx",+ "Oc",+ "Oo",+ "Op",+ "Ot",+ "Ox",+ "Pa",+ "Pc",+ "Pf",+ "Po",+ "Pq",+ "Qc",+ "Ql",+ "Qo",+ "Qq",+ "Sc",+ "So",+ "Sq",+ "St",+ "Sx",+ "Sy",+ "Ta",+ "Tn",+ "Ux",+ "Va",+ "Vt",+ "Xc",+ "Xo",+ "Xr"]
@@ -0,0 +1,70 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.Mdoc.Standards+ Copyright : © 2024 Evan Silberman+ License : GNU GPL, version 2 or above++ Maintainer : Evan Silberman <evan@jklol.net>+ Stability : WIP+ Portability : portable++-}+module Text.Pandoc.Readers.Mdoc.Standards (standard) where++import Data.Map (fromList, Map)+import qualified Data.Map as M+import Data.Text++standard :: Text -> Maybe Text+standard = flip M.lookup standards++standards :: Map Text Text+standards = fromList [+ ("-p1003.1-88", "IEEE Std 1003.1-1988 (“POSIX.1”)"),+ ("-p1003.1-90", "IEEE Std 1003.1-1990 (“POSIX.1”)"),+ ("-p1003.1-96", "ISO/IEC 9945-1:1996 (“POSIX.1”)"),+ ("-p1003.1-2001", "IEEE Std 1003.1-2001 (“POSIX.1”)"),+ ("-p1003.1-2004", "IEEE Std 1003.1-2004 (“POSIX.1”)"),+ ("-p1003.1-2008", "IEEE Std 1003.1-2008 (“POSIX.1”)"),+ ("-p1003.1-2024", "IEEE Std 1003.1-2024 (“POSIX.1”)"),+ ("-p1003.1", "IEEE Std 1003.1 (“POSIX.1”)"),+ ("-p1003.1b", "IEEE Std 1003.1b (“POSIX.1b”)"),+ ("-p1003.1b-93", "IEEE Std 1003.1b-1993 (“POSIX.1b”)"),+ ("-p1003.1c-95", "IEEE Std 1003.1c-1995 (“POSIX.1c”)"),+ ("-p1003.1g-2000", "IEEE Std 1003.1g-2000 (“POSIX.1g”)"),+ ("-p1003.1i-95", "IEEE Std 1003.1i-1995 (“POSIX.1i”)"),+ ("-p1003.2", "IEEE Std 1003.2 (“POSIX.2”)"),+ ("-p1003.2-92", "IEEE Std 1003.2-1992 (“POSIX.2”)"),+ ("-p1003.2a-92", "IEEE Std 1003.2a-1992 (“POSIX.2”)"),+ ("-isoC", "ISO/IEC 9899:1990 (“ISO C90”)"),+ ("-isoC-90", "ISO/IEC 9899:1990 (“ISO C90”)"),+ ("-isoC-amd1", "ISO/IEC 9899/AMD1:1995 (“ISO C90, Amendment 1”)"),+ ("-isoC-tcor1", "ISO/IEC 9899/TCOR1:1994 (“ISO C90, Technical Corrigendum 1”)"),+ ("-isoC-tcor2", "ISO/IEC 9899/TCOR2:1995 (“ISO C90, Technical Corrigendum 2”)"),+ ("-isoC-99", "ISO/IEC 9899:1999 (“ISO C99”)"),+ ("-isoC-2011", "ISO/IEC 9899:2011 (“ISO C11”)"),+ ("-isoC-2023", "ISO/IEC 9899:2024 (“ISO C23”)"),+ ("-iso9945-1-90", "ISO/IEC 9945-1:1990 (“POSIX.1”)"),+ ("-iso9945-1-96", "ISO/IEC 9945-1:1996 (“POSIX.1”)"),+ ("-iso9945-2-93", "ISO/IEC 9945-2:1993 (“POSIX.2”)"),+ ("-ansiC", "ANSI X3.159-1989 (“ANSI C89”)"),+ ("-ansiC-89", "ANSI X3.159-1989 (“ANSI C89”)"),+ ("-ieee754", "IEEE Std 754-1985"),+ ("-iso8802-3", "ISO 8802-3: 1989"),+ ("-iso8601", "ISO 8601"),+ ("-ieee1275-94", "IEEE Std 1275-1994 (“Open Firmware”)"),+ ("-xpg3", "X/Open Portability Guide Issue 3 (“XPG3”)"),+ ("-xpg4", "X/Open Portability Guide Issue 4 (“XPG4”)"),+ ("-xpg4.2", "X/Open Portability Guide Issue 4, Version 2 (“XPG4.2”)"),+ ("-xbd5", "X/Open Base Definitions Issue 5 (“XBD5”)"),+ ("-xcu5", "X/Open Commands and Utilities Issue 5 (“XCU5”)"),+ ("-xsh5", "X/Open System Interfaces and Headers Issue 5 (“XSH5”)"),+ ("-xns5", "X/Open Networking Services Issue 5 (“XNS5”)"),+ ("-xns5.2", "X/Open Networking Services Issue 5.2 (“XNS5.2”)"),+ ("-xcurses4.2", "X/Open Curses Issue 4, Version 2 (“XCURSES4.2”)"),+ ("-susv1", "Version 1 of the Single UNIX Specification (“SUSv1”)"),+ ("-susv2", "Version 2 of the Single UNIX Specification (“SUSv2”)"),+ ("-susv3", "Version 3 of the Single UNIX Specification (“SUSv3”)"),+ ("-susv4", "Version 4 of the Single UNIX Specification (“SUSv4”)"),+ ("-svid4", "System V Interface Definition, Fourth Edition (“SVID4”)")+ ]
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.MediaWiki- Copyright : Copyright (C) 2012-2022 John MacFarlane+ Copyright : Copyright (C) 2012-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -13,13 +13,13 @@ {- TODO: _ correctly handle tables within tables-_ parse templates?+_ parse templates(?) and built-in magic words -} module Text.Pandoc.Readers.MediaWiki ( readMediaWiki ) where import Control.Monad import Control.Monad.Except (throwError)-import Data.Char (isDigit, isSpace)+import Data.Char (isDigit, isLetter, isSpace) import qualified Data.Foldable as F import Data.List (intersperse) import Data.Maybe (fromMaybe, maybeToList)@@ -28,16 +28,17 @@ import Data.Text (Text) import qualified Data.Text as T import Text.HTML.TagSoup-import Text.Pandoc.Builder (Blocks, Inlines, trimInlines) import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Builder (Blocks, Inlines, trimInlines)+import Text.Pandoc.Char (isCJK) import Text.Pandoc.Class.PandocMonad (PandocMonad (..)) import Text.Pandoc.Definition import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Parsing hiding (nested, tableCaption)-import Text.Pandoc.Readers.HTML (htmlTag, isBlockTag, isCommentTag)-import Text.Pandoc.Shared (safeRead, stringify, stripTrailingNewlines,- trim, splitTextBy, tshow, formatCode)+import Text.Pandoc.Parsing hiding (tableCaption)+import Text.Pandoc.Readers.HTML (htmlTag, isCommentTag, toAttr)+import Text.Pandoc.Shared (formatCode, safeRead, splitTextBy, stringify,+ stripTrailingNewlines, trim, tshow) import Text.Pandoc.XML (fromEntities) -- | Read mediawiki from an input string and return a Pandoc document.@@ -54,6 +55,8 @@ , mwIdentifierList = Set.empty , mwLogMessages = [] , mwInTT = False+ , mwAllowNewlines = True+ , mwMeta = nullMeta } sources case parsed of@@ -67,9 +70,11 @@ , mwIdentifierList :: Set.Set Text , mwLogMessages :: [LogMessage] , mwInTT :: Bool+ , mwAllowNewlines :: Bool+ , mwMeta :: Meta } -type MWParser m = ParserT Sources MWState m+type MWParser m = ParsecT Sources MWState m instance HasReaderOptions MWState where extractReaderOptions = mwOptions@@ -86,19 +91,8 @@ -- auxiliary functions -- --- This is used to prevent exponential blowups for things like:--- ''a'''a''a'''a''a'''a''a'''a-nested :: PandocMonad m => MWParser m a -> MWParser m a-nested p = do- nestlevel <- mwMaxNestingLevel `fmap` getState- guard $ nestlevel > 0- updateState $ \st -> st{ mwMaxNestingLevel = mwMaxNestingLevel st - 1 }- res <- p- updateState $ \st -> st{ mwMaxNestingLevel = nestlevel }- return res- specialChars :: [Char]-specialChars = "'[]<=&*{}|\":\\"+specialChars = "'[]<=&*{}|\":\\_" spaceChars :: [Char] spaceChars = " \n\t"@@ -110,21 +104,86 @@ newBlockTags = ["haskell","syntaxhighlight","source","gallery","references"] isBlockTag' :: Tag Text -> Bool-isBlockTag' tag@(TagOpen t _) = (isBlockTag tag || t `elem` newBlockTags) &&- t `notElem` eitherBlockOrInline-isBlockTag' (TagClose "ref") = True -- needed so 'special' doesn't parse it-isBlockTag' tag@(TagClose t) = (isBlockTag tag || t `elem` newBlockTags) &&- t `notElem` eitherBlockOrInline-isBlockTag' tag = isBlockTag tag+isBlockTag' (TagOpen t _) = isBlockTagName t+isBlockTag' (TagClose t) = isBlockTagName t+isBlockTag' _ = False +isBlockTagName :: Text -> Bool+isBlockTagName t =+ t `elem` [ "blockquote"+ , "caption"+ , "col"+ , "colgroup"+ , "dd"+ , "div"+ , "dl"+ , "dt"+ , "h1"+ , "h2"+ , "h3"+ , "h4"+ , "h5"+ , "h6"+ , "hr"+ , "li"+ , "meta"+ , "ol"+ , "p"+ , "pre"+ , "rp"+ , "table"+ , "td"+ , "th"+ , "time"+ , "tr"+ , "ul"+ , "center"+ ] || t `elem` newBlockTags+ isInlineTag' :: Tag Text -> Bool isInlineTag' (TagComment _) = True-isInlineTag' (TagClose "ref") = False -- see below inlineTag-isInlineTag' t = not (isBlockTag' t)+isInlineTag' (TagOpen t _) = isInlineTagName t+isInlineTag' (TagClose t) = isInlineTagName t+isInlineTag' _ = False -eitherBlockOrInline :: [Text]-eitherBlockOrInline = ["applet", "button", "del", "iframe", "ins",- "map", "area", "object"]+isInlineTagName :: Text -> Bool+isInlineTagName t =+ t `elem` [ "abbr"+ , "b"+ , "bdi"+ , "bdo"+ , "big"+ , "br"+ , "cite"+ , "code"+ , "data"+ , "del"+ , "dfn"+ , "em"+ , "i"+ , "ins"+ , "kbd"+ , "link"+ , "mark"+ , "q"+ , "rt"+ , "ruby"+ , "s"+ , "samp"+ , "small"+ , "span"+ , "strong"+ , "sub"+ , "sup"+ , "u"+ , "var"+ , "wbr"+ , "font"+ , "rb"+ , "rtc"+ , "strike"+ , "tt"+ ] htmlComment :: PandocMonad m => MWParser m () htmlComment = () <$ htmlTag isCommentTag@@ -168,11 +227,12 @@ spaces eof categoryLinks <- reverse . mwCategoryLinks <$> getState+ meta <- mwMeta <$> getState let categories = if null categoryLinks then mempty else B.para $ mconcat $ intersperse B.space categoryLinks reportLogMessages- return $ B.doc $ bs <> categories+ return $ Pandoc meta (B.toList bs <> B.toList categories) -- -- block parsers@@ -219,25 +279,25 @@ Just w -> fromMaybe 1.0 $ parseWidth w Nothing -> 1.0 caption <- option mempty tableCaption+ optional newline optional rowsep hasheader <- option False $ True <$ lookAhead (skipSpaces *> char '!')- (cellspecs',hdr) <- unzip <$> tableRow- let widths = map ((tableWidth *) . snd) cellspecs'+ (cellwidths,hdr) <- unzip <$> tableRow+ let widths = map (tableWidth *) (concat cellwidths) let restwidth = tableWidth - sum widths let zerocols = length $ filter (==0.0) widths let defaultwidth = if zerocols == 0 || zerocols == length widths then ColWidthDefault else ColWidth $ restwidth / fromIntegral zerocols let widths' = map (\w -> if w > 0 then ColWidth w else defaultwidth) widths- let cellspecs = zip (map fst cellspecs') widths'+ let cellspecs = zip (calculateAlignments hdr) widths' rows' <- many $ try $ rowsep *> (map snd <$> tableRow) optional blanklines tableEnd- let cols = length hdr let (headers,rows) = if hasheader then (hdr, rows')- else (replicate cols mempty, hdr:rows')- let toRow = Row nullAttr . map B.simpleCell+ else ([], hdr:rows')+ let toRow = Row nullAttr toHeaderRow l = [toRow l | not (null l)] return $ B.table (B.simpleCaption $ B.plain caption) cellspecs@@ -245,15 +305,25 @@ [TableBody nullAttr 0 [] $ map toRow rows] (TableFoot nullAttr []) +calculateAlignments :: [Cell] -> [Alignment]+calculateAlignments = concatMap cellAligns+ where+ cellAligns :: Cell -> [Alignment]+ cellAligns (Cell _ align _ (ColSpan colspan) _) = replicate colspan align+ parseAttrs :: PandocMonad m => MWParser m [(Text,Text)] parseAttrs = many1 parseAttr parseAttr :: PandocMonad m => MWParser m (Text, Text) parseAttr = try $ do skipMany spaceChar- k <- many1Char letter+ kFirst <- letter+ kRest <- many (alphaNum <|> oneOf "_-:.")+ let k = T.pack (kFirst : kRest)+ skipMany spaceChar char '='- v <- (char '"' >> many1TillChar (satisfy (/='\n')) (char '"'))+ skipMany spaceChar+ v <- (char '"' >> manyTillChar (satisfy (/='\n')) (char '"')) <|> many1Char (satisfy $ \c -> not (isSpace c) && c /= '|') return (k,v) @@ -270,56 +340,60 @@ <* skipMany htmlComment <* blanklines -cellsep :: PandocMonad m => MWParser m ()+cellsep :: PandocMonad m => MWParser m [(Text,Text)] cellsep = try $ do col <- sourceColumn <$> getPosition- skipSpaces- let pipeSep = do- char '|'- notFollowedBy (oneOf "-}+")- if col == 1- then optional (char '|')- else void (char '|')- let exclSep = do- char '!'- if col == 1- then optional (char '!')- else void (char '!')- pipeSep <|> exclSep+ skipMany spaceChar+ c <- oneOf "|!"+ when (col > 1) $ void $ char c+ notFollowedBy (oneOf "-}")+ attribs <- option [] (parseAttrs <* skipMany spaceChar <* char '|')+ skipMany spaceChar+ pure attribs tableCaption :: PandocMonad m => MWParser m Inlines tableCaption = try $ do+ optional rowsep guardColumnOne skipSpaces sym "|+" optional (try $ parseAttrs *> skipSpaces *> char '|' *> blanklines) trimInlines . mconcat <$>- many (notFollowedBy (cellsep <|> rowsep) *> inline)+ many (notFollowedBy (void cellsep <|> rowsep) *> inline) -tableRow :: PandocMonad m => MWParser m [((Alignment, Double), Blocks)]+tableRow :: PandocMonad m => MWParser m [([Double], Cell)] tableRow = try $ skipMany htmlComment *> many tableCell -tableCell :: PandocMonad m => MWParser m ((Alignment, Double), Blocks)+-- multiple widths because cell might have colspan+tableCell :: PandocMonad m => MWParser m ([Double], Cell) tableCell = try $ do- cellsep- skipMany spaceChar- attrs <- option [] $ try $ parseAttrs <* skipSpaces <* char '|' <*- notFollowedBy (char '|')- skipMany spaceChar+ attribs <- cellsep pos' <- getPosition- ls <- T.concat <$> many (notFollowedBy (cellsep <|> rowsep <|> tableEnd) *>+ ls <- T.concat <$> many (notFollowedBy (void cellsep <|> rowsep <|> tableEnd) *> ((snd <$> withRaw table) <|> countChar 1 anyChar)) bs <- parseFromString (do setPosition pos' mconcat <$> many block) ls- let align = case lookup "align" attrs of+ let align = case lookup "align" attribs of Just "left" -> AlignLeft Just "right" -> AlignRight Just "center" -> AlignCenter _ -> AlignDefault- let width = case lookup "width" attrs of- Just xs -> fromMaybe 0.0 $ parseWidth xs- Nothing -> 0.0- return ((align, width), bs)+ let rowspan = RowSpan . fromMaybe 1 $+ safeRead =<< lookup "rowspan" attribs+ let colspan = ColSpan . fromMaybe 1 $+ safeRead =<< lookup "colspan" attribs+ let ColSpan rawcolspan = colspan+ let handledAttribs = ["align", "colspan", "rowspan"]+ attribs' = [ (k, v) | (k, v) <- attribs+ , k `notElem` handledAttribs+ ]+ let widths = case lookup "width" attribs of+ Just xs -> maybe (replicate rawcolspan 0.0)+ (\w -> replicate rawcolspan+ (w / fromIntegral rawcolspan))+ (parseWidth xs)+ Nothing -> replicate rawcolspan 0.0+ return (widths, B.cellWith (toAttr attribs') align rowspan colspan bs) parseWidth :: Text -> Maybe Double parseWidth s =@@ -449,9 +523,8 @@ guardColumnOne char ';' skipMany spaceChar- pos' <- getPosition- anyLine >>= parseFromString (do setPosition pos'- trimInlines . mconcat <$> many inline)+ trimInlines . mconcat <$> many (notFollowedBy (oneOf ":\r\n") *> inline) <*+ optional newline listStart :: PandocMonad m => Char -> MWParser m () listStart c = char c *> notFollowedBy listStartChar@@ -468,7 +541,7 @@ listItem :: PandocMonad m => Char -> MWParser m Blocks listItem c = try $ do- guardColumnOne+ guardColumnOne <|> guard (c == ':') -- def can start on same line as term extras <- many (try $ char c <* lookAhead listStartChar) if null extras then listItem' c@@ -495,8 +568,9 @@ -- }} -- * next list item -- which seems to be valid mediawiki.+-- Also multiline math: see #9293. listChunk :: PandocMonad m => MWParser m Text-listChunk = template <|> countChar 1 anyChar+listChunk = template <|> (snd <$> withRaw math) <|> countChar 1 anyChar listItem' :: PandocMonad m => Char -> MWParser m Blocks listItem' c = try $ do@@ -527,6 +601,7 @@ <|> doubleQuotes <|> strong <|> emph+ <|> behaviorSwitch <|> image <|> internalLink <|> externalLink@@ -565,7 +640,11 @@ inlineTag :: PandocMonad m => MWParser m Inlines inlineTag = do- (tag, _) <- lookAhead $ htmlTag isInlineTag'+ (tag, _) <- lookAhead $ htmlTag (\tag -> case tag of+ TagOpen "hask" _ -> True+ TagOpen "ref" _ -> True+ TagOpen "nowiki" _ -> True+ _ -> isInlineTag' tag) case tag of TagOpen "ref" _ -> B.note . singleParaToPlain <$> blocksInTags "ref" TagOpen "nowiki" _ -> try $ do@@ -580,6 +659,10 @@ TagOpen "del" _ -> B.strikeout <$> inlinesInTags "del" TagOpen "sub" _ -> B.subscript <$> inlinesInTags "sub" TagOpen "sup" _ -> B.superscript <$> inlinesInTags "sup"+ TagOpen "var" _ -> B.codeWith ("",["variable"],[]) <$> textInTags "var"+ TagOpen "samp" _ -> B.codeWith ("",["sample"],[]) <$> textInTags "samp"+ TagOpen "kbd" _ -> B.spanWith ("",["kbd"],[]) <$> inlinesInTags "kbd"+ TagOpen "mark" _ -> B.spanWith ("",["mark"],[]) <$> inlinesInTags "mark" TagOpen "code" _ -> encode <$> inlinesInTags "code" TagOpen "tt" _ -> do inTT <- mwInTT <$> getState@@ -591,8 +674,15 @@ _ -> B.rawInline "html" . snd <$> htmlTag (~== tag) special :: PandocMonad m => MWParser m Inlines-special = B.str <$> countChar 1 (notFollowedBy' (htmlTag isBlockTag') *>- oneOf specialChars)+special = B.str . T.singleton <$>+ (notFollowedBy' (htmlTag (\t -> isInlineTag' t ||+ isBlockTag' t ||+ case t of+ TagClose "ref" -> True+ TagClose "hask" -> True+ TagClose "nowiki" -> True+ _ -> False)+ ) *> oneOf specialChars) inlineHtml :: PandocMonad m => MWParser m Inlines inlineHtml = B.rawInline "html" . snd <$> htmlTag isInlineTag'@@ -602,23 +692,25 @@ <|> B.softbreak <$ endline endline :: PandocMonad m => MWParser m ()-endline = () <$ try (newline <*- notFollowedBy spaceChar <*- notFollowedBy newline <*- notFollowedBy' hrule <*- notFollowedBy tableStart <*- notFollowedBy' header <*- notFollowedBy anyListStart)+endline = do+ getState >>= guard . mwAllowNewlines+ () <$ try (newline <* notFollowedBy spaceChar <*+ notFollowedBy newline <*+ notFollowedBy' hrule <*+ notFollowedBy tableStart <*+ notFollowedBy' header <*+ notFollowedBy anyListStart) -imageIdentifiers :: PandocMonad m => [MWParser m ()]-imageIdentifiers = [sym (identifier <> ":") | identifier <- identifiers]- where identifiers = ["File", "Image", "Archivo", "Datei", "Fichier",- "Bild"]+imageIdentifier :: PandocMonad m => MWParser m ()+imageIdentifier = try $ do+ ident <- T.pack <$> many1Till letter (char ':')+ guard $ T.toLower ident `elem`+ ["file", "image", "archivo", "datei", "fichier", "bild"] image :: PandocMonad m => MWParser m Inlines image = try $ do sym "[["- choice imageIdentifiers+ imageIdentifier fname <- addUnderscores <$> many1Char (noneOf "|]") _ <- many imageOption dims <- try (char '|' *> sepBy (manyChar digit) (char 'x') <* string "px")@@ -645,7 +737,7 @@ <|> try (oneOfStrings ["link=","alt=","page=","class="] <* many (noneOf "|]")) addUnderscores :: Text -> Text-addUnderscores = T.intercalate "_" . splitTextBy sep+addUnderscores = T.intercalate "_" . splitTextBy sep . T.strip where sep c = isSpace c || c == '_' @@ -659,8 +751,9 @@ -- [[Help:Contents|] -> "Contents" <|> return (B.text $ T.drop 1 $ T.dropWhile (/=':') pagename) ) sym "]]"- linktrail <- B.text <$> manyChar letter- let link = B.link (addUnderscores pagename) "wikilink" (label <> linktrail)+ -- see #8525:+ linktrail <- B.text <$> manyChar (satisfy (\c -> isLetter c && not (isCJK c)))+ let link = B.linkWith (mempty, ["wikilink"], mempty) (addUnderscores pagename) (stringify label) (label <> linktrail) if "Category:" `T.isPrefixOf` pagename then do updateState $ \st -> st{ mwCategoryLinks = link : mwCategoryLinks st }@@ -690,12 +783,12 @@ trimInlines . mconcat <$> try (start >> many1Till inline end) emph :: PandocMonad m => MWParser m Inlines-emph = B.emph <$> nested (inlinesBetween start end)+emph = B.emph <$> inlinesBetween start end where start = sym "''" end = try $ notFollowedBy' (() <$ strong) >> sym "''" strong :: PandocMonad m => MWParser m Inlines-strong = B.strong <$> nested (inlinesBetween start end)+strong = B.strong <$> inlinesBetween start end where start = sym "'''" end = sym "'''" @@ -704,6 +797,40 @@ guardEnabled Ext_smart inTT <- mwInTT <$> getState guard (not inTT)- B.doubleQuoted <$> nested (inlinesBetween openDoubleQuote closeDoubleQuote)+ B.doubleQuoted <$> inlinesBetween openDoubleQuote closeDoubleQuote where openDoubleQuote = sym "\"" >> lookAhead nonspaceChar closeDoubleQuote = try $ sym "\""++behaviorSwitch :: PandocMonad m => MWParser m Inlines+behaviorSwitch = try $ do+ let reservedMagicWords = [ "NOTOC"+ , "FORCETOC"+ , "TOC"+ , "NOEDITSECTION"+ , "NEWSECTIONLINK"+ , "NONEWSECTIONLINK"+ , "NOGALLERY"+ , "HIDDENCAT"+ , "EXPECTUNUSEDCATEGORY"+ , "NOCONTENTCONVERT"+ , "NOCC"+ , "NOTITLECONVERT"+ , "NOTC"+ , "INDEX"+ , "NOINDEX"+ , "STATICREDIRECT"+ , "EXPECTUNUSEDTEMPLATE"+ -- From popular extensions+ , "NOGLOBAL"+ , "DISAMBIG"+ , "ARCHIVEDTALK"+ , "NOTALK"+ ]+ string "__"+ name <- many1 alphaNum+ string "__"+ case name `elem` reservedMagicWords of+ True -> do+ updateState $ \st -> st{ mwMeta = B.setMeta (T.toLower $ T.pack name) True (mwMeta st) }+ return mempty+ False -> return $ B.str $ "__" <> T.pack name <> "__"
@@ -2,7 +2,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Text.Pandoc.Readers.Metadata- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -21,80 +21,118 @@ import Control.Monad.Except (throwError) import qualified Data.ByteString as B import qualified Data.Map as M+import qualified Data.Vector as V import Data.Text (Text) import qualified Data.Text as T import qualified Data.Yaml as Yaml-import Data.Aeson (Value(..), Object, Result(..), fromJSON, (.:?), withObject)-import Data.Aeson.Types (parse)+import qualified Data.Yaml.Internal as Yaml+import qualified Text.Libyaml as Y+import Data.Aeson (Value(..), Object, Result(..), fromJSON, (.:?), withObject,+ FromJSON)+import Data.Aeson.Types (formatRelativePath, parse) import Text.Pandoc.Shared (tshow, blocksToInlines)-import Text.Pandoc.Class.PandocMonad (PandocMonad (..))-import Text.Pandoc.Definition hiding (Null)+import Text.Pandoc.Class (PandocMonad (..), report)+import Text.Pandoc.Definition import Text.Pandoc.Error+import Text.Pandoc.Logging (LogMessage(YamlWarning)) import Text.Pandoc.Parsing hiding (tableWith, parse)- import qualified Text.Pandoc.UTF8 as UTF8+import System.IO.Unsafe (unsafePerformIO) yamlBsToMeta :: (PandocMonad m, HasLastStrPosition st)- => ParserT Sources st m (Future st MetaValue)+ => ParsecT Sources st m (Future st MetaValue) -> B.ByteString- -> ParserT Sources st m (Future st Meta)+ -> ParsecT Sources st m (Future st Meta) yamlBsToMeta pMetaValue bstr = do- case Yaml.decodeAllEither' bstr of- Right (Object o:_) -> fmap Meta <$> yamlMap pMetaValue o- Right [] -> return . return $ mempty- Right [Null] -> return . return $ mempty- Right _ -> Prelude.fail "expected YAML object"+ pos <- getPosition+ case decodeAllWithWarnings bstr of+ Right (warnings, xs) -> do+ mapM_ (\(Yaml.DuplicateKey jpath) ->+ report (YamlWarning pos $ "Duplicate key: " <>+ T.pack (formatRelativePath jpath)))+ warnings+ case xs of+ (Object o : _) -> fmap Meta <$> yamlMap pMetaValue o+ [Null] -> return . return $ mempty+ [] -> return . return $ mempty+ _ -> Prelude.fail "expected YAML object" Left err' -> do- throwError $ PandocParseError- $ T.pack $ Yaml.prettyPrintParseException err'+ let msg = T.pack $ "Error parsing YAML metadata at " <>+ show pos <> ":\n" <>+ Yaml.prettyPrintParseException err'+ throwError $ PandocParseError $+ if "did not find expected key" `T.isInfixOf` msg+ then msg <>+ "\nConsider enclosing the entire field in 'single quotes'"+ else msg +decodeAllWithWarnings :: FromJSON a+ => B.ByteString+ -> (Either Yaml.ParseException ([Yaml.Warning], [a]))+decodeAllWithWarnings = either Left (\(ws,res)+ -> case res of+ Left s -> Left (Yaml.AesonException s)+ Right v -> Right (ws, v))+ . unsafePerformIO+ . Yaml.decodeAllHelper+ . Y.decode+ -- Returns filtered list of references. yamlBsToRefs :: (PandocMonad m, HasLastStrPosition st)- => ParserT Sources st m (Future st MetaValue)+ => ParsecT Sources st m (Future st MetaValue) -> (Text -> Bool) -- ^ Filter for id -> B.ByteString- -> ParserT Sources st m (Future st [MetaValue])+ -> ParsecT Sources st m (Future st [MetaValue]) yamlBsToRefs pMetaValue idpred bstr = case Yaml.decodeAllEither' bstr of Right (Object m : _) -> do- let isSelected (String t) = idpred t- isSelected _ = False- let hasSelectedId (Object o) =- case parse (withObject "ref" (.:? "id")) (Object o) of- Success (Just id') -> isSelected id'- _ -> False- hasSelectedId _ = False case parse (withObject "metadata" (.:? "references")) (Object m) of Success (Just refs) -> sequence <$> mapM (yamlToMetaValue pMetaValue) (filter hasSelectedId refs) _ -> return $ return []+ Right (Array v : _) -> do+ let refs = filter hasSelectedId $ V.toList v+ sequence <$> mapM (yamlToMetaValue pMetaValue) (filter hasSelectedId refs) Right _ -> return . return $ []- Left err' -> do- throwError $ PandocParseError- $ T.pack $ Yaml.prettyPrintParseException err'+ Left err' -> throwError $ PandocParseError+ $ T.pack $ Yaml.prettyPrintParseException err'+ where+ isSelected (String t) = idpred t+ isSelected _ = False+ hasSelectedId (Object o) =+ case parse (withObject "ref" (.:? "id")) (Object o) of+ Success (Just id') -> isSelected id'+ _ -> False+ hasSelectedId _ = False normalizeMetaValue :: (PandocMonad m, HasLastStrPosition st)- => ParserT Sources st m (Future st MetaValue)+ => ParsecT Sources st m (Future st MetaValue) -> Text- -> ParserT Sources st m (Future st MetaValue)+ -> ParsecT Sources st m (Future st MetaValue) normalizeMetaValue pMetaValue x = -- Note: a standard quoted or unquoted YAML value will -- not end in a newline, but a "block" set off with -- `|` or `>` will. if "\n" `T.isSuffixOf` (T.dropWhileEnd isSpaceChar x) -- see #6823- then parseFromString' pMetaValue (x <> "\n")- else parseFromString' asInlines x- where asInlines = fmap b2i <$> pMetaValue+ then parseFromString' pMetaValue (x <> "\n\n")+ else try (parseFromString' asInlines x') -- see #8358+ <|> -- see #8465+ parseFromString' asInlines (x' <> "\n\n")+ where x' = T.dropWhile isSpaceOrNlChar x+ asInlines = fmap b2i <$> pMetaValue b2i (MetaBlocks bs) = MetaInlines (blocksToInlines bs) b2i y = y isSpaceChar ' ' = True isSpaceChar '\t' = True isSpaceChar _ = False+ isSpaceOrNlChar '\r' = True+ isSpaceOrNlChar '\n' = True+ isSpaceOrNlChar c = isSpaceChar c yamlToMetaValue :: (PandocMonad m, HasLastStrPosition st)- => ParserT Sources st m (Future st MetaValue)+ => ParsecT Sources st m (Future st MetaValue) -> Value- -> ParserT Sources st m (Future st MetaValue)+ -> ParsecT Sources st m (Future st MetaValue) yamlToMetaValue pMetaValue v = case v of String t -> normalizeMetaValue pMetaValue t@@ -112,9 +150,9 @@ Object o -> fmap MetaMap <$> yamlMap pMetaValue o yamlMap :: (PandocMonad m, HasLastStrPosition st)- => ParserT Sources st m (Future st MetaValue)+ => ParsecT Sources st m (Future st MetaValue) -> Object- -> ParserT Sources st m (Future st (M.Map Text MetaValue))+ -> ParsecT Sources st m (Future st (M.Map Text MetaValue)) yamlMap pMetaValue o = do case fromJSON (Object o) of Error err' -> throwError $ PandocParseError $ T.pack err'@@ -131,9 +169,10 @@ -- | Parse a YAML metadata block using the supplied 'MetaValue' parser. yamlMetaBlock :: (HasLastStrPosition st, PandocMonad m)- => ParserT Sources st m (Future st MetaValue)- -> ParserT Sources st m (Future st Meta)+ => ParsecT Sources st m (Future st MetaValue)+ -> ParsecT Sources st m (Future st Meta) yamlMetaBlock parser = try $ do+ pos <- getPosition string "---" blankline notFollowedBy blankline -- if --- is followed by a blank it's an HRULE@@ -141,7 +180,11 @@ -- by including --- and ..., we allow yaml blocks with just comments: let rawYaml = T.unlines ("---" : (rawYamlLines ++ ["..."])) optional blanklines- yamlBsToMeta parser $ UTF8.fromText rawYaml+ oldPos <- getPosition+ setPosition pos+ res <- yamlBsToMeta parser $ UTF8.fromText rawYaml+ setPosition oldPos+ pure res -stopLine :: Monad m => ParserT Sources st m ()+stopLine :: Monad m => ParsecT Sources st m () stopLine = try $ (string "---" <|> string "...") >> blankline >> return ()
@@ -23,7 +23,7 @@ import Control.Monad.Except (throwError) import Data.Bifunctor import Data.Default-import Data.List (transpose, uncons)+import Data.List (transpose) import qualified Data.Map as M import qualified Data.Set as Set import Data.Maybe (fromMaybe, isNothing, maybeToList)@@ -33,7 +33,6 @@ import qualified Text.Pandoc.Builder as B import Text.Pandoc.Class.PandocMonad (PandocMonad (..)) import Text.Pandoc.Definition-import Text.Pandoc.Error (PandocError (PandocParsecError)) import Text.Pandoc.Logging import Text.Pandoc.Options import Text.Pandoc.Parsing@@ -49,7 +48,7 @@ res <- flip runReaderT def $ runParserT parseMuse def{ museOptions = opts } (initialSourceName sources) sources case res of- Left e -> throwError $ PandocParsecError sources e+ Left e -> throwError $ fromParsecError sources e Right d -> return d type F = Future MuseState@@ -83,7 +82,7 @@ , museInPara = False } -type MuseParser m = ParserT Sources MuseState (ReaderT MuseEnv m)+type MuseParser m = ParsecT Sources MuseState (ReaderT MuseEnv m) instance HasReaderOptions MuseState where extractReaderOptions = museOptions@@ -156,7 +155,7 @@ -- * Parsers -- | Parse end-of-line, which can be either a newline or end-of-file.-eol :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s st m ()+eol :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s st m () eol = void newline <|> eof getIndent :: PandocMonad m@@ -652,7 +651,10 @@ [TableBody nullAttr 0 [] $ map toRow $ rows ++ body ++ footers] (TableFoot nullAttr []) where attrs = (AlignDefault, ColWidthDefault) <$ transpose (headers ++ body ++ footers)- (headRow, rows) = fromMaybe ([], []) $ uncons headers+ (headRow, rows) =+ case headers of+ (r:rs) -> (r, rs)+ [] -> ([], []) toRow = Row nullAttr . map B.simpleCell toHeaderRow l = [toRow l | not (null l)]
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.Native- Copyright : Copyright (C) 2011-2022 John MacFarlane+ Copyright : Copyright (C) 2011-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -0,0 +1,114 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Reader.ODT+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++Entry point to the odt reader.+-}++module Text.Pandoc.Readers.ODT ( readODT ) where++import Codec.Archive.Zip+import Text.Pandoc.XML.Light+import Text.Pandoc.Walk++import Data.Char (isDigit)+import qualified Data.ByteString.Lazy as B++import System.FilePath++import Control.Monad.Except (throwError)++import qualified Data.Text as T++import Text.Pandoc.Class.PandocMonad (PandocMonad)+import qualified Text.Pandoc.Class.PandocMonad as P+import Text.Pandoc.Definition+import Text.Pandoc.Error+import Text.Pandoc.MediaBag+import Text.Pandoc.Options+import qualified Text.Pandoc.UTF8 as UTF8++import Text.Pandoc.Readers.ODT.ContentReader+import Text.Pandoc.Readers.ODT.StyleReader++import Text.Pandoc.Readers.ODT.Generic.Fallible+import Text.Pandoc.Readers.ODT.Generic.XMLConverter+import Text.Pandoc.Shared (filteredFilesFromArchive)++readODT :: PandocMonad m+ => ReaderOptions+ -> B.ByteString+ -> m Pandoc+readODT opts bytes = case readODT' opts bytes of+ Right (doc, mb) -> do+ P.setMediaBag mb+ return $ walk makeFigure doc+ Left e -> throwError e++-- the ODT parser uses old-style figures: an image with title beginning+-- "fig:" in a paragraph by itself. Convert these to new Figure elements.+makeFigure :: Block -> Block+makeFigure (Para [ Image (ident, classes, kvs) capt (src, tit) ])+ | "fig:" `T.isPrefixOf` tit+ = Figure (ident, [], []) (Caption Nothing [Plain capt'])+ [Plain [Image ("", classes, kvs) capt (src, "")]]+ where+ capt' = case capt of -- strip "Figure 1:" for consistency+ (Str _ : Space : Str t : Space : xs)+ | T.all (\c -> isDigit c || c == ':') t+ , ":" `T.isSuffixOf` t -> xs+ xs -> xs+makeFigure x = x++--+readODT' :: ReaderOptions+ -> B.ByteString+ -> Either PandocError (Pandoc, MediaBag)+readODT' _ bytes = bytesToODT bytes-- of+-- Right (pandoc, mediaBag) -> Right (pandoc , mediaBag)+-- Left err -> Left err++--+bytesToODT :: B.ByteString -> Either PandocError (Pandoc, MediaBag)+bytesToODT bytes = case toArchiveOrFail bytes of+ Right archive -> archiveToODT archive+ Left err -> Left $ PandocParseError+ $ "Could not unzip ODT: " <> T.pack err++--+archiveToODT :: Archive -> Either PandocError (Pandoc, MediaBag)+archiveToODT archive = do+ let onFailure msg Nothing = Left $ PandocParseError msg+ onFailure _ (Just x) = Right x+ contentEntry <- onFailure "Could not find content.xml"+ (findEntryByPath "content.xml" archive)+ stylesEntry <- onFailure "Could not find styles.xml"+ (findEntryByPath "styles.xml" archive)+ contentElem <- entryToXmlElem contentEntry+ stylesElem <- entryToXmlElem stylesEntry+ styles <- either+ (\_ -> Left $ PandocParseError "Could not read styles")+ Right+ (chooseMax (readStylesAt stylesElem ) (readStylesAt contentElem))+ let filePathIsODTMedia :: FilePath -> Bool+ filePathIsODTMedia fp =+ let (dir, name) = splitFileName fp+ in (dir == "Pictures/") || (dir /= "./" && name == "content.xml")+ let media = filteredFilesFromArchive archive filePathIsODTMedia+ let startState = readerState styles media+ either (\_ -> Left $ PandocParseError "Could not convert opendocument") Right+ (runConverter' read_body startState contentElem)+++--+entryToXmlElem :: Entry -> Either PandocError Element+entryToXmlElem entry =+ case parseXMLElement . UTF8.toTextLazy . fromEntry $ entry of+ Right x -> Right x+ Left msg -> Left $ PandocXMLError (T.pack $ eRelativePath entry) msg
@@ -0,0 +1,153 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TupleSections #-}+{- |+ Module : Text.Pandoc.Readers.ODT.Arrows.State+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++An arrow that transports a state. It is in essence a more powerful version of+the standard state monad. As it is such a simple extension, there are+other version out there that do exactly the same.+The implementation is duplicated, though, to add some useful features.+Most of these might be implemented without access to innards, but it's much+faster and easier to implement this way.+-}++module Text.Pandoc.Readers.ODT.Arrows.State+ ( ArrowState(..)+ , withState+ , modifyState+ , ignoringState+ , fromState+ , extractFromState+ , tryModifyState+ , withSubStateF+ , withSubStateF'+ , foldS+ , iterateS+ , iterateSL+ , iterateS'+ ) where++import qualified Data.List as L+import Control.Arrow+import qualified Control.Category as Cat+import Control.Monad+import Text.Pandoc.Readers.ODT.Arrows.Utils+import Text.Pandoc.Readers.ODT.Generic.Fallible+++newtype ArrowState state a b = ArrowState+ { runArrowState :: (state, a) -> (state, b) }++-- | Constructor+withState :: (state -> a -> (state, b)) -> ArrowState state a b+withState = ArrowState . uncurry++-- | Constructor+modifyState :: (state -> state ) -> ArrowState state a a+modifyState = ArrowState . first++-- | Constructor+ignoringState :: ( a -> b ) -> ArrowState state a b+ignoringState = ArrowState . second++-- | Constructor+fromState :: (state -> (state, b)) -> ArrowState state a b+fromState = ArrowState . (.fst)++-- | Constructor+extractFromState :: (state -> b ) -> ArrowState state x b+extractFromState f = ArrowState $ \(state,_) -> (state, f state)++-- | Constructor+tryModifyState :: (state -> Either f state)+ -> ArrowState state a (Either f a)+tryModifyState f = ArrowState $ \(state,a)+ -> (state,).Left ||| (,Right a) $ f state++instance Cat.Category (ArrowState s) where+ id = ArrowState id+ arrow2 . arrow1 = ArrowState $ runArrowState arrow2 . runArrowState arrow1++instance Arrow (ArrowState state) where+ arr = ignoringState+ first a = ArrowState $ \(s,(aF,aS))+ -> second (,aS) $ runArrowState a (s,aF)+ second a = ArrowState $ \(s,(aF,aS))+ -> second (aF,) $ runArrowState a (s,aS)++instance ArrowChoice (ArrowState state) where+ left a = ArrowState $ \(s,e) -> case e of+ Left l -> second Left $ runArrowState a (s,l)+ Right r -> (s, Right r)+ right a = ArrowState $ \(s,e) -> case e of+ Left l -> (s, Left l)+ Right r -> second Right $ runArrowState a (s,r)++instance ArrowApply (ArrowState state) where+ app = ArrowState $ \(s, (f,b)) -> runArrowState f (s,b)++-- | Switches the type of the state temporarily.+-- Drops the intermediate result state, behaving like a fallible+-- identity arrow, save for side effects in the state.+withSubStateF :: ArrowState s x (Either f s')+ -> ArrowState s' s (Either f s )+ -> ArrowState s x (Either f x )+withSubStateF unlift a = keepingTheValue (withSubStateF' unlift a)+ >>^ spreadChoice+ >>^ fmap fst++-- | Switches the type of the state temporarily.+-- Returns the resulting sub-state.+withSubStateF' :: ArrowState s x (Either f s')+ -> ArrowState s' s (Either f s )+ -> ArrowState s x (Either f s')+withSubStateF' unlift a = ArrowState go+ where go p@(s,_) = tryRunning unlift+ ( tryRunning a (second Right) )+ p+ where tryRunning a' b v = case runArrowState a' v of+ (_ , Left f) -> (s, Left f)+ (x , Right y) -> b (y,x)++-- | Fold a state arrow through something 'Foldable'. Collect the results+-- in a 'Monoid'.+-- Intermediate form of a fold between one with "only" a 'Monoid'+-- and one with any function.+foldS :: (Foldable f, Monoid m) => ArrowState s x m -> ArrowState s (f x) m+foldS a = ArrowState $ \(s,f) -> foldr a' (s,mempty) f+ where a' x (s',m) = second (mappend m) $ runArrowState a (s',x)++-- | Fold a state arrow through something 'Foldable'. Collect the results in a+-- 'MonadPlus'.+iterateS :: (Foldable f, MonadPlus m)+ => ArrowState s x y+ -> ArrowState s (f x) (m y)+iterateS a = ArrowState $ \(s,f) -> foldr a' (s,mzero) f+ where a' x (s',m) = second (mplus m.return) $ runArrowState a (s',x)++-- | Fold a state arrow through something 'Foldable'. Collect the results in a+-- 'MonadPlus'.+iterateSL :: (Foldable f, MonadPlus m)+ => ArrowState s x y+ -> ArrowState s (f x) (m y)+iterateSL a = ArrowState $ \(s,f) -> L.foldl' a' (s,mzero) f+ where a' (s',m) x = second (mplus m.return) $ runArrowState a (s',x)+++-- | Fold a fallible state arrow through something 'Foldable'.+-- Collect the results in a 'MonadPlus'.+-- If the iteration fails, the state will be reset to the initial one.+iterateS' :: (Foldable f, MonadPlus m)+ => ArrowState s x (Either e y )+ -> ArrowState s (f x) (Either e (m y))+iterateS' a = ArrowState $ \(s,f) -> foldr (a' s) (s,Right mzero) f+ where a' s x (s',Right m) = case runArrowState a (s',x) of+ (s'',Right m') -> (s'',Right $ mplus m $ return m')+ (_ ,Left e ) -> (s ,Left e )+ a' _ _ e = e
@@ -0,0 +1,241 @@+{- |+ Module : Text.Pandoc.Readers.ODT.Arrows.Utils+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++Utility functions for Arrows (Kleisli monads).++Some general notes on notation:++* "^" is meant to stand for a pure function that is lifted into an arrow+based on its usage for that purpose in "Control.Arrow".+* "?" is meant to stand for the usage of a 'FallibleArrow' or a pure function+with an equivalent return value.+* "_" stands for the dropping of a value.+-}++-- We export everything+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+import Control.Monad (join)++import Text.Pandoc.Readers.ODT.Generic.Fallible+import Text.Pandoc.Readers.ODT.Generic.Utils++and2 :: (Arrow a) => a b c -> a b c' -> a b (c,c')+and2 = (&&&)++and3 :: (Arrow a)+ => a b c0->a b c1->a b c2+ -> a b (c0,c1,c2 )+and4 :: (Arrow a)+ => a b c0->a b c1->a b c2->a b c3+ -> a b (c0,c1,c2,c3 )+and5 :: (Arrow a)+ => a b c0->a b c1->a b c2->a b c3->a b c4+ -> a b (c0,c1,c2,c3,c4 )+and6 :: (Arrow a)+ => a b c0->a b c1->a b c2->a b c3->a b c4->a b c5+ -> a b (c0,c1,c2,c3,c4,c5 )++and3 a b c = and2 a b &&& c+ >>^ \((z,y ) , x) -> (z,y,x )+and4 a b c d = and3 a b c &&& d+ >>^ \((z,y,x ) , w) -> (z,y,x,w )+and5 a b c d e = and4 a b c d &&& e+ >>^ \((z,y,x,w ) , v) -> (z,y,x,w,v )+and6 a b c d e f = and5 a b c d e &&& f+ >>^ \((z,y,x,w,v ) , u) -> (z,y,x,w,v,u )++liftA2 :: (Arrow a) => (x -> y -> z) -> a b x -> a b y -> a b z+liftA2 f a b = a &&& b >>^ uncurry f++liftA3 :: (Arrow a) => (z->y->x -> r)+ -> a b z->a b y->a b x+ -> a b r+liftA4 :: (Arrow a) => (z->y->x->w -> r)+ -> a b z->a b y->a b x->a b w+ -> a b r+liftA5 :: (Arrow a) => (z->y->x->w->v -> r)+ -> a b z->a b y->a b x->a b w->a b v+ -> a b r+liftA6 :: (Arrow a) => (z->y->x->w->v->u -> r)+ -> a b z->a b y->a b x->a b w->a b v->a b u+ -> a b r++liftA3 fun a b c = and3 a b c >>^ uncurry3 fun+liftA4 fun a b c d = and4 a b c d >>^ uncurry4 fun+liftA5 fun a b c d e = and5 a b c d e >>^ uncurry5 fun+liftA6 fun a b c d e f = and6 a b c d e f >>^ uncurry6 fun++liftA :: (Arrow a) => (y -> z) -> a b y -> a b z+liftA fun a = a >>^ fun+++-- | Duplicate a value to subsequently feed it into different arrows.+-- Can almost always be replaced with '(&&&)', 'keepingTheValue',+-- or even '(|||)'.+-- Equivalent to+-- > returnA &&& returnA+duplicate :: (Arrow a) => a b (b,b)+duplicate = arr $ join (,)++-- | Applies a function to the uncurried result-pair of an arrow-application.+-- (The %-symbol was chosen to evoke an association with pairs.)+(>>%) :: (Arrow a) => a x (b,c) -> (b -> c -> d) -> a x d+a >>% f = a >>^ uncurry f++infixr 2 >>%+++-- | Duplicate a value and apply an arrow to the second instance.+-- Equivalent to+-- > \a -> duplicate >>> second a+-- or+-- > \a -> returnA &&& a+keepingTheValue :: (Arrow a) => a b c -> a b (b,c)+keepingTheValue a = returnA &&& a++( ^||| ) :: (ArrowChoice a) => (b -> d) -> a c d -> a (Either b c) d+( |||^ ) :: (ArrowChoice a) => a b d -> (c -> d) -> a (Either b c) d+( ^|||^ ) :: (ArrowChoice a) => (b -> d) -> (c -> d) -> a (Either b c) d++l ^||| r = arr l ||| r+l |||^ r = l ||| arr r+l ^|||^ r = arr l ||| arr r++infixr 2 ^||| , |||^, ^|||^++( ^&&& ) :: (Arrow a) => (b -> c) -> a b c' -> a b (c,c')+( &&&^ ) :: (Arrow a) => a b c -> (b -> c') -> a b (c,c')++l ^&&& r = arr l &&& r+l &&&^ r = l &&& arr r++infixr 3 ^&&&, &&&^+++-- | Converts @Right a@ into @Just a@ and @Left _@ into @Nothing@.+choiceToMaybe :: (ArrowChoice a) => a (Either l r) (Maybe r)+choiceToMaybe = arr eitherToMaybe++-- | Converts @Nothing@ into @Left ()@ and @Just a@ into @Right a@.+maybeToChoice :: (ArrowChoice a) => a (Maybe b) (Fallible b)+maybeToChoice = arr maybeToEither++-- | Lifts a constant value into an arrow+returnV :: (Arrow a) => c -> a x c+returnV = arr.const++-- | Defines Left as failure, Right as success+type FallibleArrow a input failure success = a input (Either failure success)++--+liftAsSuccess :: (ArrowChoice a)+ => a x success+ -> FallibleArrow a x failure success+liftAsSuccess a = a >>^ Right++-- | Execute the second arrow if the first succeeds+(>>?) :: (ArrowChoice a)+ => FallibleArrow a x failure success+ -> FallibleArrow a success failure success'+ -> FallibleArrow a x failure success'+a >>? b = a >>> Left ^||| b++-- | Execute the lifted second arrow if the first succeeds+(>>?^) :: (ArrowChoice a)+ => FallibleArrow a x failure success+ -> (success -> success')+ -> FallibleArrow a x failure success'+a >>?^ f = a >>^ Left ^|||^ Right . f++-- | Execute the lifted second arrow if the first succeeds+(>>?^?) :: (ArrowChoice a)+ => FallibleArrow a x failure success+ -> (success -> Either failure success')+ -> FallibleArrow a x failure success'+a >>?^? b = a >>> Left ^|||^ b++-- | Execute the second arrow if the lifted first arrow succeeds+(^>>?) :: (ArrowChoice a)+ => (x -> Either failure success)+ -> FallibleArrow a success failure success'+ -> FallibleArrow a x failure success'+a ^>>? b = a ^>> Left ^||| b++-- | Execute the second, non-fallible arrow if the first arrow succeeds+(>>?!) :: (ArrowChoice a)+ => FallibleArrow a x failure success+ -> a success success'+ -> FallibleArrow a x failure success'+a >>?! f = a >>> right f++---+(>>?%) :: (ArrowChoice a)+ => FallibleArrow a x f (b,b')+ -> (b -> b' -> c)+ -> FallibleArrow a x f c+a >>?% f = a >>?^ uncurry f+++---+(>>?%?) :: (ArrowChoice a)+ => FallibleArrow a x f (b,b')+ -> (b -> b' -> Either f c)+ -> FallibleArrow a x f c+a >>?%? f = a >>?^? uncurry f++infixr 1 >>?, >>?^, >>?^?+infixr 1 ^>>?, >>?!+infixr 1 >>?%, >>?%?++-- | An arrow version of a short-circuit (<|>)+ifFailedDo :: (ArrowChoice a)+ => FallibleArrow a x f y+ -> FallibleArrow a x f y+ -> FallibleArrow a x f y+ifFailedDo a b = keepingTheValue a >>> repackage ^>> (b |||^ Right)+ where repackage (x , Left _) = Left x+ repackage (_ , Right y) = Right y++infixr 1 `ifFailedDo`
@@ -0,0 +1,26 @@+{- |+ Module : Text.Pandoc.Readers.ODT.Base+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++Core types of the odt reader.+-}++module Text.Pandoc.Readers.ODT.Base+ ( ODTConverterState+ , XMLReader+ , XMLReaderSafe+ ) where++import Text.Pandoc.Readers.ODT.Generic.XMLConverter+import Text.Pandoc.Readers.ODT.Namespaces++type ODTConverterState s = XMLConverterState Namespace s++type XMLReader s a b = FallibleXMLConverter Namespace s a b++type XMLReaderSafe s a b = XMLConverter Namespace s a b
@@ -0,0 +1,1054 @@+{-# LANGUAGE Arrows #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.ODT.ContentReader+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++The core of the odt reader that converts odt features into Pandoc types.+-}++module Text.Pandoc.Readers.ODT.ContentReader+( readerState+, read_body+) where++import Prelude hiding (Applicative(..))+import Control.Applicative hiding (liftA, liftA2, liftA3)+import Control.Arrow+import Control.Monad ((<=<))++import qualified Data.ByteString.Lazy as B+import Data.Foldable (fold)+import Data.List (find)+import qualified Data.Map as M+import qualified Data.Text as T+import Data.Maybe+import Data.Monoid (Alt (..))++import Text.TeXMath (readMathML, writeTeX)+import qualified Text.Pandoc.XML.Light as XML++import Text.Pandoc.Builder hiding (underline)+import Text.Pandoc.MediaBag (MediaBag, insertMedia)+import Text.Pandoc.Shared+import Text.Pandoc.Extensions (extensionsFromList, Extension(..))+import qualified Text.Pandoc.UTF8 as UTF8++import Text.Pandoc.Readers.Docx.Combine (combineBlocks)++import Text.Pandoc.Readers.ODT.Base+import Text.Pandoc.Readers.ODT.Namespaces+import Text.Pandoc.Readers.ODT.StyleReader++import Text.Pandoc.Readers.ODT.Arrows.State (foldS)+import Text.Pandoc.Readers.ODT.Arrows.Utils+import Text.Pandoc.Readers.ODT.Generic.Fallible+import Text.Pandoc.Readers.ODT.Generic.Utils+import Text.Pandoc.Readers.ODT.Generic.XMLConverter++import Network.URI (parseRelativeReference, URI(uriPath))+import qualified Data.Set as Set++--------------------------------------------------------------------------------+-- State+--------------------------------------------------------------------------------++type Anchor = T.Text+type Media = [(FilePath, B.ByteString)]++data ReaderState+ = ReaderState { -- | A collection of styles read somewhere else.+ -- It is only queried here, not modified.+ styleSet :: Styles+ -- | A stack of the styles of parent elements.+ -- Used to look up inherited style properties.+ , styleTrace :: [Style]+ -- | Keeps track of the current depth in nested lists+ , currentListLevel :: ListLevel+ -- | Keeps track of the previous list start counters,+ -- so whenever a new list continues numbering,+ -- we know what number to start from.+ -- If list does not continue numbering, the counter+ -- is being reset.+ , listContinuationStartCounters :: M.Map ListLevel Int+ -- | Lists may provide their own style, but they don't have+ -- to. If they do not, the style of a parent list may be used+ -- or even a default list style from the paragraph style.+ -- This value keeps track of the closest list style there+ -- currently is.+ , currentListStyle :: Maybe ListStyle+ -- | A map from internal anchor names to "pretty" ones.+ -- The mapping is a purely cosmetic one.+ , bookmarkAnchors :: M.Map Anchor Anchor+ -- | A map of files / binary data from the archive+ , envMedia :: Media+ -- | Hold binary resources used in the document+ , odtMediaBag :: MediaBag+ }+ deriving ( Show )++readerState :: Styles -> Media -> ReaderState+readerState styles media = ReaderState styles [] 0 M.empty Nothing M.empty media mempty++--+pushStyle' :: Style -> ReaderState -> ReaderState+pushStyle' style state = state { styleTrace = style : styleTrace state }++--+popStyle' :: ReaderState -> ReaderState+popStyle' state = case styleTrace state of+ _:trace -> state { styleTrace = trace }+ _ -> state+--+modifyListLevel :: (ListLevel -> ListLevel) -> (ReaderState -> ReaderState)+modifyListLevel f state = state { currentListLevel = f (currentListLevel state) }++--+modifyListContinuationStartCounter :: ListLevel -> Int -> (ReaderState -> ReaderState)+modifyListContinuationStartCounter listLevel count state =+ state { listContinuationStartCounters = M.insert listLevel count (listContinuationStartCounters state) }++--+shiftListLevel :: ListLevel -> (ReaderState -> ReaderState)+shiftListLevel diff = modifyListLevel (+ diff)++--+swapCurrentListStyle :: Maybe ListStyle -> ReaderState+ -> (ReaderState, Maybe ListStyle)+swapCurrentListStyle mListStyle state = ( state { currentListStyle = mListStyle }+ , currentListStyle state+ )++--+lookupPrettyAnchor :: Anchor -> ReaderState -> Maybe Anchor+lookupPrettyAnchor anchor ReaderState{..} = M.lookup anchor bookmarkAnchors++--+putPrettyAnchor :: Anchor -> Anchor -> ReaderState -> ReaderState+putPrettyAnchor ugly pretty state@ReaderState{..}+ = state { bookmarkAnchors = M.insert ugly pretty bookmarkAnchors }++--+usedAnchors :: ReaderState -> [Anchor]+usedAnchors ReaderState{..} = M.elems bookmarkAnchors++getMediaBag :: ReaderState -> MediaBag+getMediaBag ReaderState{..} = odtMediaBag++getMediaEnv :: ReaderState -> Media+getMediaEnv ReaderState{..} = envMedia++insertMedia' :: (FilePath, B.ByteString) -> ReaderState -> ReaderState+insertMedia' (fp, bs) state@ReaderState{..}+ = state { odtMediaBag = insertMedia fp Nothing bs odtMediaBag }++--------------------------------------------------------------------------------+-- Reader type and associated tools+--------------------------------------------------------------------------------++type ODTReader a b = XMLReader ReaderState a b++type ODTReaderSafe a b = XMLReaderSafe ReaderState a b++-- | Extract something from the styles+fromStyles :: (a -> Styles -> b) -> ODTReaderSafe a b+fromStyles f = keepingTheValue+ (getExtraState >>^ styleSet)+ >>% f++--+getStyleByName :: ODTReader StyleName Style+getStyleByName = fromStyles lookupStyle >>^ maybeToChoice++--+findStyleFamily :: ODTReader Style StyleFamily+findStyleFamily = fromStyles getStyleFamily >>^ maybeToChoice++--+lookupListStyle :: ODTReader StyleName ListStyle+lookupListStyle = fromStyles lookupListStyleByName >>^ maybeToChoice++--+switchCurrentListStyle :: ODTReaderSafe (Maybe ListStyle) (Maybe ListStyle)+switchCurrentListStyle = keepingTheValue getExtraState+ >>% swapCurrentListStyle+ >>> first setExtraState+ >>^ snd++--+pushStyle :: ODTReaderSafe Style Style+pushStyle = keepingTheValue (+ ( keepingTheValue getExtraState+ >>% pushStyle'+ )+ >>> setExtraState+ )+ >>^ fst++--+popStyle :: ODTReaderSafe x x+popStyle = keepingTheValue (+ getExtraState+ >>> arr popStyle'+ >>> setExtraState+ )+ >>^ fst++--+getCurrentListLevel :: ODTReaderSafe a ListLevel+getCurrentListLevel = getExtraState >>^ currentListLevel++--+getListContinuationStartCounters :: ODTReaderSafe a (M.Map ListLevel Int)+getListContinuationStartCounters = getExtraState >>^ listContinuationStartCounters+++--+getPreviousListStartCounter :: ODTReaderSafe ListLevel Int+getPreviousListStartCounter = proc listLevel -> do+ counts <- getListContinuationStartCounters -< ()+ returnA -< M.findWithDefault 0 listLevel counts++--+updateMediaWithResource :: ODTReaderSafe (FilePath, B.ByteString) (FilePath, B.ByteString)+updateMediaWithResource = keepingTheValue (+ (keepingTheValue getExtraState+ >>% insertMedia'+ )+ >>> setExtraState+ )+ >>^ fst++lookupResource :: ODTReaderSafe FilePath (FilePath, B.ByteString)+lookupResource = proc target -> do+ state <- getExtraState -< ()+ case lookup target (getMediaEnv state) of+ Just bs -> returnV (target, bs) -<< ()+ Nothing -> returnV ("", B.empty) -< ()++type AnchorPrefix = T.Text++-- | An adaptation of 'uniqueIdent' from "Text.Pandoc.Shared" that generates a+-- unique identifier but without assuming that the id should be for a header.+-- Second argument is a list of already used identifiers.+uniqueIdentFrom :: AnchorPrefix -> [Anchor] -> Anchor+uniqueIdentFrom baseIdent usedIdents =+ let numIdent n = baseIdent <> "-" <> T.pack (show n)+ in if baseIdent `elem` usedIdents+ then maybe baseIdent numIdent+ $ find (\x -> numIdent x `notElem` usedIdents) ([1..60000] :: [Int])+ -- if we have more than 60,000, allow repeats+ else baseIdent++-- | First argument: basis for a new "pretty" anchor if none exists yet+-- Second argument: a key ("ugly" anchor)+-- Returns: saved "pretty" anchor or created new one+getPrettyAnchor :: ODTReaderSafe (AnchorPrefix, Anchor) Anchor+getPrettyAnchor = proc (baseIdent, uglyAnchor) -> do+ state <- getExtraState -< ()+ case lookupPrettyAnchor uglyAnchor state of+ Just prettyAnchor -> returnA -< prettyAnchor+ Nothing -> do+ let newPretty = uniqueIdentFrom baseIdent (usedAnchors state)+ modifyExtraState (putPrettyAnchor uglyAnchor newPretty) -<< newPretty++-- | Input: basis for a new header anchor+-- Output: saved new anchor+getHeaderAnchor :: ODTReaderSafe Inlines Anchor+getHeaderAnchor = proc title -> do+ state <- getExtraState -< ()+ let exts = extensionsFromList [Ext_auto_identifiers]+ let anchor = uniqueIdent exts (toList title)+ (Set.fromList $ usedAnchors state)+ modifyExtraState (putPrettyAnchor anchor anchor) -<< anchor+++--------------------------------------------------------------------------------+-- Working with styles+--------------------------------------------------------------------------------++--+readStyleByName :: ODTReader a (StyleName, Style)+readStyleByName =+ findAttr NsText "style-name" >>? keepingTheValue getStyleByName >>^ liftE+ where+ liftE :: (StyleName, Fallible Style) -> Fallible (StyleName, Style)+ liftE (name, Right v) = Right (name, v)+ liftE (_, Left v) = Left v++--+isStyleToTrace :: ODTReader Style Bool+isStyleToTrace = findStyleFamily >>?^ (==FaText)++--+withNewStyle :: ODTReaderSafe x Inlines -> ODTReaderSafe x Inlines+withNewStyle a = proc x -> do+ fStyle <- readStyleByName -< ()+ case fStyle of+ Right (styleName, _) | isCodeStyle styleName -> do+ inlines <- a -< x+ arr inlineCode -<< inlines+ Right (_, style) -> do+ mFamily <- arr styleFamily -< style+ fTextProps <- arr ( maybeToChoice+ . textProperties+ . styleProperties+ ) -< style+ case fTextProps of+ Right textProps -> do+ state <- getExtraState -< ()+ let triple = (state, textProps, mFamily)+ modifier <- arr modifierFromStyleDiff -< triple+ fShouldTrace <- isStyleToTrace -< style+ case fShouldTrace of+ Right shouldTrace ->+ if shouldTrace+ then do+ pushStyle -< style+ inlines <- a -< x+ popStyle -< ()+ arr modifier -<< inlines+ else+ -- In case anything goes wrong+ a -< x+ Left _ -> a -< x+ Left _ -> a -< x+ Left _ -> a -< x+ where+ isCodeStyle :: StyleName -> Bool+ isCodeStyle "Source_Text" = True+ isCodeStyle "Source_20_Text" = True+ isCodeStyle _ = False++ inlineCode :: Inlines -> Inlines+ inlineCode = code . T.concat . map stringify . toList++type PropertyTriple = (ReaderState, TextProperties, Maybe StyleFamily)+type InlineModifier = Inlines -> Inlines++-- | Given data about the local style changes, calculates how to modify+-- an instance of 'Inlines'+modifierFromStyleDiff :: PropertyTriple -> InlineModifier+modifierFromStyleDiff propertyTriple =+ composition $+ getVPosModifier propertyTriple+ : map (first ($ propertyTriple) >>> ifThen_else ignore)+ [ (hasEmphChanged , emph )+ , (hasChanged isStrong , strong )+ , (hasChanged strikethrough , strikeout )+ ]+ where+ ifThen_else else' (if',then') = if if' then then' else else'++ ignore = id :: InlineModifier++ getVPosModifier :: PropertyTriple -> InlineModifier+ getVPosModifier triple@(_,textProps,_) =+ let getVPos = Just . verticalPosition+ in case lookupPreviousValueM getVPos triple of+ Nothing -> ignore+ Just oldVPos -> getVPosModifier' (oldVPos, verticalPosition textProps)++ getVPosModifier' (oldVPos , newVPos ) | oldVPos == newVPos = ignore+ getVPosModifier' ( _ , VPosSub ) = subscript+ getVPosModifier' ( _ , VPosSuper ) = superscript+ getVPosModifier' ( _ , _ ) = ignore++ hasEmphChanged :: PropertyTriple -> Bool+ hasEmphChanged = swing any [ hasChanged isEmphasised+ , hasChangedM pitch+ , hasChanged underline+ ]++ hasChanged property triple@(_, property -> newProperty, _) =+ (/= Just newProperty) (lookupPreviousValue property triple)++ hasChangedM property triple@(_, textProps,_) =+ fromMaybe False $ (/=) <$> property textProps <*> lookupPreviousValueM property triple++ lookupPreviousValue f = lookupPreviousStyleValue (fmap f . textProperties)++ lookupPreviousValueM f = lookupPreviousStyleValue (f <=< textProperties)++ lookupPreviousStyleValue f (ReaderState{..},_,mFamily)+ = findBy f (extendedStylePropertyChain styleTrace styleSet)+ <|> (f . lookupDefaultStyle' styleSet =<< mFamily)+++type ParaModifier = Blocks -> Blocks++_MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_MM_ :: Int+_MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_PERCENT_ :: Int+_MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_MM_ = 5+_MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_PERCENT_ = 5++-- | Returns either 'id' or 'blockQuote' depending if any of the StyleProperties+-- are indented at quote level.+getParaModifier :: ListLevel -> [StyleProperties] -> ParaModifier+getParaModifier listLevel props+ | listLevel > 0 = id -- see #9505, list paragraphs need indentation+ | any isBlockQuote props = blockQuote+ | otherwise = id+ where+ isBlockQuote SProps {..} | Just paraProps <- paraProperties+ , isQuoteWidth (margin_left paraProps)+ = True+ | otherwise+ = False+ isQuoteWidth mMargin+ | LengthValueMM margin <- mMargin+ , margin > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_MM_+ = True+ | PercentValue margin <- mMargin+ , margin > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_PERCENT_+ = True+ | otherwise+ = False++--+constructPara :: ODTReaderSafe a Blocks -> ODTReaderSafe a Blocks+constructPara reader = proc blocks -> do+ fStyle <- readStyleByName -< blocks+ case fStyle of+ Left _ -> reader -< blocks+ Right (styleName, _) | isTableCaptionStyle styleName -> do+ blocks' <- reader -< blocks+ arr tableCaptionP -< blocks'+ Right (_, style) -> do+ props <- fromStyles extendedStylePropertyChain -< [style]+ listLevel <- getCurrentListLevel -< ()+ let modifier = getParaModifier listLevel props+ blocks' <- reader -< blocks+ arr modifier -<< blocks'+ where+ isTableCaptionStyle :: StyleName -> Bool+ isTableCaptionStyle "Table" = True+ isTableCaptionStyle _ = False+ tableCaptionP b = divWith ("", ["caption"], []) b++type ListConstructor = [Blocks] -> Blocks++getListConstructor :: ListLevelStyle -> Int -> ListConstructor+getListConstructor ListLevelStyle{..} startNum =+ case listLevelType of+ LltBullet -> bulletList+ LltImage -> bulletList+ LltNumbered -> let listNumberStyle = toListNumberStyle listItemFormat+ listNumberDelim = toListNumberDelim listItemPrefix+ listItemSuffix+ in orderedListWith (startNum, listNumberStyle, listNumberDelim)+ where+ toListNumberStyle LinfNone = DefaultStyle+ toListNumberStyle LinfNumber = Decimal+ toListNumberStyle LinfRomanLC = LowerRoman+ toListNumberStyle LinfRomanUC = UpperRoman+ toListNumberStyle LinfAlphaLC = LowerAlpha+ toListNumberStyle LinfAlphaUC = UpperAlpha+ toListNumberStyle (LinfString _) = Example++ toListNumberDelim Nothing (Just ".") = Period+ toListNumberDelim (Just "" ) (Just ".") = Period+ toListNumberDelim Nothing (Just ")") = OneParen+ toListNumberDelim (Just "" ) (Just ")") = OneParen+ toListNumberDelim (Just "(") (Just ")") = TwoParens+ toListNumberDelim _ _ = DefaultDelim++-- | Determines which style to use for a list, which level to use of that+-- style, and which type of list to create as a result of this information.+-- Then prepares the state for eventual child lists and constructs the list from+-- the results.+-- Two main cases are handled: The list may provide its own style or it may+-- rely on a parent list's style. I the former case the current style in the+-- state must be switched before and after the call to the child converter+-- while in the latter the child converter can be called directly.+-- If anything goes wrong, a default ordered-list-constructor is used.+constructList :: ODTReaderSafe x [Blocks] -> ODTReaderSafe x Blocks+constructList reader = proc x -> do+ modifyExtraState (shiftListLevel 1) -< ()+ listLevel <- getCurrentListLevel -< ()+ listContinuationStartCounter <- getPreviousListStartCounter -< listLevel+ fStyleName <- findAttr NsText "style-name" -< ()+ fContNumbering <- findAttr NsText "continue-numbering" -< ()+ listItemCount <- reader >>^ length -< x++ let continueNumbering = case fContNumbering of+ Right "true" -> True+ _ -> False++ let startNumForListLevelStyle = listStartingNumber continueNumbering listContinuationStartCounter+ let defaultOrderedListConstructor = constructOrderedList (startNumForListLevelStyle Nothing) listLevel listItemCount++ case fStyleName of+ Right styleName -> do+ fListStyle <- lookupListStyle -< styleName+ case fListStyle of+ Right listStyle -> do+ fListLevelStyle <- arr (uncurry getListLevelStyle) -< (listLevel, listStyle)+ case fListLevelStyle of+ Just listLevelStyle -> do+ let startNum = startNumForListLevelStyle $ Just listLevelStyle+ oldListStyle <- switchCurrentListStyle -< Just listStyle+ blocks <- constructListWith listLevelStyle startNum listLevel listItemCount -<< x+ switchCurrentListStyle -< oldListStyle+ returnA -< blocks+ Nothing -> defaultOrderedListConstructor -<< x+ Left _ -> defaultOrderedListConstructor -<< x+ Left _ -> do+ state <- getExtraState -< ()+ mListStyle <- arr currentListStyle -< state+ case mListStyle of+ Just listStyle -> do+ fListLevelStyle <- arr (uncurry getListLevelStyle) -< (listLevel, listStyle)+ case fListLevelStyle of+ Just listLevelStyle -> do+ let startNum = startNumForListLevelStyle $ Just listLevelStyle+ constructListWith listLevelStyle startNum listLevel listItemCount -<< x+ Nothing -> defaultOrderedListConstructor -<< x+ Nothing -> defaultOrderedListConstructor -<< x+ where+ listStartingNumber continueNumbering listContinuationStartCounter mListLevelStyle+ | continueNumbering = listContinuationStartCounter+ | isJust mListLevelStyle = listItemStart (fromJust mListLevelStyle)+ | otherwise = 1+ constructOrderedList startNum listLevel listItemCount =+ reader+ >>> modifyExtraState (shiftListLevel (-1))+ >>> modifyExtraState (modifyListContinuationStartCounter listLevel (startNum + listItemCount))+ >>^ orderedListWith (startNum, DefaultStyle, DefaultDelim)+ constructListWith listLevelStyle startNum listLevel listItemCount =+ reader+ >>> getListConstructor listLevelStyle startNum+ ^>> modifyExtraState (shiftListLevel (-1))+ >>> modifyExtraState (modifyListContinuationStartCounter listLevel (startNum + listItemCount))++--------------------------------------------------------------------------------+-- Readers+--------------------------------------------------------------------------------++type ElementMatcher result = (Namespace, ElementName, ODTReader result result)++type InlineMatcher = ElementMatcher Inlines++type BlockMatcher = ElementMatcher Blocks++newtype FirstMatch a = FirstMatch (Alt Maybe a)+ deriving (Foldable, Monoid, Semigroup)++firstMatch :: a -> FirstMatch a+firstMatch = FirstMatch . Alt . Just++newtype CombiningBlocks = CombiningBlocks { unCombiningBlocks :: Blocks }++instance Semigroup CombiningBlocks where+ CombiningBlocks l <> CombiningBlocks r = CombiningBlocks (combineBlocks l r)++instance Monoid CombiningBlocks where+ mempty = CombiningBlocks mempty++--+matchingElement :: (Monoid e)+ => Namespace -> ElementName+ -> ODTReaderSafe e e+ -> ElementMatcher e+matchingElement ns name reader = (ns, name, asResultAccumulator reader)+ where+ asResultAccumulator :: (ArrowChoice a, Monoid m) => a m m -> a m (Fallible m)+ asResultAccumulator a = liftAsSuccess $ keepingTheValue a >>% mappend++--+matchChildContent' :: (Monoid result)+ => [ElementMatcher result]+ -> ODTReaderSafe a result+matchChildContent' ls = returnV mempty >>> matchContent' ls++--+matchSmushedChildBlocks' :: [ElementMatcher CombiningBlocks] -> ODTReaderSafe a Blocks+matchSmushedChildBlocks' ls = liftA unCombiningBlocks+ $ returnV mempty+ >>> matchContent' ls++--+matchChildContent :: (Monoid result)+ => [ElementMatcher result]+ -> ODTReaderSafe (result, XML.Content) result+ -> ODTReaderSafe a result+matchChildContent ls fallback = returnV mempty >>> matchContent ls fallback++--------------------------------------------+-- Matchers+--------------------------------------------++----------------------+-- Basics+----------------------++--+-- | Open Document allows several consecutive spaces if they are marked up+read_plain_text :: ODTReaderSafe (Inlines, XML.Content) Inlines+read_plain_text = fst ^&&& read_plain_text' >>% recover+ where+ -- fallible version+ read_plain_text' :: ODTReader (Inlines, XML.Content) Inlines+ read_plain_text' = ( second ( arr extractText )+ >>^ spreadChoice >>?! second text+ )+ >>?% mappend+ --+ extractText :: XML.Content -> Fallible T.Text+ extractText (XML.Text cData) = succeedWith (XML.cdData cData)+ extractText _ = failEmpty++read_text_seq :: InlineMatcher+read_text_seq = matchingElement NsText "sequence"+ $ matchChildContent [] read_plain_text+++-- specifically. I honor that, although the current implementation of 'mappend'+-- for 'Inlines' in "Text.Pandoc.Builder" will collapse them again.+-- The rational is to be prepared for future modifications.+read_spaces :: InlineMatcher+read_spaces = matchingElement NsText "s" (+ readAttrWithDefault NsText "c" 1 -- how many spaces?+ >>^ fromList.(`replicate` Space)+ )+--+read_line_break :: InlineMatcher+read_line_break = matchingElement NsText "line-break"+ $ returnV linebreak+--+read_tab :: InlineMatcher+read_tab = matchingElement NsText "tab"+ $ returnV space+--+read_span :: InlineMatcher+read_span = matchingElement NsText "span"+ $ withNewStyle+ $ matchChildContent [ read_span+ , read_spaces+ , read_line_break+ , read_tab+ , read_link+ , read_frame+ , read_note+ , read_citation+ , read_bookmark+ , read_bookmark_start+ , read_reference_start+ , read_bookmark_ref+ , read_reference_ref+ ] read_plain_text++--+read_paragraph :: ElementMatcher CombiningBlocks+read_paragraph = matchingElement NsText "p" $+ liftA CombiningBlocks $ proc blocks -> do+ fStyle <- readStyleByName -< blocks+ case fStyle of+ Right style | isPreformattedStyle style -> do+ liftA (codeBlock . stringify) $ matchParagraphContent -< blocks+ _ ->+ constructPara $ liftA para $ withNewStyle matchParagraphContent -< blocks+ where+ isPreformattedStyle :: (StyleName, Style) -> Bool+ isPreformattedStyle ("Preformatted_20_Text", _) = True+ isPreformattedStyle (_, Style { styleParentName = Just "Preformatted_20_Text" }) = True+ isPreformattedStyle _ = False+++matchParagraphContent :: ODTReaderSafe a Inlines+matchParagraphContent = matchChildContent [ read_span+ , read_spaces+ , read_line_break+ , read_tab+ , read_link+ , read_note+ , read_citation+ , read_bookmark+ , read_bookmark_start+ , read_reference_start+ , read_bookmark_ref+ , read_reference_ref+ , read_frame+ , read_text_seq+ ] read_plain_text+++----------------------+-- Headers+----------------------++--+read_header :: ElementMatcher CombiningBlocks+read_header = matchingElement NsText "h"+ $ proc blocks -> do+ level <- ( readAttrWithDefault NsText "outline-level" 1+ ) -< blocks+ children <- ( matchChildContent [ read_span+ , read_spaces+ , read_line_break+ , read_tab+ , read_link+ , read_note+ , read_citation+ , read_bookmark+ , read_bookmark_start+ , read_reference_start+ , read_bookmark_ref+ , read_reference_ref+ , read_frame+ ] read_plain_text+ ) -< blocks+ anchor <- getHeaderAnchor -< children+ let idAttr = (anchor, [], []) -- no classes, no key-value pairs+ arr (CombiningBlocks . uncurry3 headerWith) -< (idAttr, level, children)++----------------------+-- Lists+----------------------++--+read_list :: ElementMatcher CombiningBlocks+read_list = matchingElement NsText "list"+ $ liftA CombiningBlocks+ $ constructList+ $ matchChildContent' [ read_list_item+ , read_list_header+ ]+--+read_list_item :: ElementMatcher [Blocks]+read_list_item = read_list_element "list-item"++read_list_header :: ElementMatcher [Blocks]+read_list_header = read_list_element "list-header"++read_list_element :: ElementName -> ElementMatcher [Blocks]+read_list_element listElement = matchingElement NsText listElement+ $ liftA (compactify.(:[]))+ ( matchSmushedChildBlocks' [ read_paragraph+ , read_header+ , read_list+ , read_section+ ]+ )++----------------------+-- Sections+----------------------++read_section :: ElementMatcher CombiningBlocks+read_section = matchingElement NsText "section"+ $ liftA (CombiningBlocks . divWith nullAttr)+ $ matchSmushedChildBlocks' [ read_paragraph+ , read_header+ , read_list+ , read_table+ , read_section+ ]+++----------------------+-- Links+----------------------++read_link :: InlineMatcher+read_link = matchingElement NsText "a"+ $ liftA3 link+ ( findAttrTextWithDefault NsXLink "href" ""+ >>> arr fixRelativeLink )+ ( findAttrTextWithDefault NsOffice "title" "" )+ ( matchChildContent [ read_span+ , read_note+ , read_citation+ , read_bookmark+ , read_bookmark_start+ , read_reference_start+ , read_bookmark_ref+ , read_reference_ref+ ] read_plain_text )++fixRelativeLink :: T.Text -> T.Text+fixRelativeLink uri =+ case parseRelativeReference (T.unpack uri) of+ Nothing -> uri+ Just u ->+ case uriPath u of+ '.':'.':'/':xs -> tshow $ u{ uriPath = xs }+ _ -> uri++-------------------------+-- Footnotes+-------------------------++read_note :: InlineMatcher+read_note = matchingElement NsText "note"+ $ liftA note+ $ matchChildContent' [ read_note_body ]++read_note_body :: BlockMatcher+read_note_body = matchingElement NsText "note-body"+ $ matchSmushedChildBlocks' [ read_paragraph ]++-------------------------+-- Citations+-------------------------++read_citation :: InlineMatcher+read_citation = matchingElement NsText "bibliography-mark"+ $ liftA2 cite+ ( liftA2 makeCitation+ ( findAttrTextWithDefault NsText "identifier" "" )+ ( readAttrWithDefault NsText "number" 0 )+ )+ ( matchChildContent [] read_plain_text )+ where+ makeCitation :: T.Text -> Int -> [Citation]+ makeCitation citeId num = [Citation citeId [] [] NormalCitation num 0]+++----------------------+-- Tables+----------------------++--+read_table :: ElementMatcher CombiningBlocks+read_table = matchingElement NsTable "table"+ $ liftA (CombiningBlocks . table')+ $ (matchChildContent' [read_table_header]) &&&+ (matchChildContent' [read_table_row])++-- | A table without a caption.+table' :: ([[Cell]], [[Cell]]) -> Blocks+table' (headers, rows) =+ table emptyCaption (replicate numcols defaults) th [tb] tf+ where+ defaults = (AlignDefault, ColWidthDefault)+ numcols = maximum $ map length $ headers ++ rows+ toRow = Row nullAttr+ th = TableHead nullAttr $ map toRow headers+ tb = TableBody nullAttr 0 [] $ map toRow rows+ tf = TableFoot nullAttr []++--+read_table_header :: ElementMatcher [[Cell]]+read_table_header = matchingElement NsTable "table-header-rows"+ $ matchChildContent' [ read_table_row+ ]++--+read_table_row :: ElementMatcher [[Cell]]+read_table_row = matchingElement NsTable "table-row"+ $ liftA (:[])+ $ matchChildContent' [ read_table_cell+ ]++--+read_table_cell :: ElementMatcher [Cell]+read_table_cell = matchingElement NsTable "table-cell"+ $ liftA3 cell'+ (readAttrWithDefault NsTable "number-rows-spanned" 1 >>^ RowSpan)+ (readAttrWithDefault NsTable "number-columns-spanned" 1 >>^ ColSpan)+ $ matchSmushedChildBlocks' [ read_paragraph+ , read_list+ ]+ where+ cell' rowSpan colSpan blocks = map (cell AlignDefault rowSpan colSpan) $ compactify [blocks]++----------------------+-- Frames+----------------------++--+read_frame :: InlineMatcher+read_frame = matchingElement NsDraw "frame"+ $ filterChildrenName' NsDraw (`elem` ["image", "object", "text-box"])+ >>> foldS read_frame_child+ >>> arr fold++read_frame_child :: ODTReaderSafe XML.Element (FirstMatch Inlines)+read_frame_child =+ proc child -> case elName child of+ "image" -> read_frame_img -< child+ "object" -> read_frame_mathml -< child+ "text-box" -> read_frame_text_box -< child+ _ -> returnV mempty -< ()++read_frame_img :: ODTReaderSafe XML.Element (FirstMatch Inlines)+read_frame_img =+ proc img -> do+ src <- executeIn (findAttr' NsXLink "href") -< img+ case fold src of+ "" -> returnV mempty -< ()+ src' -> do+ let exts = extensionsFromList [Ext_auto_identifiers]+ src'' = fixRelativeLink src'+ resource <- lookupResource -< T.unpack src''+ _ <- updateMediaWithResource -< resource+ w <- findAttrText' NsSVG "width" -< ()+ h <- findAttrText' NsSVG "height" -< ()+ titleNodes <- matchChildContent' [ read_frame_title ] -< ()+ alt <- matchChildContent [] read_plain_text -< ()+ arr (firstMatch . uncurry4 imageWith) -<+ (image_attributes w h, src'', inlineListToIdentifier exts (toList titleNodes), alt)++read_frame_title :: InlineMatcher+read_frame_title = matchingElement NsSVG "title" (matchChildContent [] read_plain_text)++image_attributes :: Maybe T.Text -> Maybe T.Text -> Attr+image_attributes x y =+ ( "", [], dim "width" x ++ dim "height" y)+ where+ dim _ (Just "") = []+ dim name (Just v) = [(name, v)]+ dim _ Nothing = []++read_frame_mathml :: ODTReaderSafe XML.Element (FirstMatch Inlines)+read_frame_mathml =+ proc obj -> do+ src <- executeIn (findAttr' NsXLink "href") -< obj+ case fold src of+ "" -> returnV mempty -< ()+ src' -> do+ let path = T.unpack $+ fromMaybe src' (T.stripPrefix "./" src') <> "/content.xml"+ (_, mathml) <- lookupResource -< path+ case readMathML (UTF8.toText $ B.toStrict mathml) of+ Left _ -> returnV mempty -< ()+ Right exps -> arr (firstMatch . displayMath . writeTeX) -< exps++read_frame_text_box :: ODTReaderSafe XML.Element (FirstMatch Inlines)+read_frame_text_box = proc box -> do+ paragraphs <- executeIn (matchSmushedChildBlocks' [ read_paragraph ]) -< box+ arr read_img_with_caption -< toList paragraphs++read_img_with_caption :: [Block] -> FirstMatch Inlines+read_img_with_caption (Para [Image attr alt (src,title)] : _) =+ firstMatch $ singleton (Image attr alt (src, "fig:" <> title)) -- no text, default caption+read_img_with_caption (Para (Image attr _ (src,title) : txt) : _) =+ firstMatch $ singleton (Image attr txt (src, "fig:" <> title) ) -- override caption with the text that follows+read_img_with_caption ( Para (_ : xs) : ys) =+ read_img_with_caption (Para xs : ys)+read_img_with_caption _ =+ mempty++----------------------+-- Internal links+----------------------++_ANCHOR_PREFIX_ :: T.Text+_ANCHOR_PREFIX_ = "anchor"++--+readAnchorAttr :: ODTReader a Anchor+readAnchorAttr = findAttrText NsText "name"++-- | Beware: may fail+findAnchorName :: ODTReader AnchorPrefix Anchor+findAnchorName = ( keepingTheValue readAnchorAttr+ >>^ spreadChoice+ ) >>?! getPrettyAnchor+++--+maybeAddAnchorFrom :: ODTReader Inlines AnchorPrefix+ -> ODTReaderSafe Inlines Inlines+maybeAddAnchorFrom anchorReader =+ keepingTheValue (anchorReader >>? findAnchorName >>?^ toAnchorElem)+ >>>+ proc (inlines, fAnchorElem) -> do+ case fAnchorElem of+ Right anchorElem -> returnA -< anchorElem+ Left _ -> returnA -< inlines+ where+ toAnchorElem :: Anchor -> Inlines+ toAnchorElem anchorID = spanWith (anchorID, [], []) mempty+ -- no classes, no key-value pairs++--+read_bookmark :: InlineMatcher+read_bookmark = matchingElement NsText "bookmark"+ $ maybeAddAnchorFrom (liftAsSuccess $ returnV _ANCHOR_PREFIX_)++--+read_bookmark_start :: InlineMatcher+read_bookmark_start = matchingElement NsText "bookmark-start"+ $ maybeAddAnchorFrom (liftAsSuccess $ returnV _ANCHOR_PREFIX_)++--+read_reference_start :: InlineMatcher+read_reference_start = matchingElement NsText "reference-mark-start"+ $ maybeAddAnchorFrom readAnchorAttr++-- | Beware: may fail+findAnchorRef :: ODTReader a Anchor+findAnchorRef = ( findAttrText NsText "ref-name"+ >>?^ (_ANCHOR_PREFIX_,)+ ) >>?! getPrettyAnchor+++--+maybeInAnchorRef :: ODTReaderSafe Inlines Inlines+maybeInAnchorRef = proc inlines -> do+ fRef <- findAnchorRef -< ()+ case fRef of+ Right anchor ->+ arr (toAnchorRef anchor) -<< inlines+ Left _ -> returnA -< inlines+ where+ toAnchorRef :: Anchor -> Inlines -> Inlines+ toAnchorRef anchor = link ("#" <> anchor) "" -- no title++--+read_bookmark_ref :: InlineMatcher+read_bookmark_ref = matchingElement NsText "bookmark-ref"+ $ maybeInAnchorRef+ <<< matchChildContent [] read_plain_text++--+read_reference_ref :: InlineMatcher+read_reference_ref = matchingElement NsText "reference-ref"+ $ maybeInAnchorRef+ <<< matchChildContent [] read_plain_text+++----------------------+-- Entry point+----------------------++read_text :: ODTReaderSafe a Pandoc+read_text = matchSmushedChildBlocks' [ read_header+ , read_paragraph+ , read_list+ , read_section+ , read_table+ ]+ >>^ doc++post_process :: Pandoc -> Pandoc+post_process (Pandoc m blocks) =+ Pandoc m (post_process' blocks)++post_process' :: [Block] -> [Block]+post_process' (Table attr _ specs th tb tf : Div ("", ["caption"], _) blks : xs)+ = Table attr (Caption Nothing blks) specs th tb tf : post_process' xs+post_process' bs = bs++read_body :: ODTReader a (Pandoc, MediaBag)+read_body = executeInSub NsOffice "body"+ $ executeInSub NsOffice "text"+ $ liftAsSuccess+ $ proc inlines -> do+ txt <- read_text -< inlines+ state <- getExtraState -< ()+ returnA -< (post_process txt, getMediaBag state)
@@ -0,0 +1,113 @@+{- |+ Module : Text.Pandoc.Readers.ODT.Generic.Fallible+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++Data types and utilities representing failure. Most of it is based on the+"Either" type in its usual configuration (left represents failure).++In most cases, the failure type is implied or required to be a "Monoid".++The choice of "Either" instead of a custom type makes it easier to write+compatible instances of "ArrowChoice".+-}++-- We export everything+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 = ()++type Fallible a = Either Failure a+++--+maybeToEither :: Maybe a -> Fallible a+maybeToEither (Just a) = Right a+maybeToEither Nothing = Left ()++--+eitherToMaybe :: Either _l a -> Maybe a+eitherToMaybe (Left _) = Nothing+eitherToMaybe (Right a) = Just a++-- | > recover a === either (const a) id+recover :: a -> Either _f a -> a+recover a (Left _) = a+recover _ (Right a) = a++-- | I would love to use 'fail'. Alas, 'Monad.fail'...+failWith :: failure -> Either failure _x+failWith f = Left f++--+failEmpty :: (Monoid failure) => Either failure _x+failEmpty = failWith mempty++--+succeedWith :: a -> Either _x a+succeedWith = Right++--+collapseEither :: Either failure (Either failure x)+ -> Either failure x+collapseEither (Left f ) = Left f+collapseEither (Right (Left f)) = Left f+collapseEither (Right (Right x)) = Right x++-- | If either of the values represents a non-error, the result is a+-- (possibly combined) non-error. If both values represent an error, an error+-- is returned.+chooseMax :: (Monoid a, Monoid b) => Either a b -> Either a b -> Either a b+chooseMax = chooseMaxWith mappend++-- | If either of the values represents a non-error, the result is a+-- (possibly combined) non-error. If both values represent an error, an error+-- is returned.+chooseMaxWith :: (Monoid a) => (b -> b -> b)+ -> Either a b+ -> Either a b+ -> Either a b+chooseMaxWith (><) (Right a) (Right b) = Right $ a >< b+chooseMaxWith _ (Left a) (Left b) = Left $ a `mappend` b+chooseMaxWith _ (Right a) _ = Right a+chooseMaxWith _ _ (Right b) = Right b+++-- | Class of containers that can escalate contained 'Either's.+-- The word "Vector" is meant in the sense of a disease transmitter.+class ChoiceVector v where+ spreadChoice :: v (Either f a) -> Either f (v a)++instance ChoiceVector ((,) a) where+ spreadChoice (_, Left f) = Left f+ spreadChoice (x, Right y) = Right (x,y)+ -- Wasn't there a newtype somewhere with the elements flipped?++-- | Wrapper for a list. While the normal list instance of 'ChoiceVector'+-- fails whenever it can, this type will never fail.+newtype SuccessList a = SuccessList { collectNonFailing :: [a] }+ deriving ( Eq, Ord, Show )++instance ChoiceVector SuccessList where+ spreadChoice = Right . SuccessList . foldr unTagRight [] . collectNonFailing+ where unTagRight (Right x) = (x:)+ unTagRight _ = id
@@ -0,0 +1,49 @@+{- |+ Module : Text.Pandoc.Readers.ODT.Generic.Namespaces+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++A class containing a set of namespace identifiers. Used to convert between+typesafe Haskell namespace identifiers and unsafe "real world" namespaces.+-}++module Text.Pandoc.Readers.ODT.Generic.Namespaces+ ( NameSpaceIRI+ , NameSpaceIRIs+ , NameSpaceID(..)+ ) where++import qualified Data.Map as M+import Data.Text (Text)++--+type NameSpaceIRI = Text++--+type NameSpaceIRIs nsID = M.Map nsID NameSpaceIRI++--+class (Eq nsID, Ord nsID) => NameSpaceID nsID where++ -- | Given a IRI, possibly update the map and return the id of the namespace.+ -- May fail if the namespace is unknown and the application does not+ -- allow unknown namespaces.+ getNamespaceID :: NameSpaceIRI+ -> NameSpaceIRIs nsID+ -> Maybe (NameSpaceIRIs nsID, nsID)+ -- | Given a namespace id, lookup its IRI. May be overridden for performance.+ getIRI :: nsID+ -> NameSpaceIRIs nsID+ -> Maybe NameSpaceIRI+ -- | The root element of an XML document has a namespace, too, and the+ -- "XML.Light-parser" is eager to remove the corresponding namespace+ -- attribute.+ -- As a result, at least this root namespace must be provided.+ getInitialIRImap :: NameSpaceIRIs nsID++ getIRI = M.lookup+ getInitialIRImap = M.empty
@@ -0,0 +1,36 @@+{- |+ Module : Text.Pandoc.Readers.ODT.Generic.SetMap+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++A map of values to sets of values.+-}++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++type SetMap k v = M.Map k (S.Set v)++empty :: SetMap k v+empty = M.empty++fromList :: (Ord k, Ord v) => [(k,v)] -> SetMap k v+fromList = foldr (uncurry insert) empty++insert :: (Ord k, Ord v) => k -> v -> SetMap k v -> SetMap k v+insert key value setMap = M.insertWith S.union key (S.singleton value) setMap++union3 :: (Ord k) => SetMap k v -> SetMap k v -> SetMap k v -> SetMap k v+union3 sm1 sm2 sm3 = sm1 `M.union` sm2 `M.union` sm3
@@ -0,0 +1,116 @@+{-# LANGUAGE ViewPatterns #-}+{- |+ Module : Text.Pandoc.Reader.ODT.Generic.Utils+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++General utility functions for the odt reader.+-}++module Text.Pandoc.Readers.ODT.Generic.Utils+( uncurry3+, uncurry4+, uncurry5+, uncurry6+, swap+, reverseComposition+, tryToRead+, Lookupable(..)+, readLookupable+, readPercent+, findBy+, swing+, composition+) where++import Control.Category (Category, (<<<), (>>>))+import qualified Control.Category as Cat (id)+import Data.Char (isSpace)+import qualified Data.Foldable as F (Foldable, foldr)+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as T++-- | Equivalent to+-- > foldr (.) id+-- where '(.)' are 'id' are the ones from "Control.Category"+-- and 'foldr' is the one from "Data.Foldable".+-- The noun-form was chosen to be consistent with 'sum', 'product' etc+-- based on the discussion at+-- <https://groups.google.com/forum/#!topic/haskell-cafe/VkOZM1zaHOI>+-- (that I was not part of)+composition :: (Category cat, F.Foldable f) => f (cat a a) -> cat a a+composition = F.foldr (<<<) Cat.id++-- | Equivalent to+-- > foldr (flip (.)) id+-- where '(.)' are 'id' are the ones from "Control.Category"+-- and 'foldr' is the one from "Data.Foldable".+-- A reversed version of 'composition'.+reverseComposition :: (Category cat, F.Foldable f) => f (cat a a) -> cat a a+reverseComposition = F.foldr (>>>) Cat.id++-- | This function often makes it possible to switch values with the functions+-- that are applied to them.+--+-- Examples:+-- > swing map :: [a -> b] -> a -> [b]+-- > swing any :: [a -> Bool] -> a -> Bool+-- > swing foldr :: b -> a -> [a -> b -> b] -> b+-- > swing scanr :: c -> a -> [a -> c -> c] -> c+-- > swing zipWith :: [a -> b -> c] -> a -> [b] -> [c]+-- > swing find :: [a -> Bool] -> a -> Maybe (a -> Bool)+--+-- Stolen from <https://wiki.haskell.org/Pointfree>+swing :: (((a -> b) -> b) -> c -> d) -> c -> a -> d+swing = flip.(.flip id)+-- swing f c a = f ($ a) c+++-- | Alternative to 'read'/'reads'. The former of these throws errors+-- (nobody wants that) while the latter returns "to much" for simple purposes.+-- This function instead applies 'reads' and returns the first match (if any)+-- in a 'Maybe'.+tryToRead :: (Read r) => Text -> Maybe r+tryToRead = (reads . T.unpack) >>> listToMaybe >>> fmap fst++-- | A version of 'reads' that requires a '%' sign after the number+readPercent :: ReadS Int+readPercent s = [ (i,s') | (i , r ) <- reads s+ , ("%" , s') <- lex r+ ]++-- | Data that can be looked up.+-- This is mostly a utility to read data with kind *.+class Lookupable a where+ lookupTable :: [(Text, a)]++-- | Very similar to a simple 'lookup' in the 'lookupTable', but with a lexer.+readLookupable :: (Lookupable a) => Text -> Maybe a+readLookupable s =+ lookup (T.takeWhile (not . isSpace) $ T.dropWhile isSpace s) lookupTable++uncurry3 :: (a->b->c -> z) -> (a,b,c ) -> z+uncurry4 :: (a->b->c->d -> z) -> (a,b,c,d ) -> z+uncurry5 :: (a->b->c->d->e -> z) -> (a,b,c,d,e ) -> z+uncurry6 :: (a->b->c->d->e->f -> z) -> (a,b,c,d,e,f ) -> z++uncurry3 fun (a,b,c ) = fun a b c+uncurry4 fun (a,b,c,d ) = fun a b c d+uncurry5 fun (a,b,c,d,e ) = fun a b c d e+uncurry6 fun (a,b,c,d,e,f ) = fun a b c d e f++swap :: (a,b) -> (b,a)+swap (a,b) = (b,a)++-- | A version of "Data.List.find" that uses a converter to a Maybe instance.+-- The returned value is the first which the converter returns in a 'Just'+-- wrapper.+findBy :: (a -> Maybe b) -> [a] -> Maybe b+findBy _ [] = Nothing+findBy f ((f -> Just x):_ ) = Just x+findBy f ( _:xs) = findBy f xs
@@ -0,0 +1,781 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PatternGuards #-}+{- |+ Module : Text.Pandoc.Readers.ODT.Generic.XMLConverter+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++A generalized XML parser based on stateful arrows.+It might be sufficient to define this reader as a comonad, but there is+not a lot of use in trying.+-}++module Text.Pandoc.Readers.ODT.Generic.XMLConverter+( ElementName+, XMLConverterState+, XMLConverter+, FallibleXMLConverter+, runConverter'+, getExtraState+, setExtraState+, modifyExtraState+, producingExtraState+, findChild'+, filterChildrenName'+, isSet'+, isSetWithDefault+, elName+, searchAttr+, lookupAttr+, lookupAttr'+, lookupDefaultingAttr+, findAttr'+, findAttrText'+, findAttr+, findAttrText+, findAttrTextWithDefault+, readAttr+, readAttr'+, readAttrWithDefault+, getAttr+, executeIn+, executeInSub+, withEveryL+, tryAll+, matchContent'+, matchContent+) where++import Prelude hiding (Applicative(..))+import Control.Applicative hiding ( liftA, liftA2 )+import Control.Monad ( MonadPlus )+import Control.Arrow++import Data.Bool ( bool )+import Data.Either ( rights )+import qualified Data.Map as M+import Data.Text (Text)+import Data.Default+import Data.Maybe+import qualified Data.List as L+import qualified Data.List.NonEmpty as NonEmpty+import Data.List.NonEmpty (NonEmpty(..))++import qualified Text.Pandoc.XML.Light as XML++import Text.Pandoc.Readers.ODT.Arrows.State+import Text.Pandoc.Readers.ODT.Arrows.Utils+import Text.Pandoc.Readers.ODT.Generic.Namespaces+import Text.Pandoc.Readers.ODT.Generic.Utils+import Text.Pandoc.Readers.ODT.Generic.Fallible++--------------------------------------------------------------------------------+-- Basis types for readability+--------------------------------------------------------------------------------++--+type ElementName = Text+type AttributeName = Text+type AttributeValue = Text+type TextAttributeValue = Text++--+type NameSpacePrefix = Text++--+type NameSpacePrefixes nsID = M.Map nsID NameSpacePrefix++--------------------------------------------------------------------------------+-- Main converter state+--------------------------------------------------------------------------------++-- GADT so some of the NameSpaceID restrictions can be deduced+data XMLConverterState nsID extraState where+ XMLConverterState :: NameSpaceID nsID+ => { -- | A stack of parent elements. The top element is the current one.+ -- Arguably, a real Zipper would be better. But that is an+ -- optimization that can be made at a later time, e.g. when+ -- replacing Text.XML.Light.+ parentElements :: NonEmpty XML.Element+ -- | A map from internal namespace IDs to the namespace prefixes+ -- used in XML elements+ , namespacePrefixes :: NameSpacePrefixes nsID+ -- | A map from internal namespace IDs to namespace IRIs+ -- (Only necessary for matching namespace IDs and prefixes)+ , namespaceIRIs :: NameSpaceIRIs nsID+ -- | A place to put "something else". This feature is used heavily+ -- to keep the main code cleaner. More specifically, the main reader+ -- is divided into different stages. Each stage lifts something up+ -- here, which the next stage can then use. This could of course be+ -- generalized to a state-tree or used for the namespace IRIs. The+ -- border between states and values is an imaginary one, after all.+ -- But the separation as it is seems to be enough for now.+ , moreState :: extraState+ }+ -> XMLConverterState nsID extraState++--+createStartState :: (NameSpaceID nsID)+ => XML.Element+ -> extraState+ -> XMLConverterState nsID extraState+createStartState element extraState =+ XMLConverterState+ { parentElements = element :| []+ , namespacePrefixes = M.empty+ , namespaceIRIs = getInitialIRImap+ , moreState = extraState+ }++-- | Functor over extra state+instance Functor (XMLConverterState nsID) where+ fmap f ( XMLConverterState parents prefixes iRIs extraState )+ = XMLConverterState parents prefixes iRIs (f extraState)++--+replaceExtraState :: extraState+ -> XMLConverterState nsID _x+ -> XMLConverterState nsID extraState+replaceExtraState x s+ = fmap (const x) s++--+currentElement :: XMLConverterState nsID extraState+ -> XML.Element+currentElement state = NonEmpty.head (parentElements state)++-- | Replace the current position by another, modifying the extra state+-- in the process+swapStack' :: XMLConverterState nsID extraState+ -> NonEmpty XML.Element+ -> ( XMLConverterState nsID extraState+ , NonEmpty XML.Element )+swapStack' state stack+ = ( state { parentElements = stack }+ , parentElements state+ )++--+pushElement :: XML.Element+ -> XMLConverterState nsID extraState+ -> XMLConverterState nsID extraState+pushElement e state = state { parentElements =+ NonEmpty.cons e (parentElements state) }++-- | Pop the top element from the call stack, unless it is the last one.+popElement :: XMLConverterState nsID extraState+ -> Maybe (XMLConverterState nsID extraState)+popElement state+ | _ :| (e:es) <- parentElements state+ = Just $ state { parentElements = e :| es }+ | otherwise = Nothing++--------------------------------------------------------------------------------+-- Main type+--------------------------------------------------------------------------------++-- It might be a good idea to pack the converters in a GADT+-- Downside: data instead of type+-- Upside: 'Failure' could be made a parameter as well.++--+type XMLConverter nsID extraState input output+ = ArrowState (XMLConverterState nsID extraState ) input output++type FallibleXMLConverter nsID extraState input output+ = XMLConverter nsID extraState input (Fallible output)++--+runConverter :: XMLConverter nsID extraState input output+ -> XMLConverterState nsID extraState+ -> input+ -> output+runConverter converter state input = snd $ runArrowState converter (state,input)++runConverter' :: (NameSpaceID nsID)+ => FallibleXMLConverter nsID extraState () success+ -> extraState+ -> XML.Element+ -> Fallible success+runConverter' converter extraState element = runConverter (readNSattributes >>? converter) (createStartState element extraState) ()++--+getCurrentElement :: XMLConverter nsID extraState x XML.Element+getCurrentElement = extractFromState currentElement++--+getExtraState :: XMLConverter nsID extraState x extraState+getExtraState = extractFromState moreState++--+setExtraState :: XMLConverter nsID extraState extraState extraState+setExtraState = withState $ \state extra+ -> (replaceExtraState extra state , extra)+++-- | Lifts a function to the extra state.+modifyExtraState :: (extraState -> extraState)+ -> XMLConverter nsID extraState x x+modifyExtraState = modifyState.fmap+++-- | First sets the extra state to the new value. Then modifies the original+-- extra state with a converter that uses the new state. Finally, the+-- intermediate state is dropped and the extra state is lifted into the+-- state as it was at the beginning of the function.+-- As a result, exactly the extra state and nothing else is changed.+-- The resulting converter even behaves like an identity converter on the+-- value level.+--+-- (The -ing form is meant to be mnemonic in a sequence of arrows as in+-- convertingExtraState () converter >>> doOtherStuff)+--+convertingExtraState :: extraState'+ -> FallibleXMLConverter nsID extraState' extraState extraState+ -> FallibleXMLConverter nsID extraState x x+convertingExtraState v a = withSubStateF setVAsExtraState modifyWithA+ where+ setVAsExtraState = liftAsSuccess $ extractFromState id >>^ replaceExtraState v+ modifyWithA = keepingTheValue (moreState ^>> a)+ >>^ spreadChoice >>?% flip replaceExtraState++-- | First sets the extra state to the new value. Then produces a new+-- extra state with a converter that uses the new state. Finally, the+-- intermediate state is dropped and the extra state is lifted into the+-- state as it was at the beginning of the function.+-- As a result, exactly the extra state and nothing else is changed.+-- The resulting converter even behaves like an identity converter on the+-- value level.+--+-- Equivalent to+--+-- > \v x a -> convertingExtraState v (returnV x >>> a)+--+-- (The -ing form is meant to be mnemonic in a sequence of arrows as in+-- producingExtraState () () producer >>> doOtherStuff)+--+producingExtraState :: extraState'+ -> a+ -> FallibleXMLConverter nsID extraState' a extraState+ -> FallibleXMLConverter nsID extraState x x+producingExtraState v x a = convertingExtraState v (returnV x >>> a)+++--------------------------------------------------------------------------------+-- Work in namespaces+--------------------------------------------------------------------------------++-- | Arrow version of 'getIRI'+lookupNSiri :: (NameSpaceID nsID)+ => nsID+ -> XMLConverter nsID extraState x (Maybe NameSpaceIRI)+lookupNSiri nsID = extractFromState+ $ \state -> getIRI nsID $ namespaceIRIs state++--+lookupNSprefix :: (NameSpaceID nsID)+ => nsID+ -> XMLConverter nsID extraState x (Maybe NameSpacePrefix)+lookupNSprefix nsID = extractFromState+ $ \state -> M.lookup nsID $ namespacePrefixes state++-- | Extracts namespace attributes from the current element and tries to+-- update the current mapping accordingly+readNSattributes :: (NameSpaceID nsID)+ => FallibleXMLConverter nsID extraState x ()+readNSattributes = fromState $ \state -> maybe (state, failEmpty )+ ( , succeedWith ())+ (extractNSAttrs state )+ where+ extractNSAttrs :: (NameSpaceID nsID)+ => XMLConverterState nsID extraState+ -> Maybe (XMLConverterState nsID extraState)+ extractNSAttrs startState+ = L.foldl' (\state d -> state >>= addNS d)+ (Just startState)+ nsAttribs+ where nsAttribs = mapMaybe readNSattr (XML.elAttribs element)+ element = currentElement startState+ readNSattr (XML.Attr (XML.QName name _ (Just "xmlns")) iri)+ = Just (name, iri)+ readNSattr _ = Nothing+ addNS (prefix, iri) state = fmap updateState+ $ getNamespaceID iri+ $ namespaceIRIs state+ where updateState (iris,nsID)+ = state { namespaceIRIs = iris+ , namespacePrefixes = M.insert nsID prefix+ $ namespacePrefixes state+ }++--------------------------------------------------------------------------------+-- Common namespace accessors+--------------------------------------------------------------------------------++-- | Given a namespace id and an element name, creates a 'XML.QName' for+-- internal use+qualifyName :: (NameSpaceID nsID)+ => nsID -> ElementName+ -> XMLConverter nsID extraState x XML.QName+qualifyName nsID name = lookupNSiri nsID+ &&& lookupNSprefix nsID+ >>% XML.QName name++-- | Checks if a given element matches both a specified namespace id+-- and a predicate+elemNameMatches :: (NameSpaceID nsID)+ => nsID -> (ElementName -> Bool)+ -> XMLConverter nsID extraState XML.Element Bool+elemNameMatches nsID f = keepingTheValue (lookupNSiri nsID) >>% hasMatchingName+ where hasMatchingName e iri = let name = XML.elName e+ in f (XML.qName name)+ && XML.qURI name == iri++-- | Checks if a given element matches both a specified namespace id+-- and a specified element name+elemNameIs :: (NameSpaceID nsID)+ => nsID -> ElementName+ -> XMLConverter nsID extraState XML.Element Bool+elemNameIs nsID name = elemNameMatches nsID (== name)++--------------------------------------------------------------------------------+-- General content+--------------------------------------------------------------------------------++elName :: XML.Element -> ElementName+elName = XML.qName . XML.elName++--+elContent :: XMLConverter nsID extraState x [XML.Content]+elContent = getCurrentElement+ >>^ XML.elContent++--------------------------------------------------------------------------------+-- Children+--------------------------------------------------------------------------------++--+--+findChildren :: (NameSpaceID nsID)+ => nsID -> ElementName+ -> XMLConverter nsID extraState x [XML.Element]+findChildren nsID name = qualifyName nsID name+ &&& getCurrentElement+ >>% XML.findChildren++--+findChild' :: (NameSpaceID nsID)+ => nsID+ -> ElementName+ -> XMLConverter nsID extraState x (Maybe XML.Element)+findChild' nsID name = qualifyName nsID name+ &&& getCurrentElement+ >>% XML.findChild++--+findChild :: (NameSpaceID nsID)+ => nsID -> ElementName+ -> FallibleXMLConverter nsID extraState x XML.Element+findChild nsID name = findChild' nsID name+ >>> maybeToChoice++filterChildrenName' :: (NameSpaceID nsID)+ => nsID+ -> (ElementName -> Bool)+ -> XMLConverter nsID extraState x [XML.Element]+filterChildrenName' nsID f = getCurrentElement+ >>> arr XML.elChildren+ >>> iterateS (keepingTheValue (elemNameMatches nsID f))+ >>> arr (map fst . filter snd)++--------------------------------------------------------------------------------+-- Attributes+--------------------------------------------------------------------------------++--+isSet' :: (NameSpaceID nsID)+ => nsID -> AttributeName+ -> XMLConverter nsID extraState x (Maybe Bool)+isSet' nsID attrName = findAttr' nsID attrName+ >>^ (>>= stringToBool')++isSetWithDefault :: (NameSpaceID nsID)+ => nsID -> AttributeName+ -> Bool+ -> XMLConverter nsID extraState x Bool+isSetWithDefault nsID attrName def'+ = isSet' nsID attrName+ >>^ fromMaybe def'++-- | Lookup value in a dictionary, fail if no attribute found or value+-- not in dictionary+searchAttrIn :: (NameSpaceID nsID)+ => nsID -> AttributeName+ -> [(AttributeValue,a)]+ -> FallibleXMLConverter nsID extraState x a+searchAttrIn nsID attrName dict+ = findAttr nsID attrName+ >>?^? maybeToChoice.(`lookup` dict )++-- | Lookup value in a dictionary. If attribute or value not found,+-- return default value+searchAttr :: (NameSpaceID nsID)+ => nsID -> AttributeName+ -> a+ -> [(AttributeValue,a)]+ -> XMLConverter nsID extraState x a+searchAttr nsID attrName defV dict+ = searchAttrIn nsID attrName dict+ >>> const defV ^|||^ id++-- | Read a 'Lookupable' attribute. Fail if no match.+lookupAttr :: (NameSpaceID nsID, Lookupable a)+ => nsID -> AttributeName+ -> FallibleXMLConverter nsID extraState x a+lookupAttr nsID attrName = lookupAttr' nsID attrName+ >>^ maybeToChoice+++-- | Read a 'Lookupable' attribute. Return the result as a 'Maybe'.+lookupAttr' :: (NameSpaceID nsID, Lookupable a)+ => nsID -> AttributeName+ -> XMLConverter nsID extraState x (Maybe a)+lookupAttr' nsID attrName+ = findAttr' nsID attrName+ >>^ (>>= readLookupable)++-- | Read a 'Lookupable' attribute with explicit default+lookupAttrWithDefault :: (NameSpaceID nsID, Lookupable a)+ => nsID -> AttributeName+ -> a+ -> XMLConverter nsID extraState x a+lookupAttrWithDefault nsID attrName deflt+ = lookupAttr' nsID attrName+ >>^ fromMaybe deflt++-- | Read a 'Lookupable' attribute with implicit default+lookupDefaultingAttr :: (NameSpaceID nsID, Lookupable a, Default a)+ => nsID -> AttributeName+ -> XMLConverter nsID extraState x a+lookupDefaultingAttr nsID attrName+ = lookupAttrWithDefault nsID attrName def++-- | Return value as a (Maybe Text)+findAttr' :: (NameSpaceID nsID)+ => nsID -> AttributeName+ -> XMLConverter nsID extraState x (Maybe AttributeValue)+findAttr' nsID attrName = qualifyName nsID attrName+ &&& getCurrentElement+ >>% XML.findAttr++-- | Return value as a (Maybe Text)+findAttrText' :: (NameSpaceID nsID)+ => nsID -> AttributeName+ -> XMLConverter nsID extraState x (Maybe TextAttributeValue)+findAttrText' nsID attrName+ = qualifyName nsID attrName+ &&& getCurrentElement+ >>% XML.findAttr++-- | Return value as string or fail+findAttr :: (NameSpaceID nsID)+ => nsID -> AttributeName+ -> FallibleXMLConverter nsID extraState x AttributeValue+findAttr nsID attrName = findAttr' nsID attrName+ >>> maybeToChoice++-- | Return value as text or fail+findAttrText :: (NameSpaceID nsID)+ => nsID -> AttributeName+ -> FallibleXMLConverter nsID extraState x TextAttributeValue+findAttrText nsID attrName+ = findAttr' nsID attrName+ >>> maybeToChoice++-- | Return value as string or return provided default value+findAttrTextWithDefault :: (NameSpaceID nsID)+ => nsID -> AttributeName+ -> TextAttributeValue+ -> XMLConverter nsID extraState x TextAttributeValue+findAttrTextWithDefault nsID attrName deflt+ = findAttr' nsID attrName+ >>^ fromMaybe deflt++-- | Read and return value or fail+readAttr :: (NameSpaceID nsID, Read attrValue)+ => nsID -> AttributeName+ -> FallibleXMLConverter nsID extraState x attrValue+readAttr nsID attrName = readAttr' nsID attrName+ >>> maybeToChoice++-- | Read and return value or return Nothing+readAttr' :: (NameSpaceID nsID, Read attrValue)+ => nsID -> AttributeName+ -> XMLConverter nsID extraState x (Maybe attrValue)+readAttr' nsID attrName = findAttr' nsID attrName+ >>^ (>>= tryToRead)++-- | Read and return value or return provided default value+readAttrWithDefault :: (NameSpaceID nsID, Read attrValue)+ => nsID -> AttributeName+ -> attrValue+ -> XMLConverter nsID extraState x attrValue+readAttrWithDefault nsID attrName deflt+ = findAttr' nsID attrName+ >>^ (>>= tryToRead)+ >>^ fromMaybe deflt++-- | Read and return value or return default value from 'Default' instance+getAttr :: (NameSpaceID nsID, Read attrValue, Default attrValue)+ => nsID -> AttributeName+ -> XMLConverter nsID extraState x attrValue+getAttr nsID attrName = readAttrWithDefault nsID attrName def++--------------------------------------------------------------------------------+-- Movements+--------------------------------------------------------------------------------++--+jumpThere :: XMLConverter nsID extraState XML.Element XML.Element+jumpThere = withState (\state element+ -> ( pushElement element state , element )+ )++--+swapStack :: XMLConverter nsID extraState (NonEmpty XML.Element)+ (NonEmpty XML.Element)+swapStack = withState swapStack'++--+jumpBack :: FallibleXMLConverter nsID extraState _x _x+jumpBack = tryModifyState (popElement >>> maybeToChoice)++-- | Support function for "procedural" converters: jump to an element, execute+-- a converter, jump back.+-- This version is safer than 'executeThere', because it does not rely on the+-- internal stack. As a result, the converter can not move around in arbitrary+-- ways. The downside is of course that some of the environment is not+-- accessible to the converter.+switchingTheStack :: XMLConverter nsID moreState a b+ -> XMLConverter nsID moreState (a, XML.Element) b+switchingTheStack a = second ( (:| []) ^>> swapStack )+ >>> first a+ >>> second swapStack+ >>^ fst++-- | Support function for "procedural" converters: jumps to an element, executes+-- a converter, jumps back.+-- Make sure that the converter is well-behaved; that is it should+-- return to the exact position it started from in /every possible path/ of+-- execution, even if it "fails". If it does not, you may encounter+-- strange bugs. If you are not sure about the behaviour or want to use+-- shortcuts, you can often use 'switchingTheStack' instead.+executeThere :: FallibleXMLConverter nsID moreState a b+ -> FallibleXMLConverter nsID moreState (a, XML.Element) b+executeThere a = second jumpThere+ >>> fst+ ^>> a+ >>> jumpBack -- >>? jumpBack would not ensure the jump.+ >>^ collapseEither+++-- | Do something in a specific element, then come back+executeIn :: XMLConverter nsID extraState XML.Element s+ -> XMLConverter nsID extraState XML.Element s+executeIn a = duplicate >>> switchingTheStack a++-- | Do something in a sub-element, then come back+executeInSub :: (NameSpaceID nsID)+ => nsID -> ElementName+ -> FallibleXMLConverter nsID extraState f s+ -> FallibleXMLConverter nsID extraState f s+executeInSub nsID name a = keepingTheValue+ (findChild nsID name)+ >>> ignoringState liftFailure+ >>? switchingTheStack a+ where liftFailure (_, Left f) = Left f+ liftFailure (x, Right e) = Right (x, e)++--------------------------------------------------------------------------------+-- Iterating over children+--------------------------------------------------------------------------------++-- Helper converter to prepare different types of iterations.+-- It lifts the children (of a certain type) of the current element+-- into the value level and pairs each one with the current input value.+prepareIteration :: (NameSpaceID nsID)+ => nsID -> ElementName+ -> XMLConverter nsID extraState b [(b, XML.Element)]+prepareIteration nsID name = keepingTheValue+ (findChildren nsID name)+ >>% distributeValue++--+withEveryL :: (NameSpaceID nsID)+ => nsID -> ElementName+ -> FallibleXMLConverter nsID extraState a b+ -> FallibleXMLConverter nsID extraState a [b]+withEveryL = withEvery++-- | Applies a converter to every child element of a specific type.+-- Collects results in a 'MonadPlus'.+-- Fails completely if any conversion fails.+withEvery :: (NameSpaceID nsID, MonadPlus m)+ => nsID -> ElementName+ -> FallibleXMLConverter nsID extraState a b+ -> FallibleXMLConverter nsID extraState a (m b)+withEvery nsID name a = prepareIteration nsID name+ >>> iterateS' (switchingTheStack a)++-- | Applies a converter to every child element of a specific type.+-- Collects all successful results in a list.+tryAll :: (NameSpaceID nsID)+ => nsID -> ElementName+ -> FallibleXMLConverter nsID extraState b a+ -> XMLConverter nsID extraState b [a]+tryAll nsID name a = prepareIteration nsID name+ >>> iterateS (switchingTheStack a)+ >>^ rights++--------------------------------------------------------------------------------+-- Matching children+--------------------------------------------------------------------------------++type IdXMLConverter nsID moreState x+ = XMLConverter nsID moreState x x++type MaybeCConverter nsID moreState x+ = Maybe (IdXMLConverter nsID moreState (x, XML.Content))++-- Chainable converter that helps deciding which converter to actually use.+type ContentMatchConverter nsID extraState x+ = IdXMLConverter nsID+ extraState+ (MaybeCConverter nsID extraState x, XML.Content)++-- Helper function: The @c@ is actually a converter that is to be selected by+-- matching XML content to the first two parameters.+-- The fold used to match elements however is very simple, so to use it,+-- this function wraps the converter in another converter that unifies+-- the accumulator. Think of a lot of converters with the resulting type+-- chained together. The accumulator not only transports the element+-- unchanged to the next matcher, it also does the actual selecting by+-- combining the intermediate results with '(<|>)'.+makeMatcherC :: (NameSpaceID nsID)+ => nsID -> ElementName+ -> FallibleXMLConverter nsID extraState a a+ -> ContentMatchConverter nsID extraState a+makeMatcherC nsID name c = ( second ( contentToElem+ >>> returnV Nothing+ ||| ( elemNameIs nsID name+ >>^ bool Nothing (Just cWithJump)+ )+ )+ >>% (<|>)+ ) &&&^ snd+ where cWithJump = ( fst+ ^&&& ( second contentToElem+ >>> spreadChoice+ ^>>? executeThere c+ )+ >>% recover)+ &&&^ snd+ contentToElem :: FallibleXMLConverter nsID extraState XML.Content XML.Element+ contentToElem = arr $ \case+ XML.Elem e' -> succeedWith e'+ _ -> failEmpty++-- Creates and chains a bunch of matchers+prepareMatchersC :: (NameSpaceID nsID)+ => [(nsID, ElementName, FallibleXMLConverter nsID extraState x x)]+ -> ContentMatchConverter nsID extraState x+--prepareMatchersC = foldSs . (map $ uncurry3 makeMatcherC)+prepareMatchersC = reverseComposition . map (uncurry3 makeMatcherC)++-- | Takes a list of element-data - converter groups and+-- * Finds all content of the current element+-- * Matches each group to each piece of content in order+-- (at most one group per piece of content)+-- * Filters non-matched content+-- * Chains all found converters in content-order+-- * Applies the chain to the input element+matchContent' :: (NameSpaceID nsID)+ => [(nsID, ElementName, FallibleXMLConverter nsID extraState a a)]+ -> XMLConverter nsID extraState a a+matchContent' lookups = matchContent lookups (arr fst)++-- | Takes a list of element-data - converter groups and+-- * Finds all content of the current element+-- * Matches each group to each piece of content in order+-- (at most one group per piece of content)+-- * Adds a default converter for all non-matched content+-- * Chains all found converters in content-order+-- * Applies the chain to the input element+matchContent :: (NameSpaceID nsID)+ => [(nsID, ElementName, FallibleXMLConverter nsID extraState a a)]+ -> XMLConverter nsID extraState (a,XML.Content) a+ -> XMLConverter nsID extraState a a+matchContent lookups fallback+ = let matcher = prepareMatchersC lookups+ in keepingTheValue (+ elContent+ >>> map (Nothing,)+ ^>> iterateSL matcher+ >>^ map swallowOrFallback+ -- >>> foldSs+ >>> reverseComposition+ )+ >>> swap+ ^>> app+ where+ -- let the converter swallow the content and drop the content+ -- in the return value+ swallowOrFallback (Just converter,content) = (,content) ^>> converter >>^ fst+ swallowOrFallback (Nothing ,content) = (,content) ^>> fallback++--------------------------------------------------------------------------------+-- Internals+--------------------------------------------------------------------------------++stringToBool' :: Text -> Maybe Bool+stringToBool' val | val `elem` trueValues = Just True+ | val `elem` falseValues = Just False+ | otherwise = Nothing+ where trueValues = ["true" ,"on" ,"1"]+ falseValues = ["false","off","0"]+++distributeValue :: a -> [b] -> [(a,b)]+distributeValue = map.(,)++--------------------------------------------------------------------------------++{-+NOTES+It might be a good idea to refactor the namespace stuff.+E.g.: if a namespace constructor took a string as a parameter, things like+> a ?>/< (NsText,"body")+would be nicer.+Together with a rename and some trickery, something like+> |< NsText "body" >< NsText "p" ?> a </> </>|+might even be possible.++Some day, XML.Light should be replaced by something better.+While doing that, it might be useful to replace String as the type of element+names with something else, too. (Of course with OverloadedStrings).+While doing that, maybe the types can be created in a way that something like+> NsText:"body"+could be used. Overloading (:) does not sounds like the best idea, but if the+element name type was a list, this might be possible.+Of course that would be a bit hackish, so the "right" way would probably be+something like+> InNS NsText "body"+but isn't that a bit boring? ;)+-}
@@ -0,0 +1,93 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Reader.ODT.Namespaces+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++Namespaces used in odt files.+-}++module Text.Pandoc.Readers.ODT.Namespaces ( Namespace (..)+ ) where++import qualified Data.Map as M (empty, insert)+import Data.Maybe (fromMaybe, listToMaybe)+import Data.Text (Text)+import qualified Data.Text as T+import Text.Pandoc.Readers.ODT.Generic.Namespaces+++instance NameSpaceID Namespace where++ getInitialIRImap = nsIDmap++ getNamespaceID "" m = Just(m, NsXML)+ getNamespaceID iri m = asPair $ fromMaybe (NsOther iri) (findID iri)+ where asPair nsID = Just (M.insert nsID iri m, nsID)+++findID :: NameSpaceIRI -> Maybe Namespace+findID iri = listToMaybe [nsID | (iri',nsID) <- nsIDs, iri' `T.isPrefixOf` iri]++nsIDmap :: NameSpaceIRIs Namespace+nsIDmap = foldr (uncurry $ flip M.insert) M.empty nsIDs++data Namespace = -- Open Document core+ NsOffice | NsStyle | NsText | NsTable | NsForm+ | NsDraw | Ns3D | NsAnim | NsChart | NsConfig+ | NsDB | NsMeta | NsNumber | NsScript | NsManifest+ | NsPresentation+ -- Metadata+ | NsODF+ -- Compatible elements+ | NsXSL_FO | NsSVG | NsSmil+ -- External standards+ | NsMathML | NsXForms | NsXLink | NsXHtml | NsGRDDL+ | NsDublinCore+ -- Metadata manifest+ | NsPKG+ -- Others+ | NsOpenFormula+ -- Core XML (basically only for the 'id'-attribute)+ | NsXML+ -- Fallback+ | NsOther Text+ deriving ( Eq, Ord, Show )++-- | Not the actual iri's, but large prefixes of them - this way there are+-- less versioning problems and the like.+nsIDs :: [(Text, Namespace)]+nsIDs = [+ ("urn:oasis:names:tc:opendocument:xmlns:animation" , NsAnim ),+ ("urn:oasis:names:tc:opendocument:xmlns:chart" , NsChart ),+ ("urn:oasis:names:tc:opendocument:xmlns:config" , NsConfig ),+ ("urn:oasis:names:tc:opendocument:xmlns:database" , NsDB ),+ ("urn:oasis:names:tc:opendocument:xmlns:dr3d" , Ns3D ),+ ("urn:oasis:names:tc:opendocument:xmlns:drawing" , NsDraw ),+ ("urn:oasis:names:tc:opendocument:xmlns:form" , NsForm ),+ ("urn:oasis:names:tc:opendocument:xmlns:manifest" , NsManifest ),+ ("urn:oasis:names:tc:opendocument:xmlns:meta" , NsMeta ),+ ("urn:oasis:names:tc:opendocument:xmlns:datastyle" , NsNumber ),+ ("urn:oasis:names:tc:opendocument:xmlns:of" , NsOpenFormula ),+ ("urn:oasis:names:tc:opendocument:xmlns:office:1.0" , NsOffice ),+ ("urn:oasis:names:tc:opendocument:xmlns:presentation" , NsPresentation ),+ ("urn:oasis:names:tc:opendocument:xmlns:script" , NsScript ),+ ("urn:oasis:names:tc:opendocument:xmlns:style" , NsStyle ),+ ("urn:oasis:names:tc:opendocument:xmlns:table" , NsTable ),+ ("urn:oasis:names:tc:opendocument:xmlns:text" , NsText ),+ ("urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible", NsXSL_FO ),+ ("urn:oasis:names:tc:opendocument:xmlns:smil-compatible" , NsSmil ),+ ("urn:oasis:names:tc:opendocument:xmlns:svg-compatible" , NsSVG ),+ ("http://docs.oasis-open.org/ns/office/1.2/meta/odf" , NsODF ),+ ("http://docs.oasis-open.org/ns/office/1.2/meta/pkg" , NsPKG ),+ ("http://purl.org/dc/elements" , NsDublinCore ),+ ("http://www.w3.org/2003/g/data-view" , NsGRDDL ),+ ("http://www.w3.org/1998/Math/MathML" , NsMathML ),+ ("http://www.w3.org/1999/xhtml" , NsXHtml ),+ ("http://www.w3.org/2002/xforms" , NsXForms ),+ ("http://www.w3.org/1999/xlink" , NsXLink )+ ]
@@ -0,0 +1,640 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE Arrows #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.ODT.StyleReader+ Copyright : Copyright (C) 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>+ Stability : alpha+ Portability : portable++Reader for the style information in an odt document.+-}++module Text.Pandoc.Readers.ODT.StyleReader+( Style (..)+, StyleName+, StyleFamily (..)+, Styles (..)+, StyleProperties (..)+, TextProperties (..)+, ParaProperties (..)+, VerticalTextPosition (..)+, ListItemNumberFormat (..)+, ListLevel+, ListStyle (..)+, ListLevelStyle (..)+, ListLevelType (..)+, LengthOrPercent (..)+, lookupStyle+, getListLevelStyle+, getStyleFamily+, lookupDefaultStyle'+, lookupListStyleByName+, extendedStylePropertyChain+, readStylesAt+) where++import Prelude hiding (Applicative(..))+import Control.Applicative hiding (liftA, liftA2, liftA3)+import Control.Arrow++import Data.Default+import qualified Data.Foldable as F+import qualified Data.List as L+import qualified Data.Map as M+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Set as S++import qualified Text.Pandoc.XML.Light as XML++import Text.Pandoc.Shared (safeRead, tshow)++import Text.Pandoc.Readers.ODT.Arrows.Utils++import Text.Pandoc.Readers.ODT.Generic.Fallible+import qualified Text.Pandoc.Readers.ODT.Generic.SetMap as SM+import Text.Pandoc.Readers.ODT.Generic.Utils+import Text.Pandoc.Readers.ODT.Generic.XMLConverter++import Text.Pandoc.Readers.ODT.Base+import Text.Pandoc.Readers.ODT.Namespaces++readStylesAt :: XML.Element -> Fallible Styles+readStylesAt e = runConverter' readAllStyles mempty e++--------------------------------------------------------------------------------+-- Reader for font declarations and font pitches+--------------------------------------------------------------------------------++-- Pandoc has no support for different font pitches. Yet knowing them can be+-- very helpful in cases where Pandoc has more semantics than OpenDocument.+-- In these cases, the pitch can help deciding as what to define a block of+-- text. So let's start with a type for font pitches:++data FontPitch = PitchVariable | PitchFixed+ deriving ( Eq, Show )++instance Lookupable FontPitch where+ lookupTable = [ ("variable" , PitchVariable)+ , ("fixed" , PitchFixed )+ ]++instance Default FontPitch where+ def = PitchVariable++-- The font pitch can be specified in a style directly. Normally, however,+-- it is defined in the font. That is also the specs' recommendation.+--+-- Thus, we want++type FontFaceName = Text++type FontPitches = M.Map FontFaceName FontPitch++-- To get there, the fonts have to be read and the pitches extracted.+-- But the resulting map are only needed at one later place, so it should not be+-- transported on the value level, especially as we already use a state arrow.+-- So instead, the resulting map is lifted into the state of the reader.+-- (An alternative might be ImplicitParams, but again, we already have a state.)+--+-- So the main style readers will have the types+type StyleReader a b = XMLReader FontPitches a b+-- and+type StyleReaderSafe a b = XMLReaderSafe FontPitches a b+-- respectively.+--+-- But before we can work with these, we need to define the reader that reads+-- the fonts:++-- | A reader for font pitches+fontPitchReader :: XMLReader s a FontPitches+fontPitchReader = executeInSub NsOffice "font-face-decls" (+ withEveryL NsStyle "font-face" (liftAsSuccess (+ findAttr' NsStyle "name"+ &&&+ lookupDefaultingAttr NsStyle "font-pitch"+ ))+ >>?^ ( M.fromList . L.foldl' accumLegalPitches [] )+ ) `ifFailedDo` returnV (Right M.empty)+ where accumLegalPitches ls (Nothing,_) = ls+ accumLegalPitches ls (Just n,p) = (n,p):ls+++-- | A wrapper around the font pitch reader that lifts the result into the+-- state.+readFontPitches :: StyleReader a a+readFontPitches = producingExtraState () () fontPitchReader+++-- | Looking up a pitch in the state of the arrow.+--+-- The function does the following:+-- * Look for the font pitch in an attribute.+-- * If that fails, look for the font name, look up the font in the state+-- and use the pitch from there.+-- * Return the result in a Maybe+--+findPitch :: XMLReaderSafe FontPitches a (Maybe FontPitch)+findPitch = ( lookupAttr NsStyle "font-pitch"+ `ifFailedDo` findAttr NsStyle "font-name"+ >>? ( keepingTheValue getExtraState+ >>% M.lookup+ >>^ maybeToChoice+ )+ )+ >>> choiceToMaybe++--------------------------------------------------------------------------------+-- Definitions of main data+--------------------------------------------------------------------------------++type StyleName = Text++-- | There are two types of styles: named styles with a style family and an+-- optional style parent, and default styles for each style family,+-- defining default style properties+data Styles = Styles+ { stylesByName :: M.Map StyleName Style+ , listStylesByName :: M.Map StyleName ListStyle+ , defaultStyleMap :: M.Map StyleFamily StyleProperties+ }+ deriving ( Show )++-- Styles from a monoid under union+instance Semigroup Styles where+ (Styles sBn1 dSm1 lsBn1) <> (Styles sBn2 dSm2 lsBn2)+ = Styles (M.union sBn1 sBn2)+ (M.union dSm1 dSm2)+ (M.union lsBn1 lsBn2)+instance Monoid Styles where+ mempty = Styles M.empty M.empty M.empty+ mappend = (<>)++-- Not all families from the specifications are implemented, only those we need.+-- But there are none that are not mentioned here.+data StyleFamily = FaText | FaParagraph+-- | FaTable | FaTableCell | FaTableColumn | FaTableRow+-- | FaGraphic | FaDrawing | FaChart+-- | FaPresentation+-- | FaRuby+ deriving ( Eq, Ord, Show )++instance Lookupable StyleFamily where+ lookupTable = [ ( "text" , FaText )+ , ( "paragraph" , FaParagraph )+-- , ( "table" , FaTable )+-- , ( "table-cell" , FaTableCell )+-- , ( "table-column" , FaTableColumn )+-- , ( "table-row" , FaTableRow )+-- , ( "graphic" , FaGraphic )+-- , ( "drawing-page" , FaDrawing )+-- , ( "chart" , FaChart )+-- , ( "presentation" , FaPresentation )+-- , ( "ruby" , FaRuby )+ ]++-- | A named style+data Style = Style { styleFamily :: Maybe StyleFamily+ , styleParentName :: Maybe StyleName+ , listStyle :: Maybe StyleName+ , styleProperties :: StyleProperties+ }+ deriving ( Eq, Show )++data StyleProperties = SProps { textProperties :: Maybe TextProperties+ , paraProperties :: Maybe ParaProperties+-- , tableColProperties :: Maybe TColProperties+-- , tableRowProperties :: Maybe TRowProperties+-- , tableCellProperties :: Maybe TCellProperties+-- , tableProperties :: Maybe TableProperties+-- , graphicProperties :: Maybe GraphProperties+ }+ deriving ( Eq, Show )++instance Default StyleProperties where+ def = SProps { textProperties = Just def+ , paraProperties = Just def+ }++data TextProperties = PropT { isEmphasised :: Bool+ , isStrong :: Bool+ , pitch :: Maybe FontPitch+ , verticalPosition :: VerticalTextPosition+ , underline :: Maybe UnderlineMode+ , strikethrough :: Maybe UnderlineMode+ }+ deriving ( Eq, Show )++instance Default TextProperties where+ def = PropT { isEmphasised = False+ , isStrong = False+ , pitch = Just def+ , verticalPosition = def+ , underline = Nothing+ , strikethrough = Nothing+ }++data ParaProperties = PropP { paraNumbering :: ParaNumbering+ , indentation :: LengthOrPercent+ , margin_left :: LengthOrPercent+ }+ deriving ( Eq, Show )++instance Default ParaProperties where+ def = PropP { paraNumbering = NumberingNone+ , indentation = def+ , margin_left = def+ }++----+-- All the little data types that make up the properties+----++data VerticalTextPosition = VPosNormal | VPosSuper | VPosSub+ deriving ( Eq, Show )++instance Default VerticalTextPosition where+ def = VPosNormal++instance Read VerticalTextPosition where+ readsPrec _ s = [ (VPosSub , s') | ("sub" , s') <- lexS ]+ ++ [ (VPosSuper , s') | ("super" , s') <- lexS ]+ ++ [ (signumToVPos n , s') | ( n , s') <- readPercent s ]+ where+ lexS = lex s+ signumToVPos n | n < 0 = VPosSub+ | n > 0 = VPosSuper+ | otherwise = VPosNormal++data UnderlineMode = UnderlineModeNormal | UnderlineModeSkipWhitespace+ deriving ( Eq, Show )++instance Lookupable UnderlineMode where+ lookupTable = [ ( "continuous" , UnderlineModeNormal )+ , ( "skip-white-space" , UnderlineModeSkipWhitespace )+ ]+++data ParaNumbering = NumberingNone | NumberingKeep | NumberingRestart Int+ deriving ( Eq, Show )++data LengthOrPercent = LengthValueMM Int | PercentValue Int+ deriving ( Eq, Show )++instance Default LengthOrPercent where+ def = LengthValueMM 0++instance Read LengthOrPercent where+ readsPrec _ s =+ [ (PercentValue percent , s' ) | (percent , s' ) <- readPercent s]+ ++ [ (LengthValueMM lengthMM , s'') | (length' , s' ) <- reads s+ , (unit , s'') <- reads s'+ , let lengthMM = estimateInMillimeter+ length' unit+ ]++data XslUnit = XslUnitMM | XslUnitCM+ | XslUnitInch+ | XslUnitPoints | XslUnitPica+ | XslUnitPixel+ | XslUnitEM++instance Show XslUnit where+ show XslUnitMM = "mm"+ show XslUnitCM = "cm"+ show XslUnitInch = "in"+ show XslUnitPoints = "pt"+ show XslUnitPica = "pc"+ show XslUnitPixel = "px"+ show XslUnitEM = "em"++instance Read XslUnit where+ readsPrec _ "mm" = [(XslUnitMM , "")]+ readsPrec _ "cm" = [(XslUnitCM , "")]+ readsPrec _ "in" = [(XslUnitInch , "")]+ readsPrec _ "pt" = [(XslUnitPoints , "")]+ readsPrec _ "pc" = [(XslUnitPica , "")]+ readsPrec _ "px" = [(XslUnitPixel , "")]+ readsPrec _ "em" = [(XslUnitEM , "")]+ readsPrec _ _ = []++-- | Rough conversion of measures into millimetres.+-- Pixels and em's are actually implementation dependent/relative measures,+-- so I could not really easily calculate anything exact here even if I wanted.+-- But I do not care about exactness right now, as I only use measures+-- to determine if a paragraph is "indented" or not.+estimateInMillimeter :: Double -> XslUnit -> Int+estimateInMillimeter n XslUnitMM = round n+estimateInMillimeter n XslUnitCM = round $ n * 10+estimateInMillimeter n XslUnitInch = round $ n * 25.4+estimateInMillimeter n XslUnitPoints = round $ n * (1/72) * 25.4+estimateInMillimeter n XslUnitPica = round $ n * 12 * (1/72) * 25.4+estimateInMillimeter n XslUnitPixel = round $ n * (1/72) * 25.4+estimateInMillimeter n XslUnitEM = round $ n * 16 * (1/72) * 25.4+++----+-- List styles+----++type ListLevel = Int++newtype ListStyle = ListStyle { levelStyles :: M.Map ListLevel ListLevelStyle+ }+ deriving ( Eq, Show )++--+getListLevelStyle :: ListLevel -> ListStyle -> Maybe ListLevelStyle+getListLevelStyle level ListStyle{..} =+ let (lower , exactHit , _) = M.splitLookup level levelStyles+ in exactHit <|> fmap fst (M.maxView lower)+ -- findBy (`M.lookup` levelStyles) [level, (level-1) .. 1]+ -- \^ simpler, but in general less efficient++data ListLevelStyle = ListLevelStyle { listLevelType :: ListLevelType+ , listItemPrefix :: Maybe Text+ , listItemSuffix :: Maybe Text+ , listItemFormat :: ListItemNumberFormat+ , listItemStart :: Int+ }+ deriving ( Eq, Ord )++instance Show ListLevelStyle where+ show ListLevelStyle{..} = "<LLS|"+ ++ show listLevelType+ ++ "|"+ ++ maybeToString (T.unpack <$> listItemPrefix)+ ++ show listItemFormat+ ++ maybeToString (T.unpack <$> listItemSuffix)+ ++ ">"+ where maybeToString = fromMaybe ""++data ListLevelType = LltBullet | LltImage | LltNumbered+ deriving ( Eq, Ord, Show )++data ListItemNumberFormat = LinfNone+ | LinfNumber+ | LinfRomanLC | LinfRomanUC+ | LinfAlphaLC | LinfAlphaUC+ | LinfString String+ deriving ( Eq, Ord )++instance Show ListItemNumberFormat where+ show LinfNone = ""+ show LinfNumber = "1"+ show LinfRomanLC = "i"+ show LinfRomanUC = "I"+ show LinfAlphaLC = "a"+ show LinfAlphaUC = "A"+ show (LinfString s) = s++instance Default ListItemNumberFormat where+ def = LinfNone++instance Read ListItemNumberFormat where+ readsPrec _ "" = [(LinfNone , "")]+ readsPrec _ "1" = [(LinfNumber , "")]+ readsPrec _ "i" = [(LinfRomanLC , "")]+ readsPrec _ "I" = [(LinfRomanUC , "")]+ readsPrec _ "a" = [(LinfAlphaLC , "")]+ readsPrec _ "A" = [(LinfAlphaUC , "")]+ readsPrec _ s = [(LinfString s , "")]++--------------------------------------------------------------------------------+-- Readers+--+-- ...it seems like a whole lot of this should be automatically derivable+-- or at least moveable into a class. Most of this is data concealed in+-- code.+--------------------------------------------------------------------------------++--+readAllStyles :: StyleReader a Styles+readAllStyles = ( readFontPitches+ >>?! ( readAutomaticStyles+ &&& readStyles ))+ >>?%? chooseMax+ -- all top elements are always on the same hierarchy level++--+readStyles :: StyleReader a Styles+readStyles = executeInSub NsOffice "styles" $ liftAsSuccess+ $ liftA3 Styles+ ( tryAll NsStyle "style" readStyle >>^ M.fromList )+ ( tryAll NsText "list-style" readListStyle >>^ M.fromList )+ ( tryAll NsStyle "default-style" readDefaultStyle >>^ M.fromList )++--+readAutomaticStyles :: StyleReader a Styles+readAutomaticStyles = executeInSub NsOffice "automatic-styles" $ liftAsSuccess+ $ liftA3 Styles+ ( tryAll NsStyle "style" readStyle >>^ M.fromList )+ ( tryAll NsText "list-style" readListStyle >>^ M.fromList )+ ( returnV M.empty )++--+readDefaultStyle :: StyleReader a (StyleFamily, StyleProperties)+readDefaultStyle = lookupAttr NsStyle "family"+ >>?! keepingTheValue readStyleProperties++--+readStyle :: StyleReader a (StyleName,Style)+readStyle = findAttr NsStyle "name"+ >>?! keepingTheValue+ ( liftA4 Style+ ( lookupAttr' NsStyle "family" )+ ( findAttr' NsStyle "parent-style-name" )+ ( findAttr' NsStyle "list-style-name" )+ readStyleProperties+ )++--+readStyleProperties :: StyleReaderSafe a StyleProperties+readStyleProperties = liftA2 SProps+ ( readTextProperties >>> choiceToMaybe )+ ( readParaProperties >>> choiceToMaybe )++--+readTextProperties :: StyleReader a TextProperties+readTextProperties =+ executeInSub NsStyle "text-properties" $ liftAsSuccess+ ( liftA6 PropT+ ( searchAttr NsXSL_FO "font-style" False isFontEmphasised )+ ( searchAttr NsXSL_FO "font-weight" False isFontBold )+ findPitch+ ( getAttr NsStyle "text-position" )+ readUnderlineMode+ readStrikeThroughMode+ )+ where isFontEmphasised = [("normal",False),("italic",True),("oblique",True)]+ isFontBold = ("normal",False):("bold",True)+ :map ((,True) . tshow) ([100,200..900]::[Int])++readUnderlineMode :: StyleReaderSafe a (Maybe UnderlineMode)+readUnderlineMode = readLineMode "text-underline-mode"+ "text-underline-style"++readStrikeThroughMode :: StyleReaderSafe a (Maybe UnderlineMode)+readStrikeThroughMode = readLineMode "text-line-through-mode"+ "text-line-through-style"++readLineMode :: Text -> Text -> StyleReaderSafe a (Maybe UnderlineMode)+readLineMode modeAttr styleAttr = proc x -> do+ isUL <- searchAttr NsStyle styleAttr False isLinePresent -< x+ mode <- lookupAttr' NsStyle modeAttr -< x+ if isUL+ then case mode of+ Just m -> returnA -< Just m+ Nothing -> returnA -< Just UnderlineModeNormal+ else returnA -< Nothing+ where+ isLinePresent = ("none",False) : map (,True)+ [ "dash" , "dot-dash" , "dot-dot-dash" , "dotted"+ , "long-dash" , "solid" , "wave"+ ]++--+readParaProperties :: StyleReader a ParaProperties+readParaProperties =+ executeInSub NsStyle "paragraph-properties" $ liftAsSuccess+ ( liftA3 PropP+ ( liftA2 readNumbering+ ( isSet' NsText "number-lines" )+ ( readAttr' NsText "line-number" )+ )+ ( liftA2 readIndentation+ ( isSetWithDefault NsStyle "auto-text-indent" False )+ ( getAttr NsXSL_FO "text-indent" )+ )+ ( getAttr NsXSL_FO "margin-left" )+ )+ where readNumbering (Just True) (Just n) = NumberingRestart n+ readNumbering (Just True) _ = NumberingKeep+ readNumbering _ _ = NumberingNone++ readIndentation False indent = indent+ readIndentation True _ = def++----+-- List styles+----++--+readListStyle :: StyleReader a (StyleName, ListStyle)+readListStyle =+ findAttr NsStyle "name"+ >>?! keepingTheValue+ ( liftA ListStyle+ $ liftA3 SM.union3+ ( readListLevelStyles NsText "list-level-style-number" LltNumbered )+ ( readListLevelStyles NsText "list-level-style-bullet" LltBullet )+ ( readListLevelStyles NsText "list-level-style-image" LltImage ) >>^ M.mapMaybe chooseMostSpecificListLevelStyle+ )+--+readListLevelStyles :: Namespace -> ElementName+ -> ListLevelType+ -> StyleReaderSafe a (SM.SetMap Int ListLevelStyle)+readListLevelStyles namespace elementName levelType =+ tryAll namespace elementName (readListLevelStyle levelType)+ >>^ SM.fromList++--+readListLevelStyle :: ListLevelType -> StyleReader a (Int, ListLevelStyle)+readListLevelStyle levelType = readAttr NsText "level"+ >>?! keepingTheValue+ ( liftA5 toListLevelStyle+ ( returnV levelType )+ ( findAttr' NsStyle "num-prefix" )+ ( findAttr' NsStyle "num-suffix" )+ ( getAttr NsStyle "num-format" )+ ( findAttrText' NsText "start-value" )+ )+ where+ toListLevelStyle _ p s LinfNone b = ListLevelStyle LltBullet p s LinfNone (startValue b)+ toListLevelStyle _ p s f@(LinfString _) b = ListLevelStyle LltBullet p s f (startValue b)+ toListLevelStyle t p s f b = ListLevelStyle t p s f (startValue b)+ startValue mbx = fromMaybe 1 (mbx >>= safeRead)++--+chooseMostSpecificListLevelStyle :: S.Set ListLevelStyle -> Maybe ListLevelStyle+chooseMostSpecificListLevelStyle ls = F.foldr select Nothing ls+ where+ select l Nothing = Just l+ select ( ListLevelStyle t1 p1 s1 f1 b1 )+ ( Just ( ListLevelStyle t2 p2 s2 f2 _ ))+ = Just $ ListLevelStyle (select' t1 t2) (p1 <|> p2) (s1 <|> s2)+ (selectLinf f1 f2) b1+ select' LltNumbered _ = LltNumbered+ select' _ LltNumbered = LltNumbered+ select' _ _ = LltBullet+ selectLinf LinfNone f2 = f2+ selectLinf f1 LinfNone = f1+ selectLinf (LinfString _) f2 = f2+ selectLinf f1 (LinfString _) = f1+ selectLinf f1 _ = f1+++--------------------------------------------------------------------------------+-- Tools to access style data+--------------------------------------------------------------------------------++--+lookupStyle :: StyleName -> Styles -> Maybe Style+lookupStyle name Styles{..} = M.lookup name stylesByName++--+lookupDefaultStyle' :: Styles -> StyleFamily -> StyleProperties+lookupDefaultStyle' Styles{..} family = fromMaybe def+ (M.lookup family defaultStyleMap)++--+lookupListStyleByName :: StyleName -> Styles -> Maybe ListStyle+lookupListStyleByName name Styles{..} = M.lookup name listStylesByName+++-- | Returns a chain of parent of the current style. The direct parent will+-- be the first element of the list, followed by its parent and so on.+-- The current style is not in the list.+parents :: Style -> Styles -> [Style]+parents style styles = L.unfoldr findNextParent style -- Ha!+ where findNextParent Style{..}+ = fmap duplicate $ (`lookupStyle` styles) =<< styleParentName++-- | Looks up the style family of the current style. Normally, every style+-- should have one. But if not, all parents are searched.+getStyleFamily :: Style -> Styles -> Maybe StyleFamily+getStyleFamily style@Style{..} styles+ = styleFamily+ <|> F.asum (map (`getStyleFamily` styles) $ parents style styles)++-- | Each 'Style' has certain 'StyleProperties'. But sometimes not all property+-- values are specified. Instead, a value might be inherited from a+-- parent style. This function makes this chain of inheritance+-- concrete and easily accessible by encapsulating the necessary lookups.+-- The resulting list contains the direct properties of the style as the first+-- element, the ones of the direct parent element as the next one, and so on.+--+-- Note: There should also be default properties for each style family. These+-- are @not@ contained in this list because properties inherited from+-- parent elements take precedence over default styles.+--+-- This function is primarily meant to be used through convenience wrappers.+--+stylePropertyChain :: Style -> Styles -> [StyleProperties]+stylePropertyChain style styles+ = map styleProperties (style : parents style styles)++--+extendedStylePropertyChain :: [Style] -> Styles -> [StyleProperties]+extendedStylePropertyChain [] _ = []+extendedStylePropertyChain [style] styles = stylePropertyChain style styles+ ++ maybeToList (fmap (lookupDefaultStyle' styles) (getStyleFamily style styles))+extendedStylePropertyChain (style:trace) styles = stylePropertyChain style styles+ ++ extendedStylePropertyChain trace styles
@@ -0,0 +1,95 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.OOXML.Shared+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++Shared utilities for Office Open XML (OOXML) readers (DOCX, PPTX).+Provides common functions for ZIP archive handling, XML parsing,+namespace management, and DrawingML parsing.+-}+module Text.Pandoc.Readers.OOXML.Shared+ ( -- * Constants+ emusPerInch+ , emuToInches+ , inchesToEmu+ -- * Types+ , NameSpaces+ , elemName+ , elemToNameSpaces+ , isElem+ , findChildByName+ , findChildrenByName+ , findElementByName+ , findAttrByName+ ) where++import qualified Data.Map as M+import qualified Data.Text as T+import Data.Text (Text)+import Text.Pandoc.XML.Light++-- | Type alias for namespace mappings+type NameSpaces = M.Map Text Text++-- | English Metric Units per inch+-- 1 inch = 914400 EMUs (used in OOXML for dimensions)+emusPerInch :: Integer+emusPerInch = 914400++-- | Convert EMUs to inches+emuToInches :: Integer -> Double+emuToInches n = fromIntegral n / fromIntegral emusPerInch++-- | Convert inches to EMUs+inchesToEmu :: Double -> Integer+inchesToEmu n = round (n * fromIntegral emusPerInch)++-- | Extract namespace declarations from element attributes+elemToNameSpaces :: Element -> NameSpaces+elemToNameSpaces = foldr (\(Attr qn val) ->+ case qn of+ QName s _ (Just "xmlns") -> M.insert s val+ _ -> id) mempty . elAttribs++-- | Create a qualified name from namespace map, prefix, and local name+elemName :: NameSpaces -> Text -> Text -> QName+elemName ns prefix name =+ QName name+ (M.lookup prefix ns)+ (if T.null prefix then Nothing else Just prefix)++-- | Check if element matches namespace prefix and local name+isElem :: NameSpaces -> Text -> Text -> Element -> Bool+isElem ns prefix name element =+ let ns' = ns <> elemToNameSpaces element+ in qName (elName element) == name &&+ qURI (elName element) == M.lookup prefix ns'++-- | Find first child element matching namespace and name+findChildByName :: NameSpaces -> Text -> Text -> Element -> Maybe Element+findChildByName ns pref name el =+ let ns' = ns <> elemToNameSpaces el+ in findChild (elemName ns' pref name) el++-- | Find all children matching namespace and name+findChildrenByName :: NameSpaces -> Text -> Text -> Element -> [Element]+findChildrenByName ns pref name el =+ let ns' = ns <> elemToNameSpaces el+ in findChildren (elemName ns' pref name) el++-- | Find element anywhere in descendants matching namespace and name+findElementByName :: NameSpaces -> Text -> Text -> Element -> Maybe Element+findElementByName ns pref name el =+ let ns' = ns <> elemToNameSpaces el+ in findElement (elemName ns' pref name) el++-- | Find attribute value by namespace prefix and name+findAttrByName :: NameSpaces -> Text -> Text -> Element -> Maybe Text+findAttrByName ns pref name el =+ let ns' = ns <> elemToNameSpaces el+ in findAttr (elemName ns' pref name) el
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.OPML- Copyright : Copyright (C) 2013-2022 John MacFarlane+ Copyright : Copyright (C) 2013-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -1,97 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Reader.Odt- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--Entry point to the odt reader.--}--module Text.Pandoc.Readers.Odt ( readOdt ) where--import Codec.Archive.Zip-import Text.Pandoc.XML.Light--import qualified Data.ByteString.Lazy as B--import System.FilePath--import Control.Monad.Except (throwError)--import qualified Data.Text as T--import Text.Pandoc.Class.PandocMonad (PandocMonad)-import qualified Text.Pandoc.Class.PandocMonad as P-import Text.Pandoc.Definition-import Text.Pandoc.Error-import Text.Pandoc.MediaBag-import Text.Pandoc.Options-import qualified Text.Pandoc.UTF8 as UTF8--import Text.Pandoc.Readers.Odt.ContentReader-import Text.Pandoc.Readers.Odt.StyleReader--import Text.Pandoc.Readers.Odt.Generic.Fallible-import Text.Pandoc.Readers.Odt.Generic.XMLConverter-import Text.Pandoc.Shared (filteredFilesFromArchive)--readOdt :: PandocMonad m- => ReaderOptions- -> B.ByteString- -> m Pandoc-readOdt opts bytes = case readOdt' opts bytes of- Right (doc, mb) -> do- P.setMediaBag mb- return doc- Left e -> throwError e-----readOdt' :: ReaderOptions- -> B.ByteString- -> Either PandocError (Pandoc, MediaBag)-readOdt' _ bytes = bytesToOdt bytes-- of--- Right (pandoc, mediaBag) -> Right (pandoc , mediaBag)--- Left err -> Left err-----bytesToOdt :: B.ByteString -> Either PandocError (Pandoc, MediaBag)-bytesToOdt bytes = case toArchiveOrFail bytes of- Right archive -> archiveToOdt archive- Left err -> Left $ PandocParseError- $ "Could not unzip ODT: " <> T.pack err-----archiveToOdt :: Archive -> Either PandocError (Pandoc, MediaBag)-archiveToOdt archive = do- let onFailure msg Nothing = Left $ PandocParseError msg- onFailure _ (Just x) = Right x- contentEntry <- onFailure "Could not find content.xml"- (findEntryByPath "content.xml" archive)- stylesEntry <- onFailure "Could not find styles.xml"- (findEntryByPath "styles.xml" archive)- contentElem <- entryToXmlElem contentEntry- stylesElem <- entryToXmlElem stylesEntry- styles <- either- (\_ -> Left $ PandocParseError "Could not read styles")- Right- (chooseMax (readStylesAt stylesElem ) (readStylesAt contentElem))- let filePathIsOdtMedia :: FilePath -> Bool- filePathIsOdtMedia fp =- let (dir, name) = splitFileName fp- in (dir == "Pictures/") || (dir /= "./" && name == "content.xml")- let media = filteredFilesFromArchive archive filePathIsOdtMedia- let startState = readerState styles media- either (\_ -> Left $ PandocParseError "Could not convert opendocument") Right- (runConverter' read_body startState contentElem)------entryToXmlElem :: Entry -> Either PandocError Element-entryToXmlElem entry =- case parseXMLElement . UTF8.toTextLazy . fromEntry $ entry of- Right x -> Right x- Left msg -> Left $ PandocXMLError (T.pack $ eRelativePath entry) msg
@@ -1,139 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TupleSections #-}-{- |- Module : Text.Pandoc.Readers.Odt.Arrows.State- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--An arrow that transports a state. It is in essence a more powerful version of-the standard state monad. As it is such a simple extension, there are-other version out there that do exactly the same.-The implementation is duplicated, though, to add some useful features.-Most of these might be implemented without access to innards, but it's much-faster and easier to implement this way.--}--module Text.Pandoc.Readers.Odt.Arrows.State where--import Control.Arrow-import qualified Control.Category as Cat-import Control.Monad-import Data.List (foldl')-import Text.Pandoc.Readers.Odt.Arrows.Utils-import Text.Pandoc.Readers.Odt.Generic.Fallible---newtype ArrowState state a b = ArrowState- { runArrowState :: (state, a) -> (state, b) }---- | Constructor-withState :: (state -> a -> (state, b)) -> ArrowState state a b-withState = ArrowState . uncurry---- | Constructor-modifyState :: (state -> state ) -> ArrowState state a a-modifyState = ArrowState . first---- | Constructor-ignoringState :: ( a -> b ) -> ArrowState state a b-ignoringState = ArrowState . second---- | Constructor-fromState :: (state -> (state, b)) -> ArrowState state a b-fromState = ArrowState . (.fst)---- | Constructor-extractFromState :: (state -> b ) -> ArrowState state x b-extractFromState f = ArrowState $ \(state,_) -> (state, f state)---- | Constructor-tryModifyState :: (state -> Either f state)- -> ArrowState state a (Either f a)-tryModifyState f = ArrowState $ \(state,a)- -> (state,).Left ||| (,Right a) $ f state--instance Cat.Category (ArrowState s) where- id = ArrowState id- arrow2 . arrow1 = ArrowState $ runArrowState arrow2 . runArrowState arrow1--instance Arrow (ArrowState state) where- arr = ignoringState- first a = ArrowState $ \(s,(aF,aS))- -> second (,aS) $ runArrowState a (s,aF)- second a = ArrowState $ \(s,(aF,aS))- -> second (aF,) $ runArrowState a (s,aS)--instance ArrowChoice (ArrowState state) where- left a = ArrowState $ \(s,e) -> case e of- Left l -> second Left $ runArrowState a (s,l)- Right r -> (s, Right r)- right a = ArrowState $ \(s,e) -> case e of- Left l -> (s, Left l)- Right r -> second Right $ runArrowState a (s,r)--instance ArrowApply (ArrowState state) where- app = ArrowState $ \(s, (f,b)) -> runArrowState f (s,b)---- | Switches the type of the state temporarily.--- Drops the intermediate result state, behaving like a fallible--- identity arrow, save for side effects in the state.-withSubStateF :: ArrowState s x (Either f s')- -> ArrowState s' s (Either f s )- -> ArrowState s x (Either f x )-withSubStateF unlift a = keepingTheValue (withSubStateF' unlift a)- >>^ spreadChoice- >>^ fmap fst---- | Switches the type of the state temporarily.--- Returns the resulting sub-state.-withSubStateF' :: ArrowState s x (Either f s')- -> ArrowState s' s (Either f s )- -> ArrowState s x (Either f s')-withSubStateF' unlift a = ArrowState go- where go p@(s,_) = tryRunning unlift- ( tryRunning a (second Right) )- p- where tryRunning a' b v = case runArrowState a' v of- (_ , Left f) -> (s, Left f)- (x , Right y) -> b (y,x)---- | Fold a state arrow through something 'Foldable'. Collect the results--- in a 'Monoid'.--- Intermediate form of a fold between one with "only" a 'Monoid'--- and one with any function.-foldS :: (Foldable f, Monoid m) => ArrowState s x m -> ArrowState s (f x) m-foldS a = ArrowState $ \(s,f) -> foldr a' (s,mempty) f- where a' x (s',m) = second (mappend m) $ runArrowState a (s',x)---- | Fold a state arrow through something 'Foldable'. Collect the results in a--- 'MonadPlus'.-iterateS :: (Foldable f, MonadPlus m)- => ArrowState s x y- -> ArrowState s (f x) (m y)-iterateS a = ArrowState $ \(s,f) -> foldr a' (s,mzero) f- where a' x (s',m) = second (mplus m.return) $ runArrowState a (s',x)---- | Fold a state arrow through something 'Foldable'. Collect the results in a--- 'MonadPlus'.-iterateSL :: (Foldable f, MonadPlus m)- => ArrowState s x y- -> ArrowState s (f x) (m y)-iterateSL a = ArrowState $ \(s,f) -> foldl' a' (s,mzero) f- where a' (s',m) x = second (mplus m.return) $ runArrowState a (s',x)----- | Fold a fallible state arrow through something 'Foldable'.--- Collect the results in a 'MonadPlus'.--- If the iteration fails, the state will be reset to the initial one.-iterateS' :: (Foldable f, MonadPlus m)- => ArrowState s x (Either e y )- -> ArrowState s (f x) (Either e (m y))-iterateS' a = ArrowState $ \(s,f) -> foldr (a' s) (s,Right mzero) f- where a' s x (s',Right m) = case runArrowState a (s',x) of- (s'',Right m') -> (s'',Right $ mplus m $ return m')- (_ ,Left e ) -> (s ,Left e )- a' _ _ e = e
@@ -1,214 +0,0 @@-{- |- Module : Text.Pandoc.Readers.Odt.Arrows.Utils- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--Utility functions for Arrows (Kleisli monads).--Some general notes on notation:--* "^" is meant to stand for a pure function that is lifted into an arrow-based on its usage for that purpose in "Control.Arrow".-* "?" is meant to stand for the usage of a 'FallibleArrow' or a pure function-with an equivalent return value.-* "_" stands for the dropping of a value.--}---- We export everything-module Text.Pandoc.Readers.Odt.Arrows.Utils where--import Prelude hiding (Applicative(..))-import Control.Arrow-import Control.Monad (join)--import Text.Pandoc.Readers.Odt.Generic.Fallible-import Text.Pandoc.Readers.Odt.Generic.Utils--and2 :: (Arrow a) => a b c -> a b c' -> a b (c,c')-and2 = (&&&)--and3 :: (Arrow a)- => a b c0->a b c1->a b c2- -> a b (c0,c1,c2 )-and4 :: (Arrow a)- => a b c0->a b c1->a b c2->a b c3- -> a b (c0,c1,c2,c3 )-and5 :: (Arrow a)- => a b c0->a b c1->a b c2->a b c3->a b c4- -> a b (c0,c1,c2,c3,c4 )-and6 :: (Arrow a)- => a b c0->a b c1->a b c2->a b c3->a b c4->a b c5- -> a b (c0,c1,c2,c3,c4,c5 )--and3 a b c = and2 a b &&& c- >>^ \((z,y ) , x) -> (z,y,x )-and4 a b c d = and3 a b c &&& d- >>^ \((z,y,x ) , w) -> (z,y,x,w )-and5 a b c d e = and4 a b c d &&& e- >>^ \((z,y,x,w ) , v) -> (z,y,x,w,v )-and6 a b c d e f = and5 a b c d e &&& f- >>^ \((z,y,x,w,v ) , u) -> (z,y,x,w,v,u )--liftA2 :: (Arrow a) => (x -> y -> z) -> a b x -> a b y -> a b z-liftA2 f a b = a &&& b >>^ uncurry f--liftA3 :: (Arrow a) => (z->y->x -> r)- -> a b z->a b y->a b x- -> a b r-liftA4 :: (Arrow a) => (z->y->x->w -> r)- -> a b z->a b y->a b x->a b w- -> a b r-liftA5 :: (Arrow a) => (z->y->x->w->v -> r)- -> a b z->a b y->a b x->a b w->a b v- -> a b r-liftA6 :: (Arrow a) => (z->y->x->w->v->u -> r)- -> a b z->a b y->a b x->a b w->a b v->a b u- -> a b r--liftA3 fun a b c = and3 a b c >>^ uncurry3 fun-liftA4 fun a b c d = and4 a b c d >>^ uncurry4 fun-liftA5 fun a b c d e = and5 a b c d e >>^ uncurry5 fun-liftA6 fun a b c d e f = and6 a b c d e f >>^ uncurry6 fun--liftA :: (Arrow a) => (y -> z) -> a b y -> a b z-liftA fun a = a >>^ fun----- | Duplicate a value to subsequently feed it into different arrows.--- Can almost always be replaced with '(&&&)', 'keepingTheValue',--- or even '(|||)'.--- Equivalent to--- > returnA &&& returnA-duplicate :: (Arrow a) => a b (b,b)-duplicate = arr $ join (,)---- | Applies a function to the uncurried result-pair of an arrow-application.--- (The %-symbol was chosen to evoke an association with pairs.)-(>>%) :: (Arrow a) => a x (b,c) -> (b -> c -> d) -> a x d-a >>% f = a >>^ uncurry f--infixr 2 >>%----- | Duplicate a value and apply an arrow to the second instance.--- Equivalent to--- > \a -> duplicate >>> second a--- or--- > \a -> returnA &&& a-keepingTheValue :: (Arrow a) => a b c -> a b (b,c)-keepingTheValue a = returnA &&& a--( ^||| ) :: (ArrowChoice a) => (b -> d) -> a c d -> a (Either b c) d-( |||^ ) :: (ArrowChoice a) => a b d -> (c -> d) -> a (Either b c) d-( ^|||^ ) :: (ArrowChoice a) => (b -> d) -> (c -> d) -> a (Either b c) d--l ^||| r = arr l ||| r-l |||^ r = l ||| arr r-l ^|||^ r = arr l ||| arr r--infixr 2 ^||| , |||^, ^|||^--( ^&&& ) :: (Arrow a) => (b -> c) -> a b c' -> a b (c,c')-( &&&^ ) :: (Arrow a) => a b c -> (b -> c') -> a b (c,c')--l ^&&& r = arr l &&& r-l &&&^ r = l &&& arr r--infixr 3 ^&&&, &&&^----- | Converts @Right a@ into @Just a@ and @Left _@ into @Nothing@.-choiceToMaybe :: (ArrowChoice a) => a (Either l r) (Maybe r)-choiceToMaybe = arr eitherToMaybe---- | Converts @Nothing@ into @Left ()@ and @Just a@ into @Right a@.-maybeToChoice :: (ArrowChoice a) => a (Maybe b) (Fallible b)-maybeToChoice = arr maybeToEither---- | Lifts a constant value into an arrow-returnV :: (Arrow a) => c -> a x c-returnV = arr.const---- | Defines Left as failure, Right as success-type FallibleArrow a input failure success = a input (Either failure success)-----liftAsSuccess :: (ArrowChoice a)- => a x success- -> FallibleArrow a x failure success-liftAsSuccess a = a >>^ Right---- | Execute the second arrow if the first succeeds-(>>?) :: (ArrowChoice a)- => FallibleArrow a x failure success- -> FallibleArrow a success failure success'- -> FallibleArrow a x failure success'-a >>? b = a >>> Left ^||| b---- | Execute the lifted second arrow if the first succeeds-(>>?^) :: (ArrowChoice a)- => FallibleArrow a x failure success- -> (success -> success')- -> FallibleArrow a x failure success'-a >>?^ f = a >>^ Left ^|||^ Right . f---- | Execute the lifted second arrow if the first succeeds-(>>?^?) :: (ArrowChoice a)- => FallibleArrow a x failure success- -> (success -> Either failure success')- -> FallibleArrow a x failure success'-a >>?^? b = a >>> Left ^|||^ b---- | Execute the second arrow if the lifted first arrow succeeds-(^>>?) :: (ArrowChoice a)- => (x -> Either failure success)- -> FallibleArrow a success failure success'- -> FallibleArrow a x failure success'-a ^>>? b = a ^>> Left ^||| b---- | Execute the second, non-fallible arrow if the first arrow succeeds-(>>?!) :: (ArrowChoice a)- => FallibleArrow a x failure success- -> a success success'- -> FallibleArrow a x failure success'-a >>?! f = a >>> right f------(>>?%) :: (ArrowChoice a)- => FallibleArrow a x f (b,b')- -> (b -> b' -> c)- -> FallibleArrow a x f c-a >>?% f = a >>?^ uncurry f------(^>>?%) :: (ArrowChoice a)- => (x -> Either f (b,b'))- -> (b -> b' -> c)- -> FallibleArrow a x f c-a ^>>?% f = arr a >>?^ uncurry f------(>>?%?) :: (ArrowChoice a)- => FallibleArrow a x f (b,b')- -> (b -> b' -> Either f c)- -> FallibleArrow a x f c-a >>?%? f = a >>?^? uncurry f--infixr 1 >>?, >>?^, >>?^?-infixr 1 ^>>?, >>?!-infixr 1 >>?%, ^>>?%, >>?%?---- | An arrow version of a short-circuit (<|>)-ifFailedDo :: (ArrowChoice a)- => FallibleArrow a x f y- -> FallibleArrow a x f y- -> FallibleArrow a x f y-ifFailedDo a b = keepingTheValue a >>> repackage ^>> (b |||^ Right)- where repackage (x , Left _) = Left x- repackage (_ , Right y) = Right y--infixr 1 `ifFailedDo`
@@ -1,22 +0,0 @@-{- |- Module : Text.Pandoc.Readers.Odt.Base- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--Core types of the odt reader.--}--module Text.Pandoc.Readers.Odt.Base where--import Text.Pandoc.Readers.Odt.Generic.XMLConverter-import Text.Pandoc.Readers.Odt.Namespaces--type OdtConverterState s = XMLConverterState Namespace s--type XMLReader s a b = FallibleXMLConverter Namespace s a b--type XMLReaderSafe s a b = XMLConverter Namespace s a b
@@ -1,950 +0,0 @@-{-# LANGUAGE Arrows #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Readers.Odt.ContentReader- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--The core of the odt reader that converts odt features into Pandoc types.--}--module Text.Pandoc.Readers.Odt.ContentReader-( readerState-, read_body-) where--import Prelude hiding (Applicative(..))-import Control.Applicative hiding (liftA, liftA2, liftA3)-import Control.Arrow-import Control.Monad ((<=<))--import qualified Data.ByteString.Lazy as B-import Data.Foldable (fold)-import Data.List (find)-import qualified Data.Map as M-import qualified Data.Text as T-import Data.Maybe-import Data.Monoid (Alt (..))--import Text.TeXMath (readMathML, writeTeX)-import qualified Text.Pandoc.XML.Light as XML--import Text.Pandoc.Builder hiding (underline)-import Text.Pandoc.MediaBag (MediaBag, insertMedia)-import Text.Pandoc.Shared-import Text.Pandoc.Extensions (extensionsFromList, Extension(..))-import qualified Text.Pandoc.UTF8 as UTF8--import Text.Pandoc.Readers.Odt.Base-import Text.Pandoc.Readers.Odt.Namespaces-import Text.Pandoc.Readers.Odt.StyleReader--import Text.Pandoc.Readers.Odt.Arrows.State (foldS)-import Text.Pandoc.Readers.Odt.Arrows.Utils-import Text.Pandoc.Readers.Odt.Generic.Fallible-import Text.Pandoc.Readers.Odt.Generic.Utils-import Text.Pandoc.Readers.Odt.Generic.XMLConverter--import qualified Data.Set as Set------------------------------------------------------------------------------------- State-----------------------------------------------------------------------------------type Anchor = T.Text-type Media = [(FilePath, B.ByteString)]--data ReaderState- = ReaderState { -- | A collection of styles read somewhere else.- -- It is only queried here, not modified.- styleSet :: Styles- -- | A stack of the styles of parent elements.- -- Used to look up inherited style properties.- , styleTrace :: [Style]- -- | Keeps track of the current depth in nested lists- , currentListLevel :: ListLevel- -- | Lists may provide their own style, but they don't have- -- to. If they do not, the style of a parent list may be used- -- or even a default list style from the paragraph style.- -- This value keeps track of the closest list style there- -- currently is.- , currentListStyle :: Maybe ListStyle- -- | A map from internal anchor names to "pretty" ones.- -- The mapping is a purely cosmetic one.- , bookmarkAnchors :: M.Map Anchor Anchor- -- | A map of files / binary data from the archive- , envMedia :: Media- -- | Hold binary resources used in the document- , odtMediaBag :: MediaBag- }- deriving ( Show )--readerState :: Styles -> Media -> ReaderState-readerState styles media = ReaderState styles [] 0 Nothing M.empty media mempty-----pushStyle' :: Style -> ReaderState -> ReaderState-pushStyle' style state = state { styleTrace = style : styleTrace state }-----popStyle' :: ReaderState -> ReaderState-popStyle' state = case styleTrace state of- _:trace -> state { styleTrace = trace }- _ -> state-----modifyListLevel :: (ListLevel -> ListLevel) -> (ReaderState -> ReaderState)-modifyListLevel f state = state { currentListLevel = f (currentListLevel state) }-----shiftListLevel :: ListLevel -> (ReaderState -> ReaderState)-shiftListLevel diff = modifyListLevel (+ diff)-----swapCurrentListStyle :: Maybe ListStyle -> ReaderState- -> (ReaderState, Maybe ListStyle)-swapCurrentListStyle mListStyle state = ( state { currentListStyle = mListStyle }- , currentListStyle state- )-----lookupPrettyAnchor :: Anchor -> ReaderState -> Maybe Anchor-lookupPrettyAnchor anchor ReaderState{..} = M.lookup anchor bookmarkAnchors-----putPrettyAnchor :: Anchor -> Anchor -> ReaderState -> ReaderState-putPrettyAnchor ugly pretty state@ReaderState{..}- = state { bookmarkAnchors = M.insert ugly pretty bookmarkAnchors }-----usedAnchors :: ReaderState -> [Anchor]-usedAnchors ReaderState{..} = M.elems bookmarkAnchors--getMediaBag :: ReaderState -> MediaBag-getMediaBag ReaderState{..} = odtMediaBag--getMediaEnv :: ReaderState -> Media-getMediaEnv ReaderState{..} = envMedia--insertMedia' :: (FilePath, B.ByteString) -> ReaderState -> ReaderState-insertMedia' (fp, bs) state@ReaderState{..}- = state { odtMediaBag = insertMedia fp Nothing bs odtMediaBag }------------------------------------------------------------------------------------- Reader type and associated tools-----------------------------------------------------------------------------------type OdtReader a b = XMLReader ReaderState a b--type OdtReaderSafe a b = XMLReaderSafe ReaderState a b---- | Extract something from the styles-fromStyles :: (a -> Styles -> b) -> OdtReaderSafe a b-fromStyles f = keepingTheValue- (getExtraState >>^ styleSet)- >>% f-----getStyleByName :: OdtReader StyleName Style-getStyleByName = fromStyles lookupStyle >>^ maybeToChoice-----findStyleFamily :: OdtReader Style StyleFamily-findStyleFamily = fromStyles getStyleFamily >>^ maybeToChoice-----lookupListStyle :: OdtReader StyleName ListStyle-lookupListStyle = fromStyles lookupListStyleByName >>^ maybeToChoice-----switchCurrentListStyle :: OdtReaderSafe (Maybe ListStyle) (Maybe ListStyle)-switchCurrentListStyle = keepingTheValue getExtraState- >>% swapCurrentListStyle- >>> first setExtraState- >>^ snd-----pushStyle :: OdtReaderSafe Style Style-pushStyle = keepingTheValue (- ( keepingTheValue getExtraState- >>% pushStyle'- )- >>> setExtraState- )- >>^ fst-----popStyle :: OdtReaderSafe x x-popStyle = keepingTheValue (- getExtraState- >>> arr popStyle'- >>> setExtraState- )- >>^ fst-----getCurrentListLevel :: OdtReaderSafe _x ListLevel-getCurrentListLevel = getExtraState >>^ currentListLevel-----updateMediaWithResource :: OdtReaderSafe (FilePath, B.ByteString) (FilePath, B.ByteString)-updateMediaWithResource = keepingTheValue (- (keepingTheValue getExtraState- >>% insertMedia'- )- >>> setExtraState- )- >>^ fst--lookupResource :: OdtReaderSafe FilePath (FilePath, B.ByteString)-lookupResource = proc target -> do- state <- getExtraState -< ()- case lookup target (getMediaEnv state) of- Just bs -> returnV (target, bs) -<< ()- Nothing -> returnV ("", B.empty) -< ()--type AnchorPrefix = T.Text---- | An adaptation of 'uniqueIdent' from "Text.Pandoc.Shared" that generates a--- unique identifier but without assuming that the id should be for a header.--- Second argument is a list of already used identifiers.-uniqueIdentFrom :: AnchorPrefix -> [Anchor] -> Anchor-uniqueIdentFrom baseIdent usedIdents =- let numIdent n = baseIdent <> "-" <> T.pack (show n)- in if baseIdent `elem` usedIdents- then maybe baseIdent numIdent- $ find (\x -> numIdent x `notElem` usedIdents) ([1..60000] :: [Int])- -- if we have more than 60,000, allow repeats- else baseIdent---- | First argument: basis for a new "pretty" anchor if none exists yet--- Second argument: a key ("ugly" anchor)--- Returns: saved "pretty" anchor or created new one-getPrettyAnchor :: OdtReaderSafe (AnchorPrefix, Anchor) Anchor-getPrettyAnchor = proc (baseIdent, uglyAnchor) -> do- state <- getExtraState -< ()- case lookupPrettyAnchor uglyAnchor state of- Just prettyAnchor -> returnA -< prettyAnchor- Nothing -> do- let newPretty = uniqueIdentFrom baseIdent (usedAnchors state)- modifyExtraState (putPrettyAnchor uglyAnchor newPretty) -<< newPretty---- | Input: basis for a new header anchor--- Output: saved new anchor-getHeaderAnchor :: OdtReaderSafe Inlines Anchor-getHeaderAnchor = proc title -> do- state <- getExtraState -< ()- let exts = extensionsFromList [Ext_auto_identifiers]- let anchor = uniqueIdent exts (toList title)- (Set.fromList $ usedAnchors state)- modifyExtraState (putPrettyAnchor anchor anchor) -<< anchor-------------------------------------------------------------------------------------- Working with styles--------------------------------------------------------------------------------------readStyleByName :: OdtReader _x (StyleName, Style)-readStyleByName =- findAttr NsText "style-name" >>? keepingTheValue getStyleByName >>^ liftE- where- liftE :: (StyleName, Fallible Style) -> Fallible (StyleName, Style)- liftE (name, Right v) = Right (name, v)- liftE (_, Left v) = Left v-----isStyleToTrace :: OdtReader Style Bool-isStyleToTrace = findStyleFamily >>?^ (==FaText)-----withNewStyle :: OdtReaderSafe x Inlines -> OdtReaderSafe x Inlines-withNewStyle a = proc x -> do- fStyle <- readStyleByName -< ()- case fStyle of- Right (styleName, _) | isCodeStyle styleName -> do- inlines <- a -< x- arr inlineCode -<< inlines- Right (_, style) -> do- mFamily <- arr styleFamily -< style- fTextProps <- arr ( maybeToChoice- . textProperties- . styleProperties- ) -< style- case fTextProps of- Right textProps -> do- state <- getExtraState -< ()- let triple = (state, textProps, mFamily)- modifier <- arr modifierFromStyleDiff -< triple- fShouldTrace <- isStyleToTrace -< style- case fShouldTrace of- Right shouldTrace ->- if shouldTrace- then do- pushStyle -< style- inlines <- a -< x- popStyle -< ()- arr modifier -<< inlines- else- -- In case anything goes wrong- a -< x- Left _ -> a -< x- Left _ -> a -< x- Left _ -> a -< x- where- isCodeStyle :: StyleName -> Bool- isCodeStyle "Source_Text" = True- isCodeStyle _ = False-- inlineCode :: Inlines -> Inlines- inlineCode = code . T.concat . map stringify . toList--type PropertyTriple = (ReaderState, TextProperties, Maybe StyleFamily)-type InlineModifier = Inlines -> Inlines---- | Given data about the local style changes, calculates how to modify--- an instance of 'Inlines'-modifierFromStyleDiff :: PropertyTriple -> InlineModifier-modifierFromStyleDiff propertyTriple =- composition $- getVPosModifier propertyTriple- : map (first ($ propertyTriple) >>> ifThen_else ignore)- [ (hasEmphChanged , emph )- , (hasChanged isStrong , strong )- , (hasChanged strikethrough , strikeout )- ]- where- ifThen_else else' (if',then') = if if' then then' else else'-- ignore = id :: InlineModifier-- getVPosModifier :: PropertyTriple -> InlineModifier- getVPosModifier triple@(_,textProps,_) =- let getVPos = Just . verticalPosition- in case lookupPreviousValueM getVPos triple of- Nothing -> ignore- Just oldVPos -> getVPosModifier' (oldVPos, verticalPosition textProps)-- getVPosModifier' (oldVPos , newVPos ) | oldVPos == newVPos = ignore- getVPosModifier' ( _ , VPosSub ) = subscript- getVPosModifier' ( _ , VPosSuper ) = superscript- getVPosModifier' ( _ , _ ) = ignore-- hasEmphChanged :: PropertyTriple -> Bool- hasEmphChanged = swing any [ hasChanged isEmphasised- , hasChangedM pitch- , hasChanged underline- ]-- hasChanged property triple@(_, property -> newProperty, _) =- (/= Just newProperty) (lookupPreviousValue property triple)-- hasChangedM property triple@(_, textProps,_) =- fromMaybe False $ (/=) <$> property textProps <*> lookupPreviousValueM property triple-- lookupPreviousValue f = lookupPreviousStyleValue (fmap f . textProperties)-- lookupPreviousValueM f = lookupPreviousStyleValue (f <=< textProperties)-- lookupPreviousStyleValue f (ReaderState{..},_,mFamily)- = findBy f (extendedStylePropertyChain styleTrace styleSet)- <|> (f . lookupDefaultStyle' styleSet =<< mFamily)---type ParaModifier = Blocks -> Blocks--_MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_MM_ :: Int-_MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_PERCENT_ :: Int-_MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_MM_ = 5-_MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_PERCENT_ = 5---- | Returns either 'id' or 'blockQuote' depending on the current indentation-getParaModifier :: Style -> ParaModifier-getParaModifier Style{..} | Just props <- paraProperties styleProperties- , isBlockQuote (indentation props)- (margin_left props)- = blockQuote- | otherwise- = id- where- isBlockQuote mIndent mMargin- | LengthValueMM indent <- mIndent- , indent > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_MM_- = True- | LengthValueMM margin <- mMargin- , margin > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_MM_- = True- | LengthValueMM indent <- mIndent- , LengthValueMM margin <- mMargin- = indent + margin > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_MM_-- | PercentValue indent <- mIndent- , indent > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_PERCENT_- = True- | PercentValue margin <- mMargin- , margin > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_PERCENT_- = True- | PercentValue indent <- mIndent- , PercentValue margin <- mMargin- = indent + margin > _MINIMUM_INDENTATION_FOR_BLOCKQUOTES_IN_PERCENT_-- | otherwise- = False-----constructPara :: OdtReaderSafe Blocks Blocks -> OdtReaderSafe Blocks Blocks-constructPara reader = proc blocks -> do- fStyle <- readStyleByName -< blocks- case fStyle of- Left _ -> reader -< blocks- Right (styleName, _) | isTableCaptionStyle styleName -> do- blocks' <- reader -< blocks- arr tableCaptionP -< blocks'- Right (_, style) -> do- let modifier = getParaModifier style- blocks' <- reader -< blocks- arr modifier -<< blocks'- where- isTableCaptionStyle :: StyleName -> Bool- isTableCaptionStyle "Table" = True- isTableCaptionStyle _ = False- tableCaptionP b = divWith ("", ["caption"], []) b--type ListConstructor = [Blocks] -> Blocks--getListConstructor :: ListLevelStyle -> ListConstructor-getListConstructor ListLevelStyle{..} =- case listLevelType of- LltBullet -> bulletList- LltImage -> bulletList- LltNumbered -> let listNumberStyle = toListNumberStyle listItemFormat- listNumberDelim = toListNumberDelim listItemPrefix- listItemSuffix- in orderedListWith (listItemStart, listNumberStyle, listNumberDelim)- where- toListNumberStyle LinfNone = DefaultStyle- toListNumberStyle LinfNumber = Decimal- toListNumberStyle LinfRomanLC = LowerRoman- toListNumberStyle LinfRomanUC = UpperRoman- toListNumberStyle LinfAlphaLC = LowerAlpha- toListNumberStyle LinfAlphaUC = UpperAlpha- toListNumberStyle (LinfString _) = Example-- toListNumberDelim Nothing (Just ".") = Period- toListNumberDelim (Just "" ) (Just ".") = Period- toListNumberDelim Nothing (Just ")") = OneParen- toListNumberDelim (Just "" ) (Just ")") = OneParen- toListNumberDelim (Just "(") (Just ")") = TwoParens- toListNumberDelim _ _ = DefaultDelim----- | Determines which style to use for a list, which level to use of that--- style, and which type of list to create as a result of this information.--- Then prepares the state for eventual child lists and constructs the list from--- the results.--- Two main cases are handled: The list may provide its own style or it may--- rely on a parent list's style. I the former case the current style in the--- state must be switched before and after the call to the child converter--- while in the latter the child converter can be called directly.--- If anything goes wrong, a default ordered-list-constructor is used.-constructList :: OdtReaderSafe x [Blocks] -> OdtReaderSafe x Blocks-constructList reader = proc x -> do- modifyExtraState (shiftListLevel 1) -< ()- listLevel <- getCurrentListLevel -< ()- fStyleName <- findAttr NsText "style-name" -< ()- case fStyleName of- Right styleName -> do- fListStyle <- lookupListStyle -< styleName- case fListStyle of- Right listStyle -> do- fLLS <- arr (uncurry getListLevelStyle) -< (listLevel,listStyle)- case fLLS of- Just listLevelStyle -> do- oldListStyle <- switchCurrentListStyle -< Just listStyle- blocks <- constructListWith listLevelStyle -<< x- switchCurrentListStyle -< oldListStyle- returnA -< blocks- Nothing -> constructOrderedList -< x- Left _ -> constructOrderedList -< x- Left _ -> do- state <- getExtraState -< ()- mListStyle <- arr currentListStyle -< state- case mListStyle of- Just listStyle -> do- fLLS <- arr (uncurry getListLevelStyle) -< (listLevel,listStyle)- case fLLS of- Just listLevelStyle -> constructListWith listLevelStyle -<< x- Nothing -> constructOrderedList -< x- Nothing -> constructOrderedList -< x- where- constructOrderedList =- reader- >>> modifyExtraState (shiftListLevel (-1))- >>^ orderedList- constructListWith listLevelStyle =- reader- >>> getListConstructor listLevelStyle- ^>> modifyExtraState (shiftListLevel (-1))------------------------------------------------------------------------------------- Readers-----------------------------------------------------------------------------------type ElementMatcher result = (Namespace, ElementName, OdtReader result result)--type InlineMatcher = ElementMatcher Inlines--type BlockMatcher = ElementMatcher Blocks--newtype FirstMatch a = FirstMatch (Alt Maybe a)- deriving (Foldable, Monoid, Semigroup)--firstMatch :: a -> FirstMatch a-firstMatch = FirstMatch . Alt . Just-----matchingElement :: (Monoid e)- => Namespace -> ElementName- -> OdtReaderSafe e e- -> ElementMatcher e-matchingElement ns name reader = (ns, name, asResultAccumulator reader)- where- asResultAccumulator :: (ArrowChoice a, Monoid m) => a m m -> a m (Fallible m)- asResultAccumulator a = liftAsSuccess $ keepingTheValue a >>% mappend-----matchChildContent' :: (Monoid result)- => [ElementMatcher result]- -> OdtReaderSafe _x result-matchChildContent' ls = returnV mempty >>> matchContent' ls-----matchChildContent :: (Monoid result)- => [ElementMatcher result]- -> OdtReaderSafe (result, XML.Content) result- -> OdtReaderSafe _x result-matchChildContent ls fallback = returnV mempty >>> matchContent ls fallback------------------------------------------------- Matchers------------------------------------------------------------------------ Basics------------------------------ | Open Document allows several consecutive spaces if they are marked up-read_plain_text :: OdtReaderSafe (Inlines, XML.Content) Inlines-read_plain_text = fst ^&&& read_plain_text' >>% recover- where- -- fallible version- read_plain_text' :: OdtReader (Inlines, XML.Content) Inlines- read_plain_text' = ( second ( arr extractText )- >>^ spreadChoice >>?! second text- )- >>?% mappend- --- extractText :: XML.Content -> Fallible T.Text- extractText (XML.Text cData) = succeedWith (XML.cdData cData)- extractText _ = failEmpty--read_text_seq :: InlineMatcher-read_text_seq = matchingElement NsText "sequence"- $ matchChildContent [] read_plain_text----- specifically. I honor that, although the current implementation of 'mappend'--- for 'Inlines' in "Text.Pandoc.Builder" will collapse them again.--- The rational is to be prepared for future modifications.-read_spaces :: InlineMatcher-read_spaces = matchingElement NsText "s" (- readAttrWithDefault NsText "c" 1 -- how many spaces?- >>^ fromList.(`replicate` Space)- )----read_line_break :: InlineMatcher-read_line_break = matchingElement NsText "line-break"- $ returnV linebreak----read_tab :: InlineMatcher-read_tab = matchingElement NsText "tab"- $ returnV space----read_span :: InlineMatcher-read_span = matchingElement NsText "span"- $ withNewStyle- $ matchChildContent [ read_span- , read_spaces- , read_line_break- , read_tab- , read_link- , read_note- , read_citation- , read_bookmark- , read_bookmark_start- , read_reference_start- , read_bookmark_ref- , read_reference_ref- ] read_plain_text-----read_paragraph :: BlockMatcher-read_paragraph = matchingElement NsText "p"- $ constructPara- $ liftA para- $ withNewStyle- $ matchChildContent [ read_span- , read_spaces- , read_line_break- , read_tab- , read_link- , read_note- , read_citation- , read_bookmark- , read_bookmark_start- , read_reference_start- , read_bookmark_ref- , read_reference_ref- , read_frame- , read_text_seq- ] read_plain_text---------------------------- Headers----------------------------read_header :: BlockMatcher-read_header = matchingElement NsText "h"- $ proc blocks -> do- level <- ( readAttrWithDefault NsText "outline-level" 1- ) -< blocks- children <- ( matchChildContent [ read_span- , read_spaces- , read_line_break- , read_tab- , read_link- , read_note- , read_citation- , read_bookmark- , read_bookmark_start- , read_reference_start- , read_bookmark_ref- , read_reference_ref- , read_frame- ] read_plain_text- ) -< blocks- anchor <- getHeaderAnchor -< children- let idAttr = (anchor, [], []) -- no classes, no key-value pairs- arr (uncurry3 headerWith) -< (idAttr, level, children)--------------------------- Lists----------------------------read_list :: BlockMatcher-read_list = matchingElement NsText "list"--- $ withIncreasedListLevel- $ constructList--- $ liftA bulletList- $ matchChildContent' [ read_list_item- , read_list_header- ]----read_list_item :: ElementMatcher [Blocks]-read_list_item = read_list_element "list-item"--read_list_header :: ElementMatcher [Blocks]-read_list_header = read_list_element "list-header"--read_list_element :: ElementName -> ElementMatcher [Blocks]-read_list_element listElement = matchingElement NsText listElement- $ liftA (compactify.(:[]))- ( matchChildContent' [ read_paragraph- , read_header- , read_list- ]- )---------------------------- Links-------------------------read_link :: InlineMatcher-read_link = matchingElement NsText "a"- $ liftA3 link- ( findAttrTextWithDefault NsXLink "href" "" )- ( findAttrTextWithDefault NsOffice "title" "" )- ( matchChildContent [ read_span- , read_note- , read_citation- , read_bookmark- , read_bookmark_start- , read_reference_start- , read_bookmark_ref- , read_reference_ref- ] read_plain_text )------------------------------- Footnotes----------------------------read_note :: InlineMatcher-read_note = matchingElement NsText "note"- $ liftA note- $ matchChildContent' [ read_note_body ]--read_note_body :: BlockMatcher-read_note_body = matchingElement NsText "note-body"- $ matchChildContent' [ read_paragraph ]------------------------------ Citations----------------------------read_citation :: InlineMatcher-read_citation = matchingElement NsText "bibliography-mark"- $ liftA2 cite- ( liftA2 makeCitation- ( findAttrTextWithDefault NsText "identifier" "" )- ( readAttrWithDefault NsText "number" 0 )- )- ( matchChildContent [] read_plain_text )- where- makeCitation :: T.Text -> Int -> [Citation]- makeCitation citeId num = [Citation citeId [] [] NormalCitation num 0]---------------------------- Tables----------------------------read_table :: BlockMatcher-read_table = matchingElement NsTable "table"- $ liftA simpleTable'- $ 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 []-----read_table_row :: ElementMatcher [[Blocks]]-read_table_row = matchingElement NsTable "table-row"- $ liftA (:[])- $ matchChildContent' [ read_table_cell- ]-----read_table_cell :: ElementMatcher [Blocks]-read_table_cell = matchingElement NsTable "table-cell"- $ liftA (compactify.(:[]))- $ matchChildContent' [ read_paragraph- ]--------------------------- Frames----------------------------read_frame :: InlineMatcher-read_frame = matchingElement NsDraw "frame"- $ filterChildrenName' NsDraw (`elem` ["image", "object", "text-box"])- >>> foldS read_frame_child- >>> arr fold--read_frame_child :: OdtReaderSafe XML.Element (FirstMatch Inlines)-read_frame_child =- proc child -> case elName child of- "image" -> read_frame_img -< child- "object" -> read_frame_mathml -< child- "text-box" -> read_frame_text_box -< child- _ -> returnV mempty -< ()--read_frame_img :: OdtReaderSafe XML.Element (FirstMatch Inlines)-read_frame_img =- proc img -> do- src <- executeIn (findAttr' NsXLink "href") -< img- case fold src of- "" -> returnV mempty -< ()- src' -> do- let exts = extensionsFromList [Ext_auto_identifiers]- resource <- lookupResource -< T.unpack src'- _ <- updateMediaWithResource -< resource- w <- findAttrText' NsSVG "width" -< ()- h <- findAttrText' NsSVG "height" -< ()- titleNodes <- matchChildContent' [ read_frame_title ] -< ()- alt <- matchChildContent [] read_plain_text -< ()- arr (firstMatch . uncurry4 imageWith) -<- (image_attributes w h, src', inlineListToIdentifier exts (toList titleNodes), alt)--read_frame_title :: InlineMatcher-read_frame_title = matchingElement NsSVG "title" (matchChildContent [] read_plain_text)--image_attributes :: Maybe T.Text -> Maybe T.Text -> Attr-image_attributes x y =- ( "", [], dim "width" x ++ dim "height" y)- where- dim _ (Just "") = []- dim name (Just v) = [(name, v)]- dim _ Nothing = []--read_frame_mathml :: OdtReaderSafe XML.Element (FirstMatch Inlines)-read_frame_mathml =- proc obj -> do- src <- executeIn (findAttr' NsXLink "href") -< obj- case fold src of- "" -> returnV mempty -< ()- src' -> do- let path = T.unpack $- fromMaybe src' (T.stripPrefix "./" src') <> "/content.xml"- (_, mathml) <- lookupResource -< path- case readMathML (UTF8.toText $ B.toStrict mathml) of- Left _ -> returnV mempty -< ()- Right exps -> arr (firstMatch . displayMath . writeTeX) -< exps--read_frame_text_box :: OdtReaderSafe XML.Element (FirstMatch Inlines)-read_frame_text_box = proc box -> do- paragraphs <- executeIn (matchChildContent' [ read_paragraph ]) -< box- arr read_img_with_caption -< toList paragraphs--read_img_with_caption :: [Block] -> FirstMatch Inlines-read_img_with_caption (Para [Image attr alt (src,title)] : _) =- firstMatch $ singleton (Image attr alt (src, "fig:" <> title)) -- no text, default caption-read_img_with_caption (Para (Image attr _ (src,title) : txt) : _) =- firstMatch $ singleton (Image attr txt (src, "fig:" <> title) ) -- override caption with the text that follows-read_img_with_caption ( Para (_ : xs) : ys) =- read_img_with_caption (Para xs : ys)-read_img_with_caption _ =- mempty--------------------------- Internal links-------------------------_ANCHOR_PREFIX_ :: T.Text-_ANCHOR_PREFIX_ = "anchor"-----readAnchorAttr :: OdtReader _x Anchor-readAnchorAttr = findAttrText NsText "name"---- | Beware: may fail-findAnchorName :: OdtReader AnchorPrefix Anchor-findAnchorName = ( keepingTheValue readAnchorAttr- >>^ spreadChoice- ) >>?! getPrettyAnchor------maybeAddAnchorFrom :: OdtReader Inlines AnchorPrefix- -> OdtReaderSafe Inlines Inlines-maybeAddAnchorFrom anchorReader =- keepingTheValue (anchorReader >>? findAnchorName >>?^ toAnchorElem)- >>>- proc (inlines, fAnchorElem) -> do- case fAnchorElem of- Right anchorElem -> returnA -< anchorElem- Left _ -> returnA -< inlines- where- toAnchorElem :: Anchor -> Inlines- toAnchorElem anchorID = spanWith (anchorID, [], []) mempty- -- no classes, no key-value pairs-----read_bookmark :: InlineMatcher-read_bookmark = matchingElement NsText "bookmark"- $ maybeAddAnchorFrom (liftAsSuccess $ returnV _ANCHOR_PREFIX_)-----read_bookmark_start :: InlineMatcher-read_bookmark_start = matchingElement NsText "bookmark-start"- $ maybeAddAnchorFrom (liftAsSuccess $ returnV _ANCHOR_PREFIX_)-----read_reference_start :: InlineMatcher-read_reference_start = matchingElement NsText "reference-mark-start"- $ maybeAddAnchorFrom readAnchorAttr---- | Beware: may fail-findAnchorRef :: OdtReader _x Anchor-findAnchorRef = ( findAttrText NsText "ref-name"- >>?^ (_ANCHOR_PREFIX_,)- ) >>?! getPrettyAnchor------maybeInAnchorRef :: OdtReaderSafe Inlines Inlines-maybeInAnchorRef = proc inlines -> do- fRef <- findAnchorRef -< ()- case fRef of- Right anchor ->- arr (toAnchorRef anchor) -<< inlines- Left _ -> returnA -< inlines- where- toAnchorRef :: Anchor -> Inlines -> Inlines- toAnchorRef anchor = link ("#" <> anchor) "" -- no title-----read_bookmark_ref :: InlineMatcher-read_bookmark_ref = matchingElement NsText "bookmark-ref"- $ maybeInAnchorRef- <<< matchChildContent [] read_plain_text-----read_reference_ref :: InlineMatcher-read_reference_ref = matchingElement NsText "reference-ref"- $ maybeInAnchorRef- <<< matchChildContent [] read_plain_text---------------------------- Entry point-------------------------read_text :: OdtReaderSafe _x Pandoc-read_text = matchChildContent' [ read_header- , read_paragraph- , read_list- , read_table- ]- >>^ doc--post_process :: Pandoc -> Pandoc-post_process (Pandoc m blocks) =- Pandoc m (post_process' blocks)--post_process' :: [Block] -> [Block]-post_process' (Table attr _ specs th tb tf : Div ("", ["caption"], _) blks : xs)- = Table attr (Caption Nothing blks) specs th tb tf : post_process' xs-post_process' bs = bs--read_body :: OdtReader _x (Pandoc, MediaBag)-read_body = executeInSub NsOffice "body"- $ executeInSub NsOffice "text"- $ liftAsSuccess- $ proc inlines -> do- txt <- read_text -< inlines- state <- getExtraState -< ()- returnA -< (post_process txt, getMediaBag state)
@@ -1,104 +0,0 @@-{- |- Module : Text.Pandoc.Readers.Odt.Generic.Fallible- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--Data types and utilities representing failure. Most of it is based on the-"Either" type in its usual configuration (left represents failure).--In most cases, the failure type is implied or required to be a "Monoid".--The choice of "Either" instead of a custom type makes it easier to write-compatible instances of "ArrowChoice".--}---- We export everything-module Text.Pandoc.Readers.Odt.Generic.Fallible where---- | Default for now. Will probably become a class at some point.-type Failure = ()--type Fallible a = Either Failure a------maybeToEither :: Maybe a -> Fallible a-maybeToEither (Just a) = Right a-maybeToEither Nothing = Left ()-----eitherToMaybe :: Either _l a -> Maybe a-eitherToMaybe (Left _) = Nothing-eitherToMaybe (Right a) = Just a---- | > fromLeft f === either f id-fromLeft :: (a -> b) -> Either a b -> b-fromLeft f (Left a) = f a-fromLeft _ (Right b) = b---- | > recover a === fromLeft (const a) === either (const a) id-recover :: a -> Either _f a -> a-recover a (Left _) = a-recover _ (Right a) = a---- | I would love to use 'fail'. Alas, 'Monad.fail'...-failWith :: failure -> Either failure _x-failWith f = Left f-----failEmpty :: (Monoid failure) => Either failure _x-failEmpty = failWith mempty-----succeedWith :: a -> Either _x a-succeedWith = Right-----collapseEither :: Either failure (Either failure x)- -> Either failure x-collapseEither (Left f ) = Left f-collapseEither (Right (Left f)) = Left f-collapseEither (Right (Right x)) = Right x---- | If either of the values represents a non-error, the result is a--- (possibly combined) non-error. If both values represent an error, an error--- is returned.-chooseMax :: (Monoid a, Monoid b) => Either a b -> Either a b -> Either a b-chooseMax = chooseMaxWith mappend---- | If either of the values represents a non-error, the result is a--- (possibly combined) non-error. If both values represent an error, an error--- is returned.-chooseMaxWith :: (Monoid a) => (b -> b -> b)- -> Either a b- -> Either a b- -> Either a b-chooseMaxWith (><) (Right a) (Right b) = Right $ a >< b-chooseMaxWith _ (Left a) (Left b) = Left $ a `mappend` b-chooseMaxWith _ (Right a) _ = Right a-chooseMaxWith _ _ (Right b) = Right b----- | Class of containers that can escalate contained 'Either's.--- The word "Vector" is meant in the sense of a disease transmitter.-class ChoiceVector v where- spreadChoice :: v (Either f a) -> Either f (v a)--instance ChoiceVector ((,) a) where- spreadChoice (_, Left f) = Left f- spreadChoice (x, Right y) = Right (x,y)- -- Wasn't there a newtype somewhere with the elements flipped?---- | Wrapper for a list. While the normal list instance of 'ChoiceVector'--- fails whenever it can, this type will never fail.-newtype SuccessList a = SuccessList { collectNonFailing :: [a] }- deriving ( Eq, Ord, Show )--instance ChoiceVector SuccessList where- spreadChoice = Right . SuccessList . foldr unTagRight [] . collectNonFailing- where unTagRight (Right x) = (x:)- unTagRight _ = id
@@ -1,45 +0,0 @@-{- |- Module : Text.Pandoc.Readers.Odt.Generic.Namespaces- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--A class containing a set of namespace identifiers. Used to convert between-typesafe Haskell namespace identifiers and unsafe "real world" namespaces.--}--module Text.Pandoc.Readers.Odt.Generic.Namespaces where--import qualified Data.Map as M-import Data.Text (Text)-----type NameSpaceIRI = Text-----type NameSpaceIRIs nsID = M.Map nsID NameSpaceIRI-----class (Eq nsID, Ord nsID) => NameSpaceID nsID where-- -- | Given a IRI, possibly update the map and return the id of the namespace.- -- May fail if the namespace is unknown and the application does not- -- allow unknown namespaces.- getNamespaceID :: NameSpaceIRI- -> NameSpaceIRIs nsID- -> Maybe (NameSpaceIRIs nsID, nsID)- -- | Given a namespace id, lookup its IRI. May be overridden for performance.- getIRI :: nsID- -> NameSpaceIRIs nsID- -> Maybe NameSpaceIRI- -- | The root element of an XML document has a namespace, too, and the- -- "XML.Light-parser" is eager to remove the corresponding namespace- -- attribute.- -- As a result, at least this root namespace must be provided.- getInitialIRImap :: NameSpaceIRIs nsID-- getIRI = M.lookup- getInitialIRImap = M.empty
@@ -1,30 +0,0 @@-{- |- Module : Text.Pandoc.Readers.Odt.Generic.SetMap- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--A map of values to sets of values.--}--module Text.Pandoc.Readers.Odt.Generic.SetMap where--import qualified Data.Map as M-import qualified Data.Set as S--type SetMap k v = M.Map k (S.Set v)--empty :: SetMap k v-empty = M.empty--fromList :: (Ord k, Ord v) => [(k,v)] -> SetMap k v-fromList = foldr (uncurry insert) empty--insert :: (Ord k, Ord v) => k -> v -> SetMap k v -> SetMap k v-insert key value setMap = M.insertWith S.union key (S.singleton value) setMap--union3 :: (Ord k) => SetMap k v -> SetMap k v -> SetMap k v -> SetMap k v-union3 sm1 sm2 sm3 = sm1 `M.union` sm2 `M.union` sm3
@@ -1,116 +0,0 @@-{-# LANGUAGE ViewPatterns #-}-{- |- Module : Text.Pandoc.Reader.Odt.Generic.Utils- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--General utility functions for the odt reader.--}--module Text.Pandoc.Readers.Odt.Generic.Utils-( uncurry3-, uncurry4-, uncurry5-, uncurry6-, swap-, reverseComposition-, tryToRead-, Lookupable(..)-, readLookupable-, readPercent-, findBy-, swing-, composition-) where--import Control.Category (Category, (<<<), (>>>))-import qualified Control.Category as Cat (id)-import Data.Char (isSpace)-import qualified Data.Foldable as F (Foldable, foldr)-import Data.Maybe-import Data.Text (Text)-import qualified Data.Text as T---- | Equivalent to--- > foldr (.) id--- where '(.)' are 'id' are the ones from "Control.Category"--- and 'foldr' is the one from "Data.Foldable".--- The noun-form was chosen to be consistent with 'sum', 'product' etc--- based on the discussion at--- <https://groups.google.com/forum/#!topic/haskell-cafe/VkOZM1zaHOI>--- (that I was not part of)-composition :: (Category cat, F.Foldable f) => f (cat a a) -> cat a a-composition = F.foldr (<<<) Cat.id---- | Equivalent to--- > foldr (flip (.)) id--- where '(.)' are 'id' are the ones from "Control.Category"--- and 'foldr' is the one from "Data.Foldable".--- A reversed version of 'composition'.-reverseComposition :: (Category cat, F.Foldable f) => f (cat a a) -> cat a a-reverseComposition = F.foldr (>>>) Cat.id---- | This function often makes it possible to switch values with the functions--- that are applied to them.------ Examples:--- > swing map :: [a -> b] -> a -> [b]--- > swing any :: [a -> Bool] -> a -> Bool--- > swing foldr :: b -> a -> [a -> b -> b] -> b--- > swing scanr :: c -> a -> [a -> c -> c] -> c--- > swing zipWith :: [a -> b -> c] -> a -> [b] -> [c]--- > swing find :: [a -> Bool] -> a -> Maybe (a -> Bool)------ Stolen from <https://wiki.haskell.org/Pointfree>-swing :: (((a -> b) -> b) -> c -> d) -> c -> a -> d-swing = flip.(.flip id)--- swing f c a = f ($ a) c----- | Alternative to 'read'/'reads'. The former of these throws errors--- (nobody wants that) while the latter returns "to much" for simple purposes.--- This function instead applies 'reads' and returns the first match (if any)--- in a 'Maybe'.-tryToRead :: (Read r) => Text -> Maybe r-tryToRead = (reads . T.unpack) >>> listToMaybe >>> fmap fst---- | A version of 'reads' that requires a '%' sign after the number-readPercent :: ReadS Int-readPercent s = [ (i,s') | (i , r ) <- reads s- , ("%" , s') <- lex r- ]---- | Data that can be looked up.--- This is mostly a utility to read data with kind *.-class Lookupable a where- lookupTable :: [(Text, a)]---- | Very similar to a simple 'lookup' in the 'lookupTable', but with a lexer.-readLookupable :: (Lookupable a) => Text -> Maybe a-readLookupable s =- lookup (T.takeWhile (not . isSpace) $ T.dropWhile isSpace s) lookupTable--uncurry3 :: (a->b->c -> z) -> (a,b,c ) -> z-uncurry4 :: (a->b->c->d -> z) -> (a,b,c,d ) -> z-uncurry5 :: (a->b->c->d->e -> z) -> (a,b,c,d,e ) -> z-uncurry6 :: (a->b->c->d->e->f -> z) -> (a,b,c,d,e,f ) -> z--uncurry3 fun (a,b,c ) = fun a b c-uncurry4 fun (a,b,c,d ) = fun a b c d-uncurry5 fun (a,b,c,d,e ) = fun a b c d e-uncurry6 fun (a,b,c,d,e,f ) = fun a b c d e f--swap :: (a,b) -> (b,a)-swap (a,b) = (b,a)---- | A version of "Data.List.find" that uses a converter to a Maybe instance.--- The returned value is the first which the converter returns in a 'Just'--- wrapper.-findBy :: (a -> Maybe b) -> [a] -> Maybe b-findBy _ [] = Nothing-findBy f ((f -> Just x):_ ) = Just x-findBy f ( _:xs) = findBy f xs
@@ -1,785 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE PatternGuards #-}-{- |- Module : Text.Pandoc.Readers.Odt.Generic.XMLConverter- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--A generalized XML parser based on stateful arrows.-It might be sufficient to define this reader as a comonad, but there is-not a lot of use in trying.--}--module Text.Pandoc.Readers.Odt.Generic.XMLConverter-( ElementName-, XMLConverterState-, XMLConverter-, FallibleXMLConverter-, runConverter'-, getExtraState-, setExtraState-, modifyExtraState-, producingExtraState-, findChild'-, filterChildrenName'-, isSet'-, isSetWithDefault-, elName-, searchAttr-, lookupAttr-, lookupAttr'-, lookupDefaultingAttr-, findAttr'-, findAttrText'-, findAttr-, findAttrText-, findAttrWithDefault-, findAttrTextWithDefault-, readAttr-, readAttr'-, readAttrWithDefault-, getAttr-, executeIn-, executeInSub-, withEveryL-, tryAll-, matchContent'-, matchContent-) where--import Prelude hiding (Applicative(..))-import Control.Applicative hiding ( liftA, liftA2 )-import Control.Monad ( MonadPlus )-import Control.Arrow--import Data.Bool ( bool )-import Data.Either ( rights )-import qualified Data.Map as M-import Data.Text (Text)-import Data.Default-import Data.Maybe-import Data.List (foldl')--import qualified Text.Pandoc.XML.Light as XML--import Text.Pandoc.Readers.Odt.Arrows.State-import Text.Pandoc.Readers.Odt.Arrows.Utils-import Text.Pandoc.Readers.Odt.Generic.Namespaces-import Text.Pandoc.Readers.Odt.Generic.Utils-import Text.Pandoc.Readers.Odt.Generic.Fallible------------------------------------------------------------------------------------- Basis types for readability--------------------------------------------------------------------------------------type ElementName = Text-type AttributeName = Text-type AttributeValue = Text-type TextAttributeValue = Text-----type NameSpacePrefix = Text-----type NameSpacePrefixes nsID = M.Map nsID NameSpacePrefix------------------------------------------------------------------------------------- Main converter state------------------------------------------------------------------------------------- GADT so some of the NameSpaceID restrictions can be deduced-data XMLConverterState nsID extraState where- XMLConverterState :: NameSpaceID nsID- => { -- | A stack of parent elements. The top element is the current one.- -- Arguably, a real Zipper would be better. But that is an- -- optimization that can be made at a later time, e.g. when- -- replacing Text.XML.Light.- parentElements :: [XML.Element]- -- | A map from internal namespace IDs to the namespace prefixes- -- used in XML elements- , namespacePrefixes :: NameSpacePrefixes nsID- -- | A map from internal namespace IDs to namespace IRIs- -- (Only necessary for matching namespace IDs and prefixes)- , namespaceIRIs :: NameSpaceIRIs nsID- -- | A place to put "something else". This feature is used heavily- -- to keep the main code cleaner. More specifically, the main reader- -- is divided into different stages. Each stage lifts something up- -- here, which the next stage can then use. This could of course be- -- generalized to a state-tree or used for the namespace IRIs. The- -- border between states and values is an imaginary one, after all.- -- But the separation as it is seems to be enough for now.- , moreState :: extraState- }- -> XMLConverterState nsID extraState-----createStartState :: (NameSpaceID nsID)- => XML.Element- -> extraState- -> XMLConverterState nsID extraState-createStartState element extraState =- XMLConverterState- { parentElements = [element]- , namespacePrefixes = M.empty- , namespaceIRIs = getInitialIRImap- , moreState = extraState- }---- | Functor over extra state-instance Functor (XMLConverterState nsID) where- fmap f ( XMLConverterState parents prefixes iRIs extraState )- = XMLConverterState parents prefixes iRIs (f extraState)-----replaceExtraState :: extraState- -> XMLConverterState nsID _x- -> XMLConverterState nsID extraState-replaceExtraState x s- = fmap (const x) s-----currentElement :: XMLConverterState nsID extraState- -> XML.Element-currentElement state = head (parentElements state)---- | Replace the current position by another, modifying the extra state--- in the process-swapStack' :: XMLConverterState nsID extraState- -> [XML.Element]- -> ( XMLConverterState nsID extraState , [XML.Element] )-swapStack' state stack- = ( state { parentElements = stack }- , parentElements state- )-----pushElement :: XML.Element- -> XMLConverterState nsID extraState- -> XMLConverterState nsID extraState-pushElement e state = state { parentElements = e:parentElements state }---- | Pop the top element from the call stack, unless it is the last one.-popElement :: XMLConverterState nsID extraState- -> Maybe (XMLConverterState nsID extraState)-popElement state- | _:es@(_:_) <- parentElements state = Just $ state { parentElements = es }- | otherwise = Nothing------------------------------------------------------------------------------------- Main type------------------------------------------------------------------------------------- It might be a good idea to pack the converters in a GADT--- Downside: data instead of type--- Upside: 'Failure' could be made a parameter as well.-----type XMLConverter nsID extraState input output- = ArrowState (XMLConverterState nsID extraState ) input output--type FallibleXMLConverter nsID extraState input output- = XMLConverter nsID extraState input (Fallible output)-----runConverter :: XMLConverter nsID extraState input output- -> XMLConverterState nsID extraState- -> input- -> output-runConverter converter state input = snd $ runArrowState converter (state,input)--runConverter' :: (NameSpaceID nsID)- => FallibleXMLConverter nsID extraState () success- -> extraState- -> XML.Element- -> Fallible success-runConverter' converter extraState element = runConverter (readNSattributes >>? converter) (createStartState element extraState) ()-----getCurrentElement :: XMLConverter nsID extraState x XML.Element-getCurrentElement = extractFromState currentElement-----getExtraState :: XMLConverter nsID extraState x extraState-getExtraState = extractFromState moreState-----setExtraState :: XMLConverter nsID extraState extraState extraState-setExtraState = withState $ \state extra- -> (replaceExtraState extra state , extra)----- | Lifts a function to the extra state.-modifyExtraState :: (extraState -> extraState)- -> XMLConverter nsID extraState x x-modifyExtraState = modifyState.fmap----- | First sets the extra state to the new value. Then modifies the original--- extra state with a converter that uses the new state. Finally, the--- intermediate state is dropped and the extra state is lifted into the--- state as it was at the beginning of the function.--- As a result, exactly the extra state and nothing else is changed.--- The resulting converter even behaves like an identity converter on the--- value level.------ (The -ing form is meant to be mnemonic in a sequence of arrows as in--- convertingExtraState () converter >>> doOtherStuff)----convertingExtraState :: extraState'- -> FallibleXMLConverter nsID extraState' extraState extraState- -> FallibleXMLConverter nsID extraState x x-convertingExtraState v a = withSubStateF setVAsExtraState modifyWithA- where- setVAsExtraState = liftAsSuccess $ extractFromState id >>^ replaceExtraState v- modifyWithA = keepingTheValue (moreState ^>> a)- >>^ spreadChoice >>?% flip replaceExtraState---- | First sets the extra state to the new value. Then produces a new--- extra state with a converter that uses the new state. Finally, the--- intermediate state is dropped and the extra state is lifted into the--- state as it was at the beginning of the function.--- As a result, exactly the extra state and nothing else is changed.--- The resulting converter even behaves like an identity converter on the--- value level.------ Equivalent to------ > \v x a -> convertingExtraState v (returnV x >>> a)------ (The -ing form is meant to be mnemonic in a sequence of arrows as in--- producingExtraState () () producer >>> doOtherStuff)----producingExtraState :: extraState'- -> a- -> FallibleXMLConverter nsID extraState' a extraState- -> FallibleXMLConverter nsID extraState x x-producingExtraState v x a = convertingExtraState v (returnV x >>> a)-------------------------------------------------------------------------------------- Work in namespaces------------------------------------------------------------------------------------- | Arrow version of 'getIRI'-lookupNSiri :: (NameSpaceID nsID)- => nsID- -> XMLConverter nsID extraState x (Maybe NameSpaceIRI)-lookupNSiri nsID = extractFromState- $ \state -> getIRI nsID $ namespaceIRIs state-----lookupNSprefix :: (NameSpaceID nsID)- => nsID- -> XMLConverter nsID extraState x (Maybe NameSpacePrefix)-lookupNSprefix nsID = extractFromState- $ \state -> M.lookup nsID $ namespacePrefixes state---- | Extracts namespace attributes from the current element and tries to--- update the current mapping accordingly-readNSattributes :: (NameSpaceID nsID)- => FallibleXMLConverter nsID extraState x ()-readNSattributes = fromState $ \state -> maybe (state, failEmpty )- ( , succeedWith ())- (extractNSAttrs state )- where- extractNSAttrs :: (NameSpaceID nsID)- => XMLConverterState nsID extraState- -> Maybe (XMLConverterState nsID extraState)- extractNSAttrs startState- = foldl' (\state d -> state >>= addNS d)- (Just startState)- nsAttribs- where nsAttribs = mapMaybe readNSattr (XML.elAttribs element)- element = currentElement startState- readNSattr (XML.Attr (XML.QName name _ (Just "xmlns")) iri)- = Just (name, iri)- readNSattr _ = Nothing- addNS (prefix, iri) state = fmap updateState- $ getNamespaceID iri- $ namespaceIRIs state- where updateState (iris,nsID)- = state { namespaceIRIs = iris- , namespacePrefixes = M.insert nsID prefix- $ namespacePrefixes state- }------------------------------------------------------------------------------------- Common namespace accessors------------------------------------------------------------------------------------- | Given a namespace id and an element name, creates a 'XML.QName' for--- internal use-qualifyName :: (NameSpaceID nsID)- => nsID -> ElementName- -> XMLConverter nsID extraState x XML.QName-qualifyName nsID name = lookupNSiri nsID- &&& lookupNSprefix nsID- >>% XML.QName name---- | Checks if a given element matches both a specified namespace id--- and a predicate-elemNameMatches :: (NameSpaceID nsID)- => nsID -> (ElementName -> Bool)- -> XMLConverter nsID extraState XML.Element Bool-elemNameMatches nsID f = keepingTheValue (lookupNSiri nsID) >>% hasMatchingName- where hasMatchingName e iri = let name = XML.elName e- in f (XML.qName name)- && XML.qURI name == iri---- | Checks if a given element matches both a specified namespace id--- and a specified element name-elemNameIs :: (NameSpaceID nsID)- => nsID -> ElementName- -> XMLConverter nsID extraState XML.Element Bool-elemNameIs nsID name = elemNameMatches nsID (== name)------------------------------------------------------------------------------------- General content-----------------------------------------------------------------------------------elName :: XML.Element -> ElementName-elName = XML.qName . XML.elName-----elContent :: XMLConverter nsID extraState x [XML.Content]-elContent = getCurrentElement- >>^ XML.elContent------------------------------------------------------------------------------------- Children-----------------------------------------------------------------------------------------findChildren :: (NameSpaceID nsID)- => nsID -> ElementName- -> XMLConverter nsID extraState x [XML.Element]-findChildren nsID name = qualifyName nsID name- &&& getCurrentElement- >>% XML.findChildren-----findChild' :: (NameSpaceID nsID)- => nsID- -> ElementName- -> XMLConverter nsID extraState x (Maybe XML.Element)-findChild' nsID name = qualifyName nsID name- &&& getCurrentElement- >>% XML.findChild-----findChild :: (NameSpaceID nsID)- => nsID -> ElementName- -> FallibleXMLConverter nsID extraState x XML.Element-findChild nsID name = findChild' nsID name- >>> maybeToChoice--filterChildrenName' :: (NameSpaceID nsID)- => nsID- -> (ElementName -> Bool)- -> XMLConverter nsID extraState x [XML.Element]-filterChildrenName' nsID f = getCurrentElement- >>> arr XML.elChildren- >>> iterateS (keepingTheValue (elemNameMatches nsID f))- >>> arr (map fst . filter snd)------------------------------------------------------------------------------------- Attributes--------------------------------------------------------------------------------------isSet' :: (NameSpaceID nsID)- => nsID -> AttributeName- -> XMLConverter nsID extraState x (Maybe Bool)-isSet' nsID attrName = findAttr' nsID attrName- >>^ (>>= stringToBool')--isSetWithDefault :: (NameSpaceID nsID)- => nsID -> AttributeName- -> Bool- -> XMLConverter nsID extraState x Bool-isSetWithDefault nsID attrName def'- = isSet' nsID attrName- >>^ fromMaybe def'---- | Lookup value in a dictionary, fail if no attribute found or value--- not in dictionary-searchAttrIn :: (NameSpaceID nsID)- => nsID -> AttributeName- -> [(AttributeValue,a)]- -> FallibleXMLConverter nsID extraState x a-searchAttrIn nsID attrName dict- = findAttr nsID attrName- >>?^? maybeToChoice.(`lookup` dict )---- | Lookup value in a dictionary. If attribute or value not found,--- return default value-searchAttr :: (NameSpaceID nsID)- => nsID -> AttributeName- -> a- -> [(AttributeValue,a)]- -> XMLConverter nsID extraState x a-searchAttr nsID attrName defV dict- = searchAttrIn nsID attrName dict- >>> const defV ^|||^ id---- | Read a 'Lookupable' attribute. Fail if no match.-lookupAttr :: (NameSpaceID nsID, Lookupable a)- => nsID -> AttributeName- -> FallibleXMLConverter nsID extraState x a-lookupAttr nsID attrName = lookupAttr' nsID attrName- >>^ maybeToChoice----- | Read a 'Lookupable' attribute. Return the result as a 'Maybe'.-lookupAttr' :: (NameSpaceID nsID, Lookupable a)- => nsID -> AttributeName- -> XMLConverter nsID extraState x (Maybe a)-lookupAttr' nsID attrName- = findAttr' nsID attrName- >>^ (>>= readLookupable)---- | Read a 'Lookupable' attribute with explicit default-lookupAttrWithDefault :: (NameSpaceID nsID, Lookupable a)- => nsID -> AttributeName- -> a- -> XMLConverter nsID extraState x a-lookupAttrWithDefault nsID attrName deflt- = lookupAttr' nsID attrName- >>^ fromMaybe deflt---- | Read a 'Lookupable' attribute with implicit default-lookupDefaultingAttr :: (NameSpaceID nsID, Lookupable a, Default a)- => nsID -> AttributeName- -> XMLConverter nsID extraState x a-lookupDefaultingAttr nsID attrName- = lookupAttrWithDefault nsID attrName def---- | Return value as a (Maybe Text)-findAttr' :: (NameSpaceID nsID)- => nsID -> AttributeName- -> XMLConverter nsID extraState x (Maybe AttributeValue)-findAttr' nsID attrName = qualifyName nsID attrName- &&& getCurrentElement- >>% XML.findAttr---- | Return value as a (Maybe Text)-findAttrText' :: (NameSpaceID nsID)- => nsID -> AttributeName- -> XMLConverter nsID extraState x (Maybe TextAttributeValue)-findAttrText' nsID attrName- = qualifyName nsID attrName- &&& getCurrentElement- >>% XML.findAttr---- | Return value as string or fail-findAttr :: (NameSpaceID nsID)- => nsID -> AttributeName- -> FallibleXMLConverter nsID extraState x AttributeValue-findAttr nsID attrName = findAttr' nsID attrName- >>> maybeToChoice---- | Return value as text or fail-findAttrText :: (NameSpaceID nsID)- => nsID -> AttributeName- -> FallibleXMLConverter nsID extraState x TextAttributeValue-findAttrText nsID attrName- = findAttr' nsID attrName- >>> maybeToChoice---- | Return value as string or return provided default value-findAttrWithDefault :: (NameSpaceID nsID)- => nsID -> AttributeName- -> AttributeValue- -> XMLConverter nsID extraState x AttributeValue-findAttrWithDefault nsID attrName deflt- = findAttr' nsID attrName- >>^ fromMaybe deflt---- | Return value as string or return provided default value-findAttrTextWithDefault :: (NameSpaceID nsID)- => nsID -> AttributeName- -> TextAttributeValue- -> XMLConverter nsID extraState x TextAttributeValue-findAttrTextWithDefault nsID attrName deflt- = findAttr' nsID attrName- >>^ fromMaybe deflt---- | Read and return value or fail-readAttr :: (NameSpaceID nsID, Read attrValue)- => nsID -> AttributeName- -> FallibleXMLConverter nsID extraState x attrValue-readAttr nsID attrName = readAttr' nsID attrName- >>> maybeToChoice---- | Read and return value or return Nothing-readAttr' :: (NameSpaceID nsID, Read attrValue)- => nsID -> AttributeName- -> XMLConverter nsID extraState x (Maybe attrValue)-readAttr' nsID attrName = findAttr' nsID attrName- >>^ (>>= tryToRead)---- | Read and return value or return provided default value-readAttrWithDefault :: (NameSpaceID nsID, Read attrValue)- => nsID -> AttributeName- -> attrValue- -> XMLConverter nsID extraState x attrValue-readAttrWithDefault nsID attrName deflt- = findAttr' nsID attrName- >>^ (>>= tryToRead)- >>^ fromMaybe deflt---- | Read and return value or return default value from 'Default' instance-getAttr :: (NameSpaceID nsID, Read attrValue, Default attrValue)- => nsID -> AttributeName- -> XMLConverter nsID extraState x attrValue-getAttr nsID attrName = readAttrWithDefault nsID attrName def------------------------------------------------------------------------------------- Movements--------------------------------------------------------------------------------------jumpThere :: XMLConverter nsID extraState XML.Element XML.Element-jumpThere = withState (\state element- -> ( pushElement element state , element )- )-----swapStack :: XMLConverter nsID extraState [XML.Element] [XML.Element]-swapStack = withState swapStack'-----jumpBack :: FallibleXMLConverter nsID extraState _x _x-jumpBack = tryModifyState (popElement >>> maybeToChoice)---- | Support function for "procedural" converters: jump to an element, execute--- a converter, jump back.--- This version is safer than 'executeThere', because it does not rely on the--- internal stack. As a result, the converter can not move around in arbitrary--- ways. The downside is of course that some of the environment is not--- accessible to the converter.-switchingTheStack :: XMLConverter nsID moreState a b- -> XMLConverter nsID moreState (a, XML.Element) b-switchingTheStack a = second ( (:[]) ^>> swapStack )- >>> first a- >>> second swapStack- >>^ fst---- | Support function for "procedural" converters: jumps to an element, executes--- a converter, jumps back.--- Make sure that the converter is well-behaved; that is it should--- return to the exact position it started from in /every possible path/ of--- execution, even if it "fails". If it does not, you may encounter--- strange bugs. If you are not sure about the behaviour or want to use--- shortcuts, you can often use 'switchingTheStack' instead.-executeThere :: FallibleXMLConverter nsID moreState a b- -> FallibleXMLConverter nsID moreState (a, XML.Element) b-executeThere a = second jumpThere- >>> fst- ^>> a- >>> jumpBack -- >>? jumpBack would not ensure the jump.- >>^ collapseEither----- | Do something in a specific element, then come back-executeIn :: XMLConverter nsID extraState XML.Element s- -> XMLConverter nsID extraState XML.Element s-executeIn a = duplicate >>> switchingTheStack a---- | Do something in a sub-element, then come back-executeInSub :: (NameSpaceID nsID)- => nsID -> ElementName- -> FallibleXMLConverter nsID extraState f s- -> FallibleXMLConverter nsID extraState f s-executeInSub nsID name a = keepingTheValue- (findChild nsID name)- >>> ignoringState liftFailure- >>? switchingTheStack a- where liftFailure (_, Left f) = Left f- liftFailure (x, Right e) = Right (x, e)------------------------------------------------------------------------------------- Iterating over children------------------------------------------------------------------------------------- Helper converter to prepare different types of iterations.--- It lifts the children (of a certain type) of the current element--- into the value level and pairs each one with the current input value.-prepareIteration :: (NameSpaceID nsID)- => nsID -> ElementName- -> XMLConverter nsID extraState b [(b, XML.Element)]-prepareIteration nsID name = keepingTheValue- (findChildren nsID name)- >>% distributeValue-----withEveryL :: (NameSpaceID nsID)- => nsID -> ElementName- -> FallibleXMLConverter nsID extraState a b- -> FallibleXMLConverter nsID extraState a [b]-withEveryL = withEvery---- | Applies a converter to every child element of a specific type.--- Collects results in a 'MonadPlus'.--- Fails completely if any conversion fails.-withEvery :: (NameSpaceID nsID, MonadPlus m)- => nsID -> ElementName- -> FallibleXMLConverter nsID extraState a b- -> FallibleXMLConverter nsID extraState a (m b)-withEvery nsID name a = prepareIteration nsID name- >>> iterateS' (switchingTheStack a)---- | Applies a converter to every child element of a specific type.--- Collects all successful results in a list.-tryAll :: (NameSpaceID nsID)- => nsID -> ElementName- -> FallibleXMLConverter nsID extraState b a- -> XMLConverter nsID extraState b [a]-tryAll nsID name a = prepareIteration nsID name- >>> iterateS (switchingTheStack a)- >>^ rights------------------------------------------------------------------------------------- Matching children-----------------------------------------------------------------------------------type IdXMLConverter nsID moreState x- = XMLConverter nsID moreState x x--type MaybeCConverter nsID moreState x- = Maybe (IdXMLConverter nsID moreState (x, XML.Content))---- Chainable converter that helps deciding which converter to actually use.-type ContentMatchConverter nsID extraState x- = IdXMLConverter nsID- extraState- (MaybeCConverter nsID extraState x, XML.Content)---- Helper function: The @c@ is actually a converter that is to be selected by--- matching XML content to the first two parameters.--- The fold used to match elements however is very simple, so to use it,--- this function wraps the converter in another converter that unifies--- the accumulator. Think of a lot of converters with the resulting type--- chained together. The accumulator not only transports the element--- unchanged to the next matcher, it also does the actual selecting by--- combining the intermediate results with '(<|>)'.-makeMatcherC :: (NameSpaceID nsID)- => nsID -> ElementName- -> FallibleXMLConverter nsID extraState a a- -> ContentMatchConverter nsID extraState a-makeMatcherC nsID name c = ( second ( contentToElem- >>> returnV Nothing- ||| ( elemNameIs nsID name- >>^ bool Nothing (Just cWithJump)- )- )- >>% (<|>)- ) &&&^ snd- where cWithJump = ( fst- ^&&& ( second contentToElem- >>> spreadChoice- ^>>? executeThere c- )- >>% recover)- &&&^ snd- contentToElem :: FallibleXMLConverter nsID extraState XML.Content XML.Element- contentToElem = arr $ \case- XML.Elem e' -> succeedWith e'- _ -> failEmpty---- Creates and chains a bunch of matchers-prepareMatchersC :: (NameSpaceID nsID)- => [(nsID, ElementName, FallibleXMLConverter nsID extraState x x)]- -> ContentMatchConverter nsID extraState x---prepareMatchersC = foldSs . (map $ uncurry3 makeMatcherC)-prepareMatchersC = reverseComposition . map (uncurry3 makeMatcherC)---- | Takes a list of element-data - converter groups and--- * Finds all content of the current element--- * Matches each group to each piece of content in order--- (at most one group per piece of content)--- * Filters non-matched content--- * Chains all found converters in content-order--- * Applies the chain to the input element-matchContent' :: (NameSpaceID nsID)- => [(nsID, ElementName, FallibleXMLConverter nsID extraState a a)]- -> XMLConverter nsID extraState a a-matchContent' lookups = matchContent lookups (arr fst)---- | Takes a list of element-data - converter groups and--- * Finds all content of the current element--- * Matches each group to each piece of content in order--- (at most one group per piece of content)--- * Adds a default converter for all non-matched content--- * Chains all found converters in content-order--- * Applies the chain to the input element-matchContent :: (NameSpaceID nsID)- => [(nsID, ElementName, FallibleXMLConverter nsID extraState a a)]- -> XMLConverter nsID extraState (a,XML.Content) a- -> XMLConverter nsID extraState a a-matchContent lookups fallback- = let matcher = prepareMatchersC lookups- in keepingTheValue (- elContent- >>> map (Nothing,)- ^>> iterateSL matcher- >>^ map swallowOrFallback- -- >>> foldSs- >>> reverseComposition- )- >>> swap- ^>> app- where- -- let the converter swallow the content and drop the content- -- in the return value- swallowOrFallback (Just converter,content) = (,content) ^>> converter >>^ fst- swallowOrFallback (Nothing ,content) = (,content) ^>> fallback------------------------------------------------------------------------------------- Internals-----------------------------------------------------------------------------------stringToBool' :: Text -> Maybe Bool-stringToBool' val | val `elem` trueValues = Just True- | val `elem` falseValues = Just False- | otherwise = Nothing- where trueValues = ["true" ,"on" ,"1"]- falseValues = ["false","off","0"]---distributeValue :: a -> [b] -> [(a,b)]-distributeValue = map.(,)------------------------------------------------------------------------------------{--NOTES-It might be a good idea to refactor the namespace stuff.-E.g.: if a namespace constructor took a string as a parameter, things like-> a ?>/< (NsText,"body")-would be nicer.-Together with a rename and some trickery, something like-> |< NsText "body" >< NsText "p" ?> a </> </>|-might even be possible.--Some day, XML.Light should be replaced by something better.-While doing that, it might be useful to replace String as the type of element-names with something else, too. (Of course with OverloadedStrings).-While doing that, maybe the types can be created in a way that something like-> NsText:"body"-could be used. Overloading (:) does not sounds like the best idea, but if the-element name type was a list, this might be possible.-Of course that would be a bit hackish, so the "right" way would probably be-something like-> InNS NsText "body"-but isn't that a bit boring? ;)--}
@@ -1,93 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Reader.Odt.Namespaces- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--Namespaces used in odt files.--}--module Text.Pandoc.Readers.Odt.Namespaces ( Namespace (..)- ) where--import qualified Data.Map as M (empty, insert)-import Data.Maybe (fromMaybe, listToMaybe)-import Data.Text (Text)-import qualified Data.Text as T-import Text.Pandoc.Readers.Odt.Generic.Namespaces---instance NameSpaceID Namespace where-- getInitialIRImap = nsIDmap-- getNamespaceID "" m = Just(m, NsXML)- getNamespaceID iri m = asPair $ fromMaybe (NsOther iri) (findID iri)- where asPair nsID = Just (M.insert nsID iri m, nsID)---findID :: NameSpaceIRI -> Maybe Namespace-findID iri = listToMaybe [nsID | (iri',nsID) <- nsIDs, iri' `T.isPrefixOf` iri]--nsIDmap :: NameSpaceIRIs Namespace-nsIDmap = foldr (uncurry $ flip M.insert) M.empty nsIDs--data Namespace = -- Open Document core- NsOffice | NsStyle | NsText | NsTable | NsForm- | NsDraw | Ns3D | NsAnim | NsChart | NsConfig- | NsDB | NsMeta | NsNumber | NsScript | NsManifest- | NsPresentation- -- Metadata- | NsODF- -- Compatible elements- | NsXSL_FO | NsSVG | NsSmil- -- External standards- | NsMathML | NsXForms | NsXLink | NsXHtml | NsGRDDL- | NsDublinCore- -- Metadata manifest- | NsPKG- -- Others- | NsOpenFormula- -- Core XML (basically only for the 'id'-attribute)- | NsXML- -- Fallback- | NsOther Text- deriving ( Eq, Ord, Show )---- | Not the actual iri's, but large prefixes of them - this way there are--- less versioning problems and the like.-nsIDs :: [(Text, Namespace)]-nsIDs = [- ("urn:oasis:names:tc:opendocument:xmlns:animation" , NsAnim ),- ("urn:oasis:names:tc:opendocument:xmlns:chart" , NsChart ),- ("urn:oasis:names:tc:opendocument:xmlns:config" , NsConfig ),- ("urn:oasis:names:tc:opendocument:xmlns:database" , NsDB ),- ("urn:oasis:names:tc:opendocument:xmlns:dr3d" , Ns3D ),- ("urn:oasis:names:tc:opendocument:xmlns:drawing" , NsDraw ),- ("urn:oasis:names:tc:opendocument:xmlns:form" , NsForm ),- ("urn:oasis:names:tc:opendocument:xmlns:manifest" , NsManifest ),- ("urn:oasis:names:tc:opendocument:xmlns:meta" , NsMeta ),- ("urn:oasis:names:tc:opendocument:xmlns:datastyle" , NsNumber ),- ("urn:oasis:names:tc:opendocument:xmlns:of" , NsOpenFormula ),- ("urn:oasis:names:tc:opendocument:xmlns:office:1.0" , NsOffice ),- ("urn:oasis:names:tc:opendocument:xmlns:presentation" , NsPresentation ),- ("urn:oasis:names:tc:opendocument:xmlns:script" , NsScript ),- ("urn:oasis:names:tc:opendocument:xmlns:style" , NsStyle ),- ("urn:oasis:names:tc:opendocument:xmlns:table" , NsTable ),- ("urn:oasis:names:tc:opendocument:xmlns:text" , NsText ),- ("urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible", NsXSL_FO ),- ("urn:oasis:names:tc:opendocument:xmlns:smil-compatible" , NsSmil ),- ("urn:oasis:names:tc:opendocument:xmlns:svg-compatible" , NsSVG ),- ("http://docs.oasis-open.org/ns/office/1.2/meta/odf" , NsODF ),- ("http://docs.oasis-open.org/ns/office/1.2/meta/pkg" , NsPKG ),- ("http://purl.org/dc/elements" , NsDublinCore ),- ("http://www.w3.org/2003/g/data-view" , NsGRDDL ),- ("http://www.w3.org/1998/Math/MathML" , NsMathML ),- ("http://www.w3.org/1999/xhtml" , NsXHtml ),- ("http://www.w3.org/2002/xforms" , NsXForms ),- ("http://www.w3.org/1999/xlink" , NsXLink )- ]
@@ -1,640 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE Arrows #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Readers.Odt.StyleReader- Copyright : Copyright (C) 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com>- Stability : alpha- Portability : portable--Reader for the style information in an odt document.--}--module Text.Pandoc.Readers.Odt.StyleReader-( Style (..)-, StyleName-, StyleFamily (..)-, Styles (..)-, StyleProperties (..)-, TextProperties (..)-, ParaProperties (..)-, VerticalTextPosition (..)-, ListItemNumberFormat (..)-, ListLevel-, ListStyle (..)-, ListLevelStyle (..)-, ListLevelType (..)-, LengthOrPercent (..)-, lookupStyle-, getListLevelStyle-, getStyleFamily-, lookupDefaultStyle'-, lookupListStyleByName-, extendedStylePropertyChain-, readStylesAt-) where--import Prelude hiding (Applicative(..))-import Control.Applicative hiding (liftA, liftA2, liftA3)-import Control.Arrow--import Data.Default-import qualified Data.Foldable as F-import Data.List (unfoldr, foldl')-import qualified Data.Map as M-import Data.Maybe-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Set as S--import qualified Text.Pandoc.XML.Light as XML--import Text.Pandoc.Shared (safeRead, tshow)--import Text.Pandoc.Readers.Odt.Arrows.Utils--import Text.Pandoc.Readers.Odt.Generic.Fallible-import qualified Text.Pandoc.Readers.Odt.Generic.SetMap as SM-import Text.Pandoc.Readers.Odt.Generic.Utils-import Text.Pandoc.Readers.Odt.Generic.XMLConverter--import Text.Pandoc.Readers.Odt.Base-import Text.Pandoc.Readers.Odt.Namespaces--readStylesAt :: XML.Element -> Fallible Styles-readStylesAt e = runConverter' readAllStyles mempty e------------------------------------------------------------------------------------- Reader for font declarations and font pitches------------------------------------------------------------------------------------- Pandoc has no support for different font pitches. Yet knowing them can be--- very helpful in cases where Pandoc has more semantics than OpenDocument.--- In these cases, the pitch can help deciding as what to define a block of--- text. So let's start with a type for font pitches:--data FontPitch = PitchVariable | PitchFixed- deriving ( Eq, Show )--instance Lookupable FontPitch where- lookupTable = [ ("variable" , PitchVariable)- , ("fixed" , PitchFixed )- ]--instance Default FontPitch where- def = PitchVariable---- The font pitch can be specified in a style directly. Normally, however,--- it is defined in the font. That is also the specs' recommendation.------ Thus, we want--type FontFaceName = Text--type FontPitches = M.Map FontFaceName FontPitch---- To get there, the fonts have to be read and the pitches extracted.--- But the resulting map are only needed at one later place, so it should not be--- transported on the value level, especially as we already use a state arrow.--- So instead, the resulting map is lifted into the state of the reader.--- (An alternative might be ImplicitParams, but again, we already have a state.)------ So the main style readers will have the types-type StyleReader a b = XMLReader FontPitches a b--- and-type StyleReaderSafe a b = XMLReaderSafe FontPitches a b--- respectively.------ But before we can work with these, we need to define the reader that reads--- the fonts:---- | A reader for font pitches-fontPitchReader :: XMLReader _s _x FontPitches-fontPitchReader = executeInSub NsOffice "font-face-decls" (- withEveryL NsStyle "font-face" (liftAsSuccess (- findAttr' NsStyle "name"- &&&- lookupDefaultingAttr NsStyle "font-pitch"- ))- >>?^ ( M.fromList . foldl' accumLegalPitches [] )- ) `ifFailedDo` returnV (Right M.empty)- where accumLegalPitches ls (Nothing,_) = ls- accumLegalPitches ls (Just n,p) = (n,p):ls----- | A wrapper around the font pitch reader that lifts the result into the--- state.-readFontPitches :: StyleReader x x-readFontPitches = producingExtraState () () fontPitchReader----- | Looking up a pitch in the state of the arrow.------ The function does the following:--- * Look for the font pitch in an attribute.--- * If that fails, look for the font name, look up the font in the state--- and use the pitch from there.--- * Return the result in a Maybe----findPitch :: XMLReaderSafe FontPitches _x (Maybe FontPitch)-findPitch = ( lookupAttr NsStyle "font-pitch"- `ifFailedDo` findAttr NsStyle "font-name"- >>? ( keepingTheValue getExtraState- >>% M.lookup- >>^ maybeToChoice- )- )- >>> choiceToMaybe------------------------------------------------------------------------------------- Definitions of main data-----------------------------------------------------------------------------------type StyleName = Text---- | There are two types of styles: named styles with a style family and an--- optional style parent, and default styles for each style family,--- defining default style properties-data Styles = Styles- { stylesByName :: M.Map StyleName Style- , listStylesByName :: M.Map StyleName ListStyle- , defaultStyleMap :: M.Map StyleFamily StyleProperties- }- deriving ( Show )---- Styles from a monoid under union-instance Semigroup Styles where- (Styles sBn1 dSm1 lsBn1) <> (Styles sBn2 dSm2 lsBn2)- = Styles (M.union sBn1 sBn2)- (M.union dSm1 dSm2)- (M.union lsBn1 lsBn2)-instance Monoid Styles where- mempty = Styles M.empty M.empty M.empty- mappend = (<>)---- Not all families from the specifications are implemented, only those we need.--- But there are none that are not mentioned here.-data StyleFamily = FaText | FaParagraph--- | FaTable | FaTableCell | FaTableColumn | FaTableRow--- | FaGraphic | FaDrawing | FaChart--- | FaPresentation--- | FaRuby- deriving ( Eq, Ord, Show )--instance Lookupable StyleFamily where- lookupTable = [ ( "text" , FaText )- , ( "paragraph" , FaParagraph )--- , ( "table" , FaTable )--- , ( "table-cell" , FaTableCell )--- , ( "table-column" , FaTableColumn )--- , ( "table-row" , FaTableRow )--- , ( "graphic" , FaGraphic )--- , ( "drawing-page" , FaDrawing )--- , ( "chart" , FaChart )--- , ( "presentation" , FaPresentation )--- , ( "ruby" , FaRuby )- ]---- | A named style-data Style = Style { styleFamily :: Maybe StyleFamily- , styleParentName :: Maybe StyleName- , listStyle :: Maybe StyleName- , styleProperties :: StyleProperties- }- deriving ( Eq, Show )--data StyleProperties = SProps { textProperties :: Maybe TextProperties- , paraProperties :: Maybe ParaProperties--- , tableColProperties :: Maybe TColProperties--- , tableRowProperties :: Maybe TRowProperties--- , tableCellProperties :: Maybe TCellProperties--- , tableProperties :: Maybe TableProperties--- , graphicProperties :: Maybe GraphProperties- }- deriving ( Eq, Show )--instance Default StyleProperties where- def = SProps { textProperties = Just def- , paraProperties = Just def- }--data TextProperties = PropT { isEmphasised :: Bool- , isStrong :: Bool- , pitch :: Maybe FontPitch- , verticalPosition :: VerticalTextPosition- , underline :: Maybe UnderlineMode- , strikethrough :: Maybe UnderlineMode- }- deriving ( Eq, Show )--instance Default TextProperties where- def = PropT { isEmphasised = False- , isStrong = False- , pitch = Just def- , verticalPosition = def- , underline = Nothing- , strikethrough = Nothing- }--data ParaProperties = PropP { paraNumbering :: ParaNumbering- , indentation :: LengthOrPercent- , margin_left :: LengthOrPercent- }- deriving ( Eq, Show )--instance Default ParaProperties where- def = PropP { paraNumbering = NumberingNone- , indentation = def- , margin_left = def- }--------- All the little data types that make up the properties-------data VerticalTextPosition = VPosNormal | VPosSuper | VPosSub- deriving ( Eq, Show )--instance Default VerticalTextPosition where- def = VPosNormal--instance Read VerticalTextPosition where- readsPrec _ s = [ (VPosSub , s') | ("sub" , s') <- lexS ]- ++ [ (VPosSuper , s') | ("super" , s') <- lexS ]- ++ [ (signumToVPos n , s') | ( n , s') <- readPercent s ]- where- lexS = lex s- signumToVPos n | n < 0 = VPosSub- | n > 0 = VPosSuper- | otherwise = VPosNormal--data UnderlineMode = UnderlineModeNormal | UnderlineModeSkipWhitespace- deriving ( Eq, Show )--instance Lookupable UnderlineMode where- lookupTable = [ ( "continuous" , UnderlineModeNormal )- , ( "skip-white-space" , UnderlineModeSkipWhitespace )- ]---data ParaNumbering = NumberingNone | NumberingKeep | NumberingRestart Int- deriving ( Eq, Show )--data LengthOrPercent = LengthValueMM Int | PercentValue Int- deriving ( Eq, Show )--instance Default LengthOrPercent where- def = LengthValueMM 0--instance Read LengthOrPercent where- readsPrec _ s =- [ (PercentValue percent , s' ) | (percent , s' ) <- readPercent s]- ++ [ (LengthValueMM lengthMM , s'') | (length' , s' ) <- reads s- , (unit , s'') <- reads s'- , let lengthMM = estimateInMillimeter- length' unit- ]--data XslUnit = XslUnitMM | XslUnitCM- | XslUnitInch- | XslUnitPoints | XslUnitPica- | XslUnitPixel- | XslUnitEM--instance Show XslUnit where- show XslUnitMM = "mm"- show XslUnitCM = "cm"- show XslUnitInch = "in"- show XslUnitPoints = "pt"- show XslUnitPica = "pc"- show XslUnitPixel = "px"- show XslUnitEM = "em"--instance Read XslUnit where- readsPrec _ "mm" = [(XslUnitMM , "")]- readsPrec _ "cm" = [(XslUnitCM , "")]- readsPrec _ "in" = [(XslUnitInch , "")]- readsPrec _ "pt" = [(XslUnitPoints , "")]- readsPrec _ "pc" = [(XslUnitPica , "")]- readsPrec _ "px" = [(XslUnitPixel , "")]- readsPrec _ "em" = [(XslUnitEM , "")]- readsPrec _ _ = []---- | Rough conversion of measures into millimetres.--- Pixels and em's are actually implementation dependent/relative measures,--- so I could not really easily calculate anything exact here even if I wanted.--- But I do not care about exactness right now, as I only use measures--- to determine if a paragraph is "indented" or not.-estimateInMillimeter :: Int -> XslUnit -> Int-estimateInMillimeter n XslUnitMM = n-estimateInMillimeter n XslUnitCM = n * 10-estimateInMillimeter n XslUnitInch = n * 25 -- \* 25.4-estimateInMillimeter n XslUnitPoints = n `div` 3 -- \* 1/72 * 25.4-estimateInMillimeter n XslUnitPica = n * 4 -- \* 12 * 1/72 * 25.4-estimateInMillimeter n XslUnitPixel = n `div`3 -- \* 1/72 * 25.4-estimateInMillimeter n XslUnitEM = n * 7 -- \* 16 * 1/72 * 25.4---------- List styles-------type ListLevel = Int--newtype ListStyle = ListStyle { levelStyles :: M.Map ListLevel ListLevelStyle- }- deriving ( Eq, Show )-----getListLevelStyle :: ListLevel -> ListStyle -> Maybe ListLevelStyle-getListLevelStyle level ListStyle{..} =- let (lower , exactHit , _) = M.splitLookup level levelStyles- in exactHit <|> fmap fst (M.maxView lower)- -- findBy (`M.lookup` levelStyles) [level, (level-1) .. 1]- -- \^ simpler, but in general less efficient--data ListLevelStyle = ListLevelStyle { listLevelType :: ListLevelType- , listItemPrefix :: Maybe Text- , listItemSuffix :: Maybe Text- , listItemFormat :: ListItemNumberFormat- , listItemStart :: Int- }- deriving ( Eq, Ord )--instance Show ListLevelStyle where- show ListLevelStyle{..} = "<LLS|"- ++ show listLevelType- ++ "|"- ++ maybeToString (T.unpack <$> listItemPrefix)- ++ show listItemFormat- ++ maybeToString (T.unpack <$> listItemSuffix)- ++ ">"- where maybeToString = fromMaybe ""--data ListLevelType = LltBullet | LltImage | LltNumbered- deriving ( Eq, Ord, Show )--data ListItemNumberFormat = LinfNone- | LinfNumber- | LinfRomanLC | LinfRomanUC- | LinfAlphaLC | LinfAlphaUC- | LinfString String- deriving ( Eq, Ord )--instance Show ListItemNumberFormat where- show LinfNone = ""- show LinfNumber = "1"- show LinfRomanLC = "i"- show LinfRomanUC = "I"- show LinfAlphaLC = "a"- show LinfAlphaUC = "A"- show (LinfString s) = s--instance Default ListItemNumberFormat where- def = LinfNone--instance Read ListItemNumberFormat where- readsPrec _ "" = [(LinfNone , "")]- readsPrec _ "1" = [(LinfNumber , "")]- readsPrec _ "i" = [(LinfRomanLC , "")]- readsPrec _ "I" = [(LinfRomanUC , "")]- readsPrec _ "a" = [(LinfAlphaLC , "")]- readsPrec _ "A" = [(LinfAlphaUC , "")]- readsPrec _ s = [(LinfString s , "")]------------------------------------------------------------------------------------- Readers------ ...it seems like a whole lot of this should be automatically derivable--- or at least moveable into a class. Most of this is data concealed in--- code.--------------------------------------------------------------------------------------readAllStyles :: StyleReader _x Styles-readAllStyles = ( readFontPitches- >>?! ( readAutomaticStyles- &&& readStyles ))- >>?%? chooseMax- -- all top elements are always on the same hierarchy level-----readStyles :: StyleReader _x Styles-readStyles = executeInSub NsOffice "styles" $ liftAsSuccess- $ liftA3 Styles- ( tryAll NsStyle "style" readStyle >>^ M.fromList )- ( tryAll NsText "list-style" readListStyle >>^ M.fromList )- ( tryAll NsStyle "default-style" readDefaultStyle >>^ M.fromList )-----readAutomaticStyles :: StyleReader _x Styles-readAutomaticStyles = executeInSub NsOffice "automatic-styles" $ liftAsSuccess- $ liftA3 Styles- ( tryAll NsStyle "style" readStyle >>^ M.fromList )- ( tryAll NsText "list-style" readListStyle >>^ M.fromList )- ( returnV M.empty )-----readDefaultStyle :: StyleReader _x (StyleFamily, StyleProperties)-readDefaultStyle = lookupAttr NsStyle "family"- >>?! keepingTheValue readStyleProperties-----readStyle :: StyleReader _x (StyleName,Style)-readStyle = findAttr NsStyle "name"- >>?! keepingTheValue- ( liftA4 Style- ( lookupAttr' NsStyle "family" )- ( findAttr' NsStyle "parent-style-name" )- ( findAttr' NsStyle "list-style-name" )- readStyleProperties- )-----readStyleProperties :: StyleReaderSafe _x StyleProperties-readStyleProperties = liftA2 SProps- ( readTextProperties >>> choiceToMaybe )- ( readParaProperties >>> choiceToMaybe )-----readTextProperties :: StyleReader _x TextProperties-readTextProperties =- executeInSub NsStyle "text-properties" $ liftAsSuccess- ( liftA6 PropT- ( searchAttr NsXSL_FO "font-style" False isFontEmphasised )- ( searchAttr NsXSL_FO "font-weight" False isFontBold )- findPitch- ( getAttr NsStyle "text-position" )- readUnderlineMode- readStrikeThroughMode- )- where isFontEmphasised = [("normal",False),("italic",True),("oblique",True)]- isFontBold = ("normal",False):("bold",True)- :map ((,True) . tshow) ([100,200..900]::[Int])--readUnderlineMode :: StyleReaderSafe _x (Maybe UnderlineMode)-readUnderlineMode = readLineMode "text-underline-mode"- "text-underline-style"--readStrikeThroughMode :: StyleReaderSafe _x (Maybe UnderlineMode)-readStrikeThroughMode = readLineMode "text-line-through-mode"- "text-line-through-style"--readLineMode :: Text -> Text -> StyleReaderSafe _x (Maybe UnderlineMode)-readLineMode modeAttr styleAttr = proc x -> do- isUL <- searchAttr NsStyle styleAttr False isLinePresent -< x- mode <- lookupAttr' NsStyle modeAttr -< x- if isUL- then case mode of- Just m -> returnA -< Just m- Nothing -> returnA -< Just UnderlineModeNormal- else returnA -< Nothing- where- isLinePresent = ("none",False) : map (,True)- [ "dash" , "dot-dash" , "dot-dot-dash" , "dotted"- , "long-dash" , "solid" , "wave"- ]-----readParaProperties :: StyleReader _x ParaProperties-readParaProperties =- executeInSub NsStyle "paragraph-properties" $ liftAsSuccess- ( liftA3 PropP- ( liftA2 readNumbering- ( isSet' NsText "number-lines" )- ( readAttr' NsText "line-number" )- )- ( liftA2 readIndentation- ( isSetWithDefault NsStyle "auto-text-indent" False )- ( getAttr NsXSL_FO "text-indent" )- )- ( getAttr NsXSL_FO "margin-left" )- )- where readNumbering (Just True) (Just n) = NumberingRestart n- readNumbering (Just True) _ = NumberingKeep- readNumbering _ _ = NumberingNone-- readIndentation False indent = indent- readIndentation True _ = def--------- List styles----------readListStyle :: StyleReader _x (StyleName, ListStyle)-readListStyle =- findAttr NsStyle "name"- >>?! keepingTheValue- ( liftA ListStyle- $ liftA3 SM.union3- ( readListLevelStyles NsText "list-level-style-number" LltNumbered )- ( readListLevelStyles NsText "list-level-style-bullet" LltBullet )- ( readListLevelStyles NsText "list-level-style-image" LltImage ) >>^ M.mapMaybe chooseMostSpecificListLevelStyle- )----readListLevelStyles :: Namespace -> ElementName- -> ListLevelType- -> StyleReaderSafe _x (SM.SetMap Int ListLevelStyle)-readListLevelStyles namespace elementName levelType =- tryAll namespace elementName (readListLevelStyle levelType)- >>^ SM.fromList-----readListLevelStyle :: ListLevelType -> StyleReader _x (Int, ListLevelStyle)-readListLevelStyle levelType = readAttr NsText "level"- >>?! keepingTheValue- ( liftA5 toListLevelStyle- ( returnV levelType )- ( findAttr' NsStyle "num-prefix" )- ( findAttr' NsStyle "num-suffix" )- ( getAttr NsStyle "num-format" )- ( findAttrText' NsText "start-value" )- )- where- toListLevelStyle _ p s LinfNone b = ListLevelStyle LltBullet p s LinfNone (startValue b)- toListLevelStyle _ p s f@(LinfString _) b = ListLevelStyle LltBullet p s f (startValue b)- toListLevelStyle t p s f b = ListLevelStyle t p s f (startValue b)- startValue mbx = fromMaybe 1 (mbx >>= safeRead)-----chooseMostSpecificListLevelStyle :: S.Set ListLevelStyle -> Maybe ListLevelStyle-chooseMostSpecificListLevelStyle ls = F.foldr select Nothing ls- where- select l Nothing = Just l- select ( ListLevelStyle t1 p1 s1 f1 b1 )- ( Just ( ListLevelStyle t2 p2 s2 f2 _ ))- = Just $ ListLevelStyle (select' t1 t2) (p1 <|> p2) (s1 <|> s2)- (selectLinf f1 f2) b1- select' LltNumbered _ = LltNumbered- select' _ LltNumbered = LltNumbered- select' _ _ = LltBullet- selectLinf LinfNone f2 = f2- selectLinf f1 LinfNone = f1- selectLinf (LinfString _) f2 = f2- selectLinf f1 (LinfString _) = f1- selectLinf f1 _ = f1-------------------------------------------------------------------------------------- Tools to access style data--------------------------------------------------------------------------------------lookupStyle :: StyleName -> Styles -> Maybe Style-lookupStyle name Styles{..} = M.lookup name stylesByName-----lookupDefaultStyle' :: Styles -> StyleFamily -> StyleProperties-lookupDefaultStyle' Styles{..} family = fromMaybe def- (M.lookup family defaultStyleMap)-----lookupListStyleByName :: StyleName -> Styles -> Maybe ListStyle-lookupListStyleByName name Styles{..} = M.lookup name listStylesByName----- | Returns a chain of parent of the current style. The direct parent will--- be the first element of the list, followed by its parent and so on.--- The current style is not in the list.-parents :: Style -> Styles -> [Style]-parents style styles = unfoldr findNextParent style -- Ha!- where findNextParent Style{..}- = fmap duplicate $ (`lookupStyle` styles) =<< styleParentName---- | Looks up the style family of the current style. Normally, every style--- should have one. But if not, all parents are searched.-getStyleFamily :: Style -> Styles -> Maybe StyleFamily-getStyleFamily style@Style{..} styles- = styleFamily- <|> F.asum (map (`getStyleFamily` styles) $ parents style styles)---- | Each 'Style' has certain 'StyleProperties'. But sometimes not all property--- values are specified. Instead, a value might be inherited from a--- parent style. This function makes this chain of inheritance--- concrete and easily accessible by encapsulating the necessary lookups.--- The resulting list contains the direct properties of the style as the first--- element, the ones of the direct parent element as the next one, and so on.------ Note: There should also be default properties for each style family. These--- are @not@ contained in this list because properties inherited from--- parent elements take precedence over default styles.------ This function is primarily meant to be used through convenience wrappers.----stylePropertyChain :: Style -> Styles -> [StyleProperties]-stylePropertyChain style styles- = map styleProperties (style : parents style styles)-----extendedStylePropertyChain :: [Style] -> Styles -> [StyleProperties]-extendedStylePropertyChain [] _ = []-extendedStylePropertyChain [style] styles = stylePropertyChain style styles- ++ maybeToList (fmap (lookupDefaultStyle' styles) (getStyleFamily style styles))-extendedStylePropertyChain (style:trace) styles = stylePropertyChain style styles- ++ extendedStylePropertyChain trace styles
@@ -1,10 +1,9 @@-{-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.Org- Copyright : Copyright (C) 2014-2022 Albert Krewinkel+ Copyright : Copyright (C) 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Conversion of org-mode formatted plain text to 'Pandoc' document. -}
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.Org.BlockStarts- Copyright : Copyright (C) 2014-2022 Albert Krewinkel+ Copyright : Copyright (C) 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Parsers for Org-mode inline elements. -}@@ -23,12 +23,14 @@ , endOfBlock ) where -import Control.Monad (void)+import Control.Monad (void, guard) import Data.Text (Text) import Text.Pandoc.Readers.Org.Parsing import Text.Pandoc.Definition as Pandoc import Text.Pandoc.Shared (safeRead) import Text.Pandoc.Parsing (lowerAlpha, upperAlpha)+import Text.Pandoc.Extensions+import Text.Pandoc.Readers.LaTeX.Math (inlineEnvironmentNames) import Data.Functor (($>)) -- | Horizontal Line (five -- dashes or more)@@ -54,10 +56,13 @@ latexEnvStart :: Monad m => OrgParser m Text-latexEnvStart = try $- skipSpaces *> string "\\begin{"- *> latexEnvName- <* string "}"+latexEnvStart = try $ do+ skipSpaces+ string "\\begin{"+ name <- latexEnvName+ char '}'+ guard $ name `notElem` inlineEnvironmentNames+ pure name where latexEnvName :: Monad m => OrgParser m Text latexEnvName = try $ mappend <$> many1Char alphaNum <*> option "" (textStr "*")@@ -69,8 +74,7 @@ <* char ']' <* (skipSpaces <|> lookAhead eol) where parseNum = (safeRead =<< many1Char digit)- <|> snd <$> lowerAlpha- <|> snd <$> upperAlpha+ <|> snd <$> (lowerAlpha <|> upperAlpha) bulletListStart :: Monad m => OrgParser m Int bulletListStart = try $ do@@ -87,20 +91,27 @@ orderedListStart :: Monad m => OrgParser m (Int, ListAttributes) orderedListStart = try $ do ind <- length <$> many spaceChar+ fancy <- option False $ True <$ guardEnabled Ext_fancy_lists+ -- Ordered list markers allowed in org-mode+ let styles = (many1Char digit $> (if fancy+ then Decimal+ else DefaultStyle))+ : if fancy+ then [ fst <$> lowerAlpha+ , fst <$> upperAlpha ]+ else []+ let delims = [ char '.' $> (if fancy+ then Period+ else DefaultDelim)+ , char ')' $> (if fancy+ then OneParen+ else DefaultDelim)+ ] style <- choice styles delim <- choice delims skipSpaces1 <|> lookAhead eol start <- option 1 listCounterCookie return (ind + 1, (start, style, delim))- -- Ordered list markers allowed in org-mode- where- styles = [ many1Char digit $> Decimal- , fst <$> lowerAlpha- , fst <$> upperAlpha- ]- delims = [ char '.' $> Period- , char ')' $> OneParen- ] drawerStart :: Monad m => OrgParser m Text drawerStart = try $ skipSpaces *> drawerName <* skipSpaces <* newline@@ -115,7 +126,7 @@ skipSpaces <* string "#" <* lookAhead (oneOf " \n") exampleLineStart :: Monad m => OrgParser m ()-exampleLineStart = () <$ try (skipSpaces *> string ": ")+exampleLineStart = () <$ try (skipSpaces *> char ':' *> (void (char ' ') <|> lookAhead eol)) noteMarker :: Monad m => OrgParser m Text noteMarker = try $ do
@@ -1,13 +1,14 @@+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {- | Module : Text.Pandoc.Readers.Org.Blocks- Copyright : Copyright (C) 2014-2022 Albert Krewinkel+ Copyright : Copyright (C) 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Parsers for Org-mode block elements. -}@@ -25,22 +26,24 @@ import Text.Pandoc.Readers.Org.Parsing import Text.Pandoc.Readers.Org.Shared (cleanLinkText, isImageFilename, originalLang, translateLang, exportsCode)--import Text.Pandoc.Builder (Blocks, Inlines)+import Text.Pandoc.Readers.LaTeX.Math (inlineEnvironmentNames)+import Text.Pandoc.Builder (Blocks, Inlines, Many(..)) import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Shared (compactify, compactifyDL, safeRead) -import Control.Monad (foldM, guard, mplus, mzero, void)+import Control.Monad (foldM, guard, mzero, void)+import Data.Bifunctor (bimap) import Data.Char (isSpace) import Data.Default (Default) import Data.Functor (($>))-import Data.List (foldl')+import qualified Data.List as L import Data.Maybe (fromMaybe, isJust, isNothing) import Data.Text (Text) import Data.List.NonEmpty (nonEmpty) import System.FilePath+import qualified Data.Foldable as F import qualified Data.Text as T import qualified Text.Pandoc.Builder as B import qualified Text.Pandoc.Walk as Walk@@ -70,6 +73,7 @@ block :: PandocMonad m => OrgParser m (F Blocks) block = choice [ mempty <$ blanklines , table+ , dynamicBlock , orgBlock , figure , example@@ -97,7 +101,6 @@ -- | Attributes that may be added to figures (like a name or caption). data BlockAttributes = BlockAttributes { blockAttrName :: Maybe Text- , blockAttrLabel :: Maybe Text , blockAttrCaption :: Maybe (F Inlines) , blockAttrKeyValues :: [(Text, Text)] }@@ -113,7 +116,7 @@ stringyMetaAttribute :: Monad m => OrgParser m (Text, Text) stringyMetaAttribute = try $ do- metaLineStart+ metaLineStart *> notFollowedBy (stringAnyCase "begin" *> oneOf ":_") attrName <- T.toLower <$> many1TillChar nonspaceChar (char ':') skipSpaces attrValue <- anyLine <|> ("" <$ newline)@@ -127,15 +130,13 @@ blockAttributes = try $ do kv <- many stringyMetaAttribute guard $ all (isBlockAttr . fst) kv- let caption = foldl' (appendValues "caption") Nothing kv- let kvAttrs = foldl' (appendValues "attr_html") Nothing kv- let name = lookup "name" kv- let label = lookup "label" kv+ let caption = L.foldl' (appendValues "caption") Nothing kv+ let kvAttrs = L.foldl' (appendValues "attr_html") Nothing kv+ let name = snd <$> L.find ((`elem` ["name", "label"]) . fst) (reverse kv) caption' <- traverse (parseFromString inlines . (<> "\n")) caption kvAttrs' <- parseFromString keyValues . (<> "\n") $ fromMaybe mempty kvAttrs return BlockAttributes { blockAttrName = name- , blockAttrLabel = label , blockAttrCaption = caption' , blockAttrKeyValues = kvAttrs' }@@ -182,25 +183,46 @@ blkType <- blockHeaderStart ($ blkType) $ 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))- "example" -> exampleBlock blockAttrs- "quote" -> parseBlockLines (fmap B.blockQuote)- "verse" -> verseBlock- "src" -> codeBlock blockAttrs- "abstract"-> metadataBlock- _ -> parseBlockLines $- let (ident, classes, kv) = attrFromBlockAttributes blockAttrs- in fmap $ B.divWith (ident, classes ++ [blkType], kv)+ "export" -> exportBlock+ "comment" -> rawBlockLines (const mempty)+ "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" -> \x -> ignHeaders *> parseBlockLines (fmap B.blockQuote) x+ "verse" -> verseBlock+ "src" -> codeBlock blockAttrs+ "note" -> admonitionBlock "note" blockAttrs+ "warning" -> admonitionBlock "warning" blockAttrs+ "tip" -> admonitionBlock "tip" blockAttrs+ "caution" -> admonitionBlock "caution" blockAttrs+ "important" -> admonitionBlock "important" blockAttrs+ _ ->+ -- case-sensitive checks+ case blkType of+ "abstract" -> metadataBlock+ _ -> \bt -> do+ params <- blockParameters+ let (ident, classes, kv) = attrFromBlockAttributes blockAttrs+ toDiv = (B.divWith (ident, classes ++ [blkType], kv <> params))+ parseBlockLines (fmap toDiv) bt where blockHeaderStart :: Monad m => OrgParser m Text- blockHeaderStart = try $ skipSpaces *> stringAnyCase "#+begin_" *> orgArgWord+ blockHeaderStart = try $ do+ skipSpaces+ metaLineStart+ stringAnyCase "begin_"+ many1Char (satisfy (not . isSpace)) - lowercase :: Text -> Text- lowercase = T.toLower+admonitionBlock :: PandocMonad m+ => Text -> BlockAttributes -> Text -> OrgParser m (F Blocks)+admonitionBlock blockType blockAttrs rawtext = do+ bls <- ignHeaders *> parseBlockLines id rawtext+ let id' = fromMaybe mempty $ blockAttrName blockAttrs+ pure $ fmap+ (B.divWith (id', [blockType], []) .+ (B.divWith ("", ["title"], []) (B.para (B.str (T.toTitle blockType))) <>))+ bls exampleBlock :: PandocMonad m => BlockAttributes -> Text -> OrgParser m (F Blocks) exampleBlock blockAttrs _label = do@@ -209,14 +231,14 @@ newline content <- rawBlockContent "example" let id' = fromMaybe mempty $ blockAttrName blockAttrs- let codeBlck = B.codeBlockWith (id', "example":classes, kv) content+ let codeBlck = B.codeBlockWith (id', classes, kv) content return . return $ codeBlck rawBlockLines :: Monad m => (Text -> F Blocks) -> Text -> OrgParser m (F Blocks) rawBlockLines f blockType = ignHeaders *> (f <$> rawBlockContent blockType) parseBlockLines :: PandocMonad m => (F Blocks -> F Blocks) -> Text -> OrgParser m (F Blocks)-parseBlockLines f blockType = ignHeaders *> (f <$> parsedBlockContent)+parseBlockLines f blockType = (f <$> parsedBlockContent) where parsedBlockContent :: PandocMonad m => OrgParser m (F Blocks) parsedBlockContent = try $ do@@ -225,41 +247,37 @@ -- | Read the raw string content of a block rawBlockContent :: Monad m => Text -> OrgParser m Text-rawBlockContent blockType = try $ do- blkLines <- manyTill rawLine blockEnder- tabLen <- getOption readerTabStop+rawBlockContent blockType = rawBlockContent' $+ stringAnyCase ("#+end_" <> blockType)++-- | Read the raw string content of a block+rawBlockContent' :: Monad m => OrgParser m Text -> OrgParser m Text+rawBlockContent' blockEnder = try $ do+ blkLines <- manyTill rawLine (try $ skipSpaces <* blockEnder)+ tabStop <- getOption readerTabStop trimP <- orgStateTrimLeadBlkIndent <$> getState- let stripIndent strs = if trimP then map (T.drop (shortestIndent strs)) strs else strs- (T.unlines- . stripIndent- . map (tabsToSpaces tabLen . commaEscaped)- $ blkLines)+ -- split lines into indentation/contents tuples+ let splitLines = map (T.span (\c -> c == ' ' || c == '\t')) blkLines+ let countSpaces = T.foldr (\case {'\t' -> (tabStop +); _ -> (1 +)}) 0+ let shortestIndent = foldr (min . countSpaces . fst) maxBound+ . filter (not . T.null . snd) -- ignore empty lines+ $ splitLines+ let tabsToSpaces = T.replace "\t" (T.replicate tabStop " ")+ let reIndent = if trimP+ then (T.drop shortestIndent . tabsToSpaces)+ else id++ T.unlines (map (uncurry T.append . bimap reIndent commaEscaped) splitLines) <$ updateState (\s -> s { orgStateTrimLeadBlkIndent = True }) where rawLine :: Monad m => OrgParser m Text rawLine = try $ ("" <$ blankline) <|> anyLine - blockEnder :: Monad m => OrgParser m ()- blockEnder = try $ skipSpaces <* stringAnyCase ("#+end_" <> blockType)-- shortestIndent :: [Text] -> Int- shortestIndent = foldr (min . T.length . T.takeWhile isSpace) maxBound- . filter (not . T.null)-- tabsToSpaces :: Int -> Text -> Text- tabsToSpaces tabStop t =- let (ind, suff) = T.span (\c -> c == ' ' || c == '\t') t- tabNum = T.length $ T.filter (== '\n') ind- spaceNum = T.length ind - tabNum- in T.replicate (spaceNum + tabStop * tabNum) " " <> suff-- commaEscaped t =- let (ind, suff) = T.span (\c -> c == ' ' || c == '\t') t- in case T.uncons suff of- Just (',', cs)- | "*" <- T.take 1 cs -> ind <> cs- | "#+" <- T.take 2 cs -> ind <> cs- _ -> t+ commaEscaped suff = case T.uncons suff of+ Just (',', cs)+ | "*" <- T.take 1 cs -> cs+ | "#+" <- T.take 2 cs -> cs+ _ -> suff -- | Read but ignore all remaining block headers. ignHeaders :: Monad m => OrgParser m ()@@ -295,6 +313,7 @@ -- metadata under a key of the same name. metadataBlock :: PandocMonad m => Text -> OrgParser m (F Blocks) metadataBlock blockType = try $ do+ ignHeaders content <- parseBlockLines id blockType meta' <- orgStateMeta <$> getState updateState $ \st ->@@ -415,10 +434,11 @@ return (argKey, paramValue) orgParamValue :: Monad m => OrgParser m Text-orgParamValue = try $ fmap T.pack $+orgParamValue = try $ skipSpaces *> notFollowedBy orgArgKey- *> noneOf "\n\r" `many1Till` endOfValue+ *> ((char '"' *> manyChar (noneOf "\n\r\"") <* char '"') <|>+ noneOf "\n\r" `many1TillChar` endOfValue) <* skipSpaces where endOfValue = lookAhead $ try (skipSpaces <* oneOf "\n\r")@@ -426,6 +446,34 @@ --+-- Dynamic block (#+begin: ... #+end:)+--++-- | Parses a Dynamic Block, i.e., a block delimited by #+BEGIN: and+-- #+END:.+dynamicBlock :: PandocMonad m => OrgParser m (F Blocks)+dynamicBlock = try $ do+ metaLineStart *> stringAnyCase "begin:" *> spaces+ blockname <- optionMaybe orgArgWord+ blockArgs <- blockParameters+ contents <- do+ raw <- rawBlockContent' $ metaLineStart *> stringAnyCase "end:"+ parseFromString blocks (raw <> "\n")+ let attr = ("", maybe [] (:[]) blockname, blockArgs)+ return $ B.divWith attr <$> contents++-- | Parse block arguments; in order, this tries to parse a Lisp-style+-- argument list, a set of key-value pairs using /equals/, and as a+-- fallback the whole line as a single /parameters/ argument.+blockParameters :: PandocMonad m => OrgParser m [(Text, Text)]+blockParameters = choice+ [ try $ manyTill ((,) <$> orgArgKey <*> orgParamValue) newline+ , try $ manyTill ((,) <$> (spaces *> orgArgWord <* char '=') <*> orgArgWord)+ newline+ , (\x -> [ ("parameters", x) | not (T.null x)]) <$> (skipSpaces *> anyLine)+ ]++-- -- Drawers -- @@ -484,20 +532,14 @@ imageBlock isFigure figAttrs imgSrc = let figName = fromMaybe mempty $ blockAttrName figAttrs- figLabel = fromMaybe mempty $ blockAttrLabel figAttrs figCaption = fromMaybe mempty $ blockAttrCaption figAttrs figKeyVals = blockAttrKeyValues figAttrs- attr = (figLabel, mempty, figKeyVals)+ attr = (figName, mempty, figKeyVals) in if isFigure- then (\c ->- B.simpleFigureWith- attr c imgSrc (unstackFig figName)) <$> figCaption+ then (\c -> B.figureWith attr (B.simpleCaption (B.plain c))+ (B.plain $ B.image imgSrc "" mempty))+ <$> figCaption else B.para . B.imageWith attr imgSrc figName <$> figCaption- unstackFig :: Text -> Text- unstackFig figName =- if "fig:" `T.isPrefixOf` figName- then T.drop 4 figName- else figName -- | Succeeds if looking at the end of the current paragraph endOfParagraph :: Monad m => OrgParser m ()@@ -516,7 +558,7 @@ exampleLine = try $ exampleLineStart *> anyLine exampleCode :: Text -> Blocks-exampleCode = B.codeBlockWith ("", ["example"], [])+exampleCode = B.codeBlockWith ("", [], []) --@@ -637,38 +679,46 @@ } table :: PandocMonad m => OrgParser m (F Blocks)-table = do- withTables <- getExportSetting exportWithTables- tbl <- gridTableWith blocks <|> orgTable- return $ if withTables then tbl else mempty---- | A normal org table-orgTable :: PandocMonad m => OrgParser m (F Blocks)-orgTable = try $ do+table = try $ do -- don't allow a table on the first line of a list item; org requires that -- tables start at first non-space character on the line let isFirstInListItem st = orgStateParserContext st == ListItemState && isNothing (orgStateLastPreCharPos st) guard . not . isFirstInListItem =<< getState blockAttrs <- blockAttributes+ let identMb = blockAttrName blockAttrs+ tbl <- gridTableWith blocks <|> orgTable+ withTables <- getExportSetting exportWithTables+ return $ if withTables+ then do+ xs <- unMany <$> tbl+ case F.toList xs of+ [Table _ _ cs th tb tf] -> do+ capt <- case blockAttrCaption blockAttrs of+ Nothing -> pure $ Caption Nothing []+ Just ils -> do+ ils' <- ils+ pure $ B.simpleCaption . B.plain $ ils'+ let attr = (fromMaybe mempty identMb, [],+ blockAttrKeyValues blockAttrs)+ pure $ B.tableWith attr capt cs th tb tf+ _ -> tbl -- should not happen+ else mempty++-- | A normal org table+orgTable :: PandocMonad m => OrgParser m (F Blocks)+orgTable = do lookAhead tableStart rows <- tableRows-- let caption = fromMaybe mempty (blockAttrCaption blockAttrs) let orgTbl = normalizeTable <$> rowsToTable rows- let identMb = blockAttrName blockAttrs `mplus` blockAttrLabel blockAttrs- let attr = (fromMaybe mempty identMb, [], blockAttrKeyValues blockAttrs)- return $ orgToPandocTable attr <$> orgTbl <*> caption+ return $ orgToPandocTable <$> orgTbl -orgToPandocTable :: Attr- -> OrgTable- -> Inlines- -> Blocks-orgToPandocTable attr (OrgTable colProps heads lns) caption =+orgToPandocTable :: OrgTable -> Blocks+orgToPandocTable (OrgTable colProps heads lns) = let totalWidth = if any (isJust . columnRelWidth) colProps then Just . sum $ map (fromMaybe 1 . columnRelWidth) colProps else Nothing- in B.tableWith attr (B.simpleCaption $ B.plain caption)+ in B.tableWith nullAttr (Caption Nothing mempty) (map (convertColProp totalWidth) colProps) (TableHead nullAttr $ toHeaderRow heads) [TableBody nullAttr 0 [] $ map toRow lns]@@ -690,7 +740,7 @@ tableContentRow :: PandocMonad m => OrgParser m OrgTableRow tableContentRow = try $- OrgContentRow . sequence <$> (tableStart *> many1Till tableContentCell newline)+ OrgContentRow . sequence <$> (tableStart *> manyTill tableContentCell newline) tableContentCell :: PandocMonad m => OrgParser m (F Blocks) tableContentCell = try $@@ -783,6 +833,7 @@ latexFragment :: PandocMonad m => OrgParser m (F Blocks) latexFragment = try $ do envName <- latexEnvStart+ guard $ envName `notElem` inlineEnvironmentNames texOpt <- getExportSetting exportWithLatex let envStart = "\\begin{" <> envName <> "}" let envEnd = "\\end{" <> envName <> "}"@@ -859,11 +910,8 @@ orderedList :: PandocMonad m => OrgParser m (F Blocks) orderedList = try $ do (indent, attr) <- lookAhead orderedListStart- attr' <- option (fst3 attr, DefaultStyle, DefaultDelim) $- guardEnabled Ext_fancy_lists $> attr- fmap (B.orderedListWith attr' . compactify) . sequence+ fmap (B.orderedListWith attr . compactify) . sequence <$> many1 (listItem ((fst <$> orderedListStart) `indented` indent))- where fst3 (x,_,_) = x definitionListItem :: PandocMonad m => OrgParser m Int
@@ -3,10 +3,10 @@ {-# LANGUAGE TupleSections #-} {- | Module : Text.Pandoc.Readers.Org.DocumentTree- Copyright : Copyright (C) 2014-2022 Albert Krewinkel+ Copyright : Copyright (C) 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Parsers for org-mode headlines and document subtrees -}@@ -16,7 +16,7 @@ ) where import Control.Arrow ((***), first)-import Control.Monad (guard)+import Control.Monad (guard, mplus) import Data.List (intersperse) import Data.Maybe (mapMaybe) import Data.Text (Text)@@ -317,10 +317,12 @@ let toTextPair = fromKey *** fromValue customIdKey = toPropertyKey "custom_id"+ idKey = toPropertyKey "id" classKey = toPropertyKey "class" unnumberedKey = toPropertyKey "unnumbered"- specialProperties = [customIdKey, classKey, unnumberedKey]- id' = maybe mempty fromValue . lookup customIdKey $ properties+ specialProperties = [customIdKey, idKey, classKey, unnumberedKey]+ id' = maybe mempty fromValue $+ (lookup customIdKey properties `mplus` lookup idKey properties) cls = maybe mempty fromValue . lookup classKey $ properties kvs' = map toTextPair . filter ((`notElem` specialProperties) . fst) $ properties
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.Org.ExportSettings- Copyright : © 2016-2022 Albert Krewinkel+ Copyright : © 2016-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Parsers for Org-mode export options. -}
@@ -2,10 +2,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.Org.Inlines- Copyright : Copyright (C) 2014-2022 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 <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Parsers for Org-mode inline elements. -}@@ -42,10 +42,6 @@ -- -- Functions acting on the parser state ---recordAnchorId :: PandocMonad m => Text -> OrgParser m ()-recordAnchorId i = updateState $ \s ->- s{ orgStateAnchorIds = i : orgStateAnchorIds s }- pushToInlineCharStack :: PandocMonad m => Char -> OrgParser m () pushToInlineCharStack c = updateState $ \s -> s{ orgStateEmphasisCharStack = c:orgStateEmphasisCharStack s }@@ -92,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"@@ -126,8 +123,12 @@ linebreak = try $ pure B.linebreak <$ string "\\\\" <* skipSpaces <* newline str :: PandocMonad m => OrgParser m (F Inlines)-str = return . B.str <$> many1Char (noneOf $ specialChars ++ "\n\r ")+str = return . B.str <$>+ ( many1Char (noneOf $ specialChars ++ "\n\r ") >>= updatePositions' ) <* updateLastStrPos+ where+ updatePositions' str' = str' <$+ maybe mzero (updatePositions . snd) (T.unsnoc str') -- | An endline character that can be treated as a space, not a structural -- break. This should reflect the values of the Emacs variable@@ -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 =@@ -380,8 +383,9 @@ endOfCitation = try $ do many $ satisfy isCiteKeySpecialChar satisfy $ not . isCiteKeyChar- in try $ satisfy isCiteKeyChar `many1TillChar` lookAhead endOfCitation-+ in try $ do+ optional (char '&') -- this is used in org-ref v3+ satisfy isCiteKeyChar `many1TillChar` lookAhead endOfCitation -- | Supported citation types. Only a small subset of org-ref types is -- supported for now. TODO: rewrite this, use LaTeX reader as template.@@ -508,15 +512,9 @@ -- @anchor-id@ contains spaces, we are more restrictive in what is accepted as -- an anchor. anchor :: PandocMonad m => OrgParser m (F Inlines)-anchor = try $ do- anchorId <- parseAnchor- recordAnchorId anchorId+anchor = do+ anchorId <- orgAnchor returnF $ B.spanWith (solidify anchorId, [], []) mempty- where- parseAnchor = string "<<"- *> many1Char (noneOf "\t\n\r<>\"' ")- <* string ">>"- <* skipSpaces -- | Replace every char but [a-zA-Z0-9_.-:] with a hyphen '-'. This mirrors -- the org function @org-export-solidify-link-text@.@@ -596,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 '$'@@ -640,11 +652,11 @@ verbatimBetween :: PandocMonad m => Char -> OrgParser m Text-verbatimBetween c = try $- emphasisStart c *>- many1TillNOrLessNewlines 1 verbatimChar (emphasisEnd c)+verbatimBetween c = newlinesToSpaces <$>+ try (emphasisStart c *> many1TillNOrLessNewlines 1 verbatimChar (emphasisEnd c)) where verbatimChar = noneOf "\n\r" >>= updatePositions+ newlinesToSpaces = T.map (\d -> if d == '\n' then ' ' else d) -- | Parses a raw string delimited by @c@ using Org's math rules mathTextBetween :: PandocMonad m@@ -679,7 +691,6 @@ emphasisStart :: PandocMonad m => Char -> OrgParser m Char emphasisStart c = try $ do guard =<< afterEmphasisPreChar- guard =<< notAfterString char c lookAhead (noneOf emphasisForbiddenBorderChars) pushToInlineCharStack c@@ -754,7 +765,7 @@ -- | Chars not allowed at the (inner) border of emphasis emphasisForbiddenBorderChars :: [Char]-emphasisForbiddenBorderChars = "\t\n\r "+emphasisForbiddenBorderChars = "\t\n\r \x200B" -- | The maximum number of newlines within emphasisAllowedNewlines :: Int@@ -792,8 +803,8 @@ subOrSuperExpr :: PandocMonad m => OrgParser m (F Inlines) subOrSuperExpr = try $ simpleSubOrSuperText <|>- (choice [ charsInBalanced '{' '}' (noneOf "\n\r")- , enclosing ('(', ')') <$> charsInBalanced '(' ')' (noneOf "\n\r")+ (choice [ charsInBalanced '{' '}' (T.singleton <$> noneOf "\n\r")+ , enclosing ('(', ')') <$> charsInBalanced '(' ')' (T.singleton <$> noneOf "\n\r") ] >>= parseFromString (mconcat <$> many inline)) where enclosing (left, right) s = T.cons left $ T.snoc s right @@ -814,16 +825,20 @@ allowEntities <- getExportSetting exportWithEntities ils <- parseAsInlineLaTeX cmd texOpt maybe mzero returnF $- parseAsMathMLSym allowEntities cmd `mplus`- parseAsMath cmd texOpt `mplus`- ils+ if "\\begin{" `T.isPrefixOf` cmd+ then ils+ else parseAsMathMLSym allowEntities cmd `mplus`+ parseAsMath cmd texOpt `mplus`+ ils where parseAsInlineLaTeX :: PandocMonad m => Text -> TeXExport -> OrgParser m (Maybe Inlines) parseAsInlineLaTeX cs = \case- TeXExport -> maybeRight <$> runParserT inlineCommand state "" (toSources cs)+ TeXExport -> maybeRight <$> runParserT+ (B.rawInline "latex" . snd <$> withRaw inlineCommand)+ state "" (toSources cs) TeXIgnore -> return (Just mempty)- TeXVerbatim -> return (Just $ B.str cs)+ TeXVerbatim -> return (Just $ B.text cs) parseAsMathMLSym :: Bool -> Text -> Maybe Inlines parseAsMathMLSym allowEntities cs = do@@ -888,32 +903,31 @@ updateState $ \s -> s { orgStateMacroDepth = recursionDepth } return res where- argument = manyChar $ notFollowedBy eoa *> noneOf ","+ argument = manyChar $ notFollowedBy eoa *> (escapedComma <|> noneOf ",")+ 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 $@@ -925,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)
@@ -3,10 +3,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.Org.Meta- Copyright : Copyright (C) 2014-2022 Albert Krewinkel+ Copyright : Copyright (C) 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Parsers for Org-mode meta declarations. -}@@ -27,7 +27,7 @@ import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Definition import Text.Pandoc.Shared (blocksToInlines, safeRead)-import Text.Pandoc.Network.HTTP (urlEncode)+import Text.Pandoc.URI (urlEncode) import Control.Monad (mzero, void) import Data.List (intercalate, intersperse)@@ -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,10 +3,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.Org.ParserState- Copyright : Copyright (C) 2014-2022 Albert Krewinkel+ Copyright : Copyright (C) 2014-2025 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Define the Org-mode parser state. -}@@ -49,14 +49,14 @@ 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 (..), HasQuoteContext (..), HasReaderOptions (..), ParserContext (..), QuoteContext (..), SourcePos, askF, asksF, returnF, runF, trimInlinesF)-import Text.Pandoc.Readers.LaTeX.Types (Macro)+import Text.Pandoc.TeX (Macro) -- | This is used to delay evaluation until all relevant information has been -- parsed and made available in the parser state.@@ -164,8 +164,8 @@ defaultOrgParserState :: OrgParserState defaultOrgParserState = OrgParserState { orgStateAnchorIds = []- , orgStateEmphasisPreChars = "-\t ('\"{"- , orgStateEmphasisPostChars = "-\t\n .,:!?;'\")}["+ , orgStateEmphasisPreChars = "-\t ('\"{\x200B"+ , orgStateEmphasisPostChars = "-\t\n .,:!?;'\")}[\x200B" , orgStateEmphasisCharStack = [] , orgStateEmphasisNewlines = Nothing , orgStateExportSettings = def@@ -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,9 +1,9 @@ {- | Module : Text.Pandoc.Readers.Org.Parsing- Copyright : Copyright (C) 2014-2022 Albert Krewinkel+ Copyright : Copyright (C) 2014-2025 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Org-mode parsing utilities. @@ -29,6 +29,7 @@ , orgArgWordChar , orgTagWord , orgTagWordChar+ , orgAnchor -- * Re-exports from Text.Pandoc.Parser , ParserContext (..) , textStr@@ -39,6 +40,7 @@ , many1Till , many1TillChar , notFollowedBy'+ , sepBy1' , spaceChar , nonspaceChar , skipSpaces@@ -52,6 +54,7 @@ , guardEnabled , updateLastStrPos , notAfterString+ , getLastStrPos , ParserState (..) , registerHeader , QuoteContext (..)@@ -114,7 +117,7 @@ import Control.Monad.Reader (ReaderT) -- | The parser used to read org files.-type OrgParser m = ParserT Sources OrgParserState (ReaderT OrgParserLocal m)+type OrgParser m = ParsecT Sources OrgParserState (ReaderT OrgParserLocal m) -- -- Adaptions and specializations of parsing utilities@@ -163,7 +166,7 @@ -- | Parse in different context withContext :: Monad m => ParserContext -- ^ New parser context- -> OrgParser m a -- ^ Parser to run in that context+ -> OrgParser m a -- ^ Parsec to run in that context -> OrgParser m a withContext context parser = do oldContext <- orgStateParserContext <$> getState@@ -173,7 +176,7 @@ return result ----- Parser state functions+-- Parsec state functions -- -- | Get an export setting.@@ -216,3 +219,16 @@ orgTagWordChar :: Monad m => OrgParser m Char orgTagWordChar = alphaNum <|> oneOf "@%#_"++orgAnchor :: Monad m => OrgParser m Text+orgAnchor = try $ do+ string "<<"+ anchorId <- many1Char (noneOf "\t\n\r<>\"' ")+ string ">>"+ skipSpaces+ recordAnchorId anchorId+ return anchorId++recordAnchorId :: Monad m => Text -> OrgParser m ()+recordAnchorId i = updateState $ \s ->+ s{ orgStateAnchorIds = i : orgStateAnchorIds s }
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.Org.Shared- Copyright : Copyright (C) 2014-2022 Albert Krewinkel+ Copyright : Copyright (C) 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Utility functions used in other Pandoc Org modules. -}@@ -23,7 +23,6 @@ import System.FilePath (isValid, takeExtension) import qualified System.FilePath.Posix as Posix import qualified System.FilePath.Windows as Windows-import Text.Pandoc.Shared (elemText) -- | Check whether the given string looks like the path to of URL of an image. isImageFilename :: Text -> Bool@@ -33,7 +32,7 @@ `elem` imageExtensions isKnownProtocolUri = any (\x -> (x <> "://") `T.isPrefixOf` fp) protocols - imageExtensions = [ ".jpeg", ".jpg", ".png", ".gif", ".svg", ".webp", ".jxl" ]+ imageExtensions = [ ".jpeg", ".jpg", ".png", ".gif", ".svg", ".webp", ".jxl", ".avif" ] protocols = [ "file", "http", "https" ] -- | Cleanup and canonicalize a string describing a link. Return @Nothing@ if@@ -58,7 +57,7 @@ isUrl :: Text -> Bool isUrl cs = let (scheme, path) = T.break (== ':') cs- in T.all (\c -> isAlphaNum c || c `elemText` ".-") scheme+ in T.all (\c -> isAlphaNum c || T.any (== c) ".-") scheme && not (T.null path) -- | Creates an key-value pair marking the original language name specified for
@@ -0,0 +1,446 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeApplications #-}+{- |+ Module : Text.Pandoc.Readers.Pod+ Copyright : © 2024 Evan Silberman+ License : GNU GPL, version 2 or above++ Maintainer : Evan Silberman <evan@jklol.net>+ Stability : WIP+ Portability : portable++Conversion of Pod to 'Pandoc' documents+-}+module Text.Pandoc.Readers.Pod (readPod) where++import Control.Monad (void)+import Control.Monad.Except (throwError)+import Data.Char (isAsciiUpper, digitToInt)+import Data.Default (Default)+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Parsing+import Text.Pandoc.Parsing.General (isSpaceChar)+import Text.Pandoc.XML (lookupEntity)+import Text.Pandoc.Class.PandocMonad (PandocMonad(..))+import Text.Pandoc.Definition (Pandoc)+import Text.Pandoc.Error+import Text.Pandoc.Builder (Blocks, Inlines)+import qualified Text.Pandoc.Builder as B+import qualified Data.Text as T+import qualified Data.Text.Read as TR+import Text.Pandoc.Shared (stringify, textToIdentifier, tshow)+import Data.Set (Set)+import Data.Functor (($>))+import Data.Maybe (listToMaybe, fromMaybe)+import Numeric (readOct)++data PodState = PodState+ { logMessages :: [LogMessage]+ , headerIds :: Set T.Text+ , options :: ReaderOptions+} deriving (Show)++instance HasLogMessages PodState where+ addLogMessage msg st = st{ logMessages = msg : logMessages st }+ getLogMessages st = reverse $ logMessages st++instance HasIdentifierList PodState where+ extractIdentifierList = headerIds+ updateIdentifierList f st = st{headerIds = f (headerIds st)}++instance HasReaderOptions PodState where+ extractReaderOptions = options++instance Default PodState where+ def = PodState+ { logMessages = []+ , headerIds = mempty+ , options = def+ }++data PodLinkDestination = LinkUrl Inlines T.Text+ | LinkMan Inlines (Maybe Inlines)+ | LinkInternal Inlines+ deriving (Show)++defaultLinkName :: PodLinkDestination -> Inlines+defaultLinkName (LinkUrl inl _) = inl+defaultLinkName (LinkMan nm (Just sec)) = B.doubleQuoted sec <> " in " <> nm+defaultLinkName (LinkMan nm Nothing) = nm+defaultLinkName (LinkInternal sec) = B.doubleQuoted sec++type PodParser m = ParsecT Sources PodState m++readPod :: (PandocMonad m, ToSources a)+ => ReaderOptions+ -> a+ -> m Pandoc+readPod _ s = do+ let sources = toSources s+ p <- readWithM parsePod def sources+ case p of+ Right result -> return result+ Left e -> throwError e++parsePod :: PandocMonad m => PodParser m Pandoc+parsePod = do+ -- We don't actually start processing Pod until we encounter a Pod command.+ -- If we never encounter a Pod command, the document is still valid Pod, it+ -- just contains no content.+ notPod+ bs <- manyTill block eof+ reportLogMessages+ return $ B.doc $ mconcat bs++block :: PandocMonad m => PodParser m Blocks+block = verbatim <|> paragraph <|> command <?> "Pod paragraph"++command :: PandocMonad m => PodParser m Blocks+command = do+ try (char '=' >> notFollowedBy (string "item" <|> string "back" <|> string "end"))+ header <|> pod <|> cut <|> over <|> for <|> begin <|> encoding <?> "Pod command"++cmd :: PandocMonad m => T.Text -> PodParser m ()+cmd nm = do+ textStr nm+ notFollowedBy nonspaceChar+ void $ many spaceChar++encoding :: PandocMonad m => PodParser m Blocks+encoding = do+ cmd "encoding"+ anyLine+ optional blanklines+ logMessage $ IgnoredElement "=encoding; Pandoc requires UTF-8 input"+ return mempty++header :: PandocMonad m => PodParser m Blocks+header = do+ string "head"+ dig <- oneOf "123456"+ void blankline <|> skipMany1 spaceChar+ ins <- inlines+ attrs <- registerHeader B.nullAttr ins+ optional blanklines+ return $ B.headerWith attrs (digitToInt dig) ins++pod :: PandocMonad m => PodParser m Blocks+pod = do+ cmd "pod"+ optional (try inlines)+ optional blanklines+ return mempty++cut :: PandocMonad m => PodParser m Blocks+cut = cmd "cut" *> notPod++notPod :: PandocMonad m => PodParser m Blocks+notPod = do+ manyTill anyLine (eof <|> void (try (lookAhead (char '=' *> letter))))+ return mempty++over :: PandocMonad m => PodParser m Blocks+over = do+ cmd "over"+ anyLine+ blanklines+ optional $ try (char '=' *> cut)+ bs <- list <|> blockquote+ string "=back" <* blanklines+ return bs++list :: PandocMonad m => PodParser m Blocks+list = try bulletList <|> try orderedList <|> definitionList++bulletList :: PandocMonad m => PodParser m Blocks+bulletList = B.bulletList <$> many1 (item (many spaceChar *> optional (char '*')))++orderedList :: PandocMonad m => PodParser m Blocks+orderedList = do+ start <- item1+ more <- many orderedItem+ return $ B.orderedList (start : more)+ where+ item1 = item $ spaces *> char '1' *> optional (char '.')+ orderedItem = item $ spaces *> many digit *> optional (char '.')++item :: PandocMonad m => PodParser m () -> PodParser m Blocks+item p = do+ try (cmd "=item")+ p+ blanklines+ mconcat <$> many block <?> "runaway item"++definitionList :: PandocMonad m => PodParser m Blocks+definitionList = B.definitionList <$> many1 dlItem+ where+ dlItem = do+ try (cmd "=item")+ spaces+ term <- inlines+ blanklines+ -- perlpodspec sez the /section part of a link can refer to either+ -- a header or a dl item, hence treating it as a "header" here+ attrs <- registerHeader B.nullAttr term+ defn <- mconcat <$> many block <?> "runaway dlitem"+ return (B.spanWith attrs term, [defn])++blockquote :: PandocMonad m => PodParser m Blocks+blockquote = B.blockQuote . mconcat <$> many block <?> "runaway blockquote"++paragraph :: PandocMonad m => PodParser m Blocks+paragraph = do+ try (notFollowedBy (char '=' *> letter))+ inl <- inlines+ optional blanklines+ return $ B.para $ B.trimInlines inl++inlines :: PandocMonad m => PodParser m Inlines+inlines = mconcat <$> many1 (format <|> whitespace <|> str)++-- perlpodspec sez:+-- If a Pod processor sees any formatting code other than the ones listed,+-- that processor must by default treat this as an error.+format :: PandocMonad m => PodParser m Inlines+format = try $ do+ ctrl <- satisfy isAsciiUpper+ p <- getPosition+ lookAhead (char '<')+ case ctrl of+ 'B' -> B.strong <$> argument+ 'C' -> B.code . stringify <$> argument+ 'F' -> B.spanWith (mempty, ["filename"], mempty) <$> argument+ 'I' -> B.emph <$> argument+ 'S' -> argument -- TODO map nbsps+ 'X' -> argument $> mempty+ 'Z' -> argument $> mempty++ 'E' -> do+ a <- stringify <$> argument+ case entity a of+ -- per spec:+ -- Pod parsers, when faced with some unknown "E<identifier>" code,+ -- shouldn't simply replace it with nullstring (by default, at+ -- least), but may pass it through as a string consisting of the+ -- literal characters E, less-than, identifier, greater-than.+ Nothing -> do+ logMessage $ SkippedContent ("unknown entity " <> a) p+ return $ B.str $ "E<" <> a <> ">"+ Just e -> return $ B.str e++ 'L' -> link++ x -> throwError $ PandocParseError $ T.snoc "unknown Pod formatting code " x+ where+ argument = try expandedArg <|> compactArg <?> "argument"+ innerStr = B.str <$> many1Char (podCharLess ">")+ compactArg = do+ char '<'+ mconcat <$> manyTill (format <|> whitespace <|> innerStr) (char '>')+ expandedArg = do+ openLen <- length <$> many1 (char '<')+ let close = T.pack $ replicate openLen '>'+ skipMany1 spaceChar <|> void blankline+ arg <- mconcat <$> many (format <|> try (whitespace <* notFollowedBy (textStr close)) <|> str)+ many1 spaceChar+ textStr close+ return arg+ -- Some legacy entity names are required to be parsed by Pod formatters+ oct = listToMaybe . readOct @Integer+ entity "apos" = Just "'"+ entity "sol" = Just "/"+ entity "verbar" = Just "|"+ entity "lchevron" = Just "«"+ entity "rchevron" = Just "»"+ entity (T.stripPrefix "0x" -> Just suf) = lookupEntity $ "#x" <> suf+ entity (T.stripPrefix "0" -> Just suf)+ | Just (n, "") <- oct (T.unpack suf) = lookupEntity $ "#" <> tshow n+ entity (TR.decimal @Integer -> Right (x, "")) = lookupEntity $ "#" <> tshow 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+-- varying depending on whether the link is expanded or not, but at least I+-- understand what I've done. This would be less wacky with a lexing step.+link :: PandocMonad m => PodParser m Inlines+link = do+ identifier <- textToIdentifier <$> getOption readerExtensions+ (name, dest) <- try expandedLinkArg <|> compactLinkArg+ return $ mkLink identifier name dest+ where+ compactLinkArg = do+ char '<'+ name <- linkName whitespace ">"+ dest <- linkDest whitespace (char '>') ">"+ char '>'+ return (mconcat <$> name, dest)+ expandedLinkArg = do+ openLen <- length <$> many1 (char '<')+ let closeStr = textStr (T.pack $ replicate openLen '>')+ let close = skipMany1 spaceChar *> closeStr+ let sp = try $ many1 spaceChar *> notFollowedBy closeStr $> B.space+ many1 spaceChar+ name <- linkName sp ""+ dest <- linkDest sp close ""+ close+ return (mconcat <$> name, dest)+ mkLink identifier name dest =+ let name' = fromMaybe (defaultLinkName dest) name in+ case dest of+ LinkUrl _ href -> B.link href "" name'+ LinkMan nm Nothing -> B.linkWith (mempty, mempty, [("manual", stringify nm)]) "" "" name'+ LinkMan nm (Just sc) -> B.linkWith (mempty, mempty, [("manual", stringify nm), ("section", stringify sc)]) "" "" name'+ LinkInternal sc -> B.link ("#" <> identifier (stringify sc)) "" name'++ linkName sp ex = optionMaybe $ try $ many+ (try format+ <|> sp+ <|> B.str <$> many1Char (podCharLess ('|':ex))) <* char '|'+ linkDest sp close ex = try (url ex) <|> internal sp close ex <|> man sp close ex+ -- perlpodspec sez:+ -- Note that you can distinguish URL-links from anything else by the+ -- fact that they match m/\A\w+:[^:\s]\S*\z/.+ -- This is obviously not an RFC-compliant matcher for a URI scheme, but+ -- this is what the specification and the canonical implementation (Pod::Simple)+ -- do for deciding that a link target "looks like" a URL, as opposed to a+ -- manual page reference, so what we are doing here is roughly equivalent+ -- even though it is nonsense+ url ex = do+ scheme <- many1Char (letter <|> digit <|> char '_')+ colon <- T.singleton <$> char ':' <* notFollowedBy (char ':')+ rst <- many (format <|> B.str <$> many1Char (podCharLess ex))+ return $ LinkUrl+ (B.str scheme <> B.str colon <> mconcat rst)+ (scheme <> colon <> stringify rst)+ quotedSection sp close ex = do+ let mystr = B.str <$> many1Char (podCharLess ('\"':ex) <|> try (char '"' <* notFollowedBy close))+ char '"'+ ins <- mconcat <$> many1 (format <|> sp <|> mystr)+ char '"'+ return ins+ section sp close ex = try (quotedSection sp close ex) <|> mconcat <$> many1 (format <|> sp <|> B.str <$> many1Char (podCharLess ex))+ internal sp close ex = do+ char '/'+ LinkInternal <$> section sp close ex+ notSlash sp ex = format <|> sp <|> B.str <$> many1Char (podCharLess ('/':ex))+ man sp close ex = do+ page <- mconcat <$> many (notSlash sp ex)+ sec <- optionMaybe $ char '/' *> section sp close ex+ return $ LinkMan page sec++whitespace :: PandocMonad m => PodParser m Inlines+whitespace = try $ do+ many1 spaceChar *> optional newline <|> many spaceChar *> void newline+ notFollowedBy blankline+ return B.space++podCharLess :: PandocMonad m => String -> PodParser m Char+podCharLess exclude = try (satisfy isAsciiUpper <* notFollowedBy (char '<'))+ <|> satisfy (\c -> not (isSpaceChar c || isAsciiUpper c || elem c exclude))++podChar :: PandocMonad m => PodParser m Char+podChar = try (satisfy isAsciiUpper <* notFollowedBy (char '<'))+ <|> satisfy (\c -> not (isSpaceChar c || isAsciiUpper c))++str :: PandocMonad m => PodParser m Inlines+str = B.str <$> many1Char podChar++nonEmptyLine :: PandocMonad m => PodParser m T.Text+nonEmptyLine = try $ do+ pre <- manyChar spaceChar+ something <- T.singleton <$> nonspaceChar+ post <- anyLineNewline+ return $ pre <> something <> post++verbatim :: PandocMonad m => PodParser m Blocks+verbatim = do+ start <- startVerbatimLine+ lns <- many (nonEmptyLine <|>+ try (do b <- blanklines+ l <- startVerbatimLine+ return $ b <> l))+ optional blanklines+ return $ B.codeBlock $ mconcat $ start:lns+ where+ startVerbatimLine = many1Char spaceChar <> nonEmptyLine++-- =begin/=end/=for and data paragraphs+-- The =begin/=end (and single-paragraph =for variant) markers in Pod are+-- designed as an extension point for specific formatters+--+-- this doesn't strictly match the intent of "=begin :ident" pod blocks, which+-- are still meant to be processed specially by the formatter, and only land in+-- the output upon request, i.e. pod2html will process "=begin :html" blocks as+-- Pod and include them in the regular output. Since the regions contain Pod+-- markup it seems to me that the best thing to do is parse the markup and put+-- a classname on it, allowing users to respond as desired with filters.+-- Pandoc doesn't have a built-in concept of parsed Divs that are only rendered+-- to certain formats, just raw blocks.+--+-- perlpodspec allows nesting of =begin/=end regions but we currently don't+-- because it would be annoying and we have something somewhat useful we+-- can do with these blocks which is treat them as RawBlocks, which matches+-- the intent reasonably well, and that gets weirder if we parse a nested+-- structure. It seems unlikely this would be encountered in the wild.++regionIdentifier :: PandocMonad m => PodParser m T.Text+regionIdentifier = many1Char (alphaNum <|> oneOf "-_")++for :: PandocMonad m => PodParser m Blocks+for = do+ string "for"+ many1 spaceChar+ forDiv <|> forData++forDiv :: PandocMonad m => PodParser m Blocks+forDiv = do+ char ':'+ cls <- regionIdentifier+ many1 spaceChar+ B.divWith (mempty, [cls], mempty) <$> paragraph++forData :: PandocMonad m => PodParser m Blocks+forData = do+ fmt <- regionIdentifier+ ln1 <- anyLineNewline+ lns <- many nonEmptyLine+ optional blanklines+ return $ B.rawBlock fmt (T.concat (ln1 : lns))++begin :: PandocMonad m => PodParser m Blocks+begin = do+ cmd "begin"+ beginDiv <|> beginData++beginDiv :: PandocMonad m => PodParser m Blocks+beginDiv = do+ char ':'+ cls <- regionIdentifier+ anyLine -- "parameters" may appear in this position+ blanklines+ bs <- mconcat <$> many block+ textStr ("=end :" <> cls) <* blanklines+ return $ B.divWith (mempty, [cls], mempty) bs++beginData :: PandocMonad m => PodParser m Blocks+beginData = do+ fmt <- regionIdentifier+ anyLine+ blanklines+ lns <- mconcat <$> many (try rawCut <|> rawLine)+ textStr ("=end " <> fmt) <* blanklines+ return $ B.rawBlock fmt lns+ where+ rawCut = do+ char '=' *> cut+ pod <?> "=pod to close =cut within =begin/=end"+ return mempty+ rawLine = do+ try (notFollowedBy (char '=' *> letter))+ anyLineNewline
@@ -0,0 +1,43 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.Pptx+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++Conversion of PPTX (PowerPoint) documents to 'Pandoc' document.+-}+module Text.Pandoc.Readers.Pptx (readPptx) where++import qualified Data.ByteString.Lazy as B+import qualified Data.Text as T+import Codec.Archive.Zip (toArchiveOrFail)+import Control.Monad.Except (throwError)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Definition (Pandoc(..))+import Text.Pandoc.Error (PandocError(..))+import Text.Pandoc.Options (ReaderOptions)+import Text.Pandoc.Readers.Pptx.Parse (archiveToPptx)+import Text.Pandoc.Readers.Pptx.Slides (pptxToOutput)++-- | Read PPTX file into Pandoc AST+readPptx :: PandocMonad m => ReaderOptions -> B.ByteString -> m Pandoc+readPptx opts bytes =+ case toArchiveOrFail bytes of+ Right archive ->+ case archiveToPptx archive of+ Right pptx -> do+ -- Convert Pptx intermediate to Pandoc AST+ (meta, blocks) <- pptxToOutput opts pptx+ return $ Pandoc meta blocks++ Left err ->+ throwError $ PandocParseError $+ "Failed to parse PPTX: " <> err++ Left err ->+ throwError $ PandocParseError $+ "Failed to unpack PPTX archive: " <> T.pack err
@@ -0,0 +1,216 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.Pptx.Parse+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++Parsing of PPTX archive to intermediate representation.+-}+module Text.Pandoc.Readers.Pptx.Parse+ ( Pptx(..)+ , PresentationDoc(..)+ , PptxSlide(..)+ , SlideId(..)+ , archiveToPptx+ ) where++import Codec.Archive.Zip (Archive, Entry, findEntryByPath, fromEntry)+import qualified Data.ByteString.Lazy as B+import Data.List (find)+import Data.Maybe (mapMaybe)+import qualified Data.Text as T+import qualified Data.Text.Lazy.Encoding as TL+import Data.Text (Text)+import System.FilePath (splitFileName)+import Text.Pandoc.Readers.OOXML.Shared+import Text.Pandoc.XML.Light+import Text.Read (readMaybe)++-- | Slide identifier+newtype SlideId = SlideId Int deriving (Show, Eq, Ord)++-- | Complete PPTX document (intermediate representation)+data Pptx = Pptx+ { pptxPresentation :: PresentationDoc+ , pptxSlides :: [PptxSlide]+ , pptxArchive :: Archive+ } deriving (Show)++-- | Individual slide data+data PptxSlide = PptxSlide+ { slideId :: SlideId+ , slidePath :: FilePath+ , slideElement :: Element -- The parsed p:sld element+ , slideRels :: [(Text, Text)] -- Slide relationships+ } deriving (Show)++-- | Presentation-level information from presentation.xml+data PresentationDoc = PresentationDoc+ { presNameSpaces :: NameSpaces+ , presSlideSize :: (Integer, Integer) -- (width, height) in pixels+ , presSlideIds :: [(SlideId, Text)] -- (slideId, relationshipId)+ } deriving (Show)++-- | Parse PPTX archive to intermediate representation+archiveToPptx :: Archive -> Either Text Pptx+archiveToPptx archive = do+ -- Find and parse presentation.xml+ presPath <- getPresentationXmlPath archive+ presElem <- loadXMLFromArchive archive presPath+ presDoc <- elemToPresentation presElem++ -- Load presentation relationships to resolve slide paths+ presRelsPath <- getPresentationRelsPath archive presPath+ presRels <- loadRelationships archive presRelsPath++ -- Parse each slide+ slides <- mapM (parseSlide archive presRels) (presSlideIds presDoc)++ return $ Pptx presDoc slides archive++-- | Find presentation.xml via root relationships+getPresentationXmlPath :: Archive -> Either Text FilePath+getPresentationXmlPath archive = do+ -- Load _rels/.rels+ relsEntry <- maybeToEither "Missing _rels/.rels" $+ findEntryByPath "_rels/.rels" archive++ relsElem <- parseXMLFromEntry relsEntry++ -- The Relationships element has a default namespace, but Relationship children don't use prefix+ -- We need to look at all children regardless of namespace+ let relElems = onlyElems $ elContent relsElem++ -- Look for relationship containing "officeDocument" in Type attribute+ case find isOfficeDocRel relElems of+ Nothing -> Left $ "No presentation.xml relationship found. Found " <>+ T.pack (show (length relElems)) <> " relationships."+ Just rel -> do+ target <- maybeToEither "Missing Target attribute" $+ findAttr (unqual "Target") rel+ return $ T.unpack target -- Convert Text to FilePath++ where+ isOfficeDocRel el =+ case findAttr (unqual "Type") el of+ -- Must end with "/officeDocument" to avoid matching "/extended-properties"+ Just relType -> "/officeDocument" `T.isSuffixOf` relType+ Nothing -> False++-- | Load and parse XML from archive entry+loadXMLFromArchive :: Archive -> FilePath -> Either Text Element+loadXMLFromArchive archive path = do+ entry <- maybeToEither ("Entry not found: " <> T.pack path) $+ findEntryByPath path archive++ let xmlBytes = fromEntry entry+ parseXMLFromBS xmlBytes++-- | Parse XML from ByteString+parseXMLFromBS :: B.ByteString -> Either Text Element+parseXMLFromBS = parseXMLElement . TL.decodeUtf8++-- | Parse XML from Entry+parseXMLFromEntry :: Entry -> Either Text Element+parseXMLFromEntry = parseXMLFromBS . fromEntry++-- | Parse presentation.xml element to PresentationDoc+elemToPresentation :: Element -> Either Text PresentationDoc+elemToPresentation presElem = do+ let ns = elemToNameSpaces presElem++ -- Extract slide size (with defaults)+ let sizeElem = findChildByName ns "p" "sldSz" presElem+ (widthEMU, heightEMU) = case sizeElem of+ Just el ->+ let cx = readAttrInt "cx" el+ cy = readAttrInt "cy" el+ in (cx, cy)+ Nothing -> (9144000, 6858000) -- Default 10" x 7.5"++ -- Convert EMUs to pixels (approximate for metadata)+ let width = widthEMU `div` emusPerInch+ height = heightEMU `div` emusPerInch++ -- Extract slide ID list (optional - some presentations may have no slides)+ let sldIdLstElem = findChildByName ns "p" "sldIdLst" presElem++ slideRefs <- case sldIdLstElem of+ Nothing -> return [] -- No slides is valid for templates/masters-only presentations+ Just el -> do+ let sldIdElems = findChildren (elemName ns "p" "sldId") el+ mapM (extractSlideRef ns) (zip [1..] sldIdElems)++ return $ PresentationDoc+ { presNameSpaces = ns+ , presSlideSize = (width, height)+ , presSlideIds = slideRefs+ }++-- | Extract slide ID and relationship ID from p:sldId element+extractSlideRef :: NameSpaces -> (Int, Element) -> Either Text (SlideId, Text)+extractSlideRef ns (idx, sldIdElem) = do+ relId <- maybeToEither ("Missing r:id in slide " <> T.pack (show idx)) $+ findAttrByName ns "r" "id" sldIdElem++ return (SlideId idx, relId)++-- | Safe read attribute as Integer (with default of 0)+readAttrInt :: Text -> Element -> Integer+readAttrInt attrName el =+ case findAttr (unqual attrName) el of+ Just str -> case readMaybe (T.unpack str) of+ Just n -> n+ Nothing -> 0+ Nothing -> 0++-- | Get presentation relationships path+getPresentationRelsPath :: Archive -> FilePath -> Either Text FilePath+getPresentationRelsPath _archive presPath =+ -- ppt/presentation.xml → ppt/_rels/presentation.xml.rels+ let (dir, file) = splitFileName presPath+ relsPath = dir ++ "/_rels/" ++ file ++ ".rels"+ in Right relsPath++-- | Load relationships from .rels file+loadRelationships :: Archive -> FilePath -> Either Text [(Text, Text)]+loadRelationships archive relsPath =+ case findEntryByPath relsPath archive of+ Nothing -> Right [] -- No relationships is OK+ Just entry -> do+ relsElem <- parseXMLFromEntry entry+ let relElems = onlyElems $ elContent relsElem+ return $ mapMaybe extractRelationship relElems+ where+ extractRelationship el = do+ relId <- findAttr (unqual "Id") el+ target <- findAttr (unqual "Target") el+ return (relId, target)++-- | Parse a single slide+parseSlide :: Archive -> [(Text, Text)] -> (SlideId, Text) -> Either Text PptxSlide+parseSlide archive rels (sid, relId) = do+ -- Resolve relationship to get slide path+ target <- maybeToEither ("Relationship not found: " <> relId) $+ lookup relId rels++ -- Resolve relative path: ppt/slides/slide1.xml+ let slidePath' = "ppt/" <> T.unpack target++ -- Load and parse slide XML+ slideElem <- loadXMLFromArchive archive slidePath'++ -- Load slide-specific relationships+ slideRelsPath <- getPresentationRelsPath archive slidePath'+ slideRels' <- loadRelationships archive slideRelsPath++ return $ PptxSlide sid slidePath' slideElem slideRels'++-- | Helper: Maybe a -> Either Text a+maybeToEither :: Text -> Maybe a -> Either Text a+maybeToEither err Nothing = Left err+maybeToEither _ (Just x) = Right x
@@ -0,0 +1,330 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -Wno-partial-fields #-}+{- |+ Module : Text.Pandoc.Readers.Pptx.Shapes+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++Parsing of PPTX shapes (text boxes, images, tables, diagrams).+-}+module Text.Pandoc.Readers.Pptx.Shapes+ ( PptxShape(..)+ , PptxParagraph(..)+ , BulletType(..)+ , parseShapes+ , parseShape+ , shapeToBlocks+ , isTitlePlaceholder+ , extractDrawingMLText+ ) where++import Codec.Archive.Zip (Archive, findEntryByPath, fromEntry)+import qualified Data.ByteString.Lazy as B+import Data.List (find, groupBy)+import Data.Maybe (mapMaybe)+import qualified Data.Text as T+import Data.Text (Text)+import Text.Read (readMaybe)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import qualified Text.Pandoc.Class.PandocMonad as P+import Text.Pandoc.Definition+import Text.Pandoc.Readers.OOXML.Shared+import Text.Pandoc.Readers.Pptx.SmartArt+import Text.Pandoc.XML.Light++-- | Paragraph with bullet/numbering information+data PptxParagraph = PptxParagraph+ { paraLevel :: Int -- Bullet level (0, 1, 2...)+ , paraBullet :: BulletType+ , paraText :: Text+ } deriving (Show)++-- | Bullet type+data BulletType+ = NoBullet+ | Bullet -- Has bullet (character detected or implicit)+ | WingdingsBullet -- Detected via Wingdings symbol+ deriving (Show, Eq)++-- | Shape types in PPTX slides+data PptxShape+ = PptxTextBox [PptxParagraph] -- Parsed paragraphs with bullet info+ | PptxPicture+ { picRelId :: Text -- Relationship ID (lazy loading)+ , picTitle :: Text+ , picAlt :: Text+ }+ | PptxTable [[Text]] -- Simple text cells for now+ | PptxDiagramRef+ { dgmDataRelId :: Text -- Relationship to data.xml+ , dgmLayoutRelId :: Text -- Relationship to layout.xml+ }+ | PptxGraphic Text -- Placeholder for other graphics+ deriving (Show)++-- | Parse all shapes from shape tree+parseShapes :: NameSpaces -> Element -> [PptxShape]+parseShapes ns spTreeElem =+ let shapeElems = onlyElems $ elContent spTreeElem+ -- Merge parent namespaces with element namespaces+ ns' = ns <> elemToNameSpaces spTreeElem+ in mapMaybe (parseShape ns') shapeElems++-- | Parse individual shape element+parseShape :: NameSpaces -> Element -> Maybe PptxShape+parseShape ns el+ -- Text box: <p:sp> with <p:txBody>+ | isElem ns "p" "sp" el =+ case findChildByName ns "p" "txBody" el of+ Just txBody ->+ let paras = parseParagraphs ns txBody+ in if null paras+ then Nothing+ else Just $ PptxTextBox paras+ Nothing -> Nothing++ -- Picture: <p:pic>+ | isElem ns "p" "pic" el = do+ nvPicPr <- findChildByName ns "p" "nvPicPr" el+ cNvPr <- findChildByName ns "p" "cNvPr" nvPicPr++ let title = maybe "" id $ findAttr (unqual "name") cNvPr+ alt = maybe "" id $ findAttr (unqual "descr") cNvPr++ -- Get blip relationship ID+ blipFill <- findChildByName ns "p" "blipFill" el+ blip <- findChildByName ns "a" "blip" blipFill+ relId <- findAttrByName ns "r" "embed" blip++ return $ PptxPicture relId title alt++ -- GraphicFrame: table or diagram+ | isElem ns "p" "graphicFrame" el =+ case findChildByName ns "a" "graphic" el >>=+ findChildByName ns "a" "graphicData" of+ Nothing -> Nothing+ Just graphicData ->+ case findAttr (unqual "uri") graphicData of+ Nothing -> Just $ PptxGraphic "no-uri"+ Just uri ->+ if "table" `T.isInfixOf` uri+ then+ -- Table+ case findChildByName ns "a" "tbl" graphicData of+ Just tbl ->+ let rows = parseTableRows ns tbl+ in Just $ PptxTable rows+ Nothing -> Nothing+ else if "diagram" `T.isInfixOf` uri+ then+ -- SmartArt diagram - dgm namespace is declared inline on relIds element+ let dgmRelIds = find (\e -> qName (elName e) == "relIds") (elChildren graphicData)+ in case dgmRelIds of+ Nothing -> Just $ PptxGraphic "diagram-no-relIds"+ Just relIdsElem ->+ -- Get r:dm and r:lo attributes (r namespace is in parent)+ let ns' = ns <> elemToNameSpaces relIdsElem+ in case (findAttrByName ns' "r" "dm" relIdsElem,+ findAttrByName ns' "r" "lo" relIdsElem) of+ (Just dataRelId, Just layoutRelId) ->+ Just $ PptxDiagramRef dataRelId layoutRelId+ _ -> Just $ PptxGraphic "diagram-missing-rels"+ else+ -- Other graphic (chart, etc.)+ Just $ PptxGraphic ("other: " <> uri)++ -- Skip other shapes for now+ | otherwise = Nothing++-- | Parse table rows (simple text extraction)+parseTableRows :: NameSpaces -> Element -> [[Text]]+parseTableRows ns tblElem =+ let trElems = findChildrenByName ns "a" "tr" tblElem+ in map (parseTableRow ns) trElems++parseTableRow :: NameSpaces -> Element -> [Text]+parseTableRow ns trElem =+ let tcElems = findChildrenByName ns "a" "tc" trElem+ in map extractCellText tcElems+ where+ extractCellText tcElem =+ -- Get text from txBody/a:p/a:r/a:t+ case findChildByName ns "a" "txBody" tcElem of+ Just txBody -> extractDrawingMLText txBody+ Nothing -> ""++-- | Convert shape to Pandoc blocks+shapeToBlocks :: PandocMonad m => Archive -> [(Text, Text)] -> PptxShape -> m [Block]+shapeToBlocks _archive _rels (PptxTextBox paras) =+ return $ paragraphsToBlocks paras+shapeToBlocks archive rels (PptxPicture relId title alt) = do+ -- Resolve relationship to get media path+ case lookup relId rels of+ Nothing -> return [] -- Image not found+ Just target -> do+ let mediaPath = resolveMediaPath target++ -- Load image bytes and add to MediaBag+ case loadMediaFromArchive archive mediaPath of+ Nothing -> return []+ Just mediaBytes -> do+ P.insertMedia (T.unpack mediaPath) Nothing mediaBytes++ let altText = if T.null alt then [] else [Str alt]+ return [Para [Image nullAttr altText (mediaPath, title)]]++shapeToBlocks _archive _rels (PptxTable rows) =+ -- Simple table representation for now+ case rows of+ [] -> return []+ (headerRow:bodyRows) -> do+ let makeCell text = Cell nullAttr AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str text]]+ headerCells = map makeCell headerRow+ bodyCells = map (map makeCell) bodyRows+ caption = Caption Nothing []+ colSpec = replicate (length headerRow) (AlignDefault, ColWidthDefault)+ headerRow' = Row nullAttr headerCells+ bodyRows' = map (Row nullAttr) bodyCells+ thead = TableHead nullAttr [headerRow']+ tbody = [TableBody nullAttr 0 [] bodyRows']+ tfoot = TableFoot nullAttr []+ return [Table nullAttr caption colSpec thead tbody tfoot]++shapeToBlocks archive rels (PptxDiagramRef dataRelId layoutRelId) = do+ -- Parse SmartArt diagram+ case parseDiagram archive rels dataRelId layoutRelId of+ Left err -> do+ -- Failed to parse diagram, return placeholder+ return [Para [Str $ "[Diagram parse error: " <> err <> "]"]]+ Right diagram ->+ return $ diagramToBlocks diagram+shapeToBlocks _archive _rels (PptxGraphic text) =+ -- Placeholder for other graphics (charts, etc.)+ return [Para [Str $ "[Graphic: " <> text <> "]"]]++-- | Resolve media path (handle relative paths)+resolveMediaPath :: Text -> Text+resolveMediaPath target =+ if "../media/" `T.isPrefixOf` target+ then "ppt/media/" <> T.drop 9 target -- "../media/" = 9 chars+ else if "media/" `T.isPrefixOf` target+ then "ppt/" <> target+ else target++-- | Load media file from archive+loadMediaFromArchive :: Archive -> Text -> Maybe B.ByteString+loadMediaFromArchive archive path =+ case findEntryByPath (T.unpack path) archive of+ Just entry -> Just $ fromEntry entry+ Nothing -> Nothing++-- | Parse paragraphs from text box+parseParagraphs :: NameSpaces -> Element -> [PptxParagraph]+parseParagraphs ns txBody =+ let pElems = findChildrenByName ns "a" "p" txBody+ in map (parseParagraph ns) pElems++-- | Parse individual paragraph+parseParagraph :: NameSpaces -> Element -> PptxParagraph+parseParagraph ns pElem =+ let level = parseBulletLevel ns pElem+ bullet = detectBulletType ns pElem+ text = extractParagraphText ns pElem+ in PptxParagraph level bullet text++-- | Parse bullet level from paragraph properties+parseBulletLevel :: NameSpaces -> Element -> Int+parseBulletLevel ns pElem =+ case findChildByName ns "a" "pPr" pElem >>=+ findAttr (unqual "lvl") >>=+ (\s -> readMaybe (T.unpack s) :: Maybe Int) of+ Just lvl -> lvl+ Nothing -> 0 -- Default to level 0++-- | Detect bullet type+detectBulletType :: NameSpaces -> Element -> BulletType+detectBulletType ns pElem =+ -- Check for explicit <a:pPr><a:buChar>+ case findChildByName ns "a" "pPr" pElem >>=+ findChildByName ns "a" "buChar" of+ Just _buCharElem -> Bullet+ Nothing ->+ -- Check for Wingdings symbol (common in PowerPoint)+ if hasWingdingsSymbol ns pElem+ then WingdingsBullet+ else NoBullet++-- | Check if paragraph starts with Wingdings symbol+hasWingdingsSymbol :: NameSpaces -> Element -> Bool+hasWingdingsSymbol ns pElem =+ let runs = findChildrenByName ns "a" "r" pElem+ checkRun r = case findChildByName ns "a" "rPr" r >>=+ findChildByName ns "a" "sym" of+ Just symElem ->+ case findAttr (unqual "typeface") symElem of+ Just typeface -> "Wingdings" `T.isInfixOf` typeface+ Nothing -> False+ Nothing -> False+ in any checkRun runs++-- | Extract text from paragraph+extractParagraphText :: NameSpaces -> Element -> Text+extractParagraphText _ns pElem =+ -- Find all <a:t> elements and concatenate+ let textElems = filterElementsName (\qn -> qName qn == "t") pElem+ texts = map strContent textElems+ in T.unwords $ filter (not . T.null) texts++-- | Extract text from DrawingML element (finds all <a:t> descendants)+extractDrawingMLText :: Element -> Text+extractDrawingMLText el =+ let textElems = filterElementsName (\qn -> qName qn == "t") el+ texts = map strContent textElems+ in T.unwords $ filter (not . T.null) texts++-- | Convert paragraphs to blocks, grouping bullets into lists+paragraphsToBlocks :: [PptxParagraph] -> [Block]+paragraphsToBlocks paras =+ -- If we have multiple paragraphs with bullets, group them+ let hasBullets = any (\p -> paraBullet p /= NoBullet) paras+ in if hasBullets+ then groupBulletParagraphs paras+ else map (\p -> Para [Str $ paraText p]) paras++-- | Group bullet paragraphs into lists+groupBulletParagraphs :: [PptxParagraph] -> [Block]+groupBulletParagraphs paras =+ let grouped = groupBy sameBulletLevel paras+ in concatMap groupToBlock grouped+ where+ sameBulletLevel p1 p2 =+ (paraBullet p1 /= NoBullet) &&+ (paraBullet p2 /= NoBullet) &&+ (paraLevel p1 == paraLevel p2)++ groupToBlock :: [PptxParagraph] -> [Block]+ groupToBlock [] = []+ groupToBlock ps@(p:_)+ | paraBullet p /= NoBullet =+ -- Bullet list+ let items = map (\para -> [Plain [Str $ paraText para]]) ps+ in [BulletList items]+ | otherwise =+ -- Plain paragraph+ map (\para -> Para [Str $ paraText para]) ps++-- | Check if shape is title placeholder (also used in Slides module)+isTitlePlaceholder :: NameSpaces -> Element -> Bool+isTitlePlaceholder ns el =+ case findChildByName ns "p" "nvSpPr" el >>=+ findChildByName ns "p" "nvPr" >>=+ findChildByName ns "p" "ph" of+ Just phElem ->+ case findAttr (unqual "type") phElem of+ Just phType -> phType == "title" || phType == "ctrTitle"+ Nothing -> False+ Nothing -> False
@@ -0,0 +1,83 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.Pptx.Slides+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++Conversion of PPTX slides to Pandoc AST blocks.+-}+module Text.Pandoc.Readers.Pptx.Slides+ ( pptxToOutput+ ) where++import Codec.Archive.Zip (Archive)+import Data.List (find)+import Data.Maybe (mapMaybe)+import qualified Data.Text as T+import Data.Text (Text)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Definition+import Text.Pandoc.Options (ReaderOptions)+import Text.Pandoc.Readers.OOXML.Shared+import Text.Pandoc.Readers.Pptx.Parse+import Text.Pandoc.Readers.Pptx.Shapes+import Text.Pandoc.XML.Light++-- | Convert Pptx intermediate representation to Pandoc AST+pptxToOutput :: PandocMonad m => ReaderOptions -> Pptx -> m (Meta, [Block])+pptxToOutput _opts pptx = do+ let slides = pptxSlides pptx+ archive = pptxArchive pptx++ -- Convert each slide to blocks+ slideBlocks <- concat <$> mapM (slideToBlocks archive) slides++ return (mempty, slideBlocks)++-- | Convert slide to blocks+slideToBlocks :: PandocMonad m => Archive -> PptxSlide -> m [Block]+slideToBlocks archive slide = do+ let SlideId n = slideId slide+ slideElem = slideElement slide+ rels = slideRels slide+ ns = elemToNameSpaces slideElem++ -- Extract title from title placeholder+ title = extractSlideTitle ns slideElem++ -- Create header+ slideIdent = "slide-" <> T.pack (show n)+ headerText = if T.null title+ then "Slide " <> T.pack (show n)+ else title+ header = Header 2 (slideIdent, [], []) [Str headerText]++ -- Parse shapes and convert to blocks+ case findChildByName ns "p" "cSld" slideElem >>=+ findChildByName ns "p" "spTree" of+ Nothing -> return [header]+ Just spTree -> do+ -- Filter out title placeholder shapes before parsing+ let allShapeElems = onlyElems $ elContent spTree+ nonTitleShapeElems = filter (not . isTitlePlaceholder ns) allShapeElems+ shapes = mapMaybe (parseShape ns) nonTitleShapeElems+ shapeBlocks <- concat <$> mapM (shapeToBlocks archive rels) shapes+ return $ header : shapeBlocks++-- | Extract title from title placeholder+extractSlideTitle :: NameSpaces -> Element -> Text+extractSlideTitle ns slideElem =+ case findChildByName ns "p" "cSld" slideElem >>=+ findChildByName ns "p" "spTree" of+ Nothing -> ""+ Just spTree ->+ -- Find shape with ph type="title"+ let shapes = onlyElems $ elContent spTree+ titleShape = find (isTitlePlaceholder ns) shapes+ in maybe "" extractDrawingMLText titleShape++-- isTitlePlaceholder is imported from Shapes module
@@ -0,0 +1,220 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.Pptx.SmartArt+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++SmartArt diagram parsing and text extraction for PPTX.+-}+module Text.Pandoc.Readers.Pptx.SmartArt+ ( PptxDiagram(..)+ , parseDiagram+ , diagramToBlocks+ ) where++import Codec.Archive.Zip (Archive, findEntryByPath, fromEntry)+import qualified Data.Map.Strict as M+import Data.Maybe (mapMaybe)+import qualified Data.Text as T+import qualified Data.Text.Lazy.Encoding as TL+import Data.Text (Text)+import Text.Pandoc.Definition+import Text.Pandoc.Readers.OOXML.Shared+import Text.Pandoc.XML.Light++-- | SmartArt diagram data+data PptxDiagram = PptxDiagram+ { diagramType :: Text -- Layout type (chevron, cycle, etc.)+ , diagramNodes :: [(Text, [Text])] -- (nodeText, childTexts)+ } deriving (Show)++-- | Parse SmartArt diagram from relationship IDs+parseDiagram :: Archive+ -> [(Text, Text)] -- Slide relationships+ -> Text -- data relationship ID+ -> Text -- layout relationship ID+ -> Either Text PptxDiagram+parseDiagram archive rels dataRelId layoutRelId = do+ -- Resolve relationships to file paths+ dataTarget <- maybeToEither ("Relationship not found: " <> dataRelId) $+ lookup dataRelId rels+ layoutTarget <- maybeToEither ("Relationship not found: " <> layoutRelId) $+ lookup layoutRelId rels++ -- Resolve relative paths (diagrams are in ../diagrams/ from slides/)+ let dataPath = resolveDiagramPath dataTarget+ layoutPath = resolveDiagramPath layoutTarget++ -- Load XML files+ dataElem <- loadXMLFromArchive archive dataPath+ layoutElem <- loadXMLFromArchive archive layoutPath++ -- Extract layout type+ layoutType <- extractLayoutType layoutElem++ -- Extract text nodes with hierarchy+ nodes <- extractDiagramNodes dataElem++ return $ PptxDiagram layoutType nodes++-- | Resolve diagram path (handle ../diagrams/ relative paths)+resolveDiagramPath :: Text -> FilePath+resolveDiagramPath target =+ if "../diagrams/" `T.isPrefixOf` target+ then "ppt/diagrams/" ++ T.unpack (T.drop 12 target) -- "../diagrams/" = 12 chars+ else T.unpack target++-- | Load XML from archive+loadXMLFromArchive :: Archive -> FilePath -> Either Text Element+loadXMLFromArchive archive path =+ case findEntryByPath path archive of+ Nothing -> Left $ "File not found in archive: " <> T.pack path+ Just entry ->+ let xmlBytes = fromEntry entry+ lazyText = TL.decodeUtf8 xmlBytes+ in parseXMLElement lazyText++-- | Extract layout type from layout XML+extractLayoutType :: Element -> Either Text Text+extractLayoutType layoutElem = do+ -- Look for uniqueId attribute: "urn:.../layout/chevron2"+ case findAttr (unqual "uniqueId") layoutElem of+ Just uid ->+ -- Extract last part after last /+ let layoutName = T.takeWhileEnd (/= '/') uid+ in Right layoutName+ Nothing ->+ -- Fallback: look for title+ case findChildByName ns "dgm" "title" layoutElem >>=+ findAttr (unqual "val") of+ Just title -> Right title+ Nothing -> Right "unknown"+ where+ ns = elemToNameSpaces layoutElem++-- | Extract text nodes from diagram data+extractDiagramNodes :: Element -> Either Text [(Text, [Text])]+extractDiagramNodes dataElem = do+ let ns = elemToNameSpaces dataElem++ -- Find point list+ ptLst <- maybeToEither "Missing dgm:ptLst" $+ findChildByName ns "dgm" "ptLst" dataElem++ let ptElems = findChildrenByName ns "dgm" "pt" ptLst++ -- Build node map: modelId → text+ let nodeMap = M.fromList $ mapMaybe (extractNodeText ns) ptElems++ -- Parse connections+ let cxnLst = findChildByName ns "dgm" "cxnLst" dataElem+ connections = maybe [] (parseConnections ns) cxnLst++ -- Build parent-child map+ let parentMap = buildParentMap connections++ -- Find parent nodes (nodes that have children)+ let parentIds = M.keys parentMap++ -- Build hierarchy - only show nodes that are parents+ -- (children are shown under their parents)+ let hierarchy = map (buildNodeWithChildren nodeMap parentMap) parentIds+ -- Filter out nodes with empty text (presentation nodes)+ validHierarchy = filter (\(nodeText, _) -> not $ T.null nodeText) hierarchy++ return validHierarchy++-- | Extract text from a point element (returns Nothing if no text)+extractNodeText :: NameSpaces -> Element -> Maybe (Text, Text)+extractNodeText ns ptElem = do+ modelId <- findAttr (unqual "modelId") ptElem++ -- Extract text from dgm:t element (which contains a:p/a:r/a:t)+ let text = case findChildByName ns "dgm" "t" ptElem of+ Just tElem ->+ -- Recursively get ALL text content from all descendants+ getAllText tElem+ Nothing -> ""++ -- Only return nodes with actual text+ if T.null (T.strip text)+ then Nothing+ else return (modelId, text)++-- | Connection between nodes+data Connection = Connection+ { connType :: Text+ , connSrc :: Text+ , connDest :: Text+ } deriving (Show)++-- | Parse connections+parseConnections :: NameSpaces -> Element -> [Connection]+parseConnections ns cxnLst =+ let cxnElems = findChildrenByName ns "dgm" "cxn" cxnLst+ in mapMaybe (parseConnection ns) cxnElems++parseConnection :: NameSpaces -> Element -> Maybe Connection+parseConnection _ns cxnElem = do+ let cxnType = maybe "" id $ findAttr (unqual "type") cxnElem -- Empty if no type+ srcId <- findAttr (unqual "srcId") cxnElem+ destId <- findAttr (unqual "destId") cxnElem+ return $ Connection cxnType srcId destId++-- | Build parent-child map from connections+-- Use connections WITHOUT a type attribute (these are the data hierarchy)+buildParentMap :: [Connection] -> M.Map Text [Text]+buildParentMap connections =+ let dataConnections = filter (\c -> T.null (connType c)) connections+ in foldr addConn M.empty dataConnections+ where+ addConn conn m = M.insertWith (++) (connSrc conn) [connDest conn] m++-- | Build node with its children+buildNodeWithChildren :: M.Map Text Text -> M.Map Text [Text] -> Text -> (Text, [Text])+buildNodeWithChildren nodeMap parentMap nodeId =+ let nodeText = M.findWithDefault "" nodeId nodeMap+ childIds = M.findWithDefault [] nodeId parentMap+ -- Only include children that have text+ childTexts = filter (not . T.null) $+ map (\cid -> M.findWithDefault "" cid nodeMap) childIds+ in (nodeText, childTexts)++-- | Convert diagram to Pandoc blocks+diagramToBlocks :: PptxDiagram -> [Block]+diagramToBlocks diagram =+ let nodes = diagramNodes diagram+ layoutType = diagramType diagram++ -- Build content blocks+ contentBlocks = concatMap nodeToBlocks nodes++ in [Div ("", ["smartart", layoutType], [("layout", layoutType)])+ contentBlocks]++-- | Convert node to blocks+nodeToBlocks :: (Text, [Text]) -> [Block]+nodeToBlocks (nodeText, childTexts) =+ if null childTexts+ then [Para [Strong [Str nodeText]]]+ else [ Para [Strong [Str nodeText]]+ , BulletList [[Plain [Str child]] | child <- childTexts]+ ]++-- | Recursively extract all text from an element and its descendants+getAllText :: Element -> Text+getAllText el =+ let textFromContent (Text cdata) = cdData cdata+ textFromContent (Elem e) = getAllText e+ textFromContent _ = ""+ texts = map textFromContent (elContent el)+ in T.unwords $ filter (not . T.null) texts++-- Helper functions+maybeToEither :: Text -> Maybe a -> Either Text a+maybeToEither err Nothing = Left err+maybeToEither _ (Just x) = Right x
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.RIS- Copyright : Copyright (C) 2022 John MacFarlane+ Copyright : Copyright (C) 2022-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -23,13 +23,13 @@ import Text.Pandoc.Definition import Text.Pandoc.Parsing import Data.Char (isAsciiUpper, isDigit, isSpace, ord, chr)-import Data.List (foldl')+import qualified Data.List as L import Citeproc (Reference(..), ItemId(..), Val(..), Date(..), DateParts(..), toVariable) import Text.Pandoc.Builder as B import Text.Pandoc.Class (PandocMonad) import Text.Pandoc.Citeproc.MetaValue (referenceToMetaValue)-import Text.Pandoc.Citeproc.BibTeX (toName)+import Text.Pandoc.Citeproc.Name (toName, NameOpts(..)) import Control.Monad.Except (throwError) import qualified Data.Text as T import Data.Text (Text)@@ -59,7 +59,7 @@ B.doc mempty Left e -> throwError e -type RISParser m = ParserT Sources () m+type RISParser m = ParsecT Sources () m risLine :: PandocMonad m => RISParser m (Text, Text) risLine = do@@ -140,7 +140,9 @@ M.insert (toVariable k) (FancyVal v) (referenceVariables r) } addName k v r =- let new = toName [] . B.toList . B.text $ v+ let new = toName NameOpts{ nameOptsPrefixIsNonDroppingParticle = False+ , nameOptsUseJuniorComma = False }+ . B.toList . B.text $ v f Nothing = Just (NamesVal new) f (Just (NamesVal ns)) = Just (NamesVal (new ++ ns)) f (Just x) = Just x@@ -183,7 +185,7 @@ return $ fixDuplicateIds $ map risRecordToReference recs fixDuplicateIds :: [Reference Text] -> [Reference Text]-fixDuplicateIds = reverse . snd . foldl' go (mempty, [])+fixDuplicateIds = reverse . snd . L.foldl' go (mempty, []) where go (ids_seen, refs) ref = case M.lookup (referenceId ref) ids_seen of
@@ -4,7 +4,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Readers.RST- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -15,19 +15,22 @@ -} module Text.Pandoc.Readers.RST ( readRST ) where import Control.Arrow (second)-import Control.Monad (forM_, guard, liftM, mplus, mzero, when)+import Control.Monad (forM_, guard, liftM, mplus, mzero, when, unless, void) import Control.Monad.Except (throwError) import Control.Monad.Identity (Identity (..))-import Data.Char (isHexDigit, isSpace, toUpper, isAlphaNum)-import Data.List (deleteFirstsBy, elemIndex, nub, sort, transpose)+import Data.Char (isHexDigit, isSpace, toUpper, isAlphaNum, generalCategory,+ GeneralCategory(OpenPunctuation, InitialQuote, FinalQuote,+ DashPunctuation, OtherSymbol))+import Data.List (deleteFirstsBy, elemIndex, nub, partition, sort, transpose) import qualified Data.Map as M-import Data.Maybe (fromMaybe, maybeToList, isJust)+import Data.Maybe (fromMaybe, maybeToList, isJust, isNothing, catMaybes) import Data.Sequence (ViewR (..), viewr) import Data.Text (Text) import qualified Data.Text as T+import Text.Printf (printf) import Text.Pandoc.Builder (Blocks, Inlines, fromList, setMeta, trimInlines) import qualified Text.Pandoc.Builder as B-import Text.Pandoc.Class.PandocMonad (PandocMonad, fetchItem, getTimestamp)+import Text.Pandoc.Class (PandocMonad, readFileFromDirs, fetchItem, getTimestamp) import Text.Pandoc.CSV (CSVOptions (..), defaultCSVOptions, parseCSV) import Text.Pandoc.Definition import Text.Pandoc.Error@@ -36,6 +39,8 @@ import Text.Pandoc.Options import Text.Pandoc.Parsing import Text.Pandoc.Shared+import Text.Pandoc.URI+import Text.Pandoc.Walk (walkM) import qualified Text.Pandoc.UTF8 as UTF8 import Data.Time.Format import System.FilePath (takeDirectory)@@ -55,7 +60,7 @@ Right result -> return result Left e -> throwError e -type RSTParser m = ParserT Sources ParserState m+type RSTParser m = ParsecT Sources ParserState m -- -- Constants and data structure definitions@@ -112,18 +117,16 @@ metaFromDefList :: [([Inline], [[Block]])] -> Meta -> Meta metaFromDefList ds meta = adjustAuthors $ foldr f meta ds- where f (k,v) = setMeta (T.toLower $ stringify k) (mconcat $ map fromList v)+ where f (k,v) =+ case v of+ [[Plain ils]] -> setMeta (T.toLower (stringify k)) $ MetaInlines ils+ _ -> setMeta (T.toLower (stringify k)) $ mconcat $ map fromList v adjustAuthors (Meta metamap) = Meta $ M.adjust splitAuthors "author"- $ M.adjust toPlain "date"- $ M.adjust toPlain "title" $ M.mapKeys (\k -> if k == "authors" then "author" else k) metamap- toPlain (MetaBlocks [Para xs]) = MetaInlines xs- toPlain x = x- splitAuthors (MetaBlocks [Para xs])- = MetaList $ map MetaInlines+ splitAuthors (MetaInlines xs) = MetaList $ map MetaInlines $ splitAuthors' xs splitAuthors x = x splitAuthors' = map normalizeSpaces .@@ -146,44 +149,99 @@ parseRST :: PandocMonad m => RSTParser m Pandoc parseRST = do+ standalone <- getOption readerStandalone optional blanklines -- skip blank lines at beginning of file- startPos <- getPosition- -- go through once just to get list of reference keys and notes- -- docMinusKeys is the raw document with blanks where the keys were...- let chunk = referenceKey- <|> anchorDef- <|> noteBlock- <|> citationBlock- <|> (snd <$> withRaw comment)- <|> headerBlock- <|> lineClump- docMinusKeys <- Sources <$>- manyTill (do pos <- getPosition- t <- chunk- return (pos, t)) eof- -- UGLY: we collapse source position information.- -- TODO: fix the parser to use the F monad instead of two passes- setInput docMinusKeys- setPosition startPos- st' <- getState- let reversedNotes = stateNotes st'- updateState $ \s -> s { stateNotes = reverse reversedNotes- , stateIdentifiers = mempty }- -- now parse it for real... blocks <- B.toList <$> parseBlocks citations <- sort . M.toList . stateCitations <$> getState citationItems <- mapM parseCitation citations let refBlock = [Div ("citations",[],[]) $ B.toList $ B.definitionList citationItems | not (null citationItems)]- standalone <- getOption readerStandalone state <- getState let meta = stateMeta state let (blocks', meta') = if standalone then titleTransform (blocks, meta) else (blocks, meta)+ let reversedNotes = stateNotes state+ updateState $ \s -> s { stateNotes = reverse reversedNotes }+ doc <- walkM resolveReferences =<<+ walkM resolveBlockSubstitutions+ (Pandoc meta' (blocks' ++ refBlock)) reportLogMessages- return $ Pandoc meta' (blocks' ++ refBlock)+ return doc +resolveBlockSubstitutions :: PandocMonad m => Block -> RSTParser m Block+resolveBlockSubstitutions x@(Para [Link _attr _ (s,_)])+ | Just ref <- T.stripPrefix "##SUBST##" s = do+ substTable <- stateSubstitutions <$> getState+ let key@(Key key') = toKey $ stripFirstAndLast ref+ case M.lookup key substTable of+ Nothing -> do+ pos <- getPosition+ logMessage $ ReferenceNotFound (tshow key') pos+ return x+ Just target -> case+ B.toList target of+ [bl] -> return bl+ bls -> return $ Div nullAttr bls+resolveBlockSubstitutions x = return x++resolveReferences :: PandocMonad m => Inline -> RSTParser m Inline+resolveReferences x@(Link _ ils (s,_))+ | Just ref <- T.stripPrefix "##REF##" s = do+ let isAnonKey (Key (T.uncons -> Just ('_',_))) = True+ isAnonKey _ = False+ state <- getState+ let keyTable = stateKeys state+ let anonKeys = sort $ filter isAnonKey $ M.keys keyTable+ key <- if ref == "_" -- anonymous key+ then+ case anonKeys of+ [] -> mzero -- TODO log?+ (k:_) -> return k+ else return $ toKey ref+ ((src,tit), attr) <- lookupKey [] key+ -- if anonymous link, remove key so it won't be used again+ when (isAnonKey key) $ updateState $ \st ->+ st{ stateKeys = M.delete key keyTable }+ return $ Link attr ils (src, tit)+ | Just ref <- T.stripPrefix "##NOTE##" s = do+ state <- getState+ let notes = stateNotes state+ case lookup ref notes of+ Nothing -> do+ pos <- getPosition+ logMessage $ ReferenceNotFound ref pos+ return x+ Just raw -> do+ -- We temporarily empty the note list while parsing the note,+ -- so that we don't get infinite loops with notes inside notes...+ -- Note references inside other notes are allowed in reST, but+ -- not yet in this implementation.+ updateState $ \st -> st{ stateNotes = [] }+ contents <- parseFromString' parseBlocks raw+ let newnotes = if ref == "*" || ref == "#" -- auto-numbered+ -- delete the note so the next auto-numbered note+ -- doesn't get the same contents:+ then deleteFirstsBy (==) notes [(ref,raw)]+ else notes+ updateState $ \st -> st{ stateNotes = newnotes }+ return $ Note (B.toList contents)+ | Just ref <- T.stripPrefix "##SUBST##" s = do+ substTable <- stateSubstitutions <$> getState+ let key@(Key key') = toKey $ stripFirstAndLast ref+ case M.lookup key substTable of+ Nothing -> do+ pos <- getPosition+ logMessage $ ReferenceNotFound (tshow key') pos+ return x+ Just target -> case+ B.toList target of+ [Para [t]] -> return t+ [Para xs] -> return $ Span nullAttr xs+ bls -> return $ Span nullAttr $ blocksToInlines bls+ | otherwise = return x+resolveReferences x = return x+ parseCitation :: PandocMonad m => (Text, Text) -> RSTParser m (Inlines, [Blocks]) parseCitation (ref, raw) = do@@ -203,6 +261,10 @@ block = choice [ codeBlock , blockQuote , fieldList+ , optionList+ , referenceKey+ , noteBlock+ , citationBlock , directive , anchor , comment@@ -226,7 +288,7 @@ guard $ indent >= minIndent char ':' name <- many1TillChar (noneOf "\n") (char ':')- (() <$ lookAhead newline) <|> skipMany1 spaceChar+ (void (lookAhead newline)) <|> skipMany1 spaceChar first <- anyLine rest <- option "" $ try $ do lookAhead (count indent (char ' ') >> spaceChar) indentedBlock@@ -240,7 +302,10 @@ term <- parseInlineFromText name contents <- parseFromString' parseBlocks raw optional blanklines- return (term, [contents])+ let defn = case B.toList contents of+ [Para ils] -> [B.plain $ B.fromList ils] -- see #7766+ _ -> [contents]+ return (term, defn) fieldList :: PandocMonad m => RSTParser m Blocks fieldList = try $ do@@ -250,6 +315,51 @@ [] -> return mempty items' -> return $ B.definitionList items' +optionList :: PandocMonad m => RSTParser m Blocks+optionList = B.definitionList <$> many1 optionListItem++optionListItem :: PandocMonad m => RSTParser m (Inlines, [Blocks])+optionListItem = try $ do+ opts <- snd <$> withRaw (do+ let anyOpt = shortOpt <|> longOpt <|> dosOpt+ anyOpt+ many $ try (char ',' <* many spaceChar *> anyOpt))+ -- at least two spaces+ rawfirst <- try (char ' ' *> many1 (char ' ') *> anyLineNewline)+ <|> try (mempty <$ skipMany spaceChar <* newline)+ bodyElements <- do+ raw <- option "" indentedBlock+ parseFromString' parseBlocks $ (rawfirst <> raw) <> "\n\n"+ optional blanklines+ pure (B.code opts, [bodyElements])++shortOpt :: PandocMonad m => RSTParser m ()+shortOpt = try $ do+ char '-'+ alphaNum+ optional $ try (optional (char ' ') *> optArg)++optArg :: PandocMonad m => RSTParser m ()+optArg = do+ c <- letter <|> char '<'+ if c == '<'+ then void $ manyTill (noneOf "<>") (char '>')+ else skipMany (alphaNum <|> char '_' <|> char '-')++longOpt :: PandocMonad m => RSTParser m ()+longOpt = try $ do+ char '-'+ char '-'+ alphaNum+ skipMany1 (alphaNum <|> char '-' <|> char '_')+ optional $ try (oneOf " =" *> optArg)++dosOpt :: PandocMonad m => RSTParser m ()+dosOpt = try $ do+ char '/'+ alphaNum <|> char '?'+ optional $ try (char ' ' *> optArg)+ -- -- line block --@@ -305,7 +415,10 @@ Just ind -> (headerTable, ind + 1) Nothing -> (headerTable ++ [DoubleHeader c], length headerTable + 1) setState (state { stateHeaderTable = headerTable' })- attr <- registerHeader nullAttr txt+ attr@(ident,_,_) <- registerHeader nullAttr txt+ let key = toKey (stringify txt)+ updateState $ \s ->+ s { stateKeys = M.insert key (("#" <> ident,""), nullAttr) $ stateKeys s } return $ B.headerWith attr level txt doubleHeader' :: PandocMonad m => RSTParser m (Inlines, Char)@@ -334,7 +447,10 @@ Just ind -> (headerTable, ind + 1) Nothing -> (headerTable ++ [SingleHeader c], length headerTable + 1) setState (state { stateHeaderTable = headerTable' })- attr <- registerHeader nullAttr txt+ attr@(ident,_,_) <- registerHeader nullAttr txt+ let key = toKey (stringify txt)+ updateState $ \s ->+ s { stateKeys = M.insert key (("#" <> ident,""), nullAttr) $ stateKeys s } return $ B.headerWith attr level txt singleHeader' :: PandocMonad m => RSTParser m (Inlines, Char)@@ -355,7 +471,7 @@ -- hrule block -- -hrule :: Monad m => ParserT Sources st m Blocks+hrule :: Monad m => ParsecT Sources st m Blocks hrule = try $ do chr <- oneOf underlineChars count 3 (char chr)@@ -370,7 +486,7 @@ -- read a line indented by a given string indentedLine :: (HasReaderOptions st, Monad m)- => Int -> ParserT Sources st m Text+ => Int -> ParsecT Sources st m Text indentedLine indents = try $ do lookAhead spaceChar gobbleAtMostSpaces indents@@ -379,7 +495,7 @@ -- one or more indented lines, possibly separated by blank lines. -- any amount of indentation will work. indentedBlock :: (HasReaderOptions st, Monad m)- => ParserT Sources st m Text+ => ParsecT Sources st m Text indentedBlock = try $ do indents <- length <$> lookAhead (many1 spaceChar) lns <- many1 $ try $ do b <- option "" blanklines@@ -388,20 +504,20 @@ optional blanklines return $ T.unlines lns -quotedBlock :: Monad m => ParserT Sources st m Text+quotedBlock :: Monad m => ParsecT Sources st m Text quotedBlock = try $ do quote <- lookAhead $ oneOf "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" lns <- many1 $ lookAhead (char quote) >> anyLine optional blanklines return $ T.unlines lns -codeBlockStart :: Monad m => ParserT Sources st m Char+codeBlockStart :: Monad m => ParsecT Sources st m Char codeBlockStart = string "::" >> blankline >> blankline -codeBlock :: Monad m => ParserT Sources ParserState m Blocks+codeBlock :: Monad m => ParsecT Sources ParserState m Blocks codeBlock = try $ codeBlockStart >> codeBlockBody -codeBlockBody :: Monad m => ParserT Sources ParserState m Blocks+codeBlockBody :: Monad m => ParsecT Sources ParserState m Blocks codeBlockBody = do lang <- stateRstHighlight <$> getState try $ B.codeBlockWith ("", maybeToList lang, []) . stripTrailingNewlines <$>@@ -417,14 +533,14 @@ return $ B.codeBlockWith ("", ["haskell","literate"], []) $ T.intercalate "\n" lns -latexCodeBlock :: Monad m => ParserT Sources st m [Text]+latexCodeBlock :: Monad m => ParsecT Sources st m [Text] latexCodeBlock = try $ do try (latexBlockLine "\\begin{code}") many1Till anyLine (try $ latexBlockLine "\\end{code}") where latexBlockLine s = skipMany spaceChar >> string s >> blankline -birdCodeBlock :: Monad m => ParserT Sources st m [Text]+birdCodeBlock :: Monad m => ParsecT Sources st m [Text] birdCodeBlock = filterSpace <$> many1 birdTrackLine where filterSpace lns = -- if (as is normal) there is always a space after >, drop it@@ -432,7 +548,7 @@ then map (T.drop 1) lns else lns -birdTrackLine :: Monad m => ParserT Sources st m Text+birdTrackLine :: Monad m => ParsecT Sources st m Text birdTrackLine = char '>' >> anyLine --@@ -509,7 +625,7 @@ definitionList = B.definitionList <$> many1 definitionListItem -- parses bullet list start and returns its length (inc. following whitespace)-bulletListStart :: Monad m => ParserT Sources st m Int+bulletListStart :: Monad m => ParsecT Sources st m Int bulletListStart = try $ do notFollowedBy' hrule -- because hrules start out just like lists marker <- oneOf bulletListMarkers@@ -556,7 +672,7 @@ listItem start = try $ do (markerLength, first) <- rawListItem start rest <- many (listContinuation markerLength)- skipMany1 blankline <|> () <$ lookAhead start+ skipMany1 blankline <|> void (lookAhead start) -- parsing with ListItemState forces markers at beginning of lines to -- count as list item markers, even if not separated by blank space. -- see definition of "endline"@@ -594,7 +710,7 @@ comment :: Monad m => RSTParser m Blocks comment = try $ do string ".."- skipMany1 spaceChar <|> (() <$ lookAhead newline)+ skipMany1 spaceChar <|> void (lookAhead newline) -- notFollowedBy' directiveLabel -- comment comes after directive so unnec. _ <- anyLine optional indentedBlock@@ -626,13 +742,18 @@ if fieldIndent == 0 then return [] else many $ rawFieldListItem fieldIndent- body <- option "" $ try $ blanklines >> indentedBlock+ let mbfile = trim <$> lookup "file" fields+ body <- case mbfile of+ Just f | label == "raw" -> do+ currentDir <- takeDirectory . sourceName <$> getPosition+ fromMaybe mempty <$> readFileFromDirs [currentDir] (T.unpack f)+ _ -> option "" $ try $ blanklines >> indentedBlock optional blanklines let body' = body <> "\n\n" name = trim $ fromMaybe "" (lookup "name" fields) classes = T.words $ maybe "" trim (lookup "class" fields) keyvals = [(k, trim v) | (k, v) <- fields, k /= "name", k /= "class"]- imgAttr cl = (name, classes ++ alignClasses, widthAttr ++ heightAttr)+ imgAttr cl = (name, classes, alignClasses, widthAttr ++ heightAttr) where alignClasses = T.words $ maybe "" trim (lookup cl fields) <> maybe "" (\x -> "align-" <> trim x)@@ -729,17 +850,25 @@ "figure" -> do (caption, legend) <- parseFromString' extractCaption body' let src = escapeURI $ trim top- return $ B.simpleFigureWith- (imgAttr "figclass") caption src "" <> legend+ let (imgident, imgcls, aligncls, imgkvs) = imgAttr "class"+ let (figclasskv, _) = partition ((== "figclass") . fst) keyvals+ let figcls = concatMap (T.words . snd) figclasskv+ let figattr = ("", figcls ++ aligncls, [])+ let capt = B.caption Nothing (B.plain caption <> legend)+ let alt = maybe caption (B.text . trim) (lookup "alt" fields)+ return $ B.figureWith figattr capt $+ B.plain (B.imageWith (imgident, imgcls, imgkvs) src "" alt) "image" -> do let src = escapeURI $ trim top let alt = B.str $ maybe "image" trim $ lookup "alt" fields- let attr = imgAttr "class"+ let attr = (ident, cls ++ align, dims) where+ (ident, cls, align, dims) = imgAttr "class" return $ B.para $ case lookup "target" fields of Just t -> B.link (escapeURI $ trim t) "" $ B.imageWith attr src "" alt Nothing -> B.imageWith attr src "" alt+ "bibliography" -> pure $ B.divWith ("refs",[],[]) mempty "class" -> do let attrs = (name, T.words (trim top), map (second trimr) fields) -- directive content or the first immediately following element@@ -783,7 +912,10 @@ let tspecs = zip aligns' widths return $ B.singleton $ Table attr (B.caption Nothing (B.plain title)) tspecs thead tbody tfoot- _ -> return mempty+ _ -> do+ pos <- getPosition+ logMessage $ SkippedContent body pos+ return mempty where -- only valid on the very first row of a table section rowLength (Row _ rb) = sum $ cellLength <$> rb@@ -871,14 +1003,8 @@ let res = parseCSV opts rawcsv' case (<>) <$> header' <*> res of Left e ->- throwError $ PandocParsecError "csv table" e+ throwError $ fromParsecError (toSources rawcsv') e Right rawrows -> do- let singleParaToPlain bs =- case B.toList bs of- [Para ils] -> B.fromList [Plain ils]- _ -> bs- let parseCell t = singleParaToPlain- <$> parseFromString' parseBlocks (t <> "\n\n") let parseRow = mapM parseCell rows <- mapM parseRow rawrows let (headerRow,bodyRows,numOfCols) =@@ -907,6 +1033,17 @@ [TableBody nullAttr 0 [] $ map toRow bodyRows] (TableFoot nullAttr []) +singleParaToPlain :: Blocks -> Blocks+singleParaToPlain bs =+ case B.toList bs of+ [Para ils] -> B.fromList [Plain ils]+ _ -> bs++parseCell :: PandocMonad m => Text -> RSTParser m Blocks+parseCell t = singleParaToPlain+ <$> parseFromString' parseBlocks (trim t <> "\n\n")++ -- TODO: -- - Only supports :format: fields with a single format for :raw: roles, -- change Text.Pandoc.Definition.Format to fix@@ -1043,27 +1180,24 @@ --- note block --- -noteBlock :: Monad m => RSTParser m Text+noteBlock :: Monad m => RSTParser m Blocks noteBlock = try $ do- (ref, raw, replacement) <- noteBlock' noteMarker+ (ref, raw) <- noteBlock' noteMarker updateState $ \s -> s { stateNotes = (ref, raw) : stateNotes s }- -- return blanks so line count isn't affected- return replacement+ return mempty -citationBlock :: Monad m => RSTParser m Text+citationBlock :: Monad m => RSTParser m Blocks citationBlock = try $ do- (ref, raw, replacement) <- noteBlock' citationMarker+ (ref, raw) <- noteBlock' citationMarker updateState $ \s -> s { stateCitations = M.insert ref raw (stateCitations s), stateKeys = M.insert (toKey ref) (("#" <> ref,""), ("",["citation"],[])) (stateKeys s) }- -- return blanks so line count isn't affected- return replacement+ return mempty noteBlock' :: Monad m- => RSTParser m Text -> RSTParser m (Text, Text, Text)+ => RSTParser m Text -> RSTParser m (Text, Text) noteBlock' marker = try $ do- startPos <- getPosition string ".." spaceChar >> skipMany spaceChar ref <- marker@@ -1071,10 +1205,8 @@ <|> (newline >> return "") blanks <- option "" blanklines rest <- option "" indentedBlock- endPos <- getPosition let raw = first <> "\n" <> blanks <> rest <> "\n"- let replacement = T.replicate (sourceLine endPos - sourceLine startPos) "\n"- return (ref, raw, replacement)+ return (ref, raw) citationMarker :: Monad m => RSTParser m Text citationMarker = do@@ -1106,7 +1238,7 @@ -- plus isolated (no two adjacent) internal hyphens, underscores, -- periods, colons and plus signs; no whitespace or other characters -- are allowed.-simpleReferenceName :: Monad m => ParserT Sources st m Text+simpleReferenceName :: Monad m => ParsecT Sources st m Text simpleReferenceName = do x <- alphaNum xs <- many $ alphaNum@@ -1116,16 +1248,13 @@ referenceName :: PandocMonad m => RSTParser m Text referenceName = quotedReferenceName <|> simpleReferenceName -referenceKey :: PandocMonad m => RSTParser m Text+referenceKey :: PandocMonad m => RSTParser m Blocks referenceKey = do- startPos <- getPosition choice [substKey, anonymousKey, regularKey] optional blanklines- endPos <- getPosition- -- return enough blanks to replace key- return $ T.replicate (sourceLine endPos - sourceLine startPos) "\n"+ return mempty -targetURI :: Monad m => ParserT Sources st m Text+targetURI :: Monad m => ParsecT Sources st m Text targetURI = do skipSpaces optional $ try $ newline >> notFollowedBy blankline@@ -1147,26 +1276,26 @@ (alt,ref) <- withRaw $ trimInlines . mconcat <$> enclosed (char '|') (char '|') inline res <- B.toList <$> directive'- il <- case res of+ bls <- case res of -- use alt unless :alt: attribute on image: [Para [Image attr [Str "image"] (src,tit)]] ->- return $ B.imageWith attr src tit alt+ return $ B.para $ B.imageWith attr src tit alt [Para [Link _ [Image attr [Str "image"] (src,tit)] (src',tit')]] ->- return $ B.link src' tit' (B.imageWith attr src tit alt)- [Para ils] -> return $ B.fromList ils- _ -> mzero+ return $ B.para $ B.link src' tit' (B.imageWith attr src tit alt)+ _ -> return $ B.fromList res let key = toKey $ stripFirstAndLast ref updateState $ \s -> s{ stateSubstitutions =- M.insert key il $ stateSubstitutions s }+ M.insert key bls $ stateSubstitutions s } -anonymousKey :: Monad m => RSTParser m ()+anonymousKey :: PandocMonad m => RSTParser m () anonymousKey = try $ do oneOfStrings [".. __:", "__"]+ skipMany1 spaceChar src <- targetURI -- we need to ensure that the keys are ordered by occurrence in -- the document. numKeys <- M.size . stateKeys <$> getState- let key = toKey $ "_" <> T.pack (show numKeys)+ let key = toKey $ "_" <> T.pack (printf "%04d" numKeys) updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $ stateKeys s } @@ -1201,19 +1330,14 @@ updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $ stateKeys s } -anchorDef :: PandocMonad m => RSTParser m Text-anchorDef = try $ do- (refs, raw) <- withRaw $ try (referenceNames <* blanklines)- forM_ refs $ \rawkey ->- updateState $ \s -> s { stateKeys =- M.insert (toKey rawkey) (("#" <> rawkey,""), nullAttr) $ stateKeys s }- -- keep this for 2nd round of parsing, where we'll add the divs (anchor)- return raw- anchor :: PandocMonad m => RSTParser m Blocks anchor = try $ do refs <- referenceNames blanklines+ forM_ refs $ \rawkey ->+ updateState $ \s -> s { stateKeys =+ M.insert (toKey rawkey) (("#" <> rawkey,""), nullAttr)+ (stateKeys s) } b <- block let addDiv ref = B.divWith (ref, [], []) let emptySpanWithId id' = Span (id',[],[]) []@@ -1229,16 +1353,6 @@ -- because it hides them from promoteHeader, see #4240 _ -> return $ foldr addDiv b refs -headerBlock :: PandocMonad m => RSTParser m Text-headerBlock = do- ((txt, _), raw) <- withRaw (doubleHeader' <|> singleHeader')- (ident,_,_) <- registerHeader nullAttr txt- let key = toKey (stringify txt)- updateState $ \s -> s { stateKeys = M.insert key (("#" <> ident,""), nullAttr)- $ stateKeys s }- return raw-- -- -- tables --@@ -1248,76 +1362,113 @@ -- support for them -- -- Simple tables TODO:--- - column spans -- - multiline support -- - ensure that rightmost column span does not need to reach end -- - require at least 2 columns -dashedLine :: Monad m => Char -> ParserT Sources st m (Int, Int)+dashedLine :: Monad m => Char -> ParsecT Sources st m (Int, Int) dashedLine ch = do dashes <- many1 (char ch) sp <- many (char ' ')- return (length dashes, length $ dashes ++ sp)+ return (length dashes, length sp) -simpleDashedLines :: Monad m => Char -> ParserT Sources st m [(Int,Int)]-simpleDashedLines ch = try $ many1 (dashedLine ch)+simpleDashedLines :: Monad m => Char -> ParsecT Sources st m [(Int,Int)]+simpleDashedLines ch = try $ do+ lines' <- many1 (dashedLine ch)+ skipMany spaceChar+ newline+ return $ addSpaces lines'+ where+ addSpaces [] = []+ addSpaces [(dashes, _)] = [(dashes, dashes)] -- Don't count trailing whitespaces+ addSpaces ((dashes, sp) : moreLines) =+ (dashes, dashes + sp) : addSpaces moreLines -- Parse a table row separator-simpleTableSep :: Monad m => Char -> RSTParser m Char-simpleTableSep ch = try $ simpleDashedLines ch >> newline+simpleTableSep :: Monad m => Char -> RSTParser m ()+simpleTableSep ch = void (simpleDashedLines ch) -- Parse a table footer-simpleTableFooter :: Monad m => RSTParser m Text-simpleTableFooter = try $ simpleTableSep '=' >> blanklines+simpleTableFooter :: Monad m => RSTParser m ()+simpleTableFooter = try $ simpleTableSep '=' >> void blanklines -- Parse a raw line and split it into chunks by indices.-simpleTableRawLine :: Monad m => [Int] -> RSTParser m [Text]-simpleTableRawLine indices = simpleTableSplitLine indices <$> anyLine+simpleTableRawLine :: Monad m => [Int] -> RSTParser m [(Text, ColSpan)]+simpleTableRawLine indices = do+ row <- rowWithOptionalColSpan -simpleTableRawLineWithEmptyCell :: Monad m => [Int] -> RSTParser m [Text]-simpleTableRawLineWithEmptyCell indices = try $ do+ case simpleTableSplitLine indices row of+ Just rowLine -> return rowLine+ Nothing -> Prelude.fail "col spans don't match"++simpleTableRawLineWithInitialEmptyCell :: Monad m => [Int] -> RSTParser m [(Text, ColSpan)]+simpleTableRawLineWithInitialEmptyCell indices = try $ do cs <- simpleTableRawLine indices let isEmptyCell = T.all (\c -> c == ' ' || c == '\t')- guard $ any isEmptyCell cs- return cs+ case cs of+ c:_ | isEmptyCell (fst c) -> return cs+ _ -> mzero -- Parse a table row and return a list of blocks (columns).-simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [Blocks]+simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [(Blocks, RowSpan, ColSpan)] simpleTableRow indices = do- notFollowedBy' simpleTableFooter+ notFollowedBy' (void blanklines <|> simpleTableFooter) firstLine <- simpleTableRawLine indices- conLines <- many $ simpleTableRawLineWithEmptyCell indices- let cols = map T.unlines . transpose $ firstLine : conLines +++ conLines <- many $ simpleTableRawLineWithInitialEmptyCell indices+ let cols = map T.unlines . transpose $ (map fst firstLine) : (map (map fst) conLines) ++ [replicate (length indices) "" | not (null conLines)]- mapM (parseFromString' parseBlocks) cols+ let rowParser = mapM parseCell cols+ fmap (\blocks -> zip3 blocks (repeat 1) (map snd firstLine)) rowParser -simpleTableSplitLine :: [Int] -> Text -> [Text]-simpleTableSplitLine indices line =- map trimr- $ tail $ splitTextByIndices (init indices) line+simpleTableSplitLine :: [Int] -> (Text, Maybe [Int]) -> Maybe [(Text, ColSpan)]+simpleTableSplitLine indices (line, maybeColspanIndices) =+ fmap (zip tableLines) columnSpans+ where+ splitTableLines lineIndices = map trimr $ drop 1 $ splitTextByIndices (init lineIndices) line+ (tableLines, columnSpans) = case maybeColspanIndices of+ Nothing -> (splitTableLines indices, Just $ repeat 1)+ Just colSpanIndices -> (splitTableLines colSpanIndices, colSpans indices colSpanIndices) simpleTableHeader :: PandocMonad m => Bool -- ^ Headerless table- -> RSTParser m ([Blocks], [Alignment], [Int])+ -> RSTParser m ([[(Blocks, RowSpan, ColSpan)]], [Alignment], [Int]) simpleTableHeader headless = try $ do optional blanklines+ dashes <- simpleDashedLines '='+ rawContent <- if headless- then return ""- else simpleTableSep '=' >> anyLine- dashes <- if headless- then simpleDashedLines '='- else simpleDashedLines '=' <|> simpleDashedLines '-'- newline- let lines' = map snd dashes- let indices = scanl (+) 0 lines'+ then return [("", Nothing)]+ else many1 $ notFollowedBy (simpleDashedLines '=') >> rowWithOptionalColSpan++ unless headless $ simpleTableSep '='++ let (lines', indices) = dashedLinesToLinesWithIndices dashes let aligns = replicate (length lines') AlignDefault let rawHeads = if headless then []- else simpleTableSplitLine indices rawContent- heads <- mapM ( parseFromString' (mconcat <$> many plain) . trim) rawHeads- return (heads, aligns, indices)+ else map (simpleTableSplitLine indices) rawContent + when (any isNothing rawHeads) $ Prelude.fail "col spans don't match"++ let justRawHeads = catMaybes rawHeads+ let rawHeads' = map fst <$> justRawHeads+ let columnSpans = map snd <$> justRawHeads+ heads <- mapM (mapM $ parseFromString' (mconcat <$> many plain) . trim) rawHeads'+ let headsWithSpans = zipWith3 zip3 heads singleRowSpans columnSpans+ return (headsWithSpans, aligns, indices)++rowWithOptionalColSpan :: Monad m+ => RSTParser m (Text, Maybe [Int])+rowWithOptionalColSpan = do+ line <- anyLine+ colSpanHyphens <- optionMaybe $ simpleDashedLines '-'++ let colSpan = fmap colSpanFromHyphens colSpanHyphens+ return (line, colSpan)+ where+ colSpanFromHyphens colSpanHyphens = snd $ dashedLinesToLinesWithIndices colSpanHyphens+ -- Parse a simple table. simpleTable :: PandocMonad m => Bool -- ^ Headerless table@@ -1325,7 +1476,7 @@ simpleTable headless = do let wrapIdFst (a, b, c) = (Identity a, b, c) wrapId = fmap Identity- tbl <- runIdentity <$> tableWith+ tbl <- runIdentity <$> tableWithSpans (wrapIdFst <$> simpleTableHeader headless) (wrapId <$> simpleTableRow) sep simpleTableFooter@@ -1353,14 +1504,14 @@ -- inline :: PandocMonad m => RSTParser m Inlines-inline = choice [ note -- can start with whitespace, so try before ws- , link- , strong- , emph- , code- , subst- , interpretedRole- , inlineContent ] <?> "inline"+inline =+ (note -- can start with whitespace, so try before ws+ <|> do notAfterString >>= guard+ (link <|> inlineAnchor <|> strong <|> emph)+ <|> code+ <|> subst+ <|> interpretedRole+ <|> inlineContent) <?> "inline" -- strings, spaces and other characters that can appear either by -- themselves or within inline markup@@ -1369,31 +1520,31 @@ , str , endline , smart- , hyphens , escapedChar , symbol ] <?> "inline content" parseInlineFromText :: PandocMonad m => Text -> RSTParser m Inlines parseInlineFromText = parseFromString' (trimInlines . mconcat <$> many inline) -hyphens :: Monad m => RSTParser m Inlines-hyphens = do- result <- many1Char (char '-')- optional endline- -- don't want to treat endline after hyphen or dash as a space- return $ B.str result--escapedChar :: Monad m => ParserT Sources st m Inlines+escapedChar :: Monad m => RSTParser m Inlines escapedChar = do c <- escaped anyChar- return $ if c == ' ' || c == '\n' || c == '\r'- -- '\ ' is null in RST- then mempty- else B.str $ T.singleton c+ if c == ' ' || c == '\n' || c == '\r'+ -- '\ ' is null in RST+ then return mempty+ else do+ unless (canPrecedeOpener c) updateLastStrPos+ return $ B.str $ T.singleton c +canPrecedeOpener :: Char -> Bool+canPrecedeOpener c =+ generalCategory c `elem`+ [OpenPunctuation, InitialQuote, FinalQuote, DashPunctuation, OtherSymbol]+ symbol :: Monad m => RSTParser m Inlines symbol = do- result <- oneOf specialChars- return $ B.str $ T.singleton result+ c <- oneOf specialChars+ unless (canPrecedeOpener c) updateLastStrPos+ return $ B.str $ T.singleton c -- parses inline code, between codeStart and codeEnd code :: Monad m => RSTParser m Inlines@@ -1439,6 +1590,7 @@ "superscript" -> return $ B.superscript $ treatAsText contents "sub" -> return $ B.subscript $ treatAsText contents "subscript" -> return $ B.subscript $ treatAsText contents+ "mark" -> return $ B.spanWith ("",["mark"],[]) $ treatAsText contents "emphasis" -> return $ B.emph $ treatAsText contents "strong" -> return $ B.strong $ treatAsText contents "rfc-reference" -> return $ rfcLink contents@@ -1453,7 +1605,10 @@ "code" -> return $ B.codeWith attr contents "span" -> return $ B.spanWith attr $ treatAsText contents "raw" -> return $ B.rawInline (fromMaybe "" fmt) contents- custom -> do+ custom+ | Just citeType <- T.stripPrefix "cite" custom+ -> cite citeType contents+ | otherwise -> do customRoles <- stateRstCustomRoles <$> getState case M.lookup custom customRoles of Just (newRole, newFmt, newAttr) ->@@ -1474,8 +1629,45 @@ removeSpace (x:xs) = x : map headSpace xs removeSpace [] = [] +cite :: PandocMonad m => Text -> Text -> RSTParser m Inlines+cite citeType rawcite = do+ let citations =+ case map parseCite (T.splitOn "," rawcite) of+ (c:cs)+ | citeType == ":t" || citeType == ":ct"+ -> c{ citationMode = AuthorInText } : cs+ | citeType == ":year" || citeType == ":yearpar"+ -> c{ citationMode = SuppressAuthor } : cs+ cs -> cs+ pure $ B.cite citations (B.str rawcite)++parseCite :: Text -> Citation+parseCite t =+ let (_, pref, suff, ident) = T.foldl go (ParseStart, "", "", "") t+ in Citation{citationId = ident+ ,citationPrefix = B.toList $ B.text pref+ ,citationSuffix = B.toList $ B.text suff+ ,citationMode = NormalCitation+ ,citationNoteNum = 0+ ,citationHash = 0}+ where+ go (ParseStart, p, s, i) '{' = (ParsePrefix, p, s, i)+ go (ParseStart, p, s, i) c = (ParseId, p, s, T.snoc i c)+ go (ParsePrefix, p, s, i) '}' = (ParseId, p, s, i)+ go (ParsePrefix, p, s, i) c = (ParsePrefix, T.snoc p c, s, i)+ go (ParseId, p, s, i) '{' = (ParseSuffix, p, s, i)+ go (ParseId, p, s, i) c = (ParseId, p, s, T.snoc i c)+ go (ParseSuffix, p, s, i) '}' = (ParseSuffix, p, s, i)+ go (ParseSuffix, p, s, i) c = (ParseSuffix, p, T.snoc s c, i)++data ParseCiteState = ParseStart | ParsePrefix | ParseSuffix | ParseId+ deriving (Show)++-- single words consisting of alphanumerics plus isolated (no two adjacent)+-- internal hyphens, underscores, periods, colons and plus signs;+-- no whitespace or other characters are allowed roleName :: PandocMonad m => RSTParser m Text-roleName = many1Char (letter <|> char '-')+roleName = many1Char (alphaNum <|> try (oneOf "-_.:+" <* lookAhead alphaNum)) roleMarker :: PandocMonad m => RSTParser m Text roleMarker = char ':' *> roleName <* char ':'@@ -1500,7 +1692,7 @@ <|> (char '\\' >> ((\c -> ['\\',c]) <$> noneOf "\n")) <|> (string "\n" <* notFollowedBy blankline) <|> try (string "`" <*- notFollowedBy (() <$ roleMarker) <*+ notFollowedBy (void roleMarker) <* lookAhead (satisfy isAlphaNum)) ) char '`'@@ -1539,48 +1731,44 @@ char '`' notFollowedBy (char '`') -- `` marks start of inline code label' <- trimInlines . mconcat <$>- manyTill (notFollowedBy (char '`') >> inlineContent) (char '<')- src <- trim <$> manyTillChar (noneOf ">\n") (char '>')+ manyTill (notFollowedBy (char '`') >> inlineContent) (char '<')+ src <- trim . T.pack . filter (/= '\n') <$> -- see #10279+ manyTill (noneOf ">\n" <|> (char '\n' <* notFollowedBy blankline))+ (char '>') skipSpaces string "`_" optional $ char '_' -- anonymous form+ let src' | isURI src = escapeURI src+ | otherwise =+ case T.unsnoc src of+ Just (xs, '_') -> "##REF##" <> xs+ _ -> src let label'' = if label' == mempty then B.str src else label'- -- `link <google_>` is a reference link to _google!- ((src',tit),attr) <-- if isURI src- then return ((src, ""), nullAttr)- else- case T.unsnoc src of- Just (xs, '_') -> lookupKey [] (toKey xs)- _ -> return ((src, ""), nullAttr)- return $ B.linkWith attr (escapeURI src') tit label''+ let key = toKey $ stringify label'+ unless (key == Key mempty) $ do+ updateState $ \s -> s{+ stateKeys = M.insert key ((src',""), nullAttr) $ stateKeys s }+ return $ B.linkWith nullAttr src' "" label'' citationName :: PandocMonad m => RSTParser m Text citationName = do raw <- citationMarker return $ "[" <> raw <> "]" +-- We store the reference link label as the link target,+-- preceded by '##REF##'. This is replaced after the AST+-- has been built by the resolved reference. referenceLink :: PandocMonad m => RSTParser m Inlines referenceLink = try $ do ref <- (referenceName <|> citationName) <* char '_'- let label' = B.text ref- let isAnonKey (Key (T.uncons -> Just ('_',_))) = True- isAnonKey _ = False- state <- getState- let keyTable = stateKeys state- key <- option (toKey ref) $- do char '_'- let anonKeys = sort $ filter isAnonKey $ M.keys keyTable- case anonKeys of- [] -> mzero- (k:_) -> return k- ((src,tit), attr) <- lookupKey [] key- -- if anonymous link, remove key so it won't be used again- when (isAnonKey key) $ updateState $ \s ->- s{ stateKeys = M.delete key keyTable }- return $ B.linkWith attr src tit label'+ isAnonymous <- (True <$ char '_') <|> pure False+ eof <|> notFollowedBy alphaNum+ let ref' = if isAnonymous+ then "_"+ else ref+ pure $ B.linkWith nullAttr ("##REF##" <> ref') "" (B.text ref) -- We keep a list of oldkeys so we can detect lookup loops. lookupKey :: PandocMonad m@@ -1600,6 +1788,10 @@ let newkey = toKey rawkey if newkey `elem` oldkeys then do+ -- TODO the pos is not going to be accurate+ -- because we're calling this after the AST is+ -- constructed. Probably good to remove that+ -- parameter form CircularReference at some point. logMessage $ CircularReference rawkey pos return (("",""),nullAttr) else lookupKey (key:oldkeys) newkey@@ -1621,42 +1813,64 @@ subst :: PandocMonad m => RSTParser m Inlines subst = try $ do (_,ref) <- withRaw $ enclosed (char '|') (char '|') inline- state <- getState- let substTable = stateSubstitutions state- let key = toKey $ stripFirstAndLast ref- case M.lookup key substTable of- Nothing -> do- pos <- getPosition- logMessage $ ReferenceNotFound (tshow key) pos- return mempty- Just target -> return target+ let substlink = B.linkWith nullAttr ("##SUBST##" <> ref) "" (B.text ref)+ reflink <- option False (True <$ char '_')+ if reflink+ then do+ let linkref = T.drop 1 $ T.dropEnd 1 ref+ return $ B.linkWith nullAttr ("##REF##" <> linkref) "" substlink+ else return substlink note :: PandocMonad m => RSTParser m Inlines note = try $ do optional whitespace ref <- noteMarker char '_'- state <- getState- let notes = stateNotes state- case lookup ref notes of- Nothing -> do- pos <- getPosition- logMessage $ ReferenceNotFound ref pos- return mempty- Just raw -> do- -- We temporarily empty the note list while parsing the note,- -- so that we don't get infinite loops with notes inside notes...- -- Note references inside other notes are allowed in reST, but- -- not yet in this implementation.- updateState $ \st -> st{ stateNotes = [] }- contents <- parseFromString' parseBlocks raw- let newnotes = if ref == "*" || ref == "#" -- auto-numbered- -- delete the note so the next auto-numbered note- -- doesn't get the same contents:- then deleteFirstsBy (==) notes [(ref,raw)]- else notes- updateState $ \st -> st{ stateNotes = newnotes }- return $ B.note contents+ pure $ B.linkWith nullAttr ("##NOTE##" <> ref) "" (B.text ref) smart :: PandocMonad m => RSTParser m Inlines smart = smartPunctuation inline++inlineAnchor :: PandocMonad m => RSTParser m Inlines+inlineAnchor = try $ do+ char '_'+ name <- quotedReferenceName <|> simpleReferenceName+ let ident = textToIdentifier mempty name+ updateState $ \s ->+ s{ stateKeys = M.insert (toKey name) (("#" <> ident, ""), nullAttr)+ (stateKeys s) }+ pure $ B.spanWith (ident,[],[]) (B.text name)++dashedLinesToLinesWithIndices :: [(Int, Int)] -> ([Int], [Int])+dashedLinesToLinesWithIndices dashes =+ let lines' = map snd dashes+ indices = scanl (+) 0 lines'+ in (lines', indices)++-- | Determines column spans by appying indices of a table border with column span indices.+--+-- The indices need to align.+colSpans :: [Int] -> [Int] -> Maybe [ColSpan]+colSpans [] [] = Just []+colSpans [] _ = Nothing+colSpans _ [] = Nothing+colSpans (index : indices) colSpanIndices@(colIndex : colSpanIndicesTail)+ | index /= colIndex = colSpans indices colSpanIndices+ | otherwise =+ -- For a matching index start counting the column spans.+ let (spanCount, remainingIndices, remainingColSpanindices) = colSpanCount indices colSpanIndicesTail 1+ in (:) spanCount <$> colSpans remainingIndices remainingColSpanindices++-- | Counts column spans by consuming all non-matching indices until a matching one is encountered.+--+-- If the indices match, the end of a column span has been encountered and the+-- column count can be returned. Otherwise, if the indices don't match, add to+-- the span count until a matching index is found.+colSpanCount :: [Int] -> [Int] -> ColSpan -> (ColSpan, [Int], [Int])+colSpanCount [] colSpanIndices spanCount = (spanCount, [], colSpanIndices)+colSpanCount _ [] spanCount = (spanCount, [], [])+colSpanCount indices@(index : indicesTail) colSpanIndices@(colIndex : colSpanIndicesTail) spanCount+ | index == colIndex = case colSpanIndicesTail of+ [] -> (spanCount, indicesTail, colSpanIndicesTail)+ _ -> (spanCount, indices, colSpanIndices)+ | otherwise = colSpanCount indicesTail colSpanIndices $ spanCount + 1
@@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Readers.RTF- Copyright : Copyright (C) 2021-2022 John MacFarlane+ Copyright : Copyright (C) 2021-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane (<jgm@berkeley.edu>)@@ -19,7 +19,8 @@ import qualified Data.Sequence as Seq import Control.Monad import Control.Monad.Except (throwError)-import Data.List (find, foldl')+import Crypto.Hash (hashWith, SHA1(SHA1))+import qualified Data.List as L import Data.Word (Word8, Word16) import Data.Default import Data.Text (Text)@@ -27,14 +28,14 @@ import qualified Data.Text.Read as TR import Text.Pandoc.Builder (Blocks, Inlines) import qualified Text.Pandoc.Builder as B-import Text.Pandoc.Class.PandocMonad (PandocMonad (..), insertMedia)+import Text.Pandoc.Class (PandocMonad (..), insertMedia, report) import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Parsing+import Text.Pandoc.Logging (LogMessage(UnsupportedCodePage)) import Text.Pandoc.Shared (tshow) import Data.Char (isAlphaNum, chr, isAscii, isLetter, isSpace, ord) import qualified Data.ByteString.Lazy as BL-import Data.Digest.Pure.SHA (sha1, showDigest) import Data.Maybe (mapMaybe, fromMaybe) import Safe (lastMay, initSafe, headDef) -- import Debug.Trace@@ -184,7 +185,7 @@ , gInTable = False } -type RTFParser m = ParserT Sources RTFState m+type RTFParser m = ParsecT Sources RTFState m data ListType = Bullet | Ordered ListAttributes deriving (Show, Eq)@@ -217,7 +218,7 @@ | ControlSymbol !Char | UnformattedText !Text | BinData !BL.ByteString- | HexVal !Word8+ | HexVals [Word8] | Grouped [Tok] deriving (Show, Eq) @@ -229,7 +230,7 @@ controlThing = do char '\\' *> ( controlWord- <|> (HexVal <$> hexVal)+ <|> (HexVals <$> many1 hexVal) <|> (ControlSymbol <$> anyChar) ) controlWord = do name <- letterSequence@@ -251,7 +252,7 @@ hyph <- option False $ True <$ char '-' rest <- many digit if null rest- then return $! Nothing+ then return Nothing else do let pstr = T.pack rest case TR.decimal pstr of@@ -259,7 +260,7 @@ return $! Just $! if hyph then (-1) * i else i- _ -> return $! Nothing+ _ -> return Nothing hexVal = do char '\'' x <- hexDigit@@ -304,6 +305,26 @@ [] -> [] (x:xs) -> f x : xs } +-- | @\\plain@ resets character formatting to default values. Unlike a+-- full reset to 'def', it must leave paragraph-level properties (such as+-- whether we are inside a table, the list level, or the outline level)+-- intact, as well as contextual properties like the current hyperlink or+-- anchor. Resetting these caused tables to be parsed as deeply nested+-- structures when cell paragraphs used @\\plain@ after @\\intbl@.+resetCharProps :: Properties -> Properties+resetCharProps g =+ g{ gBold = False+ , gItalic = False+ , gCaps = False+ , gDeleted = False+ , gSub = False+ , gSuper = False+ , gSmallCaps = False+ , gUnderline = False+ , gFontFamily = Nothing+ , gHidden = False+ }+ addFormatting :: (Properties, Text) -> Inlines addFormatting (_, "\n") = B.linebreak addFormatting (props, _) | gHidden props = mempty@@ -423,14 +444,27 @@ processTok bs (Tok pos tok') = do setPosition pos case tok' of- HexVal{} -> return ()+ HexVals{} -> return () UnformattedText{} -> return () _ -> updateState $ \s -> s{ sEatChars = 0 } case tok' of- Grouped (Tok _ (ControlSymbol '*') : toks) ->- bs <$ (do oldTextContent <- sTextContent <$> getState- processTok mempty (Tok pos (Grouped toks))- updateState $ \st -> st{ sTextContent = oldTextContent })+ Grouped (Tok _ (ControlSymbol '*') : toks@(firsttok:_)) ->+ case firsttok of+ Tok _ (ControlWord "shppict" _) -> inGroup (foldM processTok bs toks)+ Tok _ (ControlWord "shpinst" _) -> inGroup (foldM processTok bs toks)+ _ -> bs <$ (do oldTextContent <- sTextContent <$> getState+ processTok mempty (Tok pos (Grouped toks))+ updateState $ \st -> st{ sTextContent = oldTextContent })+ Grouped (Tok _ (ControlWord "shp" _) : toks) ->+ inGroup (foldM processTok bs toks)+ Grouped [ Tok _ (ControlWord "sp" _)+ , Tok _ (Grouped [Tok _ (ControlWord "sn" _),+ Tok _ (UnformattedText sn)])+ , Tok _ (Grouped (Tok _ (ControlWord "sv" _) : svtoks))+ ] ->+ case sn of+ "pib" -> inGroup (foldM processTok bs svtoks)+ _ -> pure bs Grouped (Tok _ (ControlWord "fonttbl" _) : toks) -> inGroup $ do updateState $ \s -> s{ sFontTable = processFontTable toks } pure bs@@ -498,19 +532,22 @@ addText (T.drop n t) | otherwise -> do updateState $ \s -> s{ sEatChars = n - T.length t }- HexVal n -> bs <$ do+ HexVals ws -> bs <$ do eatChars <- sEatChars <$> getState- if eatChars == 0- then do- charset <- sCharSet <$> getState- case charset of- ANSI -> addText (T.singleton $ ansiToChar n)- Mac -> addText (T.singleton $ macToChar n)- Pc -> addText (T.singleton $ pcToChar n)- Pca -> addText (T.singleton $ pcaToChar n)- else updateState $ \s -> s{ sEatChars = eatChars - 1 }+ let ws' = drop eatChars ws+ updateState $ \s -> s{ sEatChars = if null ws'+ then eatChars - length ws+ else 0 }+ charset <- sCharSet <$> getState+ case charset of+ ANSI -> addText $ T.pack $ map defaultAnsiWordToChar ws'+ Mac -> addText $ T.pack $ map macToChar ws'+ Pc -> addText $ T.pack $ map pcToChar ws'+ Pca -> addText $ T.pack $ map pcaToChar ws' ControlWord "ansi" _ -> bs <$ updateState (\s -> s{ sCharSet = ANSI })+ ControlWord "ansicpg" (Just cpg) | cpg /= 1252 -> bs <$+ report (UnsupportedCodePage cpg) ControlWord "mac" _ -> bs <$ updateState (\s -> s{ sCharSet = Mac }) ControlWord "pc" _ -> bs <$@@ -529,9 +566,8 @@ ControlSymbol '~' -> bs <$ addText "\x00a0" ControlSymbol '-' -> bs <$ addText "\x00ad" ControlSymbol '_' -> bs <$ addText "\x2011"- ControlWord "trowd" _ -> bs <$ do -- add new row- updateState $ \s -> s{ sTableRows = TableRow [] : sTableRows s- , sCurrentCell = mempty }+ ControlWord "trowd" _ -> bs <$ beginTableRow -- begin new row+ ControlWord "row" _ -> bs <$ beginTableRow -- end current row ControlWord "cell" _ -> bs <$ do new <- emitBlocks mempty curCell <- (<> new) . sCurrentCell <$> getState@@ -541,8 +577,10 @@ TableRow (curCell : cs) : rs [] -> [TableRow [curCell]] -- shouldn't happen , sCurrentCell = mempty }- ControlWord "intbl" _ -> bs <$ modifyGroup (\g -> g{ gInTable = True })- ControlWord "plain" _ -> bs <$ modifyGroup (const def)+ ControlWord "intbl" _ -> do+ ls <- closeLists 0 -- see #11364+ ((ls <>) <$> emitBlocks bs) <* modifyGroup (\g -> g{ gInTable = True })+ ControlWord "plain" _ -> bs <$ modifyGroup resetCharProps ControlWord "lquote" _ -> bs <$ addText "\x2018" ControlWord "rquote" _ -> bs <$ addText "\x2019" ControlWord "ldblquote" _ -> bs <$ addText "\x201C"@@ -609,9 +647,10 @@ modifyGroup (\g -> g{ gUnderline = boolParam mbp }) ControlWord "ulnone" _ -> bs <$ modifyGroup (\g -> g{ gUnderline = False })- ControlWord "pard" _ -> bs <$ do+ ControlWord "pard" _ -> do+ newbs <- emitBlocks bs modifyGroup (const def)- getStyleFormatting 0 >>= foldM processTok bs+ getStyleFormatting 0 >>= foldM processTok newbs ControlWord "par" _ -> emitBlocks bs _ -> pure bs @@ -653,6 +692,19 @@ closeLists lvl _ -> pure mempty +-- Begin a new table row. Both @\\trowd@ (which sets row defaults) and+-- @\\row@ (which ends a row) start a fresh row to be filled by subsequent+-- @\\cell@s. We only push a new empty row when the current one already has+-- cells, so that documents repeating @\\trowd@ after @\\row@ (or omitting+-- @\\trowd@ between rows) both produce the same flat structure.+beginTableRow :: PandocMonad m => RTFParser m ()+beginTableRow =+ updateState $ \s ->+ s{ sTableRows = case sTableRows s of+ TableRow [] : _ -> sTableRows s+ rs -> TableRow [] : rs+ , sCurrentCell = mempty }+ closeTable :: PandocMonad m => RTFParser m Blocks closeTable = do rawrows <- sTableRows <$> getState@@ -660,10 +712,13 @@ then return mempty else do let getCells (TableRow cs) = reverse cs- let rows = map getCells . reverse $ rawrows+ -- drop empty rows produced by row terminators+ let rows = filter (not . null) . map getCells . reverse $ rawrows updateState $ \s -> s{ sCurrentCell = mempty , sTableRows = [] }- return $ B.simpleTable [] rows+ if null rows+ then return mempty+ else return $ B.simpleTable [] rows closeContainers :: PandocMonad m => RTFParser m Blocks closeContainers = do@@ -766,27 +821,48 @@ -- {\field{\*\fldinst{HYPERLINK "http://pandoc.org"}}{\fldrslt foo}} handleField :: PandocMonad m => Blocks -> [Tok] -> RTFParser m Blocks-handleField bs- (Tok _- (Grouped- (Tok _ (ControlSymbol '*')- :Tok _ (ControlWord "fldinst" Nothing)- :Tok _ (Grouped (Tok _ (UnformattedText insttext):rest))- :_))- :linktoks)- | Just linkdest <- getHyperlink insttext- = do let linkdest' = case rest of- (Tok _ (ControlSymbol '\\')- : Tok _ (UnformattedText t)- : _) | Just bkmrk <- T.stripPrefix "l" t- -> "#" <> unquote bkmrk- _ -> linkdest- modifyGroup $ \g -> g{ gHyperlink = Just linkdest' }- result <- foldM processTok bs linktoks- modifyGroup $ \g -> g{ gHyperlink = Nothing }- return result-handleField bs _ = pure bs+handleField bs ts = do+ let isFieldMod (Tok _ (ControlWord w _)) =+ w `elem` ["flddirty", "fldedit", "fldlock", "fldpriv"]+ isFieldMod _ = False + let instructionTokens (Tok _ (Grouped toks)) = Just toks+ instructionTokens unformattedTok@(Tok _ (UnformattedText _)) = Just [unformattedTok]+ instructionTokens _ = Nothing+ case dropWhile isFieldMod ts of+ [Tok _ (Grouped+ (Tok _ (ControlSymbol '*')+ :Tok _ (ControlWord "fldinst" Nothing)+ :instrtoks+ :_)),+ Tok _ (Grouped+ (Tok _ (ControlWord "fldrslt" Nothing)+ :resulttoks))] -> do+ case instructionTokens instrtoks of+ Nothing -> pure bs+ Just instrtoks' ->+ case getHyperlink instrtoks' of+ Just linkdest -> do+ modifyGroup $ \g -> g{ gHyperlink = Just linkdest }+ result <- foldM processTok bs resulttoks+ modifyGroup $ \g -> g{ gHyperlink = Nothing }+ return result+ Nothing -> foldM processTok bs resulttoks+ _ -> pure bs++getHyperlink :: [Tok] -> Maybe Text+getHyperlink [] = Nothing+getHyperlink (Tok _ (UnformattedText w) : rest)+ | Just w' <- unquote <$> T.stripPrefix "HYPERLINK" (T.strip w)+ = if T.null w'+ then case rest of+ (Tok _ (ControlSymbol '\\') : Tok _ (UnformattedText b) : _)+ | Just bkmrk <- unquote <$> T.stripPrefix "l " (T.strip b)+ -> Just $ "#" <> bkmrk+ _ -> Just mempty+ else Just w'+getHyperlink (_:ts) = getHyperlink ts+ unquote :: Text -> Text unquote = T.dropWhile (=='"') . T.dropWhileEnd (=='"') . T.strip @@ -863,7 +939,7 @@ _ -> mempty let isBasedOn (Tok _ (ControlWord "sbasedon" (Just _))) = True isBasedOn _ = False- let styBasedOn = case find isBasedOn toks of+ let styBasedOn = case L.find isBasedOn toks of Just (Tok _ (ControlWord "sbasedon" (Just i))) -> Just i _ -> Nothing let isStyleControl (Tok _ (ControlWord x _)) =@@ -888,7 +964,7 @@ handlePict :: PandocMonad m => [Tok] -> RTFParser m () handlePict toks = do- let pict = foldl' getPictData def toks+ let pict = L.foldl' getPictData def toks let altText = "image" let bytes = if picBinary pict@@ -902,7 +978,7 @@ Nothing -> (Nothing, "") case mimetype of Just mt -> do- let pictname = showDigest (sha1 bytes) <> ext+ let pictname = show (hashWith SHA1 $ BL.toStrict bytes) <> ext insertMedia pictname (Just mt) bytes modifyGroup $ \g -> g{ gImage = Just pict{ picName = T.pack pictname, picBytes = bytes } }@@ -926,14 +1002,8 @@ _ -> pict -getHyperlink :: Text -> Maybe Text-getHyperlink t =- case T.stripPrefix "HYPERLINK" (T.strip t) of- Nothing -> Nothing- Just rest -> Just $ unquote rest- processFontTable :: [Tok] -> FontTable-processFontTable = snd . foldl' go (0, mempty)+processFontTable = snd . L.foldl' go (0, mempty) where go (fontnum, tbl) (Tok _ tok') = case tok' of@@ -946,42 +1016,41 @@ (ControlWord "fdecor" _) -> (fontnum, IntMap.insert fontnum Decor tbl) (ControlWord "ftech" _) -> (fontnum, IntMap.insert fontnum Tech tbl) (ControlWord "fbidi" _) -> (fontnum, IntMap.insert fontnum Bidi tbl)- (Grouped ts) -> foldl' go (fontnum, tbl) ts+ (Grouped ts) -> L.foldl' go (fontnum, tbl) ts _ -> (fontnum, tbl) --ansiToChar :: Word8 -> Char-ansiToChar i = chr $+defaultAnsiWordToChar :: Word8 -> Char+defaultAnsiWordToChar i = case i of- 128 -> 8364- 130 -> 8218- 131 -> 402- 132 -> 8222- 133 -> 8230- 134 -> 8224- 135 -> 8225- 136 -> 710- 137 -> 8240- 138 -> 352- 139 -> 8249- 140 -> 338- 142 -> 381- 145 -> 8216- 146 -> 8217- 147 -> 8220- 148 -> 8221- 149 -> 8226- 150 -> 8211- 151 -> 8212- 152 -> 732- 153 -> 8482- 154 -> 353- 155 -> 8250- 156 -> 339- 158 -> 382- 159 -> 376- 173 -> 0xAD- _ -> fromIntegral i+ 128 -> '\8364'+ 130 -> '\8218'+ 131 -> '\402'+ 132 -> '\8222'+ 133 -> '\8230'+ 134 -> '\8224'+ 135 -> '\8225'+ 136 -> '\710'+ 137 -> '\8240'+ 138 -> '\352'+ 139 -> '\8249'+ 140 -> '\338'+ 142 -> '\381'+ 145 -> '\8216'+ 146 -> '\8217'+ 147 -> '\8220'+ 148 -> '\8221'+ 149 -> '\8226'+ 150 -> '\8211'+ 151 -> '\8212'+ 152 -> '\732'+ 153 -> '\8482'+ 154 -> '\353'+ 155 -> '\8250'+ 156 -> '\339'+ 158 -> '\382'+ 159 -> '\376'+ 173 -> '\xAD'+ _ -> chr (fromIntegral i) macToChar :: Word8 -> Char macToChar i = chr $
@@ -2,6 +2,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeFamilies #-} {- | Module : Text.Pandoc.Readers.Roff Copyright : Copyright (C) 2018-2020 Yan Pashkovsky and John MacFarlane@@ -29,11 +30,11 @@ where import Safe (lastDef)-import Control.Monad (void, mzero, mplus, guard)+import Control.Monad (void, guard) import Control.Monad.Except (throwError) import Text.Pandoc.Class.PandocMonad (getResourcePath, readFileFromDirs, PandocMonad(..), report)-import Data.Char (isLower, toLower, toUpper, chr, isAscii, isAlphaNum)+import Data.Char (isLower, toLower, toUpper, isAlphaNum) import Data.Default (Default) import qualified Data.Map as M import Data.List (intercalate)@@ -42,10 +43,9 @@ import Text.Pandoc.Options import Text.Pandoc.Parsing import Text.Pandoc.Shared (safeRead)-import Text.Pandoc.RoffChar (characterCodes, combiningAccents)+import Text.Pandoc.Readers.Roff.Escape import qualified Data.Sequence as Seq import qualified Data.Foldable as Foldable-import qualified Data.Text.Normalize as Normalize -- import Debug.Trace (traceShowId) @@ -65,6 +65,59 @@ | MacroArg Int deriving Show +instance RoffLikeLexer RoffTokens where+ -- The token stream is a list of 'LinePart's+ type Token RoffTokens = [LinePart]+ type State RoffTokens = RoffState+ emit t = [RoffStr t]+ expandString = try $ do+ pos <- getPosition+ char '\\'+ char '*'+ cs <- escapeArg <|> countChar 1 anyChar+ s <- linePartsToText <$> resolveText cs pos+ addToInput s+ escString = try $ do+ pos <- getPosition+ (do cs <- escapeArg <|> countChar 1 anyChar+ resolveText cs pos)+ <|> mempty <$ char 'S'+ backslash = do+ char '\\'+ mode <- roffMode <$> getState+ case mode of+ -- experimentally, it seems you don't always need to double+ -- the backslash in macro defs. It's essential with \\$1,+ -- but not with \\f[I]. So we make the second one optional.+ CopyMode -> optional $ char '\\'+ NormalMode -> return ()+ checkDefined name = do+ macros <- customMacros <$> getState+ case M.lookup name macros of+ Just _ -> return [RoffStr "1"]+ Nothing -> return [RoffStr "0"]+ -- \E is ignored in copy mode+ escE = do+ mode <- roffMode <$> getState+ case mode of+ CopyMode -> return mempty+ NormalMode -> return [RoffStr "\\"]+ escFont = do+ font <- escapeArg <|> countChar 1 alphaNum+ font' <- if T.null font || font == "P"+ then prevFont <$> getState+ else return $ foldr processFontLetter defaultFontSpec $ T.unpack font+ updateState $ \st -> st{ prevFont = currentFont st+ , currentFont = font' }+ return [Font font']+ where+ processFontLetter c fs+ | isLower c = processFontLetter (toUpper c) fs+ processFontLetter 'B' fs = fs{ fontBold = True }+ processFontLetter 'I' fs = fs{ fontItalic = True }+ processFontLetter 'C' fs = fs{ fontMonospace = True }+ processFontLetter _ fs = fs -- do nothing+ type Arg = [LinePart] type TableOption = (T.Text, T.Text)@@ -121,210 +174,18 @@ , afterConditional = False } -type RoffLexer m = ParserT Sources RoffState m+type RoffLexer m = ParsecT Sources RoffState m -- -- Lexer: T.Text -> RoffToken -- -eofline :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s u m ()+eofline :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s u m () eofline = void newline <|> eof <|> () <$ lookAhead (string "\\}") -spacetab :: (Stream s m Char, UpdateSourcePos s Char) => ParserT s u m Char+spacetab :: (Stream s m Char, UpdateSourcePos s Char) => ParsecT s u m Char spacetab = char ' ' <|> char '\t' -characterCodeMap :: M.Map T.Text Char-characterCodeMap =- M.fromList $ map (\(x,y) -> (y,x)) characterCodes--combiningAccentsMap :: M.Map T.Text Char-combiningAccentsMap =- M.fromList $ map (\(x,y) -> (y,x)) combiningAccents--escape :: PandocMonad m => RoffLexer m [LinePart]-escape = try $ do- backslash- escapeGlyph <|> escapeNormal--escapeGlyph :: PandocMonad m => RoffLexer m [LinePart]-escapeGlyph = do- c <- lookAhead (oneOf ['[','('])- escapeArg >>= resolveGlyph c--resolveGlyph :: PandocMonad m => Char -> T.Text -> RoffLexer m [LinePart]-resolveGlyph delimChar glyph = do- let cs = T.replace "_u" " u" glyph -- unicode glyphs separated by _- (case T.words cs of- [] -> mzero- [s] -> case M.lookup s characterCodeMap `mplus` readUnicodeChar s of- Nothing -> mzero- Just c -> return [RoffStr $ T.singleton c]- (s:ss) -> do- basechar <- case M.lookup s characterCodeMap `mplus`- readUnicodeChar s of- Nothing ->- case T.unpack s of- [ch] | isAscii ch && isAlphaNum ch ->- return ch- _ -> mzero- Just c -> return c- let addAccents [] xs = return $ Normalize.normalize Normalize.NFC $- T.reverse xs- addAccents (a:as) xs =- case M.lookup a combiningAccentsMap `mplus` readUnicodeChar a of- Just x -> addAccents as $ T.cons x xs- Nothing -> mzero- addAccents ss (T.singleton basechar) >>= \xs -> return [RoffStr xs])- <|> case delimChar of- '[' -> escUnknown ("\\[" <> glyph <> "]")- '(' -> escUnknown ("\\(" <> glyph)- '\'' -> escUnknown ("\\C'" <> glyph <> "'")- _ -> Prelude.fail "resolveGlyph: unknown glyph delimiter"--readUnicodeChar :: T.Text -> Maybe Char-readUnicodeChar t = case T.uncons t of- Just ('u', cs) | T.length cs > 3 -> chr <$> safeRead ("0x" <> cs)- _ -> Nothing--escapeNormal :: PandocMonad m => RoffLexer m [LinePart]-escapeNormal = do- c <- noneOf "{}"- optional expandString- case c of- ' ' -> return [RoffStr " "]- '"' -> mempty <$ skipMany (satisfy (/='\n')) -- line comment- '#' -> mempty <$ manyTill anyChar newline- '%' -> return mempty -- optional hyphenation- '&' -> return mempty -- nonprintable zero-width- ')' -> return mempty -- nonprintable zero-width- '*' -> escString- ',' -> return mempty -- to fix spacing after roman- '-' -> return [RoffStr "-"]- '.' -> return [RoffStr "."]- '/' -> return mempty -- to fix spacing before roman- '0' -> return [RoffStr "\x2007"] -- digit-width space- ':' -> return mempty -- zero-width break- 'A' -> quoteArg >>= checkDefined- 'B' -> escIgnore 'B' [quoteArg]- 'C' -> quoteArg >>= resolveGlyph '\''- 'D' -> escIgnore 'D' [quoteArg]- 'E' -> do- mode <- roffMode <$> getState- case mode of- CopyMode -> return mempty- NormalMode -> return [RoffStr "\\"]- 'H' -> escIgnore 'H' [quoteArg]- 'L' -> escIgnore 'L' [quoteArg]- 'M' -> escIgnore 'M' [escapeArg, countChar 1 (satisfy (/='\n'))]- 'N' -> escIgnore 'N' [quoteArg]- 'O' -> escIgnore 'O' [countChar 1 (oneOf ['0','1'])]- 'R' -> escIgnore 'R' [quoteArg]- 'S' -> escIgnore 'S' [quoteArg]- 'V' -> escIgnore 'V' [escapeArg, countChar 1 alphaNum]- 'X' -> escIgnore 'X' [quoteArg]- 'Y' -> escIgnore 'Y' [escapeArg, countChar 1 (satisfy (/='\n'))]- 'Z' -> escIgnore 'Z' [quoteArg]- '\'' -> return [RoffStr "'"]- '\n' -> return mempty -- line continuation- '^' -> return [RoffStr "\x200A"] -- 1/12 em space- '_' -> return [RoffStr "_"]- '`' -> return [RoffStr "`"]- 'a' -> return mempty -- "non-interpreted leader character"- 'b' -> escIgnore 'b' [quoteArg]- 'c' -> return mempty -- interrupt text processing- 'd' -> escIgnore 'd' [] -- forward down 1/2em- 'e' -> return [RoffStr "\\"]- 'f' -> escFont- 'g' -> escIgnore 'g' [escapeArg, countChar 1 (satisfy (/='\n'))]- 'h' -> escIgnore 'h' [quoteArg]- 'k' -> escIgnore 'k' [escapeArg, countChar 1 (satisfy (/='\n'))]- 'l' -> escIgnore 'l' [quoteArg]- 'm' -> escIgnore 'm' [escapeArg, countChar 1 (satisfy (/='\n'))]- 'n' -> escIgnore 'm' [escapeArg, countChar 1 (satisfy (/='\n'))]- 'o' -> escIgnore 'o' [quoteArg]- 'p' -> escIgnore 'p' []- 'r' -> escIgnore 'r' []- 's' -> escIgnore 's' [escapeArg, signedNumber]- 't' -> return [RoffStr "\t"]- 'u' -> escIgnore 'u' []- 'v' -> escIgnore 'v' [quoteArg]- 'w' -> escIgnore 'w' [quoteArg]- 'x' -> escIgnore 'x' [quoteArg]- 'z' -> escIgnore 'z' [countChar 1 anyChar]- '|' -> return [RoffStr "\x2006"] --1/6 em space- '~' -> return [RoffStr "\160"] -- nonbreaking space- '\\' -> do- mode <- roffMode <$> getState- case mode of- CopyMode -> char '\\'- NormalMode -> return '\\'- return [RoffStr "\\"]- _ -> return [RoffStr $ T.singleton c]- -- man 7 groff: "If a backslash is followed by a character that- -- does not constitute a defined escape sequence, the backslash- -- is silently ignored and the character maps to itself."--escIgnore :: PandocMonad m- => Char- -> [RoffLexer m T.Text]- -> RoffLexer m [LinePart]-escIgnore c argparsers = do- pos <- getPosition- arg <- snd <$> withRaw (choice argparsers) <|> return ""- report $ SkippedContent ("\\" <> T.cons c arg) pos- return mempty--escUnknown :: PandocMonad m => T.Text -> RoffLexer m [LinePart]-escUnknown s = do- pos <- getPosition- report $ SkippedContent s pos- return [RoffStr "\xFFFD"]--signedNumber :: PandocMonad m => RoffLexer m T.Text-signedNumber = try $ do- sign <- option "" ("-" <$ char '-' <|> "" <$ char '+')- ds <- many1Char digit- return (sign <> ds)---- Parses: [..] or (..-escapeArg :: PandocMonad m => RoffLexer m T.Text-escapeArg = choice- [ char '[' *> optional expandString *>- manyTillChar (noneOf ['\n',']']) (char ']')- , char '(' *> optional expandString *>- countChar 2 (satisfy (/='\n'))- ]--expandString :: PandocMonad m => RoffLexer m ()-expandString = try $ do- pos <- getPosition- char '\\'- char '*'- cs <- escapeArg <|> countChar 1 anyChar- s <- linePartsToText <$> resolveText cs pos- addToInput s---- Parses: '..'-quoteArg :: PandocMonad m => RoffLexer m T.Text-quoteArg = char '\'' *> manyTillChar (noneOf ['\n','\'']) (char '\'')--escFont :: PandocMonad m => RoffLexer m [LinePart]-escFont = do- font <- escapeArg <|> countChar 1 alphaNum- font' <- if T.null font || font == "P"- then prevFont <$> getState- else return $ foldr processFontLetter defaultFontSpec $ T.unpack font- updateState $ \st -> st{ prevFont = currentFont st- , currentFont = font' }- return [Font font']- where- processFontLetter c fs- | isLower c = processFontLetter (toUpper c) fs- processFontLetter 'B' fs = fs{ fontBold = True }- processFontLetter 'I' fs = fs{ fontItalic = True }- processFontLetter 'C' fs = fs{ fontMonospace = True }- processFontLetter _ fs = fs -- do nothing- -- separate function from lexMacro since real man files sometimes do not -- follow the rules lexComment :: PandocMonad m => RoffLexer m RoffTokens@@ -407,7 +268,8 @@ manyTill anyChar (try (string "T}")) simpleCell = do tabChar <- tableTabChar <$> getState- many (notFollowedBy (char tabChar <|> newline) >> anyChar)+ many $ (char '\\' >> anyChar)+ <|> (notFollowedBy (char tabChar <|> newline) >> anyChar) tableRow :: PandocMonad m => RoffLexer m [RoffTokens] tableRow = do@@ -503,7 +365,7 @@ expression :: PandocMonad m => RoffLexer m (Maybe Bool) expression = do- raw <- charsInBalanced '(' ')' (satisfy (/= '\n'))+ raw <- charsInBalanced '(' ')' (T.singleton <$> (satisfy (/= '\n'))) <|> many1Char nonspaceChar returnValue $ case raw of@@ -624,20 +486,6 @@ char '"' return [RoffStr "\""] -checkDefined :: PandocMonad m => T.Text -> RoffLexer m [LinePart]-checkDefined name = do- macros <- customMacros <$> getState- case M.lookup name macros of- Just _ -> return [RoffStr "1"]- Nothing -> return [RoffStr "0"]--escString :: PandocMonad m => RoffLexer m [LinePart]-escString = try $ do- pos <- getPosition- (do cs <- escapeArg <|> countChar 1 anyChar- resolveText cs pos)- <|> mempty <$ char 'S'- -- strings and macros share namespace resolveText :: PandocMonad m => T.Text -> SourcePos -> RoffLexer m [LinePart]@@ -667,17 +515,6 @@ linePart :: PandocMonad m => RoffLexer m [LinePart] linePart = macroArg <|> escape <|> regularText <|> quoteChar <|> spaceTabChar--backslash :: PandocMonad m => RoffLexer m ()-backslash = do- char '\\'- mode <- roffMode <$> getState- case mode of- -- experimentally, it seems you don't always need to double- -- the backslash in macro defs. It's essential with \\$1,- -- but not with \\f[I]. So we make the second one optional.- CopyMode -> optional $ char '\\'- NormalMode -> return () macroArg :: PandocMonad m => RoffLexer m [LinePart] macroArg = try $ do
@@ -0,0 +1,222 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilyDependencies #-}+module Text.Pandoc.Readers.Roff.Escape+ ( escape,+ escapeArg,+ escIgnore,+ RoffLikeLexer(..),+ )+where+import Text.Pandoc.Class.PandocMonad+ ( PandocMonad(..), report, PandocMonad(..), report )+import Control.Monad+ ( mzero, mplus, mzero, mplus )+import Data.Char (chr, isAscii, isAlphaNum)+import qualified Data.Map as M+import qualified Data.Text as T+import Text.Pandoc.Logging (LogMessage(..))+import Text.Pandoc.Parsing+import Text.Pandoc.Shared (safeRead)+import qualified Data.Text.Normalize as Normalize+import Text.Pandoc.RoffChar (characterCodes, combiningAccents)++-- | Functions and typeclass for escaping special characters in languages+-- that inherit the Roff syntax.+--+-- For various reasons, the mdoc reader doesn't directly reuse the previously+-- existing roff lexer. The main one is to make it possible to simultaneously+-- process roff escapes and to tokenize mdoc macros correctly based on the+-- control line contents. The extracted interface here allows the same `escape`+-- function to work with lexers that target different token types and support+-- different subsets of the original roff language.++type Lexer m x = ParsecT Sources (State x) m++-- | Lexers for Roff macro+class (Monoid (Token x)) => RoffLikeLexer x where+ -- | Type family for the lexer state+ type State x = a | a -> x+ -- | Type family for the token type being lexed+ type Token x = a | a -> x+ -- | Turn a `T.Text` into a token of the output+ emit :: T.Text -> Token x+ -- | Attempt to parse a roff predefined string sequence and push its expansion+ -- onto the input stream.+ expandString :: PandocMonad m => Lexer m x ()+ -- | Parse the name of a defined string and return its expansion as a `Token`+ escString :: PandocMonad m => Lexer m x (Token x)+ -- | Parse the escape character+ backslash :: PandocMonad m => Lexer m x ()+ -- | If the given custom macro is defined in this document, emit a+ -- tokenized "1", otherwise emit a tokenized "0", implementing the roff+ -- escape @\A@.+ checkDefined :: PandocMonad m => T.Text -> Lexer m x (Token x)+ -- | Output an appropriate token for the @\E@ escape sequence. In roff, @\E@+ -- is an "escape character intended to not be interpreted in copy mode".+ -- If the lexer being defined doesn't implement copy mode, @\E@ can just be+ -- lexed by 'backslash'+ escE :: PandocMonad m => Lexer m x (Token x)+ -- | Lex the low-level roff font selection escape @\f@.+ escFont :: PandocMonad m => Lexer m x (Token x)+++characterCodeMap :: M.Map T.Text Char+characterCodeMap =+ M.fromList $ map (\(x,y) -> (y,x)) characterCodes++combiningAccentsMap :: M.Map T.Text Char+combiningAccentsMap =+ M.fromList $ map (\(x,y) -> (y,x)) combiningAccents++escape :: (PandocMonad m, RoffLikeLexer x) => Lexer m x (Token x)+escape = try $ do+ backslash+ escapeGlyph <|> escapeNormal++escapeGlyph :: (PandocMonad m, RoffLikeLexer x) => Lexer m x (Token x)+escapeGlyph = do+ c <- lookAhead (oneOf ['[','('])+ escapeArg >>= resolveGlyph c++resolveGlyph :: (PandocMonad m, RoffLikeLexer x) => Char -> T.Text -> Lexer m x (Token x)+resolveGlyph delimChar glyph = do+ let cs = T.replace "_u" " u" glyph -- unicode glyphs separated by _+ (case T.words cs of+ [] -> mzero+ [s] -> case M.lookup s characterCodeMap `mplus` readUnicodeChar s of+ Nothing -> mzero+ Just c -> return $ emit $ T.singleton c+ (s:ss) -> do+ basechar <- case M.lookup s characterCodeMap `mplus`+ readUnicodeChar s of+ Nothing ->+ case T.unpack s of+ [ch] | isAscii ch && isAlphaNum ch ->+ return ch+ _ -> mzero+ Just c -> return c+ let addAccents [] xs = return $ Normalize.normalize Normalize.NFC $+ T.reverse xs+ addAccents (a:as) xs =+ case M.lookup a combiningAccentsMap `mplus` readUnicodeChar a of+ Just x -> addAccents as $ T.cons x xs+ Nothing -> mzero+ addAccents ss (T.singleton basechar) >>= \xs -> return $ emit xs)+ <|> case delimChar of+ '[' -> escUnknown ("\\[" <> glyph <> "]")+ '(' -> escUnknown ("\\(" <> glyph)+ '\'' -> escUnknown ("\\C'" <> glyph <> "'")+ _ -> Prelude.fail "resolveGlyph: unknown glyph delimiter"++readUnicodeChar :: T.Text -> Maybe Char+readUnicodeChar t = case T.uncons t of+ Just ('u', cs) | T.length cs > 3 -> chr <$> safeRead ("0x" <> cs)+ _ -> Nothing++escapeNormal :: (PandocMonad m, RoffLikeLexer x) => Lexer m x (Token x)+escapeNormal = do+ c <- noneOf "{}"+ optional expandString+ let groffSkip = [escapeArg, countChar 1 (satisfy (/='\n'))]+ case c of+ ' ' -> return $ emit " " -- mandoc_char(7) says this should be a nonbreaking space+ '"' -> mempty <$ skipMany (satisfy (/='\n')) -- line comment+ '#' -> mempty <$ manyTill anyChar newline+ '%' -> return mempty -- optional hyphenation+ '&' -> return mempty -- nonprintable zero-width+ ')' -> return mempty -- nonprintable zero-width+ '*' -> escString+ ',' -> return mempty -- to fix spacing after roman+ '-' -> return $ emit "-"+ '.' -> return $ emit "."+ '/' -> return mempty -- to fix spacing before roman+ '0' -> return $ emit "\x2007" -- digit-width space+ ':' -> return mempty -- zero-width break+ 'A' -> quoteArg >>= checkDefined+ 'B' -> escIgnore 'B' [quoteArg]+ 'C' -> quoteArg >>= resolveGlyph '\''+ 'D' -> escIgnore 'D' [quoteArg]+ 'E' -> escE+ 'F' -> escIgnore 'F' groffSkip+ 'H' -> escIgnore 'H' [quoteArg]+ 'L' -> escIgnore 'L' [quoteArg]+ 'M' -> escIgnore 'M' groffSkip+ 'N' -> escIgnore 'N' [quoteArg]+ 'O' -> escIgnore 'O' [countChar 1 (oneOf ['0','1'])]+ 'R' -> escIgnore 'R' [quoteArg]+ 'S' -> escIgnore 'S' [quoteArg]+ 'V' -> escIgnore 'V' groffSkip+ 'X' -> escIgnore 'X' [quoteArg]+ 'Y' -> escIgnore 'Y' groffSkip+ 'Z' -> escIgnore 'Z' [quoteArg]+ '\'' -> return $ emit "'"+ '\n' -> return mempty -- line continuation+ '^' -> return $ emit "\x200A" -- 1/12 em space+ '_' -> return $ emit "_"+ '`' -> return $ emit "`"+ 'a' -> return mempty -- "non-interpreted leader character"+ 'b' -> escIgnore 'b' [quoteArg]+ 'c' -> return mempty -- interrupt text processing+ 'd' -> escIgnore 'd' [] -- forward down 1/2em+ 'e' -> return $ emit "\\"+ 'f' -> escFont+ 'g' -> escIgnore 'g' groffSkip+ 'h' -> escIgnore 'h' [quoteArg]+ 'k' -> escIgnore 'k' groffSkip+ 'l' -> escIgnore 'l' [quoteArg]+ 'm' -> escIgnore 'm' groffSkip+ 'n' -> escIgnore 'm' groffSkip+ 'o' -> escIgnore 'o' [quoteArg]+ 'p' -> escIgnore 'p' []+ 'r' -> escIgnore 'r' []+ 's' -> escIgnore 's' [escapeArg, signedNumber]+ 't' -> return $ emit "\t"+ 'u' -> escIgnore 'u' []+ 'v' -> escIgnore 'v' [quoteArg]+ 'w' -> escIgnore 'w' [quoteArg]+ 'x' -> escIgnore 'x' [quoteArg]+ 'z' -> escIgnore 'z' [countChar 1 anyChar]+ '|' -> return $ emit "\x2006" --1/6 em space+ '~' -> return $ emit "\160" -- nonbreaking space+ '\\' -> return $ emit "\\"+ _ -> return $ emit $ T.singleton c+ -- man 7 groff: "If a backslash is followed by a character that+ -- does not constitute a defined escape sequence, the backslash+ -- is silently ignored and the character maps to itself."++escIgnore :: (PandocMonad m, RoffLikeLexer x)+ => Char+ -> [Lexer m x T.Text]+ -> Lexer m x (Token x)+escIgnore c argparsers = do+ pos <- getPosition+ arg <- snd <$> withRaw (choice argparsers) <|> return ""+ report $ SkippedContent ("\\" <> T.cons c arg) pos+ return mempty++escUnknown :: (PandocMonad m, RoffLikeLexer x) => T.Text -> Lexer m x (Token x)+escUnknown s = do+ pos <- getPosition+ report $ SkippedContent s pos+ return $ emit "\xFFFD"++signedNumber :: (PandocMonad m, RoffLikeLexer x) => Lexer m x T.Text+signedNumber = try $ do+ sign <- option "" ("-" <$ char '-' <|> "" <$ char '+')+ ds <- many1Char digit+ return (sign <> ds)++-- Parses: [..] or (..+escapeArg :: (PandocMonad m, RoffLikeLexer x) => Lexer m x T.Text+escapeArg = choice+ [ char '[' *> optional expandString *>+ manyTillChar (noneOf ['\n',']']) (char ']')+ , char '(' *> optional expandString *>+ countChar 2 (satisfy (/='\n'))+ ]++-- Parses: '..'+quoteArg :: (PandocMonad m, RoffLikeLexer x) => Lexer m x T.Text+quoteArg = char '\'' *> manyTillChar (noneOf ['\n','\'']) (char '\'')
@@ -16,7 +16,7 @@ import Control.Monad import Control.Monad.Except (throwError)-import Data.Char (isAlphaNum)+import Data.Char (isAlphaNum, isDigit, isUpper, isLower, isLetter) import qualified Data.Foldable as F import Data.Maybe (fromMaybe) import Data.Text (Text)@@ -26,7 +26,7 @@ import Text.Pandoc.Class.PandocMonad (PandocMonad (..)) import Text.Pandoc.Definition import Text.Pandoc.Options-import Text.Pandoc.Parsing hiding (enclosed, nested)+import Text.Pandoc.Parsing hiding (enclosed) import Text.Pandoc.Readers.HTML (htmlTag, isCommentTag) import Text.Pandoc.Shared (tshow) import Text.Pandoc.XML (fromEntities)@@ -43,7 +43,7 @@ Left e -> throwError e Right d -> return d -type TWParser = ParserT Sources ParserState+type TWParser = ParsecT Sources ParserState -- -- utility functions@@ -52,15 +52,6 @@ tryMsg :: Text -> TWParser m a -> TWParser m a tryMsg msg p = try p <?> T.unpack msg -nested :: PandocMonad m => TWParser m a -> TWParser m a-nested p = do- nestlevel <- stateMaxNestingLevel <$> getState- guard $ nestlevel > 0- updateState $ \st -> st{ stateMaxNestingLevel = stateMaxNestingLevel st - 1 }- res <- p- updateState $ \st -> st{ stateMaxNestingLevel = nestlevel }- return res- htmlElement :: PandocMonad m => Text -> TWParser m (Attr, Text) htmlElement tag = tryMsg tag $ do (TagOpen _ attr, _) <- htmlTag (~== TagOpen tag [])@@ -85,7 +76,7 @@ parsedContent <- try $ parseContent content return (attr, parsedContent) where- parseContent = parseFromString' $ nested $ manyTill parser endOfContent+ parseContent = parseFromString' $ manyTill parser endOfContent endOfContent = try $ skipMany blankline >> skipSpaces >> eof parseCharHtmlContentWithAttrs :: PandocMonad m@@ -231,9 +222,11 @@ (TableHead nullAttr $ toHeaderRow heads) [TableBody nullAttr 0 [] $ map toRow rows] (TableFoot nullAttr [])- align rows = replicate (columCount rows) (AlignDefault, ColWidthDefault)- columns rows = replicate (columCount rows) mempty- columCount rows = length $ head rows+ align rows = replicate (columnCount rows)+ (AlignDefault, ColWidthDefault)+ columns rows = replicate (columnCount rows) mempty+ columnCount (r:_) = length r+ columnCount [] = 0 toRow = Row nullAttr . map B.simpleCell toHeaderRow l = [toRow l | not (null l)] @@ -402,7 +395,7 @@ nestedInlines end = innerSpace <|> nestedInline where innerSpace = try $ whitespace <* notFollowedBy end- nestedInline = notFollowedBy whitespace >> nested inline+ nestedInline = notFollowedBy whitespace >> inline strong :: PandocMonad m => TWParser m B.Inlines strong = try $ B.strong <$> enclosed (char '*') nestedInlines@@ -456,7 +449,7 @@ | otherwise = isAlphaNum c str :: PandocMonad m => TWParser m B.Inlines-str = B.str <$> (many1Char alphaNum <|> countChar 1 characterReference)+str = B.str <$> (many1Char alphaNum <|> characterReference) nop :: PandocMonad m => TWParser m B.Inlines nop = try $ (void exclamation <|> void nopTag) >> followContent@@ -476,17 +469,29 @@ st <- getState guard $ stateAllowLinks st setState $ st{ stateAllowLinks = False }- (url, title, content) <- linkText+ (url, title, classes, content) <- linkText <|> simpleWikiLink setState $ st{ stateAllowLinks = True }- return $ B.link url title content+ return $ B.linkWith ("",classes,[]) url title content -linkText :: PandocMonad m => TWParser m (Text, Text, B.Inlines)+linkText :: PandocMonad m => TWParser m (Text, Text, [Text], B.Inlines) linkText = do string "[[" url <- T.pack <$> many1Till anyChar (char ']') content <- option (B.str url) (mconcat <$> linkContent) char ']'- return (url, "", content)+ return (url, "", [], content) where linkContent = char '[' >> many1Till anyChar (char ']') >>= parseLinkContent . T.pack parseLinkContent = parseFromString' $ many1 inline++simpleWikiLink :: PandocMonad m => TWParser m (Text, Text, [Text], B.Inlines)+simpleWikiLink = do+ w <- wikiWord+ return (w, "", ["wikilink"], B.str w)+ where+ wikiWord = do+ cs <- many1 $ satisfy (\x -> isLetter x && isUpper x)+ ds <- many1 $ satisfy (\x -> isDigit x || (isLetter x && isLower x))+ es <- many1 $ satisfy (\x -> isLetter x && isUpper x)+ fs <- many $ satisfy isAlphaNum+ return $ T.pack $ cs ++ ds ++ es ++ fs
@@ -3,7 +3,7 @@ {- | Module : Text.Pandoc.Readers.Textile Copyright : Copyright (C) 2010-2012 Paul Rivier- 2010-2022 John MacFarlane+ 2010-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : Paul Rivier <paul*rivier#demotera*com>@@ -38,8 +38,10 @@ import Control.Monad (guard, liftM) import Control.Monad.Except (throwError) import Data.Char (digitToInt, isUpper)-import Data.List (intersperse, transpose, foldl')+import Data.List (intersperse, transpose)+import qualified Data.List as L import Data.List.NonEmpty (NonEmpty(..), nonEmpty)+import qualified Data.Map as M import Data.Text (Text) import qualified Data.Text as T import Text.HTML.TagSoup (Tag (..), fromAttrib)@@ -49,11 +51,13 @@ import Text.Pandoc.Class.PandocMonad (PandocMonad (..)) import Text.Pandoc.CSS import Text.Pandoc.Definition+import Text.Pandoc.Logging import Text.Pandoc.Options import Text.Pandoc.Parsing import Text.Pandoc.Readers.HTML (htmlTag, isBlockTag, isInlineTag) import Text.Pandoc.Readers.LaTeX (rawLaTeXBlock, rawLaTeXInline) import Text.Pandoc.Shared (trim, tshow)+import Text.Read (readMaybe) -- | Parse a Textile text and return a Pandoc document. readTextile :: (PandocMonad m, ToSources a)@@ -67,7 +71,7 @@ Right result -> return result Left e -> throwError e -type TextileParser = ParserT Sources ParserState+type TextileParser = ParsecT Sources ParserState -- | Generate a Pandoc ADT from a textile document parseTextile :: PandocMonad m => TextileParser m Pandoc@@ -78,7 +82,7 @@ -- docMinusKeys is the raw document with blanks where the keys/notes were... let firstPassParser = do pos <- getPosition- t <- noteBlock <|> lineClump+ t <- noteBlock <|> referenceKey <|> lineClump return (pos, t) manyTill firstPassParser eof >>= setInput . Sources setPosition startPos@@ -89,7 +93,10 @@ Pandoc nullMeta . B.toList <$> parseBlocks -- FIXME noteMarker :: PandocMonad m => TextileParser m Text-noteMarker = skipMany spaceChar >> string "fn" >> T.pack <$> manyTill digit (char '.')+noteMarker = do+ skipMany spaceChar+ string "fn"+ T.pack <$> manyTill digit (string "." <|> try (string "^.")) noteBlock :: PandocMonad m => TextileParser m Text noteBlock = try $ do@@ -105,6 +112,27 @@ -- return blanks so line count isn't affected return $ T.replicate (sourceLine endPos - sourceLine startPos) "\n" +referenceKey :: PandocMonad m => TextileParser m Text+referenceKey = try $ do+ pos <- getPosition+ char '['+ refName <- T.pack <$> many1Till nonspaceChar (char ']')+ refDestination <- T.pack <$> many1Till anyChar newline+ st <- getState+ let oldKeys = stateKeys st+ let key = toKey refName+ -- Textile doesn't support link titles on the reference+ -- definition, so use the empty string+ let target = (refDestination, "")+ case M.lookup key oldKeys of+ Just (t, _) | not (t == target) ->+ -- similar to Markdown, only warn when the targets+ -- for matching named references differ+ logMessage $ DuplicateLinkReference refName pos+ _ -> return ()+ updateState $ \s -> s {stateKeys = M.insert key (target, nullAttr) oldKeys }+ return "\n"+ -- | Parse document blocks parseBlocks :: PandocMonad m => TextileParser m Blocks parseBlocks = mconcat <$> manyTill block eof@@ -120,7 +148,8 @@ , rawHtmlBlock , rawLaTeXBlock' , table- , maybeExplicitBlock "p" para+ , explicitBlock "p" (para <|> pure (B.para mempty))+ , para , mempty <$ blanklines ] @@ -147,7 +176,7 @@ char ' ' let starts = ["p", "table", "bq", "bc", "pre", "h1", "h2", "h3", "h4", "h5", "h6", "pre", "###", "notextile"]- let ender = choice $ map explicitBlockStart starts+ let ender = () <$ choice (map explicitBlockStart starts) contents <- if extended then do f <- anyLine@@ -229,30 +258,59 @@ -- | Bullet List Item of given depth, depth being the number of -- leading '*' bulletListItemAtDepth :: PandocMonad m => Int -> TextileParser m Blocks-bulletListItemAtDepth = genericListItemAtDepth '*'+bulletListItemAtDepth depth = try $ do+ bulletListStartAtDepth depth+ genericListItemContentsAtDepth depth -- | Ordered List of given depth, depth being the number of -- leading '#'+-- The first Ordered List Item may have a start attribute orderedListAtDepth :: PandocMonad m => Int -> TextileParser m Blocks orderedListAtDepth depth = try $ do- items <- many1 (orderedListItemAtDepth depth)- return $ B.orderedList items+ (startNum, firstItem) <- firstOrderedListItemAtDepth depth+ moreItems <- many (orderedListItemAtDepth depth)+ let listItems = firstItem : moreItems+ return $ B.orderedListWith (startNum, DefaultStyle, DefaultDelim) listItems +-- | The first Ordered List Item, which could have a start attribute+firstOrderedListItemAtDepth :: PandocMonad m => Int+ -> TextileParser m (Int, Blocks)+firstOrderedListItemAtDepth depth = try $ do+ startNum <- orderedListStartAtDepth depth+ contents <- genericListItemContentsAtDepth depth+ return (startNum, contents)+ -- | Ordered List Item of given depth, depth being the number of -- leading '#' orderedListItemAtDepth :: PandocMonad m => Int -> TextileParser m Blocks-orderedListItemAtDepth = genericListItemAtDepth '#'+orderedListItemAtDepth depth = try $ do+ orderedListStartAtDepth depth+ genericListItemContentsAtDepth depth --- | Common implementation of list items-genericListItemAtDepth :: PandocMonad m => Char -> Int -> TextileParser m Blocks-genericListItemAtDepth c depth = try $ do- count depth (char c) >> attributes >> whitespace+-- | Lists always start with a number of leading characters '#' or '*'+-- Ordered list start characters '#' can be followed by the start attribute+-- number, but bullet list characters '*' can not+orderedListStartAtDepth :: PandocMonad m => Int -> TextileParser m Int+orderedListStartAtDepth depth = count depth (char '#') >>+ try orderedListStartAttr <* (attributes >> whitespace)++bulletListStartAtDepth :: PandocMonad m => Int -> TextileParser m ()+bulletListStartAtDepth depth = () <$ (count depth (char '*') >>+ attributes >> whitespace)++-- | The leading characters and start attributes differ between ordered and+-- unordered lists, but their contents have the same structure and can+-- share a Parser+genericListItemContentsAtDepth :: PandocMonad m => Int+ -> TextileParser m Blocks+genericListItemContentsAtDepth depth = do contents <- mconcat <$> many ((B.plain . mconcat <$> many1 inline) <|> try (newline >> codeBlockHtml)) newline sublist <- option mempty (anyListAtDepth (depth + 1)) return $ contents <> sublist + -- | A definition list is a set of consecutive definition items definitionList :: PandocMonad m => TextileParser m Blocks definitionList = try $ B.definitionList <$> many1 definitionListItem@@ -260,12 +318,17 @@ -- | List start character. listStart :: PandocMonad m => TextileParser m () listStart = genericListStart '*'- <|> () <$ genericListStart '#'+ <|> () <$ orderedListStart <|> () <$ definitionListStart genericListStart :: PandocMonad m => Char -> TextileParser m () genericListStart c = () <$ try (many1 (char c) >> whitespace) +orderedListStart :: PandocMonad m => TextileParser m ()+orderedListStart = () <$ try (many1 (char '#') >>+ try orderedListStartAttr >>+ whitespace)+ basicDLStart :: PandocMonad m => TextileParser m () basicDLStart = do char '-'@@ -350,8 +413,12 @@ notFollowedBy blankline raw <- trim . T.pack <$> many (noneOf "|\n" <|> try (char '\n' <* notFollowedBy blankline))- content <- mconcat <$> parseFromString' (many inline) raw- return ((isHeader, alignment), B.plain content)+ content <- parseFromString' parseBlocks (raw <> "\n\n")+ -- Convert lone Para to Plain for backward compatibility+ let content' = case B.toList content of+ [Para ils] -> B.plain (B.fromList ils)+ _ -> content+ return ((isHeader, alignment), content') -- | A table row is made of many table cells tableRow :: PandocMonad m => TextileParser m [((Bool, Alignment), Blocks)]@@ -401,25 +468,27 @@ _ <- anyLine return () -explicitBlockStart :: PandocMonad m => Text -> TextileParser m ()+explicitBlockStart :: PandocMonad m => Text -> TextileParser m Attr explicitBlockStart name = try $ do string (T.unpack name)- attributes+ attr <- attributes char '.' optional whitespace optional endline+ return attr -- | Blocks like 'p' and 'table' do not need explicit block tag. -- However, they can be used to set HTML/CSS attributes when needed.-maybeExplicitBlock :: PandocMonad m- => Text -- ^ block tag name- -> TextileParser m Blocks -- ^ implicit block- -> TextileParser m Blocks-maybeExplicitBlock name blk = try $ do- optional $ explicitBlockStart name- blk--+explicitBlock :: PandocMonad m+ => Text -- ^ block tag name+ -> TextileParser m Blocks -- ^ implicit block+ -> TextileParser m Blocks+explicitBlock name blk = try $ do+ attr <- explicitBlockStart name+ contents <- blk+ return $ if attr == nullAttr+ then contents+ else B.divWith attr contents ---------- -- Inlines@@ -437,6 +506,7 @@ , endline , code , escapedInline+ , spanGroup , inlineMarkup , groupedInlineMarkup , rawHtmlInline@@ -445,7 +515,7 @@ , link , image , mark- , B.str . T.singleton <$> characterReference+ , B.str <$> characterReference , smartPunctuation inline , symbol ]@@ -461,9 +531,21 @@ , simpleInline (char '-' <* notFollowedBy (char '-')) B.strikeout , simpleInline (char '^') B.superscript , simpleInline (char '~') B.subscript- , simpleInline (char '%') id ] +-- "The <span> tag is created by percent % signs between whitespaces."+-- e.g. My mother has %{color:green;}green% eyes.+spanGroup :: PandocMonad m => TextileParser m Inlines+spanGroup = try $ do+ notAfterString >>= guard+ char '%' *> notFollowedBy whitespace+ attr <- option nullAttr attributes+ contents <- mconcat <$> manyTill+ (try (((B.space <>) <$> try (whitespace *> notFollowedBy newline *> inline))+ <|> try (notFollowedBy newline *> inline)))+ (try (char '%' <* lookAhead (newline <|> ' ' <$ whitespace)))+ pure $ B.spanWith attr contents+ -- | Trademark, registered, copyright mark :: PandocMonad m => TextileParser m Inlines mark = try $ char '(' >> (try tm <|> try reg <|> copy)@@ -569,18 +651,26 @@ attr <- attributes name <- trimInlines . mconcat <$> withQuoteContext InDoubleQuote (many1Till inline (char '"'))- char ':'- let stop = if bracketed- then char ']'- else lookAhead $ space <|> eof' <|>- try (oneOf "!.,;:" *>- (space <|> newline <|> eof'))- url <- T.pack <$> many1Till nonspaceChar stop+ url <- linkUrl bracketed let name' = if B.toList name == [Str "$"] then B.str url else name return $ if attr == nullAttr then B.link url "" name' else B.spanWith attr $ B.link url "" name' +linkUrl :: PandocMonad m => Bool -> TextileParser m Text+linkUrl bracketed = do+ char ':'+ let stop = if bracketed+ then char ']'+ else lookAhead $ space <|> eof' <|> oneOf "[]" <|>+ try (oneOf "!.,;:*" *>+ (space <|> newline <|> eof'))+ rawLink <- T.pack <$> many1Till nonspaceChar stop+ st <- getState+ return $ case M.lookup (toKey rawLink) (stateKeys st) of+ Nothing -> rawLink+ Just ((src, _), _) -> src+ -- | image embedding image :: PandocMonad m => TextileParser m Inlines image = try $ do@@ -592,7 +682,11 @@ src <- T.pack <$> many1 (noneOf " \t\n\r!(") alt <- fmap T.pack $ option "" $ try $ char '(' *> manyTill anyChar (char ')') char '!'- return $ B.imageWith attr src alt (B.str alt)+ let img = B.imageWith attr src alt (B.str alt)+ try (do -- image link+ url <- linkUrl False+ return (B.link url "" img))+ <|> return img escapedInline :: PandocMonad m => TextileParser m Inlines escapedInline = escapedEqs <|> escapedTag@@ -609,9 +703,12 @@ -- | Any special symbol defined in wordBoundaries symbol :: PandocMonad m => TextileParser m Inlines-symbol = B.str . T.singleton <$> (notFollowedBy newline *>- notFollowedBy rawHtmlBlock *>- oneOf wordBoundaries)+symbol = do+ c <- notFollowedBy newline *>+ notFollowedBy rawHtmlBlock *>+ oneOf wordBoundaries+ updateLastStrPos+ pure $ B.str . T.singleton $ c -- | Inline code code :: PandocMonad m => TextileParser m Inlines@@ -631,9 +728,16 @@ htmlTag (tagOpen (=="tt") null) B.code . T.pack <$> manyTill anyChar' (try $ htmlTag $ tagClose (=="tt")) +orderedListStartAttr :: PandocMonad m => TextileParser m Int+orderedListStartAttr = do+ digits <- many digit+ case readMaybe digits :: Maybe Int of+ Nothing -> return 1+ Just n -> return n+ -- | Html / CSS attributes attributes :: PandocMonad m => TextileParser m Attr-attributes = foldl' (flip ($)) ("",[],[]) <$>+attributes = L.foldl' (flip ($)) ("",[],[]) <$> try (do special <- option id specialAttribute attrs <- many attribute return (special : attrs))@@ -681,9 +785,9 @@ -- | Parses material surrounded by a parser. surrounded :: (PandocMonad m, Show t)- => ParserT Sources st m t -- ^ surrounding parser- -> ParserT Sources st m a -- ^ content parser (to be used repeatedly)- -> ParserT Sources st m [a]+ => ParsecT Sources st m t -- ^ surrounding parser+ -> ParsecT Sources st m a -- ^ content parser (to be used repeatedly)+ -> ParsecT Sources st m [a] surrounded border = enclosed (border *> notFollowedBy (oneOf " \t\n\r")) (try border) @@ -692,12 +796,14 @@ -> (Inlines -> Inlines) -- ^ Inline constructor -> TextileParser m Inlines -- ^ content parser (to be used repeatedly) simpleInline border construct = try $ do- notAfterString+ notAfterString >>= guard border *> notFollowedBy (oneOf " \t\n\r") attr <- attributes body <- trimInlines . mconcat <$> withQuoteContext InSingleQuote- (manyTill (notFollowedBy newline >> inline)+ (manyTill (((B.space <>) <$>+ try (whitespace *> notFollowedBy newline >> inline))+ <|> try (notFollowedBy newline >> inline)) (try border <* notFollowedBy alphaNum)) return $ construct $ if attr == nullAttr@@ -713,5 +819,5 @@ char ']' return $ sp1 <> result <> sp2 -eof' :: Monad m => ParserT Sources s m Char+eof' :: Monad m => ParsecT Sources s m Char eof' = '\n' <$ eof
@@ -24,12 +24,11 @@ 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-import Text.Pandoc.Parsing hiding (enclosed, nested)+import Text.Pandoc.Parsing hiding (enclosed) import Text.Pandoc.Shared (safeRead) import Text.Pandoc.XML (fromEntities) import Text.Printf (printf)@@ -46,7 +45,7 @@ Left e -> throwError e Right d -> return d -type TikiWikiParser = ParserT Sources ParserState+type TikiWikiParser = ParsecT Sources ParserState -- -- utility functions@@ -58,15 +57,6 @@ skip :: TikiWikiParser m a -> TikiWikiParser m () skip parser = Control.Monad.void parser -nested :: PandocMonad m => TikiWikiParser m a -> TikiWikiParser m a-nested p = do- nestlevel <- stateMaxNestingLevel <$> getState- guard $ nestlevel > 0- updateState $ \st -> st{ stateMaxNestingLevel = stateMaxNestingLevel st - 1 }- res <- p- updateState $ \st -> st{ stateMaxNestingLevel = nestlevel }- return res- -- -- main parser --@@ -80,7 +70,7 @@ block :: PandocMonad m => TikiWikiParser m B.Blocks block = do- verbosity <- getsCommonState stVerbosity+ verbosity <- getVerbosity pos <- getPosition res <- mempty <$ skipMany1 blankline <|> blockElements@@ -166,8 +156,9 @@ return $ B.simpleTable (headers rows) rows where -- The headers are as many empty strings as the number of columns- -- in the first row- headers rows = replicate (length $ head rows) ((B.plain . B.str) "")+-- in the first row+ headers [] = []+ headers (r:_) = replicate (length r) ((B.plain . B.str) "") para :: PandocMonad m => TikiWikiParser m B.Blocks para = fmap (result . mconcat) ( many1Till inline endOfParaElement)@@ -235,10 +226,9 @@ -- fixListNesting nestall | trace ("\n\nfixListNesting: " ++ (show nestall)) False = undefined -- fixListNesting nestall@(first:second:rest) = fixListNesting (first:second:rest) =- let secondBlock = head $ B.toList second in- case secondBlock of- BulletList _ -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest- OrderedList _ _ -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest+ case B.toList second of+ (BulletList _ : _) -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest+ (OrderedList _ _ : _) -> fixListNesting $ mappend (recurseOnList first) (recurseOnList second) : rest _ -> recurseOnList first : fixListNesting (second:rest) -- This function walks the Block structure for fixListNesting,@@ -248,10 +238,9 @@ -- recurseOnList item | trace ("rOL: " ++ (show $ length $ B.toList item) ++ ", " ++ (show $ B.toList item)) False = undefined recurseOnList items | length (B.toList items) == 1 =- let itemBlock = head $ B.toList items in- case itemBlock of- BulletList listItems -> B.bulletList $ fixListNesting $ map B.fromList listItems- OrderedList _ listItems -> B.orderedList $ fixListNesting $ map B.fromList listItems+ case B.toList items of+ (BulletList listItems : _) -> B.bulletList $ fixListNesting $ map B.fromList listItems+ (OrderedList _ listItems : _) -> B.orderedList $ fixListNesting $ map B.fromList listItems _ -> items -- The otherwise works because we constructed the blocks, and we@@ -450,7 +439,7 @@ nestedInlines end = innerSpace <|> nestedInline where innerSpace = try $ whitespace <* notFollowedBy end- nestedInline = notFollowedBy whitespace >> nested inline+ nestedInline = notFollowedBy whitespace >> inline -- {img attId="39" imalign="right" link="http://info.tikiwiki.org" alt="Panama Hat"} --@@ -594,7 +583,7 @@ return $ B.str $ T.pack body str :: PandocMonad m => TikiWikiParser m B.Inlines-str = fmap B.str (T.pack <$> many1 alphaNum <|> countChar 1 characterReference)+str = fmap B.str (T.pack <$> many1 alphaNum <|> characterReference) symbol :: PandocMonad m => TikiWikiParser m B.Inlines symbol = fmap B.str (countChar 1 nonspaceChar)
@@ -33,9 +33,10 @@ import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (space, spaces, uri)-import Text.Pandoc.Shared (compactify, compactifyDL, escapeURI)+import Text.Pandoc.Shared (compactify, compactifyDL)+import Text.Pandoc.URI (escapeURI) -type T2T = ParserT Sources ParserState (Reader T2TMeta)+type T2T = ParsecT Sources ParserState (Reader T2TMeta) -- | An object for the T2T macros meta information -- the contents of each field is simply substituted verbatim into the file@@ -402,7 +403,7 @@ target <- getTarget inlineMarkup (T.singleton <$> anyChar) (B.rawInline target) '\'' id --- Parser for markup indicated by a double character.+-- Parsec for markup indicated by a double character. -- Inline markup is greedy and glued -- Greedy meaning ***a*** = Bold [Str "*a*"] -- Glued meaning that markup must be tight to content
@@ -0,0 +1,781 @@+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE ScopedTypeVariables #-}++{- |+ Module : Text.Pandoc.Readers.Typst+ Copyright : Copyright (C) 2023 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Reads and evaluates a Typst document as a Pandoc AST.+-}+module Text.Pandoc.Readers.Typst+ ( readTypst+ )+where++import Text.Pandoc.Class+import Text.Pandoc.Sources+import Text.Pandoc.Options+import Text.Pandoc.Definition+import Typst ( parseTypst, evaluateTypst )+import Text.Pandoc.Error (PandocError(..))+import Text.Pandoc.Translations (Term(References), translateTerm)+import Text.Pandoc.Shared (tshow, blocksToInlines)+import Control.Monad.Except (throwError)+import Control.Monad (MonadPlus (mplus), void, guard, foldM)+import Control.Monad.Trans (lift)+import qualified Data.Foldable as F+import qualified Data.Map as M+import Data.Maybe (catMaybes, fromMaybe, isJust)+import Data.Sequence (Seq)+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import Data.Text (Text)+import qualified Data.Text as T+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Walk+import Text.Parsec+import Text.TeXMath (writeTeX)+import Text.TeXMath.Shared (getSpaceChars)+import Text.Pandoc.Readers.Typst.Math (pMathMany)+import Text.Pandoc.Readers.Typst.Parsing (pTok, ignored, getField, P,+ PState(..), defaultPState)+import Typst.Methods (formatNumber, applyPureFunction)+import Typst.Types+import qualified Data.Vector as V+import System.FilePath (takeDirectory)+import qualified System.FilePath.Windows as Windows+import qualified System.FilePath.Posix as Posix++-- | Read Typst from an input string and return a Pandoc document.+readTypst :: (PandocMonad m, ToSources a)+ => ReaderOptions -> a -> m Pandoc+readTypst opts inp = do+ let sources = toSources inp+ let inputName = case sources of+ Sources ((pos, _):_) -> sourceName pos+ _ -> ""+ case parseTypst inputName (sourcesToText sources) of+ Left e -> throwError $ PandocParseError $ T.pack $ show e+ Right parsed -> do+ let ops = Operations {+ loadBytes = readFileStrict,+ currentUTCTime = getCurrentTime,+ lookupEnvVar = fmap (fmap T.unpack) . lookupEnv . T.pack,+ checkExistence = fileExists }+ res <- evaluateTypst ops (readerTypstInputs opts) inputName parsed+ case res of+ Left e -> throwError $ PandocParseError $ tshow e+ Right content -> do+ let content' = fixNesting content+ let labs = findLabels [content']+ runParserT pPandoc defaultPState{ sLabels = labs }+ inputName [content'] >>=+ either (throwError . PandocParseError . T.pack . show) pure++pBlockElt :: PandocMonad m => P m B.Blocks+pBlockElt = try $ do+ res <- pTok (\t -> isBlock t || not (isInline t))+ -- check for following label+ mbident <- option Nothing $ Just <$> pLab+ case res of+ Elt name@(Identifier tname) pos fields -> do+ case M.lookup name blockHandlers of+ Nothing -> do+ ignored ("unknown block element " <> tname <>+ " at " <> tshow pos)+ pure mempty+ Just handler -> handler pos mbident fields+ _ -> pure mempty++pInline :: PandocMonad m => P m B.Inlines+pInline = try $ do+ res <- pTok (\t -> isInline t || not (isBlock t))+ case res of+ Txt t -> pure $ B.text t+ Lab name -> pure $ B.spanWith (name, [], []) mempty+ Elt (Identifier tname) _ _+ | "math." `T.isPrefixOf` tname+ , tname /= "math.equation" ->+ B.math . writeTeX <$> pMathMany (Seq.singleton res)+ Elt name@(Identifier tname) pos fields -> do+ labs <- sLabels <$> getState+ labelTarget <- (do result <- getField "target" fields+ case result of+ VLabel t | t `elem` labs -> pure True+ _ -> pure False)+ <|> pure False+ if tname == "ref" && not labelTarget+ then do+ -- @foo is a citation unless it links to a lab in the doc:+ let targetToKey (Identifier "target") = Identifier "key"+ targetToKey k = k+ case M.lookup "cite" inlineHandlers of+ Nothing -> do+ ignored ("unknown inline element " <> tname <>+ " at " <> tshow pos)+ pure mempty+ 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 pos Nothing fields++-- Pull block elements out of inline elements, e.g.+-- Elt "smallcaps" [ Elt "heading" [..] ] ->+-- Elt "heading" [ Elt "smallcaps" [..]]. See #11017.+fixNesting :: Content -> Content+fixNesting el@(Elt name pos fields)+ | Just (VContent elts) <- M.lookup "body" fields+ = let elts' = fmap fixNesting elts+ fields' = M.insert "body" (VContent elts') fields+ in if isBlock el+ then Elt name pos fields'+ else case getField "body" fields' of+ Just ([el'@(Elt name' pos' fields'')] :: Seq Content)+ | isBlock el'+ , not (isInline el')+ , "body" `M.member` fields''+ -> Elt name' pos' $+ M.insert "body" (VContent+ (Seq.singleton+ (Elt name pos fields'')))+ fields'+ _ -> Elt name pos fields'+fixNesting x = x++pPandoc :: PandocMonad m => P m B.Pandoc+pPandoc = do+ Elt "document" _ fields <- pTok isDocument+ bs <- getField "body" fields >>= pWithContents pBlocks+ title <- (getField "title" fields >>= pWithContents pInlines) <|>+ pure mempty+ authors <- (getField "author" fields >>=+ mapM (pWithContents pInlines) . V.toList) <|>+ ((:[]) <$> (getField "author" fields >>=+ (\x -> guard (not (null x)) *>+ pWithContents pInlines x))) <|>+ pure []+ date <- (getField "date" fields >>= pWithContents pInlines) <|>+ pure mempty+ keywords <- (getField "keywords" fields >>=+ mapM (pWithContents pInlines) . V.toList)+ <|> pure []+ meta <- sMeta <$> getState+ let meta' =+ (if title == mempty || isJust (lookupMeta "title" meta)+ then id+ else B.setMeta "title" title) .+ (if null authors+ then id+ else B.setMeta "author" authors) .+ (if null date+ then id+ else B.setMeta "date" date) .+ (if null keywords+ then id+ else B.setMeta "keywords" keywords) $ meta+ pure $ Pandoc meta' (B.toList bs)++pBlocks :: PandocMonad m => P m B.Blocks+pBlocks = mconcat <$> many pBlock++pBlock :: PandocMonad m => P m B.Blocks+pBlock = pPara <|> pBlockElt++pSpace :: PandocMonad m => P m Content+pSpace = pTok+ ( \case+ Txt t | T.all (== ' ') t -> True+ _ -> False )++pLab :: PandocMonad m => P m Text+pLab = try $ do+ optional pSpace+ Lab t <- pTok+ ( \case+ Lab _ -> True+ _ -> False+ )+ pure t++isDocument :: Content -> Bool+isDocument (Elt "document" _ _) = True+isDocument _ = False++isBlock :: Content -> Bool+isBlock (Elt "raw" _ fields) = M.lookup "block" fields == Just (VBoolean True)+isBlock (Elt name _ _) = name `Set.member` blockKeys+isBlock Lab{} = True+isBlock _ = False++isInline :: Content -> Bool+isInline (Elt "raw" _ fields) = M.lookup "block" fields /= Just (VBoolean True)+isInline (Elt name _ _) = name `Set.member` inlineKeys+isInline Lab{} = True+isInline Txt{} = True++blockKeys :: Set.Set Identifier+blockKeys = Set.fromList $ M.keys+ (blockHandlers :: M.Map Identifier+ (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 SourcePos -> Maybe Text ->+ M.Map Identifier Val -> P PandocPure B.Inlines))++blockHandlers :: PandocMonad m =>+ M.Map Identifier+ (Maybe SourcePos -> Maybe Text ->+ M.Map Identifier Val -> P m B.Blocks)+blockHandlers = M.fromList+ [("text", \_ _ fields -> do+ body <- getField "body" fields+ -- sometimes text elements include para breaks+ notFollowedBy $ void $ pWithContents pInlines body+ pWithContents pBlocks body)+ ,("title", \_ _ fields -> do+ body <- getField "body" fields+ case body of+ VContent cs -> do+ ils <- pWithContents pInlines cs <|> pure mempty+ updateState $ \s -> s{ sMeta = B.setMeta "title" ils (sMeta s) }+ pure mempty+ _ -> pure mempty)+ ,("box", \_ _ fields -> do+ body <- getField "body" fields+ B.divWith ("", ["box"], []) <$> pWithContents pBlocks body)+ ,("heading", \_ mbident fields -> do+ body <- getField "body" fields+ lev <- getField "level" fields <|> pure 1+ B.headerWith (fromMaybe "" mbident,[],[]) lev+ <$> pWithContents pInlines body)+ ,("quote", \_ _ fields -> do+ getField "block" fields >>= guard+ body <- getField "body" fields >>= pWithContents pBlocks+ attribution' <- getField "attribution" fields+ attribution <- if attribution' == mempty+ then pure mempty+ else (\x -> B.para ("\x2014\xa0" <> x)) <$>+ (pWithContents pInlines attribution')+ pure $ B.blockQuote $ body <> attribution)+ ,("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+ children <- V.toList <$> getField "children" fields+ mbstart <- getField "start" fields+ start <- case mbstart of+ Nothing -> pure 1+ Just x+ | x >= 0 -> pure x+ | otherwise -> fail "number must be positive"+ (numbering :: Text) <- getField "numbering" fields `mplus` pure ""+ let (sty, delim) =+ case numbering of+ "1." -> (B.Decimal, B.Period)+ "1)" -> (B.Decimal, B.OneParen)+ "(1)" -> (B.Decimal, B.TwoParens)+ "a." -> (B.LowerAlpha, B.Period)+ "a)" -> (B.LowerAlpha, B.OneParen)+ "(a)" -> (B.LowerAlpha, B.TwoParens)+ "A." -> (B.UpperAlpha, B.Period)+ "A)" -> (B.UpperAlpha, B.OneParen)+ "(A)" -> (B.UpperAlpha, B.TwoParens)+ "i." -> (B.LowerRoman, B.Period)+ "i)" -> (B.LowerRoman, B.OneParen)+ "(i)" -> (B.LowerRoman, B.TwoParens)+ "I." -> (B.UpperRoman, B.Period)+ "I)" -> (B.UpperRoman, B.OneParen)+ "(I)" -> (B.UpperRoman, B.TwoParens)+ _ -> (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+ children <- V.toList <$> getField "children" fields+ B.definitionList+ <$> mapM+ ( \case+ VTermItem t d -> do+ t' <- pWithContents pInlines t+ d' <- pWithContents pBlocks d+ pure (t', [d'])+ _ -> pure (mempty, [])+ )+ children)+ ,("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 ->+ maybe id (\ident -> B.divWith (ident, [], [])) mbident+ <$> (getField "body" fields >>= pWithContents pBlocks))+ ,("place", \_ _ fields -> do+ ignored "parameters of place"+ getField "body" fields >>= pWithContents pBlocks)+ ,("columns", \_ _ fields -> do+ (cnt :: Integer) <- getField "count" fields+ B.divWith ("", ["columns-flow"], [("count", T.pack (show cnt))])+ <$> (getField "body" fields >>= pWithContents pBlocks))+ ,("rect", \_ _ fields ->+ B.divWith ("", ["rect"], []) <$> (getField "body" fields >>= pWithContents pBlocks))+ ,("circle", \_ _ fields ->+ B.divWith ("", ["circle"], []) <$> (getField "body" fields >>= pWithContents pBlocks))+ ,("ellipse", \_ _ fields ->+ B.divWith ("", ["ellipse"], []) <$> (getField "body" fields >>= pWithContents pBlocks))+ ,("polygon", \_ _ fields ->+ B.divWith ("", ["polygon"], []) <$> (getField "body" fields >>= pWithContents pBlocks))+ ,("square", \_ _ fields ->+ B.divWith ("", ["square"], []) <$> (getField "body" fields >>= pWithContents pBlocks))+ ,("align", \_ _ fields -> do+ alignment <- getField "alignment" fields+ B.divWith ("", [], [("align", repr alignment)])+ <$> (getField "body" fields >>= pWithContents pBlocks))+ ,("stack", \_ _ fields -> do+ (dir :: Direction) <- getField "dir" fields `mplus` pure Ltr+ rawchildren <- getField "children" fields+ children <-+ mapM+ ( \case+ val@(VFraction {}) ->+ pure $ B.divWith ("", [], [("space", repr val)]) mempty+ val -> fromVal val >>= pWithContents pBlocks+ )+ (V.toList rawchildren)+ pure $+ 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+ body <- getField "body" fields >>= pWithContents pBlocks+ (mbCaption :: Maybe (Seq Content)) <- getField "caption" fields+ (caption :: B.Blocks) <- maybe mempty (pWithContents pBlocks) mbCaption+ pure $ case B.toList body of+ [B.Table attr _ colspecs thead tbodies tfoot] ->+ B.singleton+ (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 ->+ case ( M.lookup "start" fields+ >> M.lookup "end" fields+ >> M.lookup "angle" fields ) of+ Nothing -> pure B.horizontalRule+ _ -> pure mempty)+ ,("numbering", \_ _ fields -> do+ numStyle <- getField "numbering" fields+ (nums :: V.Vector Integer) <- getField "numbers" fields+ let toText v = fromMaybe "" $ fromVal v+ let toNum n =+ case numStyle of+ VString t -> formatNumber t (fromIntegral n)+ VFunction _ _ f ->+ case applyPureFunction f [VInteger n] of+ Success x -> toText x+ Failure _ -> "?"+ _ -> "?"+ pure $ B.plain . B.text . mconcat . map toNum $ V.toList nums)+ ,("footnote.entry", \_ _ fields ->+ getField "body" fields >>= pWithContents pBlocks)+ ,("pad", \_ _ fields -> -- ignore paddingy+ getField "body" fields >>= pWithContents pBlocks)+ ,("pagebreak", \_ _ _ -> pure $ B.divWith ("", ["page-break"], [("wrapper", "1")]) B.horizontalRule)+ ,("bibliography", \_ _ fields -> do+ let getSources v = case v of+ VString t -> MetaString t+ VArray xs -> MetaList $ map getSources $ V.toList xs+ _ -> MetaBool True -- should not occur+ let mbSources = getSources <$> M.lookup "sources" fields++ let updateBibliography x = updateState $ \s ->+ s{ sMeta = B.setMeta "bibliography" x (sMeta s) }+ maybe (pure ()) updateBibliography mbSources++ let title' = M.lookup "title" fields+ mbTitle <- case title' of+ Just VNone -> pure Nothing+ Just (VContent cs) -> Just <$> pWithContents pInlines cs+ Just (VString t) -> pure $ Just $ B.text t+ _ -> Just . B.text <$> lift (translateTerm References)+ let hdr = maybe mempty (B.header 1) mbTitle+ pure $ hdr <> B.divWith ("refs", [], []) mempty)+ ,("rotate", \_ _ fields -> do+ body <- getField "body" fields >>= pWithContents pBlocks+ let kvs = case M.lookup "angle" fields of+ Just (VAngle ang) -> [("angle", T.pack $ show ang)]+ _ -> []+ pure $ B.divWith ("", ["rotate"], kvs) body)+ ]++inlineHandlers :: PandocMonad m =>+ M.Map Identifier (Maybe SourcePos -> Maybe Text ->+ M.Map Identifier Val -> P m B.Inlines)+inlineHandlers = M.fromList+ [("ref", \_ _ fields -> do+ VLabel target <- getField "target" fields+ supplement' <- getField "supplement" fields+ supplement <- case supplement' of+ VAuto -> -- TODO for now, until we can locate the element+ pure $ B.text ("[" <> target <> "]")+ VContent cs -> pWithContents pInlines cs+ VFunction _ _ _f -> -- TODO for now, until we can locate the element+ pure $ B.text ("[" <> target <> "]")+ _ -> pure mempty+ pure $ B.linkWith ("", ["ref"], []) ("#" <> target) "" supplement)+ ,("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 ->+ B.note <$> (getField "body" fields >>= pWithContents pBlocks))+ ,("cite", \_ _ fields -> do+ VLabel key <- getField "key" fields+ (form :: Text) <- getField "form" fields <|> pure "normal"+ let citation =+ B.Citation+ { B.citationId = key,+ B.citationPrefix = mempty,+ B.citationSuffix = mempty,+ B.citationMode = case form of+ "year" -> B.SuppressAuthor+ _ -> B.NormalCitation,+ B.citationNoteNum = 0,+ B.citationHash = 0+ }+ pure $ B.cite [citation] (B.text $ "[" <> key <> "]"))+ ,("lower", \_ _ fields -> do+ body <- getField "text" fields+ walk (modString T.toLower) <$> pWithContents pInlines body)+ ,("upper", \_ _ fields -> do+ body <- getField "text" fields+ walk (modString T.toUpper) <$> pWithContents pInlines body)+ ,("emph", \_ _ fields -> do+ body <- getField "body" fields+ B.emph <$> pWithContents pInlines body)+ ,("strong", \_ _ fields -> do+ body <- getField "body" fields+ B.strong <$> pWithContents pInlines body)+ ,("sub", \_ _ fields -> do+ body <- getField "body" fields+ B.subscript <$> pWithContents pInlines body)+ ,("super", \_ _ fields -> do+ body <- getField "body" fields+ B.superscript <$> pWithContents pInlines body)+ ,("strike", \_ _ fields -> do+ body <- getField "body" fields+ B.strikeout <$> pWithContents pInlines body)+ ,("smallcaps", \_ _ fields -> do+ body <- getField "body" fields+ B.smallcaps <$> pWithContents pInlines body)+ ,("underline", \_ _ fields -> do+ body <- getField "body" fields+ B.underline <$> pWithContents pInlines body)+ ,("quote", \_ _ fields -> do+ (getField "block" fields <|> pure False) >>= guard . not+ body <- getInlineBody fields >>= pWithContents pInlines+ pure $ B.doubleQuoted $ B.trimInlines body)+ ,("link", \_ _ fields -> do+ dest <- getField "dest" fields+ src <- case dest of+ VString t -> pure t+ VLabel t -> pure $ "#" <> t+ VDict _ -> do+ ignored "link to location, linking to #"+ pure "#"+ _ -> fail "Expected string or label for dest"+ body <- getField "body" fields+ description <-+ if null body+ then+ pure $+ B.text $+ if "mailto:" `T.isPrefixOf` src+ then T.drop 7 src+ else+ if "tel:" `T.isPrefixOf` src+ then T.drop 4 src+ else src+ else pWithContents pInlines body <|>+ pWithContents+ (B.fromList . blocksToInlines . B.toList <$> pBlocks) body+ pure $ B.link src "" description)+ ,("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) <-+ fmap (renderLength False) <$> getField "height" fields+ let attr =+ ( "",+ [],+ maybe [] (\x -> [("width", x)]) mbwidth+ ++ maybe [] (\x -> [("height", x)]) mbheight+ )+ pure $ B.imageWith attr path' "" alt)+ ,("box", \_ _ fields -> do+ body <- getField "body" fields+ B.spanWith ("", ["box"], []) <$> pWithContents pInlines body)+ ,("h", \_ _ fields -> do+ amount <- getField "amount" fields `mplus` pure (LExact 1 LEm)+ let em = case amount of+ LExact x LEm -> toRational x+ _ -> case amount <> LExact 0 LPt of -- force to Pt+ LExact x LPt -> toRational x / 12+ _ -> 1 / 3 -- guess!+ pure $ B.text $ getSpaceChars em)+ ,("place", \_ _ fields -> do+ ignored "parameters of place"+ getField "body" fields >>= pWithContents pInlines)+ ,("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+ body <- getField "body" fields+ display <- getField "block" fields+ (if display then B.displayMath else B.math) . writeTeX <$> pMathMany body)+ ,("pad", \_ _ fields -> -- ignore paddingy+ getField "body" fields >>= pWithContents pInlines)+ ,("block", \_ mbident fields ->+ maybe id (\ident -> B.spanWith (ident, [], [])) mbident+ <$> (getField "body" fields >>= pWithContents pInlines))+ ,("rotate", \_ _ fields -> do+ body <- getField "body" fields >>= pWithContents pInlines+ let kvs = case M.lookup "angle" fields of+ Just (VAngle ang) -> [("angle", T.pack $ show ang)]+ _ -> []+ pure $ B.spanWith ("", ["rotate"], kvs) body)+ ]++getInlineBody :: PandocMonad m => M.Map Identifier Val -> P m (Seq Content)+getInlineBody fields =+ parbreaksToLinebreaks <$> getField "body" fields++parbreaksToLinebreaks :: Seq Content -> Seq Content+parbreaksToLinebreaks =+ fmap go . Seq.dropWhileL isParbreak . Seq.dropWhileR isParbreak+ where+ go (Elt "parbreak" pos _) = Elt "linebreak" pos mempty+ go x = x+ isParbreak (Elt "parbreak" _ _) = True+ isParbreak _ = False++pPara :: PandocMonad m => P m B.Blocks+pPara = do+ ils <- B.trimInlines . collapseAdjacentCites . mconcat <$> many1 pInline+ optional pParBreak+ pure $ if ils == mempty+ then mempty+ else B.para ils++pParBreak :: PandocMonad m => P m ()+pParBreak =+ void $+ pTok+ ( \case+ Elt "parbreak" _ _ -> True+ _ -> False+ )++pWithContents :: PandocMonad m => P m a -> Seq Content -> P m a+pWithContents pa cs = try $ do+ inp <- getInput+ setInput $ F.toList cs+ res <- pa+ eof+ setInput inp+ pure res++pInlines :: PandocMonad m => P m B.Inlines+pInlines =+ mappend <$> (collapseAdjacentCites . mconcat <$> many pInline)+ <*> ((B.softbreak <$ pParBreak) <|> pure mempty)++collapseAdjacentCites :: B.Inlines -> B.Inlines+collapseAdjacentCites = B.fromList . foldr go [] . B.toList+ where+ go (Cite cs1 ils1) (Cite cs2 ils2 : xs) =+ Cite (cs1 ++ cs2) (ils1 <> ils2) : xs+ go (Cite cs1 ils1) (Space : Cite cs2 ils2 : xs) =+ Cite (cs1 ++ cs2) (ils1 <> ils2) : xs+ go x xs = x:xs++modString :: (Text -> Text) -> B.Inline -> B.Inline+modString f (B.Str t) = B.Str (f t)+modString _ x = x++findLabels :: Seq.Seq Content -> [Text]+findLabels = foldr go []+ where+ go (Txt{}) = id+ go (Lab t) = (t :)+ go (Elt{ eltFields = fs }) = \ts -> foldr go' ts fs+ go' (VContent cs) = (findLabels cs ++)+ go' _ = id++parseTable :: PandocMonad m+ => Maybe Text -> M.Map Identifier Val -> P m B.Blocks+parseTable mbident fields = do+ children <- V.toList <$> getField "children" fields+ (columns :: Val) <- getField "columns" fields+ let toWidth (VFraction f) = Just (floor $ 1000 * f)+ toWidth _ = Nothing+ let normalizeWidths xs =+ let givenwidths = catMaybes xs+ (totgivenwidth :: Int) = sum givenwidths+ avgwidth = totgivenwidth `div` length givenwidths+ totwidth = avgwidth * length xs+ in if null givenwidths+ then replicate (length xs) B.ColWidthDefault+ else+ map+ ( \case+ Just x ->+ B.ColWidth (fromIntegral x / fromIntegral totwidth)+ Nothing ->+ B.ColWidth+ (fromIntegral avgwidth / fromIntegral totwidth)+ )+ xs+ widths <- case columns of+ VInteger x -> pure $ replicate (fromIntegral x) B.ColWidthDefault+ VArray x -> pure $ normalizeWidths $ map toWidth (V.toList x)+ VNone -> pure [B.ColWidthDefault]+ _ -> fail $ "Could not determine number of columns: " <> show columns+ let numcols = length widths+ align <- getField "align" fields+ let toAlign (VAlignment (Just horiz) _) =+ case horiz of+ HorizStart -> B.AlignLeft+ HorizLeft -> B.AlignLeft+ HorizEnd -> B.AlignRight+ HorizRight -> B.AlignRight+ HorizCenter -> B.AlignCenter+ toAlign _ = B.AlignDefault+ aligns <-+ case align of+ VAlignment {} -> pure $ replicate numcols (toAlign align)+ VArray v -> pure $ map toAlign (V.toList v)+ VFunction _ _ f -> do+ mapM+ ( \colnum -> case applyPureFunction+ f+ [VInteger colnum, VInteger 0] of+ Success x -> pure $ toAlign x+ Failure e -> fail e+ )+ [0 .. (fromIntegral numcols - 1)]+ _ -> pure $ replicate numcols B.AlignDefault+ let colspecs = zip (aligns ++ repeat B.AlignDefault) widths+ let addCell' cell Nothing = addCell' cell (Just ([], []))+ addCell' cell@(B.Cell _ _ (B.RowSpan rowspan) (B.ColSpan colspan) _)+ (Just (freecols, revrows)) =+ let freecols' =+ case (rowspan + 1) - length freecols of+ n | n < 0 -> freecols+ | otherwise -> freecols ++ replicate n numcols+ in case freecols' of+ [] -> -- should not happen+ error "empty freecols'"+ x:xs+ | colspan <= x -- there is room on current row+ -> let (as, bs) = splitAt rowspan (x:xs)+ in Just+ (map (\z -> z - colspan) as ++ bs,+ case revrows of+ [] -> [[cell]]+ r:rs -> (cell:r):rs)+ | otherwise ->+ let (as, bs) = splitAt rowspan xs+ in Just (map (\z -> z - colspan) as ++ bs, [cell]:revrows)+ let addCell tableSection cell (TableData tdata) =+ TableData (M.alter (addCell' cell) tableSection tdata)+ let toCell tableSection tableData contents = do+ case contents of+ [Elt (Identifier "grid.cell") _pos fs] -> do+ bs <- B.toList <$> (getField "body" fs >>= pWithContents pBlocks)+ rowspan <- getField "rowspan" fs <|> pure 1+ colspan <- getField "colspan" fs <|> pure 1+ align' <- (toAlign <$> getField "align" fs) <|> pure B.AlignDefault+ pure $ addCell tableSection+ (B.Cell B.nullAttr align' (B.RowSpan rowspan)+ (B.ColSpan colspan) bs) tableData+ [Elt (Identifier "table.cell") pos fs] ->+ toCell tableSection tableData [Elt (Identifier "grid.cell") pos fs]+ [Elt (Identifier "table.vline") _pos _fs] -> pure tableData+ [Elt (Identifier "table.hline") _pos _fs] -> pure tableData+ [Elt (Identifier "grid.vline") _pos _fs] -> pure tableData+ [Elt (Identifier "grid.hline") _pos _fs] -> pure tableData+ [Elt (Identifier "table.header") _pos fs] ->+ getField "children" fs >>=+ foldM (toCell THeader) tableData . V.toList+ [Elt (Identifier "table.footer") _pos fs] ->+ getField "children" fs >>=+ foldM (toCell TFooter) tableData . V.toList+ _ -> do+ bs <- B.toList <$> pWithContents pBlocks contents+ pure $ addCell tableSection+ (B.Cell B.nullAttr B.AlignDefault (B.RowSpan 1) (B.ColSpan 1) bs)+ tableData+ tableData <- foldM (toCell TBody) (TableData mempty) children+ let getRows tablePart = map (B.Row B.nullAttr . reverse)+ . maybe [] (reverse . snd)+ . M.lookup tablePart . unTableData+ let headRows = getRows THeader tableData+ let bodyRows = getRows TBody tableData+ let footRows = getRows TFooter tableData+ pure $+ B.tableWith+ (fromMaybe "" mbident, [], [])+ (B.Caption mempty mempty)+ colspecs+ (B.TableHead B.nullAttr headRows)+ [B.TableBody B.nullAttr 0 [] bodyRows]+ (B.TableFoot B.nullAttr footRows)++data TableSection = THeader | TBody | TFooter+ deriving (Show, Ord, Eq)++newtype TableData =+ TableData { unTableData :: M.Map TableSection ([Int], [[Cell]]) }+ deriving (Show)+ -- for each table section, we have a pair+ -- the first element indicates the number of column spaces left+ -- in [currentLine, nextLine, lineAfter, etc.]+ -- the second element is a list of rows, in reverse order,+ -- each of which is a list of cells, in reverse order
@@ -0,0 +1,421 @@+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Text.Pandoc.Readers.Typst.Math+ ( pMathMany+ )+where++import Control.Monad (MonadPlus (mplus))+import Data.Char (isAlphaNum, isDigit)+import Data.List (intercalate)+import qualified Data.Map as M+import Data.Maybe (fromMaybe)+import Data.Sequence (Seq)+import qualified Data.Sequence as Seq+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Vector as V+import Text.Pandoc.Parsing ( many )+import Text.Pandoc.Class ( PandocMonad )+import Text.TeXMath.Types+ ( Alignment (..),+ Exp (..),+ FractionType (..),+ TeXSymbolType (..),+ TextType (..),+ )+import Text.TeXMath.Unicode.ToTeX (getSymbolType)+import Text.Pandoc.Readers.Typst.Parsing+ ( P, pTok, ignored, pWithContents, getField, chunks )+import Typst.Types++withGroup :: [Exp] -> Exp+withGroup [x] = x+withGroup xs = EGrouped xs++data AttachmentStyle = Limits | LimitsDisplay | Scripts+ deriving (Eq, Show)++getAttachmentStyle :: PandocMonad m => M.Map Identifier Val -> P m (Maybe AttachmentStyle)+getAttachmentStyle fields = do+ (base :: Seq Content) <- getField "base" fields+ case base of+ [Elt "math.op" _ fs] -> do+ limits <- getField "limits" fs+ if limits == VBoolean True+ then pure $ Just Limits+ else pure Nothing+ [Elt "math.limits" _ fs] -> do+ inl <- getField "inline" fs+ if inl == VBoolean False+ then pure $ Just LimitsDisplay+ else pure $ Just Limits+ [Elt "math.scripts" _ _] -> pure $ Just Scripts+ _ -> pure Nothing++pMath :: PandocMonad m => P m Exp+pMath = pTok (const True) >>= handleMath++handleMath :: PandocMonad m => Content -> P m Exp+handleMath tok =+ case tok of+ Lab t -> do+ ignored ("label " <> t)+ pure (EGrouped [])+ Txt t+ | T.any isDigit t -> pure $ ENumber t+ | T.length t == 1 ->+ case T.unpack t of+ [c] | not (isAlphaNum c) -> pure $ ESymbol (getSymbolType c) t+ _ -> pure $ EIdentifier t+ | otherwise -> pure $ EText TextNormal t+ Elt "math.dif" _ _ -> pure $ EIdentifier "d"+ Elt "math.Dif" _ _ -> pure $ EIdentifier "D"+ Elt "math.equation" _ fields -> getField "body" fields >>= pMathGrouped+ Elt "text" _ fields -> do+ body <- getField "body" fields+ (mbweight :: Maybe Text) <- getField "weight" fields+ case mbweight of+ Just "bold" -> EStyled TextBold <$> pMathMany body+ _ -> pMathGrouped body+ Elt "math.op" _ fields -> EMathOperator <$> getField "text" fields+ Elt "math.frac" _ fields -> do+ num <- getField "num" fields >>= pMathGrouped+ denom <- getField "denom" fields >>= pMathGrouped+ pure $ EFraction NormalFrac num denom+ Elt "math.accent" _ fields -> do+ base <- getField "base" fields >>= pMathGrouped+ acc <- getField "accent" fields >>= pMathGrouped+ let acc' = case acc of+ ESymbol _ "\8901" -> ESymbol Accent "\775" -- \dot+ ESymbol _ "\168" -> ESymbol Accent "\776" -- \ddot+ ESymbol _ "\8764" -> ESymbol Accent "\771" -- \tilde+ ESymbol _ t -> ESymbol Accent t+ _ -> acc+ pure $ EOver False base acc'+ Elt "math.attach" _ fields -> do+ base <- getField "base" fields >>= pMathGrouped+ t' <- getField "t" fields+ b' <- getField "b" fields+ tr' <- getField "tr" fields+ tl' <- getField "tl" fields+ br' <- getField "br" fields+ bl' <- getField "bl" fields+ attachmentStyle <- getAttachmentStyle fields+ let limits = case attachmentStyle of+ Just Limits -> True+ Just LimitsDisplay -> True+ _ -> False+ let convertible = attachmentStyle == Just LimitsDisplay+ let (mbt, mbtr) =+ case (t', tr') of+ (Just top, Just topright) -> (Just top, Just topright)+ (Just top, Nothing)+ | limits -> (Just top, Nothing)+ | otherwise -> (Nothing, Just top)+ (Nothing, Just topright) -> (Nothing, Just topright)+ (Nothing, Nothing) -> (Nothing, Nothing)+ let (mbb, mbbr) =+ case (b', br') of+ (Just bot, Just botright) -> (Just bot, Just botright)+ (Just bot, Nothing)+ | limits -> (Just bot, Nothing)+ | otherwise -> (Nothing, Just bot)+ (Nothing, Just topright) -> (Nothing, Just topright)+ (Nothing, Nothing) -> (Nothing, Nothing)+ let dummy = EGrouped []+ let addPrefix x =+ case (tl', bl') of+ (Nothing, Nothing) -> pure x+ (Just top, Nothing) -> do+ res <- ESuper dummy <$> pMathGrouped top+ pure $ EGrouped [res, x]+ (Nothing, Just bot) -> do+ res <- ESub dummy <$> pMathGrouped bot+ pure $ EGrouped [res, x]+ (Just top, Just bot) -> do+ res <- ESubsup dummy <$> pMathGrouped bot <*> pMathGrouped top+ pure $ EGrouped [res, x]++ base' <- case (mbtr, mbbr) of+ (Nothing, Nothing) -> pure base+ (Nothing, Just br) -> ESub base <$> pMathGrouped br+ (Just tr, Nothing) -> ESuper base <$> pMathGrouped tr+ (Just tr, Just br) -> ESubsup base <$> pMathGrouped br <*> pMathGrouped tr++ suffix <- case (mbt, mbb) of+ (Nothing, Nothing) -> pure base'+ (Nothing, Just bot) -> EUnder convertible base' <$> pMathGrouped bot+ (Just top, Nothing) -> EOver convertible base' <$> pMathGrouped top+ (Just top, Just bot) -> EUnderover convertible base'+ <$> pMathGrouped bot <*> pMathGrouped top++ addPrefix suffix+ Elt "math.serif" _ fields ->+ EStyled TextNormal <$> (getField "body" fields >>= pMathMany)+ Elt "math.sans" _ fields ->+ EStyled TextSansSerif <$> (getField "body" fields >>= pMathMany)+ Elt "math.frak" _ fields ->+ EStyled TextFraktur <$> (getField "body" fields >>= pMathMany)+ Elt "math.mono" _ fields ->+ EStyled TextMonospace <$> (getField "body" fields >>= pMathMany)+ Elt "math.cal" _ fields ->+ EStyled TextScript <$> (getField "body" fields >>= pMathMany)+ Elt "math.bb" _ fields ->+ EStyled TextDoubleStruck <$> (getField "body" fields >>= pMathMany)+ Elt "math.upright" _ fields ->+ EStyled TextNormal <$> (getField "body" fields >>= pMathMany)+ Elt "math.bold" _ fields ->+ EStyled TextBold <$> (getField "body" fields >>= pMathMany)+ Elt "math.italic" _ fields ->+ EStyled TextItalic <$> (getField "body" fields >>= pMathMany)+ Elt "math.underline" _ fields ->+ EUnder False+ <$> (getField "body" fields >>= pMathGrouped)+ <*> pure (ESymbol TUnder "_")+ Elt "math.overline" _ fields ->+ EOver False+ <$> (getField "body" fields >>= pMathGrouped)+ <*> pure (ESymbol TOver "\175")+ Elt "math.underbrace" _ fields -> do+ mbAnn <- getField "annotation" fields+ body <- getField "body" fields >>= pMathGrouped+ let x = EUnder False body (ESymbol TUnder "\9183")+ case mbAnn of+ Nothing -> pure x+ Just ann -> EUnder False x <$> pMathGrouped ann+ Elt "math.overbrace" _ fields -> do+ mbAnn <- getField "annotation" fields+ body <- getField "body" fields >>= pMathGrouped+ let x = EOver False body (ESymbol TOver "\9182")+ case mbAnn of+ Nothing -> pure x+ Just ann -> EOver False x <$> pMathGrouped ann+ Elt "math.underbracket" _ fields -> do+ mbAnn <- getField "annotation" fields+ body <- getField "body" fields >>= pMathGrouped+ let x = EUnder False body (ESymbol TUnder "\9141")+ case mbAnn of+ Nothing -> pure x+ Just ann -> EUnder False x <$> pMathGrouped ann+ Elt "math.overbracket" _ fields -> do+ mbAnn <- getField "annotation" fields+ body <- getField "body" fields >>= pMathGrouped+ let x = EOver False body (ESymbol TOver "\9140")+ case mbAnn of+ Nothing -> pure x+ Just ann -> EOver False x <$> pMathGrouped ann+ Elt "math.underparen" _ fields -> do+ mbAnn <- getField "annotation" fields+ body <- getField "body" fields >>= pMathGrouped+ let x = EUnder False body (ESymbol TUnder "\9181")+ case mbAnn of+ Nothing -> pure x+ Just ann -> EUnder False x <$> pMathGrouped ann+ Elt "math.overparen" _ fields -> do+ mbAnn <- getField "annotation" fields+ body <- getField "body" fields >>= pMathGrouped+ let x = EOver False body (ESymbol TOver "\9180")+ case mbAnn of+ Nothing -> pure x+ Just ann -> EOver False x <$> pMathGrouped ann+ Elt "math.scripts" _ fields -> getField "body" fields >>= pMathGrouped+ Elt "math.limits" _ fields -> getField "body" fields >>= pMathGrouped+ Elt "math.root" _ fields -> do+ mbindex <- getField "index" fields+ radicand <- getField "radicand" fields >>= pMathGrouped+ case mbindex of+ Nothing -> pure $ ESqrt radicand+ Just index -> do+ index' <- pMathGrouped index+ pure $ ERoot index' radicand+ Elt "math.sqrt" _ fields ->+ ESqrt <$> (getField "radicand" fields >>= pMathGrouped)+ Elt "math.abs" _ fields -> do+ body <- getField "body" fields >>= pMathGrouped+ pure $ EDelimited "|" "|" [Right body]+ Elt "math.floor" _ fields -> do+ body <- getField "body" fields >>= pMathGrouped+ pure $ EDelimited "\8970" "\8971" [Right body]+ Elt "math.ceil" _ fields -> do+ body <- getField "body" fields >>= pMathGrouped+ pure $ EDelimited "\8968" "\8969" [Right body]+ Elt "math.norm" _ fields -> do+ body <- getField "body" fields >>= pMathGrouped+ pure $ EDelimited "\8214" "\8214" [Right body]+ Elt "math.round" _ fields -> do+ body <- getField "body" fields >>= pMathGrouped+ pure $ EDelimited "\8970" "\8969" [Right body]+ Elt "math.lr" _ fields -> do+ bodyparts <- getField "body" fields >>= mapM pMathMany . V.toList+ let rawbody = intercalate [ESymbol Pun ","] bodyparts+ let (op, rest) =+ case rawbody of+ (ESymbol _ t : xs) -> (t, xs)+ _ -> ("", rawbody)+ let (body, cl) =+ case reverse rest of+ (ESymbol _ t : _) -> (map Right (init rest), t)+ _ -> (map Right rest, "")+ pure $ EDelimited op cl body+ Elt "math.binom" _ fields -> do+ up <- getField "upper" fields >>= pMathGrouped+ low <- getField "lower" fields >>= pMathGrouped+ pure $ EDelimited "(" ")" [Right (EFraction NoLineFrac up low)]+ Elt "math.cases" _ fields -> do+ (delim :: Maybe Text) <- getField "delim" fields+ (children :: [Seq Content]) <-+ map valToContent . V.toList <$> getField "children" fields+ let isAlignPoint (Elt "math.alignpoint" _ _) = True+ isAlignPoint _ = False+ let formatRow vs = case Seq.breakl isAlignPoint vs of+ (xs, ys) -> do+ case Seq.viewl ys of+ _ Seq.:< rest -> do+ xs' <- pMathMany xs+ ys' <- pMathMany rest+ pure [xs', ys']+ _ -> (: []) <$> pMathMany vs+ rows <- mapM formatRow children+ pure $+ EDelimited+ (fromMaybe "{" delim)+ ""+ [Right (EArray [AlignLeft, AlignLeft] rows)]+ Elt "math.vec" _ fields -> do+ (op, cl) <- arrayDelims fields+ rows <-+ getField "children" fields+ >>= mapM (fmap (: []) . pMathMany) . V.toList+ pure $+ EDelimited+ op+ cl+ [Right (EArray [AlignCenter] rows)]+ Elt "math.mat" _ fields -> do+ (op, cl) <- arrayDelims fields+ let formatCell x = do+ let content = valToContent x+ let align = case Seq.viewl content of+ Elt "math.alignpoint" _ _ Seq.:< _ -> AlignLeft+ _ -> case Seq.viewr content of+ _ Seq.:> Elt "math.alignpoint" _ _ -> AlignRight+ _ -> AlignCenter+ exp' <- pMathMany content+ pure (align, exp')+ let formatRow (VArray vs) = mapM formatCell (V.toList vs)+ formatRow _ = fail "mat expected array"+ (rawrows :: V.Vector Val) <- getField "rows" fields+ rows <- mapM formatRow (V.toList rawrows)+ let aligns =+ case rows of+ [] -> []+ (r : _) -> map fst r+ pure $+ EDelimited+ op+ cl+ [Right (EArray aligns (map (map snd) rows))]+ Elt "hide" _ fields -> do+ EPhantom <$> (getField "body" fields >>= pMathGrouped)+ Elt "h" _ fields -> do+ amount <- getField "amount" fields+ let em = case amount of+ LExact x LEm -> toRational x+ _ -> case amount <> LExact 0 LPt of -- force to Pt+ LExact x LPt -> toRational x / 12+ _ -> 1 / 3 -- guess!+ pure $ ESpace em+ Elt "grid" _ fields -> do+ children <- getField "children" fields >>= mapM pMathMany . V.toList+ (columns :: Val) <- getField "columns" fields+ numcols <- case columns of+ VInteger x -> pure $ fromIntegral x+ VArray x -> pure $ V.length x+ VNone -> pure 1+ _ -> fail $ "Could not determine number of columns: " <> show columns+ let rows = chunks numcols children+ pure $ EArray (replicate numcols AlignLeft) rows+ Elt "table" pos fields -> handleMath (Elt "grid" pos fields)+ Elt "link" _ fields -> do+ body <- getField "body" fields+ ignored "hyperlink in math"+ pMathGrouped body+ Elt "math.display" _ fields -> do+ content <- getField "content" fields+ ignored "display"+ pMathGrouped content+ Elt "math.inline" _ fields -> do+ content <- getField "content" fields+ ignored "inline"+ pMathGrouped content+ Elt "math.script" _ fields -> do+ content <- getField "content" fields+ ignored "script"+ pMathGrouped content+ Elt "math.sscript" _ fields -> do+ content <- getField "content" fields+ ignored "sscript"+ pMathGrouped content+ Elt (Identifier name) _ fields -> do+ body <- getField "body" fields `mplus` pure mempty+ ignored name+ pMathGrouped body++arrayDelims :: PandocMonad m => M.Map Identifier Val -> P m (Text, Text)+arrayDelims fields = do+ (mbdelim :: Maybe Text) <- getField "delim" fields+ pure $ case mbdelim of+ Just "(" -> ("(", ")")+ Just "[" -> ("[", "]")+ Just "{" -> ("{", "}")+ Just "|" -> ("|", "|")+ Just "||" -> ("\8741", "\8741")+ _ -> ("(", ")")++pMathMany :: PandocMonad m => Seq Content -> P m [Exp]+pMathMany cs = do+ -- check for "alignpoint" and "linebreak" elements+ -- and use an array structure for alignment+ let lns = splitOnLinebreaks cs+ case lns of+ [] -> pure []+ [ln] | not (any isAlignpoint ln) -> pWithContents (many pMath) ln+ _ -> do+ rows <- mapM (mapM (pWithContents (many pMath)) . splitOnAlignpoints) lns+ let numcols = maximum $ map length rows+ let cols = take numcols $ AlignRight : cycle [AlignLeft, AlignRight]+ pure [EArray cols rows]++pMathGrouped :: PandocMonad m => Seq Content -> P m Exp+pMathGrouped = fmap withGroup . pMathMany++splitOnLinebreaks :: Seq Content -> [Seq Content]+splitOnLinebreaks xs =+ if Seq.null bs+ then+ if null as+ then []+ else [as]+ else as : splitOnLinebreaks (Seq.drop 1 bs)+ where+ (as, bs) = Seq.breakl isLinebreak xs+ isLinebreak (Elt "linebreak" _ _) = True+ isLinebreak _ = False++splitOnAlignpoints :: Seq Content -> [Seq Content]+splitOnAlignpoints xs =+ if Seq.null bs+ then+ if null as+ then []+ else [as]+ else as : splitOnAlignpoints (Seq.drop 1 bs)+ where+ (as, bs) = Seq.breakl isAlignpoint xs++isAlignpoint :: Content -> Bool+isAlignpoint (Elt "math.alignpoint" _ _) = True+isAlignpoint _ = False
@@ -0,0 +1,76 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Text.Pandoc.Readers.Typst.Parsing+ ( P,+ PState(..),+ defaultPState,+ pTok,+ pWithContents,+ ignored,+ getField,+ chunks,+ )+where+import Control.Monad (MonadPlus)+import Control.Monad.Reader (lift)+import qualified Data.Foldable as F+import qualified Data.Map as M+import Data.Maybe (fromMaybe)+import Data.Sequence (Seq)+import Data.Text (Text)+import Text.Parsec+ ( ParsecT, getInput, setInput, tokenPrim )+import Typst.Types+ ( Identifier, Content(Elt), FromVal(..), Val(VNone) )+import Text.Pandoc.Class.PandocMonad ( PandocMonad, report )+import Text.Pandoc.Logging (LogMessage(..))+import Text.Pandoc.Definition++data PState = PState+ { sLabels :: [Text]+ , sMeta :: Meta }+ deriving (Show)++defaultPState :: PState+defaultPState =+ PState+ { sLabels = []+ , sMeta = mempty }++type P m a = ParsecT [Content] PState m a+-- state tracks a list of labels in the document++pTok :: PandocMonad m => (Content -> Bool) -> P m Content+pTok f = tokenPrim show showPos match+ where+ showPos _oldpos (Elt _ (Just pos) _) _ = pos+ showPos oldpos _ _ = oldpos+ match x | f x = Just x+ match _ = Nothing++ignored :: PandocMonad m => Text -> P m ()+ignored msg = lift $ report $ IgnoredElement msg++pWithContents :: PandocMonad m => P m a -> Seq Content -> P m a+pWithContents pa cs = do+ inp <- getInput+ setInput $ F.toList cs+ res <- pa+ setInput inp+ pure res++-- | Get field value from element, defaulting to VNone.+getField ::+ (MonadFail m, MonadPlus m, FromVal a) =>+ Identifier ->+ M.Map Identifier Val ->+ m a+getField name fields = fromVal $ fromMaybe VNone $ M.lookup name fields++-- | Split a list into chunks of a given size. The last chunk may be smaller.+chunks :: Int -> [a] -> [[a]]+chunks _ [] = []+chunks n xs = take n xs : chunks n (drop n xs)
@@ -54,35 +54,28 @@ import Data.Maybe import Data.Text (Text) import qualified Data.Text as T+import Safe (lastMay) import Text.Pandoc.Builder (Blocks, Inlines, fromList, toList, trimInlines)-import qualified Text.Pandoc.Builder as B (blockQuote, bulletList, code,- codeBlockWith, definitionList,- displayMath, divWith, emph,- headerWith, horizontalRule, image,- imageWith, link, math, orderedList,- para, plain, setMeta, simpleTable,- softbreak, space, spanWith, str,- strikeout, strong, subscript,- superscript)+import qualified Text.Pandoc.Builder as B import Text.Pandoc.Class.PandocMonad (PandocMonad (..)) import Text.Pandoc.Definition (Attr, Block (BulletList, OrderedList), Inline (Space), ListNumberDelim (..), ListNumberStyle (..), Pandoc (..), nullMeta) import Text.Pandoc.Options (ReaderOptions)-import Text.Pandoc.Parsing (ParserState, ParserT, blanklines, emailAddress,+import Text.Pandoc.Parsing (ParserState, ParsecT, blanklines, emailAddress, many1Till, orderedListMarker, readWithM, registerHeader, spaceChar, stateMeta, stateOptions, uri, manyTillChar, manyChar, textStr, many1Char, countChar, many1TillChar, alphaNum, anyChar, char, newline, noneOf, oneOf,- space, spaces, string)+ space, spaces, string, choice, eof, lookAhead,+ many1, many, manyTill, notFollowedBy,+ skipMany1, try, option,+ updateState, getState, (<|>)) import Text.Pandoc.Sources (ToSources(..), Sources)-import Text.Pandoc.Shared (splitTextBy, stringify, stripFirstAndLast,- isURI, tshow)-import Text.Parsec.Combinator (between, choice, eof, lookAhead, many1,- manyTill, notFollowedBy, option, skipMany1)-import Text.Parsec.Prim (getState, many, try, updateState, (<|>))+import Text.Pandoc.Shared (splitTextBy, stringify, stripFirstAndLast, tshow)+import Text.Pandoc.URI (isURI) readVimwiki :: (PandocMonad m, ToSources a) => ReaderOptions@@ -95,7 +88,7 @@ Left e -> throwError e Right result -> return result -type VwParser = ParserT Sources ParserState+type VwParser = ParsecT Sources ParserState -- constants@@ -249,14 +242,13 @@ nameValue :: Text -> Maybe (Text, Text) nameValue s =- let t = splitTextBy (== '=') s in- if length t /= 2- then Nothing- else let (a, b) = (head t, last t) in- if (T.length b < 2) || ((T.head b, T.last b) /= ('"', '"'))- then Nothing- else Just (a, stripFirstAndLast b)-+ case splitTextBy (== '=') s of+ [a,b]+ | T.length b >= 2+ , "\"" `T.isPrefixOf` b+ , "\"" `T.isSuffixOf` b+ -> Just (a, stripFirstAndLast b)+ _ -> Nothing displayMath :: PandocMonad m => VwParser m Blocks displayMath = try $ do@@ -291,8 +283,8 @@ mixedList :: PandocMonad m => VwParser m Blocks mixedList = try $ do- (bl, _) <- mixedList' (-1)- return $ head bl+ ((bl:_), _) <- mixedList' (-1)+ return bl mixedList' :: PandocMonad m => Int -> VwParser m ([Blocks], Int) mixedList' prevInd = do@@ -345,8 +337,9 @@ listTodoMarker :: PandocMonad m => VwParser m Inlines listTodoMarker = try $ do- x <- between (many spaceChar >> char '[') (char ']' >> spaceChar)- (oneOf " .oOX")+ x <- (many spaceChar >> char '[')+ *> oneOf " .oOX"+ <* (char ']' >> spaceChar) return $ makeListMarkerSpan x makeListMarkerSpan :: Char -> Inlines@@ -406,8 +399,8 @@ -- headerless table table2 :: PandocMonad m => VwParser m ([Blocks], [[Blocks]]) table2 = try $ do- trs <- many1 tableRow- return (replicate (length $ head trs) mempty, trs)+ trs@(firstrow:_) <- many1 tableRow+ return (replicate (length firstrow) mempty, trs) tableHeaderSeparator :: PandocMonad m => VwParser m () tableHeaderSeparator = try $ do@@ -506,26 +499,23 @@ strong :: PandocMonad m => VwParser m Inlines strong = try $ do- s <- lookAhead $ between (char '*') (char '*') (many1 $ noneOf "*")- guard $ (head s `notElem` spaceChars)- && (last s `notElem` spaceChars) char '*'- contents <- mconcat <$>manyTill inline' (char '*'- >> notFollowedBy alphaNum)- return $ B.spanWith (makeId contents, [], []) mempty- <> B.strong contents+ notFollowedBy (oneOf spaceChars)+ contents <- mconcat <$> many1Till inline'+ (try (char '*' *> notFollowedBy alphaNum))+ guard $ lastMay (toList contents) /= Just Space+ return $ B.spanWith (makeId contents, [], []) mempty <> B.strong contents makeId :: Inlines -> Text makeId i = T.concat (stringify <$> toList i) emph :: PandocMonad m => VwParser m Inlines emph = try $ do- s <- lookAhead $ between (char '_') (char '_') (many1 $ noneOf "_")- guard $ (head s `notElem` spaceChars)- && (last s `notElem` spaceChars) char '_'- contents <- mconcat <$>manyTill inline' (char '_'- >> notFollowedBy alphaNum)+ notFollowedBy (oneOf spaceChars)+ contents <- mconcat <$> many1Till inline'+ (try (char '_' *> notFollowedBy alphaNum))+ guard $ lastMay (toList contents) /= Just Space return $ B.emph contents strikeout :: PandocMonad m => VwParser m Inlines@@ -557,17 +547,14 @@ then do url <- manyTillChar anyChar $ char '|' lab <- mconcat <$> manyTill inline (string "]]")- let tit = if isURI url- then ""- else "wikilink"- return $ B.link (procLink url) tit lab+ return $ B.linkWith (attr url) (procLink url) "" lab else do manyTill anyChar (string "]]") -- not using try here because [[hell]o]] is not rendered as a link in vimwiki- let tit = if isURI contents- then ""- else "wikilink"- return $ B.link (procLink contents) tit (B.str contents)+ return $ B.linkWith (attr contents) (procLink contents) "" (B.str contents)+ where+ attr t | isURI t = B.nullAttr+ | otherwise = (mempty, ["wikilink"], mempty) image :: PandocMonad m => VwParser m Inlines image = try $ do@@ -600,8 +587,8 @@ procLink' s | T.take 6 s == "local:" = "file" <> T.drop 5 s | T.take 6 s == "diary:" = "diary/" <> T.drop 6 s- | or ((`T.isPrefixOf` s) <$> [ "http:", "https:", "ftp:", "file:", "mailto:",- "news:", "telnet:" ])+ | any (`T.isPrefixOf` s) [ "http:", "https:", "ftp:", "file:", "mailto:",+ "news:", "telnet:" ] = s | s == "" = "" | T.last s == '/' = s@@ -623,8 +610,9 @@ char ':' s <- manyTillChar (noneOf spaceChars) (try (char ':' >> lookAhead space)) guard $ not $ "::" `T.isInfixOf` (":" <> s <> ":")- let ss = splitTextBy (==':') s- return $ mconcat $ makeTagSpan' (head ss):(makeTagSpan <$> tail ss)+ case splitTextBy (==':') s of+ [] -> fail "tag doesn't contain :"+ (x:xs) -> return $ mconcat $ makeTagSpan' x : (makeTagSpan <$> xs) todoMark :: PandocMonad m => VwParser m Inlines todoMark = try $ do
@@ -0,0 +1,543 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- |+-- Module : Text.Pandoc.Readers.XML+-- Copyright : Copyright (C) 2025- Massimiliano Farinella and John MacFarlane+-- License : GNU GPL, version 2 or above+--+-- Maintainer : Massimiliano Farinella <massifrg@gmail.com>+-- Stability : WIP+-- Portability : portable+--+-- Conversion of (Pandoc specific) xml to 'Pandoc' document.+module Text.Pandoc.Readers.XML (readXML) where++import Control.Monad (msum)+import Control.Monad.Except (throwError)+import Control.Monad.State.Strict (StateT (runStateT), modify)+import Data.Char (isSpace)+import Data.Default (Default (..))+import qualified Data.List as L+import qualified Data.Map as M+import Data.Maybe (catMaybes, fromMaybe, mapMaybe)+import qualified Data.Set as S (Set, fromList, member)+import Data.Text (Text)+import qualified Data.Text as T+import Data.Text.Lazy (fromStrict)+import Data.Version (Version, makeVersion)+import Text.Pandoc.Builder+import Text.Pandoc.Class.PandocMonad+import Text.Pandoc.Error (PandocError (..))+import Text.Pandoc.Options+import Text.Pandoc.Parsing (ToSources, toSources)+import Text.Pandoc.Sources (sourcesToText)+import Text.Pandoc.Version (pandocVersion)+import Text.Pandoc.XML (lookupEntity)+import Text.Pandoc.XML.Light+import Text.Pandoc.XMLFormat+import Text.Read (readMaybe)++-- TODO: use xmlPath state to give better context when an error occurs++type XMLReader m = StateT XMLReaderState m++data XMLReaderState = XMLReaderState+ { xmlApiVersion :: Version,+ xmlMeta :: Meta,+ xmlContent :: [Content],+ xmlPath :: [Text]+ }+ deriving (Show)++instance Default XMLReaderState where+ def =+ XMLReaderState+ { xmlApiVersion = pandocVersion,+ xmlMeta = mempty,+ xmlContent = [],+ xmlPath = ["root"]+ }++readXML :: (PandocMonad m, ToSources a) => ReaderOptions -> a -> m Pandoc+readXML _ inp = do+ let sources = toSources inp+ tree <-+ either (throwError . PandocXMLError "") return $+ parseXMLContents (fromStrict . sourcesToText $ sources)+ (bs, st') <- flip runStateT (def {xmlContent = tree}) $ mapM parseBlock tree+ let blockList = toList $ concatMany bs+ return $ Pandoc (xmlMeta st') blockList++concatMany :: [Many a] -> Many a+concatMany = Many . mconcat . map unMany++parseBlocks :: (PandocMonad m) => [Content] -> XMLReader m Blocks+parseBlocks contents = concatMany <$> mapM parseBlock contents++getBlocks :: (PandocMonad m) => Element -> XMLReader m Blocks+getBlocks e = parseBlocks (elContent e)++elementName :: Element -> Text+elementName e = qName $ elName e++attrValue :: Text -> Element -> Text+attrValue attr =+ fromMaybe "" . maybeAttrValue attr++maybeAttrValue :: Text -> Element -> Maybe Text+maybeAttrValue attr elt =+ lookupAttrBy (\x -> qName x == attr) (elAttribs elt)++parseBlock :: (PandocMonad m) => Content -> XMLReader m Blocks+parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE+parseBlock (Text (CData _ s _)) =+ if T.all isSpace s+ then return mempty+ else do+ throwError $ PandocXMLError "" "non-space characters out of inline context"+parseBlock (CRef x) = do+ throwError $ PandocXMLError "" ("reference \"" <> x <> "\" out of inline context")+parseBlock (Elem e) = do+ let name = elementName e+ in case (name) of+ "Pandoc" -> parsePandoc+ "?xml" -> return mempty+ "blocks" -> getBlocks e+ "meta" ->+ let entry_els = childrenNamed tgNameMetaMapEntry e+ in do+ entries <- catMaybes <$> mapM parseMetaMapEntry entry_els+ mapM_ (uncurry addMeta) entries+ return mempty+ "Para" -> para <$> getInlines (elContent e)+ "Plain" -> do+ ils <- getInlines (elContent e)+ return $ singleton . Plain . toList $ ils+ "Header" -> (headerWith attr level) <$> getInlines (elContent e)+ where+ level = textToInt (attrValue atNameLevel e) 1+ attr = filterAttrAttributes [atNameLevel] $ attrFromElement e+ "HorizontalRule" -> return horizontalRule+ "BlockQuote" -> do+ contents <- getBlocks e+ return $ blockQuote contents+ "Div" -> do+ contents <- getBlocks e+ return $ divWith (attrFromElement e) contents+ "BulletList" -> do+ items <- getListItems e+ return $ bulletList items+ "OrderedList" -> do+ items <- getListItems e+ return $ orderedListWith (getListAttributes e) items+ "DefinitionList" -> do+ let items_contents = getContentsOfElements (isElementNamed tgNameDefListItem) (elContent e)+ items <- mapM parseDefinitionListItem items_contents+ return $ definitionList items+ "Figure" -> do+ let attr = attrFromElement e+ (maybe_caption_el, contents) = partitionFirstChildNamed "Caption" $ elContent e+ figure_caption <- case (maybe_caption_el) of+ Just (caption_el) -> parseCaption $ elContent caption_el+ Nothing -> pure emptyCaption+ blocks <- parseBlocks contents+ return $ figureWith attr figure_caption blocks+ "CodeBlock" -> do+ let attr = attrFromElement e+ return $ codeBlockWith attr $ strContentRecursive e+ "RawBlock" -> do+ let format = (attrValue atNameFormat e)+ return $ rawBlock format $ strContentRecursive e+ "LineBlock" -> do+ lins <- mapM getInlines (contentsOfChildren tgNameLineItem (elContent e))+ return $ lineBlock lins+ "Table" -> do+ -- TODO: check unexpected items+ let attr = attrFromElement e+ (maybe_caption_el, after_caption) = partitionFirstChildNamed "Caption" $ elContent e+ children = elementsWithNames (S.fromList [tgNameColspecs, "TableHead", "TableBody", "TableFoot"]) after_caption+ is_element tag el = tag == elementName el+ colspecs <- getColspecs $ L.find (is_element tgNameColspecs) children+ tbs <- getTableBodies $ filter (is_element "TableBody") children+ th <- getTableHead $ L.find (is_element "TableHead") children+ tf <- getTableFoot $ L.find (is_element "TableFoot") children+ capt <- parseMaybeCaptionElement maybe_caption_el+ case colspecs of+ Nothing -> return mempty+ Just cs -> return $ fromList [Table attr capt cs th tbs tf]+ _ -> do+ throwError $ PandocXMLError "" ("unexpected element \"" <> name <> "\" in blocks context")+ where+ parsePandoc = do+ let version = maybeAttrValue atNameApiVersion e+ apiversion = case (version) of+ Just (v) -> makeVersion $ map (read . T.unpack) $ T.splitOn "," v+ Nothing -> pandocVersion+ in modify $ \st -> st {xmlApiVersion = apiversion}+ getBlocks e++getListItems :: (PandocMonad m) => Element -> XMLReader m [Blocks]+getListItems e =+ let items_els = childrenNamed tgNameListItem e+ in do+ mapM getBlocks items_els++getContentsOfElements :: (Content -> Bool) -> [Content] -> [[Content]]+getContentsOfElements filter_element contents = mapMaybe element_contents $ filter filter_element contents+ where+ element_contents :: Content -> Maybe [Content]+ element_contents c = case (c) of+ Elem e -> Just (elContent e)+ _ -> Nothing++strContentRecursive :: Element -> Text+strContentRecursive =+ strContent+ . (\e' -> e' {elContent = map elementToStr $ elContent e'})++elementToStr :: Content -> Content+elementToStr (Elem e') = Text $ CData CDataText (strContentRecursive e') Nothing+elementToStr x = x++textToInt :: Text -> Int -> Int+textToInt t deflt =+ let safe_to_int :: Text -> Maybe Int+ safe_to_int s = readMaybe $ T.unpack s+ in case (safe_to_int t) of+ Nothing -> deflt+ Just (n) -> n++parseInline :: (PandocMonad m) => Content -> XMLReader m Inlines+parseInline (Text (CData _ s _)) =+ return $ text s+parseInline (CRef ref) =+ return $+ maybe (text $ T.toUpper ref) text $+ lookupEntity ref+parseInline (Elem e) =+ let name = elementName e+ in case (name) of+ "Space" ->+ let count = textToInt (attrValue atNameSpaceCount e) 1+ in return $ fromList $ replicate count Space+ "Str" -> return $ fromList [Str $ attrValue atNameStrContent e]+ "Emph" -> innerInlines emph+ "Strong" -> innerInlines strong+ "Strikeout" -> innerInlines strikeout+ "Subscript" -> innerInlines subscript+ "Superscript" -> innerInlines superscript+ "Underline" -> innerInlines underline+ "SoftBreak" -> return softbreak+ "LineBreak" -> return linebreak+ "SmallCaps" -> innerInlines smallcaps+ "Quoted" -> case (attrValue atNameQuoteType e) of+ "SingleQuote" -> innerInlines singleQuoted+ _ -> innerInlines doubleQuoted+ "Math" -> case (attrValue atNameMathType e) of+ "DisplayMath" -> pure $ displayMath $ strContentRecursive e+ _ -> pure $ math $ strContentRecursive e+ "Span" -> innerInlines $ spanWith (attrFromElement e)+ "Code" -> do+ let attr = attrFromElement e+ return $ codeWith attr $ strContentRecursive e+ "Link" -> innerInlines $ linkWith attr url title+ where+ url = attrValue atNameLinkUrl e+ title = attrValue atNameTitle e+ attr = filterAttrAttributes [atNameLinkUrl, atNameTitle] $ attrFromElement e+ "Image" -> innerInlines $ imageWith attr url title+ where+ url = attrValue atNameImageUrl e+ title = attrValue atNameTitle e+ attr = filterAttrAttributes [atNameImageUrl, atNameTitle] $ attrFromElement e+ "RawInline" -> do+ let format = (attrValue atNameFormat e)+ return $ rawInline format $ strContentRecursive e+ "Note" -> do+ contents <- getBlocks e+ return $ note contents+ "Cite" ->+ let (maybe_citations_el, contents) = partitionFirstChildNamed tgNameCitations $ elContent e+ in case (maybe_citations_el) of+ Just citations_el -> do+ citations <- parseCitations $ elContent citations_el+ (innerInlines' contents) $ cite citations+ Nothing -> getInlines contents+ _ -> do+ throwError $ PandocXMLError "" ("unexpected element \"" <> name <> "\" in inline context")+ where+ innerInlines' contents f =+ f . concatMany+ <$> mapM parseInline contents+ innerInlines f = innerInlines' (elContent e) f++getInlines :: (PandocMonad m) => [Content] -> XMLReader m Inlines+getInlines contents = concatMany <$> mapM parseInline contents++getListAttributes :: Element -> ListAttributes+getListAttributes e = (start, style, delim)+ where+ start = textToInt (attrValue atNameStart e) 1+ style = case (attrValue atNameNumberStyle e) of+ "Example" -> Example+ "Decimal" -> Decimal+ "LowerRoman" -> LowerRoman+ "UpperRoman" -> UpperRoman+ "LowerAlpha" -> LowerAlpha+ "UpperAlpha" -> UpperAlpha+ _ -> DefaultStyle+ delim = case (attrValue atNameNumberDelim e) of+ "Period" -> Period+ "OneParen" -> OneParen+ "TwoParens" -> TwoParens+ _ -> DefaultDelim++contentsOfChildren :: Text -> [Content] -> [[Content]]+contentsOfChildren tag contents = mapMaybe childrenElementWithTag contents+ where+ childrenElementWithTag :: Content -> Maybe [Content]+ childrenElementWithTag c = case (c) of+ (Elem e) -> if tag == elementName e then Just (elContent e) else Nothing+ _ -> Nothing++alignmentFromText :: Text -> Alignment+alignmentFromText t = case t of+ "AlignLeft" -> AlignLeft+ "AlignRight" -> AlignRight+ "AlignCenter" -> AlignCenter+ _ -> AlignDefault++getColWidth :: Text -> ColWidth+getColWidth txt = case reads (T.unpack txt) of+ [(value, "")] -> if value == 0.0 then ColWidthDefault else ColWidth value+ _ -> ColWidthDefault++getColspecs :: (PandocMonad m) => Maybe Element -> XMLReader m (Maybe [ColSpec])+getColspecs Nothing = pure Nothing+getColspecs (Just cs) = do+ return $ Just $ map elementToColSpec (childrenNamed "ColSpec" cs)+ where+ elementToColSpec e = (alignmentFromText $ attrValue atNameAlignment e, getColWidth $ attrValue atNameColWidth e)++getTableBody :: (PandocMonad m) => Element -> XMLReader m (Maybe TableBody)+getTableBody body_el = do+ let attr = filterAttrAttributes [atNameRowHeadColumns] $ attrFromElement body_el+ bh = childrenNamed tgNameBodyHeader body_el+ bb = childrenNamed tgNameBodyBody body_el+ headcols = textToInt (attrValue atNameRowHeadColumns body_el) 0+ hrows <- mconcat <$> mapM getRows bh+ brows <- mconcat <$> mapM getRows bb+ return $ Just $ TableBody attr (RowHeadColumns headcols) hrows brows++getTableBodies :: (PandocMonad m) => [Element] -> XMLReader m [TableBody]+getTableBodies body_elements = do+ catMaybes <$> mapM getTableBody body_elements++getTableHead :: (PandocMonad m) => Maybe Element -> XMLReader m TableHead+getTableHead maybe_e = case maybe_e of+ Just e -> do+ let attr = attrFromElement e+ rows <- getRows e+ return $ TableHead attr rows+ Nothing -> return $ TableHead nullAttr []++getTableFoot :: (PandocMonad m) => Maybe Element -> XMLReader m TableFoot+getTableFoot maybe_e = case maybe_e of+ Just e -> do+ let attr = attrFromElement e+ rows <- getRows e+ return $ TableFoot attr rows+ Nothing -> return $ TableFoot nullAttr []++getCell :: (PandocMonad m) => Element -> XMLReader m Cell+getCell c = do+ let alignment = alignmentFromText $ attrValue atNameAlignment c+ rowspan = RowSpan $ textToInt (attrValue atNameRowspan c) 1+ colspan = ColSpan $ textToInt (attrValue atNameColspan c) 1+ attr = filterAttrAttributes [atNameAlignment, atNameRowspan, atNameColspan] $ attrFromElement c+ blocks <- getBlocks c+ return $ Cell attr alignment rowspan colspan (toList blocks)++getRows :: (PandocMonad m) => Element -> XMLReader m [Row]+getRows e = mapM getRow $ childrenNamed "Row" e+ where+ getRow r = do+ cells <- mapM getCell (childrenNamed "Cell" r)+ return $ Row (attrFromElement r) cells++parseCitations :: (PandocMonad m) => [Content] -> XMLReader m [Citation]+parseCitations contents = do+ maybecitations <- mapM getCitation contents+ return $ catMaybes maybecitations+ where+ getCitation :: (PandocMonad m) => Content -> XMLReader m (Maybe Citation)+ getCitation content = case (content) of+ (Elem e) ->+ if qName (elName e) == "Citation"+ then do+ p <- inlinesOfChildrenNamed tgNameCitationPrefix e+ s <- inlinesOfChildrenNamed tgNameCitationSuffix e+ return $+ Just+ ( Citation+ { citationId = attrValue "id" e,+ citationPrefix = toList p,+ citationSuffix = toList s,+ citationMode = case (attrValue atNameCitationMode e) of+ "AuthorInText" -> AuthorInText+ "SuppressAuthor" -> SuppressAuthor+ _ -> NormalCitation,+ citationNoteNum = textToInt (attrValue atNameCitationNoteNum e) 0,+ citationHash = textToInt (attrValue atNameCitationHash e) 0+ }+ )+ else do+ return Nothing+ _ -> do+ return Nothing+ where+ inlinesOfChildrenNamed tag e = getInlines $ concatMap (\e' -> elContent e') (childrenNamed tag e)++parseMaybeCaptionElement :: (PandocMonad m) => Maybe Element -> XMLReader m Caption+parseMaybeCaptionElement Nothing = pure emptyCaption+parseMaybeCaptionElement (Just e) = parseCaption $ elContent e++parseCaption :: (PandocMonad m) => [Content] -> XMLReader m Caption+parseCaption contents =+ let (maybe_shortcaption_el, caption_contents) = partitionFirstChildNamed tgNameShortCaption contents+ in do+ blocks <- parseBlocks caption_contents+ case (maybe_shortcaption_el) of+ Just shortcaption_el -> do+ short_caption <- getInlines (elContent shortcaption_el)+ return $ caption (Just $ toList short_caption) blocks+ Nothing -> return $ caption Nothing blocks++parseDefinitionListItem :: (PandocMonad m) => [Content] -> XMLReader m (Inlines, [Blocks])+parseDefinitionListItem contents = do+ let term_contents = getContentsOfElements (isElementNamed tgNameDefListTerm) contents+ defs_elements = elementContents $ filter (isElementNamed tgNameDefListDef) contents+ term_inlines <- getInlines (concat term_contents)+ defs <- mapM getBlocks defs_elements+ return (term_inlines, defs)++elementContents :: [Content] -> [Element]+elementContents contents = mapMaybe toElement contents+ where+ toElement :: Content -> Maybe Element+ toElement (Elem e) = Just e+ toElement _ = Nothing++isElementNamed :: Text -> Content -> Bool+isElementNamed t c = case (c) of+ Elem e -> t == elementName e+ _ -> False++childrenNamed :: Text -> Element -> [Element]+childrenNamed tag e = elementContents $ filter (isElementNamed tag) (elContent e)++elementsWithNames :: S.Set Text -> [Content] -> [Element]+elementsWithNames tags contents = mapMaybe isElementWithNameInSet contents+ where+ isElementWithNameInSet c = case (c) of+ Elem el ->+ if (elementName el) `S.member` tags+ then Just el+ else Nothing+ _ -> Nothing++partitionFirstChildNamed :: Text -> [Content] -> (Maybe Element, [Content])+partitionFirstChildNamed tag contents = case (contents) of+ (Text (CData _ s _) : rest) ->+ if T.all isSpace s+ then partitionFirstChildNamed tag rest+ else (Nothing, contents)+ (Elem e : rest) ->+ if tag == elementName e+ then (Just e, rest)+ else (Nothing, contents)+ _ -> (Nothing, contents)++type PandocAttr = (Text, [Text], [(Text, Text)])++filterAttributes :: S.Set Text -> [(Text, Text)] -> [(Text, Text)]+filterAttributes to_be_removed a = filter keep_attr a+ where+ keep_attr (k, _) = not (k `S.member` to_be_removed)++filterAttrAttributes :: [Text] -> PandocAttr -> PandocAttr+filterAttrAttributes to_be_removed (idn, classes, a) = (idn, classes, filtered)+ where+ filtered = filterAttributes (S.fromList to_be_removed) a++attrFromElement :: Element -> PandocAttr+attrFromElement e = filterAttrAttributes ["id", "class"] (idn, classes, attributes)+ where+ idn = attrValue "id" e+ classes = T.words $ attrValue "class" e+ attributes = map (\a -> (qName $ attrKey a, attrVal a)) $ elAttribs e++addMeta :: (PandocMonad m) => (ToMetaValue a) => Text -> a -> XMLReader m ()+addMeta field val = modify (setMeta field val)++instance HasMeta XMLReaderState where+ setMeta field v s = s {xmlMeta = setMeta field v (xmlMeta s)}++ deleteMeta field s = s {xmlMeta = deleteMeta field (xmlMeta s)}++parseMetaMapEntry :: (PandocMonad m) => Element -> XMLReader m (Maybe (Text, MetaValue))+parseMetaMapEntry e =+ let key = attrValue atNameMetaMapEntryKey e+ in case (key) of+ "" -> pure Nothing+ k -> do+ maybe_value <- parseMetaMapEntryContents $ elContent e+ case (maybe_value) of+ Nothing -> return Nothing+ Just v -> return $ Just (k, v)++parseMetaMapEntryContents :: (PandocMonad m) => [Content] -> XMLReader m (Maybe MetaValue)+parseMetaMapEntryContents cs = msum <$> mapM parseMeta cs++getElementText :: Element -> T.Text+getElementText el = T.concat [cdData c | Text c <- elContent el]++parseMeta :: (PandocMonad m) => Content -> XMLReader m (Maybe MetaValue)+parseMeta (Text (CData CDataRaw _ _)) = return Nothing+parseMeta (Text (CData _ s _)) =+ if T.all isSpace s+ then return Nothing+ else do+ throwError $ PandocXMLError "" "non-space characters out of inline context in metadata"+parseMeta (CRef x) =+ throwError $ PandocXMLError "" ("reference \"" <> x <> "\" out of inline context")+parseMeta (Elem e) = do+ let name = elementName e+ in case (name) of+ "MetaBool" -> case (attrValue atNameMetaBoolValue e) of+ "true" -> return $ Just $ MetaBool True+ _ -> return $ Just $ MetaBool False+ "MetaString" -> return $ Just $ MetaString (getElementText e)+ "MetaInlines" -> do+ inlines <- getInlines (elContent e)+ return $ Just $ MetaInlines $ toList inlines+ "MetaBlocks" -> do+ blocks <- getBlocks e+ return $ Just $ MetaBlocks $ toList blocks+ "MetaList" -> do+ maybe_items <- mapM parseMeta $ elContent e+ let items = catMaybes maybe_items+ in -- TODO: report empty MetaList?+ return $ Just $ MetaList items+ "MetaMap" ->+ let entry_els = childrenNamed tgNameMetaMapEntry e+ in do+ entries <- catMaybes <$> mapM parseMetaMapEntry entry_els+ if null entries+ then+ -- TODO: report empty MetaMap+ return Nothing+ else return $ Just $ MetaMap $ M.fromList entries+ _ -> do+ throwError $ PandocXMLError "" ("unexpected element \"" <> name <> "\" in metadata")
@@ -0,0 +1,40 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.Xlsx+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++Conversion of XLSX (Excel spreadsheet) documents to 'Pandoc' document.+-}+module Text.Pandoc.Readers.Xlsx (readXlsx) where++import qualified Data.ByteString.Lazy as B+import qualified Data.Text as T+import Codec.Archive.Zip (toArchiveOrFail)+import Control.Monad.Except (throwError)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Definition (Pandoc(..))+import Text.Pandoc.Error (PandocError(..))+import Text.Pandoc.Options (ReaderOptions)+import Text.Pandoc.Readers.Xlsx.Parse (archiveToXlsx)+import Text.Pandoc.Readers.Xlsx.Sheets (xlsxToOutput)++-- | Read XLSX file into Pandoc AST+readXlsx :: PandocMonad m => ReaderOptions -> B.ByteString -> m Pandoc+readXlsx opts bytes =+ case toArchiveOrFail bytes of+ Right archive ->+ case archiveToXlsx archive of+ Right xlsx -> do+ let (meta, blocks) = xlsxToOutput opts xlsx+ return $ Pandoc meta blocks+ Left err ->+ throwError $ PandocParseError $ "Failed to parse XLSX: " <> err++ Left err ->+ throwError $ PandocParseError $+ "Failed to unpack XLSX archive: " <> T.pack err
@@ -0,0 +1,63 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.Xlsx.Cells+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++Cell types and parsing for XLSX.+-}+module Text.Pandoc.Readers.Xlsx.Cells+ ( CellRef(..)+ , XlsxCell(..)+ , CellValue(..)+ , parseCellRef+ ) where++import qualified Data.Text as T+import Data.Text (Text)+import Data.Char (ord, isAlpha)+import Text.Read (readMaybe)++-- | Cell reference (A1 notation)+data CellRef = CellRef+ { cellRefCol :: Int -- 1-based (A=1, B=2, ..., AA=27)+ , cellRefRow :: Int -- 1-based+ } deriving (Show, Eq, Ord)++-- | Cell value types+data CellValue+ = TextValue Text+ | NumberValue Double+ | EmptyValue+ deriving (Show, Eq)++-- | Parsed cell+data XlsxCell = XlsxCell+ { cellRef :: CellRef+ , cellValue :: CellValue+ , cellBold :: Bool+ , cellItalic :: Bool+ } deriving (Show)++-- | Parse cell reference (A1 → CellRef)+parseCellRef :: Text -> Either Text CellRef+parseCellRef ref = do+ let (colStr, rowStr) = T.span isAlpha ref++ row <- case readMaybe (T.unpack rowStr) of+ Just r | r > 0 -> Right r+ _ -> Left $ "Invalid row: " <> rowStr++ col <- parseColumn colStr++ return $ CellRef col row++-- | Parse column (A=1, Z=26, AA=27, etc.)+parseColumn :: Text -> Either Text Int+parseColumn colStr+ | T.null colStr = Left "Empty column"+ | otherwise = Right $ T.foldl' (\acc c -> acc * 26 + (ord c - ord 'A' + 1)) 0 colStr
@@ -0,0 +1,296 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.Xlsx.Parse+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++Parsing of XLSX archive to intermediate representation.+-}+module Text.Pandoc.Readers.Xlsx.Parse+ ( Xlsx(..)+ , XlsxWorkbook(..)+ , XlsxSheet(..)+ , SheetId(..)+ , SharedStrings+ , Styles(..)+ , FontInfo(..)+ , archiveToXlsx+ ) where++import Codec.Archive.Zip (Archive, Entry, findEntryByPath, fromEntry)+import Data.List (find)+import qualified Data.Map.Strict as M+import Data.Maybe (mapMaybe, fromMaybe)+import qualified Data.Text as T+import qualified Data.Text.Lazy.Encoding as TL+import Data.Text (Text)+import qualified Data.Vector as V+import System.FilePath (splitFileName)+import Text.Pandoc.Readers.OOXML.Shared+import Text.Pandoc.Readers.Xlsx.Cells+import Text.Pandoc.XML.Light+import Text.Read (readMaybe)++-- | Sheet identifier+newtype SheetId = SheetId Int deriving (Show, Eq, Ord)++-- | Shared strings table (Vector for O(1) lookup)+type SharedStrings = V.Vector Text++-- | Font information+data FontInfo = FontInfo+ { fontBold :: Bool+ , fontItalic :: Bool+ , fontUnderline :: Bool+ } deriving (Show)++-- | Style information+data Styles = Styles+ { styleFonts :: V.Vector FontInfo+ } deriving (Show)++-- | Complete XLSX document+data Xlsx = Xlsx+ { xlsxWorkbook :: XlsxWorkbook+ , xlsxSheets :: [XlsxSheet]+ , xlsxSharedStrings :: SharedStrings+ , xlsxStyles :: Styles+ } deriving (Show)++-- | Workbook information+data XlsxWorkbook = XlsxWorkbook+ { workbookSheetNames :: [(SheetId, Text, Text)] -- (id, name, relId)+ } deriving (Show)++-- | Individual worksheet+data XlsxSheet = XlsxSheet+ { sheetId :: SheetId+ , sheetName :: Text+ , sheetCells :: M.Map CellRef XlsxCell+ } deriving (Show)++-- | Parse XLSX archive+archiveToXlsx :: Archive -> Either Text Xlsx+archiveToXlsx archive = do+ -- Find and parse workbook.xml+ workbookPath <- getWorkbookXmlPath archive+ workbookElem <- loadXMLFromArchive archive workbookPath+ workbook <- parseWorkbook workbookElem+ `addContext` ("Parsing workbook.xml from: " <> T.pack workbookPath)++ -- Load workbook relationships+ workbookRels <- loadRelationships archive (relsPathFor workbookPath)++ -- Parse shared strings (look for sharedStrings relationship)+ sharedStrings <- case findRelWithTarget workbookRels "sharedStrings" of+ Just (_, target) -> do+ let path = "xl/" ++ T.unpack target+ el <- loadXMLFromArchive archive path+ parseSharedStrings el+ Nothing -> Right V.empty++ -- Parse styles+ styles <- case findRelWithTarget workbookRels "styles" of+ Just (_, target) -> do+ let path = "xl/" ++ T.unpack target+ el <- loadXMLFromArchive archive path+ parseStyles el+ Nothing -> Right $ Styles V.empty++ -- Parse worksheets+ sheets <- mapM (\sheetInfo -> parseSheet archive workbookRels sharedStrings styles sheetInfo)+ (workbookSheetNames workbook)++ return $ Xlsx workbook sheets sharedStrings styles++-- | Find workbook.xml via root relationships+getWorkbookXmlPath :: Archive -> Either Text FilePath+getWorkbookXmlPath archive = do+ relsEntry <- maybeToEither "Missing _rels/.rels" $+ findEntryByPath "_rels/.rels" archive+ relsElem <- parseXMLFromEntry relsEntry++ let relElems = onlyElems $ elContent relsElem+ case find isOfficeDocRel relElems of+ Nothing -> Left "No workbook.xml relationship found"+ Just rel -> do+ target <- maybeToEither "Missing Target" $ findAttr (unqual "Target") rel+ return $ T.unpack target+ where+ isOfficeDocRel el =+ case (findAttr (unqual "Type") el, findAttr (unqual "Target") el) of+ (Just relType, Just target) ->+ "officeDocument" `T.isInfixOf` relType && "workbook" `T.isInfixOf` target+ _ -> False++-- | Parse workbook.xml+parseWorkbook :: Element -> Either Text XlsxWorkbook+parseWorkbook wbElem = do+ let ns = elemToNameSpaces wbElem++ -- Find sheets element (match by local name only)+ sheets <- maybeToEither "Missing <sheets>" $+ find (\e -> qName (elName e) == "sheets") (onlyElems $ elContent wbElem)++ let sheetElems = filter (\e -> qName (elName e) == "sheet") (onlyElems $ elContent sheets)+ sheetRefs <- mapM (parseSheetRef ns) (zip [1..] sheetElems)++ return $ XlsxWorkbook sheetRefs++parseSheetRef :: NameSpaces -> (Int, Element) -> Either Text (SheetId, Text, Text)+parseSheetRef ns (idx, sheetElem) = do+ let name = fromMaybe ("Sheet" <> T.pack (show idx)) $+ findAttr (unqual "name") sheetElem+ relId <- maybeToEither "Missing r:id" $+ findAttrByName ns "r" "id" sheetElem+ return (SheetId idx, name, relId)++-- | Parse shared strings+parseSharedStrings :: Element -> Either Text SharedStrings+parseSharedStrings sstElem = do+ let siElems = filter (\e -> qName (elName e) == "si") (onlyElems $ elContent sstElem)+ strings = map extractString siElems+ return $ V.fromList strings+ where+ extractString siElem =+ case find (\e -> qName (elName e) == "t") (onlyElems $ elContent siElem) of+ Just tElem -> strContent tElem+ Nothing -> getAllText siElem++-- | Parse styles (fonts only for MVP)+parseStyles :: Element -> Either Text Styles+parseStyles stylesElem = do+ -- Parse fonts (match by local name)+ let fontsElem = find (\e -> qName (elName e) == "fonts") (onlyElems $ elContent stylesElem)+ fontElems = maybe [] (\fe -> filter (\e -> qName (elName e) == "font") (onlyElems $ elContent fe)) fontsElem+ fonts = V.fromList $ map (parseFont mempty) fontElems++ return $ Styles fonts++parseFont :: NameSpaces -> Element -> FontInfo+parseFont _ns fontElem =+ FontInfo+ { fontBold = any (\e -> qName (elName e) == "b") (onlyElems $ elContent fontElem)+ , fontItalic = any (\e -> qName (elName e) == "i") (onlyElems $ elContent fontElem)+ , fontUnderline = any (\e -> qName (elName e) == "u") (onlyElems $ elContent fontElem)+ }++-- | Parse individual worksheet+parseSheet :: Archive -> [(Text, Text)] -> SharedStrings -> Styles -> (SheetId, Text, Text) -> Either Text XlsxSheet+parseSheet archive rels sharedStrings styles (sid, name, relId) = do+ target <- maybeToEither ("Sheet relationship not found: " <> relId) $+ lookup relId rels++ let sheetPath = "xl/" ++ T.unpack target+ sheetElem <- loadXMLFromArchive archive sheetPath++ cells <- parseSheetCells sheetElem sharedStrings styles++ return $ XlsxSheet sid name cells++-- | Parse sheet cells+parseSheetCells :: Element -> SharedStrings -> Styles -> Either Text (M.Map CellRef XlsxCell)+parseSheetCells sheetElem sharedStrings styles = do+ -- Find sheetData by local name+ case find (\e -> qName (elName e) == "sheetData") (onlyElems $ elContent sheetElem) of+ Nothing -> return M.empty+ Just sheetData -> do+ let rowElems = filter (\e -> qName (elName e) == "row") (onlyElems $ elContent sheetData)+ cellElems = concatMap (\r -> filter (\e -> qName (elName e) == "c") (onlyElems $ elContent r)) rowElems+ cells = mapMaybe (parseCell sharedStrings styles) cellElems+ return $ M.fromList [(cellRef c, c) | c <- cells]++-- | Parse individual cell+parseCell :: SharedStrings -> Styles -> Element -> Maybe XlsxCell+parseCell sharedStrings styles cElem = do+ -- Get cell reference+ refText <- findAttr (unqual "r") cElem+ cellRefParsed <- either (const Nothing) Just $ parseCellRef refText++ -- Get cell type (default to number if missing)+ let cellType = fromMaybe "" $ findAttr (unqual "t") cElem+ styleIdx = findAttr (unqual "s") cElem >>= readMaybe . T.unpack++ -- Get value (match by local name)+ let vElem = find (\e -> qName (elName e) == "v") (onlyElems $ elContent cElem)+ vText = maybe "" strContent vElem++ -- Parse value based on type+ let value = if cellType == "s"+ then+ -- Shared string+ case readMaybe (T.unpack vText) of+ Just idx | idx >= 0 && idx < V.length sharedStrings ->+ TextValue (sharedStrings V.! idx)+ _ -> EmptyValue+ else if T.null vText+ then EmptyValue+ else+ -- Number+ case readMaybe (T.unpack vText) of+ Just n -> NumberValue n+ Nothing -> TextValue vText++ -- Get formatting from style+ let (bold, italic) = case styleIdx of+ Just idx | idx >= 0 && idx < V.length (styleFonts styles) ->+ let font = styleFonts styles V.! idx+ in (fontBold font, fontItalic font)+ _ -> (False, False)++ return $ XlsxCell cellRefParsed value bold italic++-- Helper functions+loadXMLFromArchive :: Archive -> FilePath -> Either Text Element+loadXMLFromArchive archive path = do+ entry <- maybeToEither ("Entry not found: " <> T.pack path) $+ findEntryByPath path archive+ parseXMLFromEntry entry++parseXMLFromEntry :: Entry -> Either Text Element+parseXMLFromEntry entry =+ let lazyText = TL.decodeUtf8 $ fromEntry entry+ in parseXMLElement lazyText++loadRelationships :: Archive -> FilePath -> Either Text [(Text, Text)]+loadRelationships archive relsPath =+ case findEntryByPath relsPath archive of+ Nothing -> Right []+ Just entry -> do+ relsElem <- parseXMLFromEntry entry+ let relElems = onlyElems $ elContent relsElem+ return $ mapMaybe extractRel relElems+ where+ extractRel el = do+ relId <- findAttr (unqual "Id") el+ target <- findAttr (unqual "Target") el+ return (relId, target)++relsPathFor :: FilePath -> FilePath+relsPathFor path =+ let (dir, file) = splitFileName path+ in dir ++ "/_rels/" ++ file ++ ".rels"++findRelWithTarget :: [(Text, Text)] -> Text -> Maybe (Text, Text)+findRelWithTarget rels targetName =+ find (\(_, target) -> targetName `T.isInfixOf` target) rels++maybeToEither :: Text -> Maybe a -> Either Text a+maybeToEither err Nothing = Left err+maybeToEither _ (Just x) = Right x++getAllText :: Element -> Text+getAllText el =+ let textFromContent (Text cdata) = cdData cdata+ textFromContent (Elem e) = getAllText e+ textFromContent _ = ""+ texts = map textFromContent (elContent el)+ in T.unwords $ filter (not . T.null) texts++addContext :: Either Text a -> Text -> Either Text a+addContext (Right x) _ = Right x+addContext (Left err) ctx = Left (err <> " (context: " <> ctx <> ")")
@@ -0,0 +1,112 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Readers.Xlsx.Sheets+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++Conversion of XLSX sheets to Pandoc AST.+-}+module Text.Pandoc.Readers.Xlsx.Sheets+ ( xlsxToOutput+ ) where++import qualified Data.Map.Strict as M+import qualified Data.Text as T+import Data.List (sort, dropWhileEnd)+import Data.Char (isSpace)+import Text.Pandoc.Definition+import Text.Pandoc.Options (ReaderOptions)+import Text.Pandoc.Readers.Xlsx.Parse+import Text.Pandoc.Readers.Xlsx.Cells+import qualified Text.Pandoc.Builder as B++-- | Convert XLSX to Pandoc output+xlsxToOutput :: ReaderOptions -> Xlsx -> (Meta, [Block])+xlsxToOutput _opts xlsx =+ let sheets = xlsxSheets xlsx+ sheetBlocks = concatMap sheetToBlocks sheets+ in (mempty, sheetBlocks)++-- | Convert sheet to blocks (header + table)+sheetToBlocks :: XlsxSheet -> [Block]+sheetToBlocks sheet =+ let SheetId n = sheetId sheet+ name = sheetName sheet+ sheetIdent = "sheet-" <> T.pack (show n)+ header = Header 2 (sheetIdent, [], []) (B.toList (B.text name))++ -- Convert cells to table+ tableBlock = case cellsToTable sheet of+ Just tbl -> [tbl]+ Nothing -> [] -- Empty sheet+ in header : tableBlock++-- | Convert cells to Pandoc Table+cellsToTable :: XlsxSheet -> Maybe Block+cellsToTable sheet+ | M.null (sheetCells sheet) = Nothing+ | otherwise =+ let cells = sheetCells sheet+ -- Get bounds+ refs = sort $ M.keys cells+ minCol = minimum $ map cellRefCol refs+ maxCol = maximum $ map cellRefCol refs+ minRow = minimum $ map cellRefRow refs+ maxRow = maximum $ map cellRefRow refs++ -- Build dense grid+ grid = [ [ M.lookup (CellRef col row) cells+ | col <- [minCol..maxCol]+ ]+ | row <- [minRow..maxRow]+ ]++ -- First row is header (simple heuristic)+ (headerRow, bodyRows) = case grid of+ (h:bs) -> (h, bs)+ [] -> ([], [])++ -- Filter out trailing empty rows (rows with only whitespace)+ filteredBodyRows = dropWhileEnd isEmptyRow bodyRows++ makeCell mcell = case mcell of+ Just cell ->+ let inlines = cellToInlines cell+ in Cell nullAttr AlignDefault (RowSpan 1) (ColSpan 1) [Plain inlines]+ Nothing ->+ Cell nullAttr AlignDefault (RowSpan 1) (ColSpan 1) [Plain []]++ numCols = length headerRow+ colSpec = replicate numCols (AlignDefault, ColWidthDefault)+ thead = TableHead nullAttr [Row nullAttr $ map makeCell headerRow]+ tbody = [TableBody nullAttr 0 [] $ map (Row nullAttr . map makeCell) filteredBodyRows]+ tfoot = TableFoot nullAttr []++ in Just $ Table nullAttr (Caption Nothing []) colSpec thead tbody tfoot++-- | Check if a row contains only whitespace or empty cells+isEmptyRow :: [Maybe XlsxCell] -> Bool+isEmptyRow = all isEmptyCell+ where+ isEmptyCell Nothing = True+ isEmptyCell (Just cell) = case cellValue cell of+ EmptyValue -> True+ TextValue t -> T.all isSpace t+ NumberValue _ -> False++-- | Convert cell to Pandoc inlines+cellToInlines :: XlsxCell -> [Inline]+cellToInlines cell =+ let base = case cellValue cell of+ TextValue t -> B.toList $ B.text t+ NumberValue n -> [Str $ T.pack $ show n]+ EmptyValue -> []++ applyBold inls = if cellBold cell then [Strong inls] else inls+ applyItalic inls = if cellItalic cell then [Emph inls] else inls++ in applyItalic $ applyBold base
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.RoffChar- Copyright : Copyright (C) 2007-2022 John MacFarlane+ Copyright : Copyright (C) 2007-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -19,23 +19,25 @@ import qualified Data.Text as T -- | These are the escapes specifically mentioned in groff_man(7),--- plus @ and ellipsis.+-- plus @ and ellipsis. We use the \(aq form when possible (with+-- two-letter escapes), because these are compatible with all forms+-- of roff (#10716). standardEscapes :: [(Char, T.Text)] standardEscapes = [ ('\160', "\\ ")- , ('\'', "\\[aq]")- , ('‘', "\\[oq]")- , ('’', "\\[cq]")- , ('"', "\\[dq]")- , ('“', "\\[lq]")- , ('”', "\\[rq]")- , ('—', "\\[em]")- , ('–', "\\[en]")- , ('`', "\\[ga]")- , ('^', "\\[ha]")- , ('~', "\\[ti]")- , ('\\', "\\[rs]")- , ('@', "\\[at]") -- because we use @ as a table and math delimiter+ , ('\'', "\\(aq")+ , ('‘', "\\(oq")+ , ('’', "\\(cq")+ , ('"', "\\(dq")+ , ('“', "\\(lq")+ , ('”', "\\(rq")+ , ('—', "\\(em")+ , ('–', "\\(en")+ , ('`', "\\(ga")+ , ('^', "\\(ha")+ , ('~', "\\(ti")+ , ('\\', "\\(rs")+ , ('@', "\\(at") -- because we use @ as a table and math delimiter , ('\x2026', "\\&...") -- because u2026 doesn't render on tty ]
@@ -0,0 +1,63 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ImpredicativeTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{- |+Module : Text.Pandoc.Scripting+Copyright : © 2022-2024 Albert Krewinkel+License : GPL-2.0-or-later+Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com>++Central data structure for scripting engines.+-}+module Text.Pandoc.Scripting+ ( ScriptingEngine (..)+ , CustomComponents(..)+ , noEngine+ )+where++import Control.Monad.Except (throwError)+import Control.Monad.IO.Class (MonadIO)+import Data.Text (Text)+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Definition (Pandoc)+import Text.Pandoc.Error (PandocError (PandocNoScriptingEngine))+import Text.Pandoc.Filter.Environment (Environment)+import Text.Pandoc.Format (ExtensionsConfig)+import Text.Pandoc.Readers (Reader)+import Text.Pandoc.Writers (Writer)++-- | A component of a custom reader/writer: a custom reader,+-- a custom writer, a template for a custom writer, or a specification+-- of the extensions used by a script and their default values.+-- Note that a single script can contain all of these.+data CustomComponents m =+ CustomComponents+ { customReader :: Maybe (Reader m)+ , customWriter :: Maybe (Writer m)+ , customTemplate :: Maybe Text+ , customExtensions :: Maybe ExtensionsConfig+ }++-- | Structure to define a scripting engine.+data ScriptingEngine = ScriptingEngine+ { engineName :: Text -- ^ Name of the engine.++ , engineApplyFilter :: forall m. (PandocMonad m, MonadIO m)+ => Environment -> [String] -> FilePath+ -> Pandoc -> m Pandoc+ -- ^ Use the scripting engine to run a filter.++ , engineLoadCustom :: forall m. (PandocMonad m, MonadIO m)+ => FilePath -> m (CustomComponents m)+ -- ^ Function to load a custom reader/writer from a script.+ }++noEngine :: ScriptingEngine+noEngine = ScriptingEngine+ { engineName = "none"+ , engineApplyFilter = \_env _args _fp _doc ->+ throwError PandocNoScriptingEngine+ , engineLoadCustom = \_fp ->+ throwError PandocNoScriptingEngine+ }
@@ -1,9 +1,10 @@+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TupleSections #-} {- | Module : Text.Pandoc.SelfContained- Copyright : Copyright (C) 2011-2022 John MacFarlane+ Copyright : Copyright (C) 2011-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -17,13 +18,13 @@ module Text.Pandoc.SelfContained ( makeDataURI, makeSelfContained ) where import Codec.Compression.GZip as Gzip import Control.Applicative ((<|>))-import Control.Monad.Trans (lift) import Data.ByteString (ByteString)-import Data.ByteString.Base64 (encodeBase64)+import Data.ByteString.Base64 (encode) import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy as L import qualified Data.Text as T import Data.Char (isAlphaNum, isAscii)+import Crypto.Hash (hashWith, SHA1(SHA1)) import Network.URI (escapeURIString) import System.FilePath (takeDirectory, takeExtension, (</>)) import Text.HTML.TagSoup@@ -32,11 +33,16 @@ import Text.Pandoc.Logging import Text.Pandoc.Error (PandocError(..)) import Text.Pandoc.MIME (MimeType)-import Text.Pandoc.Shared (isURI, renderTags', trim, tshow)+import Text.Pandoc.Shared (renderTags', trim, tshow, safeRead)+import Text.Pandoc.URI (isURI) import Text.Pandoc.UTF8 (toString, toText, fromText)-import Text.Parsec (ParsecT, runParserT)+import Text.Pandoc.Parsing (ParsecT, runParserT)+import qualified Text.Pandoc.Parsing as P import Control.Monad.Except (throwError, catchError)-import qualified Text.Parsec as P+import Data.Either (lefts, rights)+import Data.Maybe (isNothing)+import qualified Data.Map as M+import Control.Monad.State isOk :: Char -> Bool isOk c = isAscii c && isAlphaNum c@@ -45,8 +51,11 @@ makeDataURI (mime, raw) = if textual then "data:" <> mime' <> "," <> T.pack (escapeURIString isOk (toString raw))- else "data:" <> mime' <> ";base64," <> encodeBase64 raw+ else "data:" <> mime' <> ";base64," <> toText (encode raw') where textual = "text/" `T.isPrefixOf` mime+ raw' = if "+xml" `T.isSuffixOf` mime+ then B.filter (/= '\r') raw -- strip off CRs+ else raw mime' = if textual && T.any (== ';') mime then mime <> ";charset=utf-8" else mime -- mime type already has charset@@ -59,7 +68,15 @@ x == "poster" || x == "data-background-image" -convertTags :: PandocMonad m => [Tag T.Text] -> m [Tag T.Text]+data ConvertState =+ ConvertState+ { isHtml5 :: Bool+ , svgMap :: M.Map T.Text (T.Text, [Attribute T.Text])+ -- map from hash to (id, svg attributes)+ } deriving (Show)++convertTags :: PandocMonad m =>+ [Tag T.Text] -> StateT ConvertState m [Tag T.Text] convertTags [] = return [] convertTags (t@TagOpen{}:ts) | fromAttrib "data-external" t == "1" = (t:) <$> convertTags ts@@ -72,7 +89,7 @@ ((t:xs') ++) <$> convertTags rest convertTags (t@(TagOpen "script" as):tc@(TagClose "script"):ts) = case fromAttrib "src" t of- "" -> (t:) <$> convertTags ts+ "" -> ([t, tc] ++) <$> convertTags ts src -> do let typeAttr = fromAttrib "type" t res <- getData typeAttr src@@ -87,7 +104,9 @@ "application/x-javascript" `T.isPrefixOf` mime) && not ("</script" `B.isInfixOf` bs) -> return $- TagOpen "script" [("type", typeAttr)|not (T.null typeAttr)]+ TagOpen "script" [(k,v) | (k,v) <- as+ , k == "type" ||+ "data-" `T.isPrefixOf` k] : TagText (toText bs) : TagClose "script" : rest@@ -109,7 +128,8 @@ (("href",dataUri) : [(x,y) | (x,y) <- as, x /= "href"]) : rest Fetched (mime, bs)- | "text/css" `T.isPrefixOf` mime+ | ("text/css" `T.isPrefixOf` mime ||+ fromAttrib "rel" t == "stylesheet") && T.null (fromAttrib "media" t) && not ("</" `B.isInfixOf` bs) -> do rest <- convertTags $@@ -130,21 +150,145 @@ convertTags (t@(TagOpen tagname as):ts) | any (isSourceAttribute tagname) as = do- as' <- mapM processAttribute as+ let inlineSvgs = tagname == "img" &&+ case T.words <$> lookup "class" as of+ Nothing -> False+ Just cs -> "inline-svg" `elem` cs+ as' <- mapM (processAttribute inlineSvgs) as+ let attrs = addRole "img" $ addAriaLabel $ rights as'+ let svgContents = lefts as' rest <- convertTags ts- return $ TagOpen tagname as' : rest- where processAttribute (x,y) =+ case svgContents of+ [] -> return $ TagOpen tagname attrs : rest+ ((hash, tags) : _) -> do+ -- drop "</img>" if present+ let rest' = case rest of+ TagClose tn : xs | tn == tagname -> xs+ _ -> rest+ svgmap <- gets svgMap+ case M.lookup hash svgmap of+ Just (svgid, svgattrs) -> do+ let attrs' = [(k,v) | (k,v) <- combineSvgAttrs svgattrs attrs+ , k /= "id"]+ return $ TagOpen "svg" attrs' :+ TagOpen "use" [("href", "#" <> svgid),+ ("width", "100%"),+ ("height", "100%")] :+ TagClose "use" :+ TagClose "svg" :+ rest'+ Nothing ->+ case dropWhile (not . isTagOpenName "svg") tags of+ TagOpen "svg" svgattrs : tags' -> do+ let attrs' = combineSvgAttrs svgattrs attrs+ let svgid = case lookup "id" attrs' of+ Just id' -> id'+ Nothing -> "svg_" <> hash+ let attrs'' = ("id", svgid) :+ [(k,v) | (k,v) <- attrs', k /= "id"]+ modify $ \st ->+ st{ svgMap = M.insert hash (svgid, attrs'') (svgMap st) }+ let fixUrl x =+ case T.breakOn "url(#" x of+ (_,"") -> x+ (before, after) -> before <>+ "url(#" <> svgid <> "_" <> T.drop 5 after+ let addIdPrefix ("id", x) = ("id", svgid <> "_" <> x)+ addIdPrefix (k, x)+ | k == "xlink:href" || k == "href" =+ case T.uncons x of+ Just ('#', x') -> (k, "#" <> svgid <> "_" <> x')+ _ -> (k, x)+ -- this clause handles things like+ -- style="fill:url(#radialGradient46);stroke:none",+ -- adding the svg id prefix to the anchor:+ addIdPrefix (k, x) = (k, fixUrl x)+ let ensureUniqueId (TagOpen tname ats) =+ TagOpen tname (map addIdPrefix ats)+ ensureUniqueId x = x+ return $ TagOpen "svg" attrs'' :+ map ensureUniqueId tags' ++ rest'+ _ -> return $ TagOpen tagname attrs : rest+ where processAttribute inlineSvgs (x,y) = if isSourceAttribute tagname (x,y) then do res <- getData (fromAttrib "type" t) y case res of- AlreadyDataURI enc -> return (x, enc)- Fetched (mt,bs) -> return (x, makeDataURI (mt,bs))- CouldNotFetch _ -> return (x, y)- else return (x,y)+ AlreadyDataURI enc -> return $ Right (x, enc)+ Fetched ("image/svg+xml", bs) | inlineSvgs -> do+ -- we filter CR in the hash to ensure that Windows+ -- and non-Windows tests agree:+ let hash = T.pack $ take 20 $ show $ hashWith SHA1+ $ B.filter (/='\r') bs+ return $ Left (hash, getSvgTags (toText bs))+ Fetched (mt,bs) -> return $ Right (x, makeDataURI (mt,bs))+ CouldNotFetch _ -> return $ Right (x, y)+ else return $ Right (x,y) convertTags (t:ts) = (t:) <$> convertTags ts +addRole :: T.Text -> [(T.Text, T.Text)] -> [(T.Text, T.Text)]+addRole role attrs =+ case lookup "role" attrs of+ Nothing -> ("role", role) : attrs+ Just _ -> attrs++addAriaLabel :: [(T.Text, T.Text)] -> [(T.Text, T.Text)]+addAriaLabel attrs =+ case lookup "aria-label" attrs of+ Just _ -> attrs+ Nothing -> case lookup "alt" attrs of+ Just alt -> ("aria-label", alt) : attrs+ Nothing -> attrs++-- we want to drop spaces, <?xml>, and comments before <svg>+-- and anything after </svg>:+getSvgTags :: T.Text -> [Tag T.Text]+getSvgTags t =+ case takeWhile (not . isTagCloseName "svg") .+ dropWhile (not . isTagOpenName "svg") $ parseTags t of+ [] -> []+ xs -> xs ++ [TagClose "svg"]++combineSvgAttrs :: [(T.Text, T.Text)] -> [(T.Text, T.Text)] -> [(T.Text, T.Text)]+combineSvgAttrs svgAttrs imgAttrs =+ case (mbViewBox, mbHeight, mbWidth) of+ (Nothing, Just h, Just w) -> -- calculate viewBox+ combinedAttrs ++ [("viewBox", T.unwords ["0", "0", tshow w, tshow h])]+ (Just (_minx,_miny,w,h), Nothing, Nothing) ->+ combinedAttrs +++ [ ("width", dropPointZero (tshow w)) |+ isNothing (lookup "width" combinedAttrs) ] +++ [ ("height", dropPointZero (tshow h)) |+ isNothing (lookup "height" combinedAttrs) ]+ _ -> combinedAttrs+ where+ dropPointZero t = case T.stripSuffix ".0" t of+ Nothing -> t+ Just t' -> t'+ combinedAttrs =+ [(k, v) | (k, v) <- imgAttrs+ , k /= "class"] +++ [(k, v) | (k, v) <- svgAttrs+ , isNothing (lookup k imgAttrs)+ , k `notElem` ["xmlns", "xmlns:xlink", "version", "class"]] +++ mergedClasses+ parseViewBox t =+ case map (safeRead . addZero) $ T.words t of+ [Just llx, Just lly, Just urx, Just ury] -> Just (llx, lly, urx, ury)+ _ -> Nothing+ addZero t =+ if "-." `T.isPrefixOf` t+ then "-0." <> T.drop 2 t -- safeRead fails on -.33, needs -0.33+ else t+ (mbViewBox :: Maybe (Double, Double, Double, Double)) =+ lookup "viewBox" svgAttrs >>= parseViewBox+ (mbHeight :: Maybe Int) = lookup "height" combinedAttrs >>= safeRead+ (mbWidth :: Maybe Int) = lookup "width" combinedAttrs >>= safeRead+ mergedClasses = case (lookup "class" imgAttrs, lookup "class" svgAttrs) of+ (Just c1, Just c2) -> [("class", c1 <> " " <> c2)]+ _ -> []+ cssURLs :: PandocMonad m => FilePath -> ByteString -> m ByteString cssURLs d orig = do@@ -275,22 +419,32 @@ return res else return raw' return $ Fetched (mime, result)- handler e = case e of- PandocResourceNotFound r -> do- report $ CouldNotFetchResource r ""- return $ CouldNotFetch e- PandocHttpError u er -> do- report $ CouldNotFetchResource u (tshow er)- return $ CouldNotFetch e- _ -> throwError e---+ handler e+ -- If fetch failed and we have a fragment and/or query,+ -- try the fetch again without these, since the resource+ -- may be local (see #1477, #11021)+ | T.any (\c -> c == '?' || c == '#') src && not (isURI src)+ = getData mimetype (removeQueryAndFragment src)+ | otherwise+ = case e of+ PandocResourceNotFound r -> do+ report $ CouldNotFetchResource r ""+ return $ CouldNotFetch e+ PandocHttpError u er -> do+ report $ CouldNotFetchResource u er+ return $ CouldNotFetch e+ _ -> throwError e+ removeQueryAndFragment = T.takeWhile (\c -> c /= '#' && c /= '?') -- | Convert HTML into self-contained HTML, incorporating images, -- scripts, and CSS using data: URIs. makeSelfContained :: PandocMonad m => T.Text -> m T.Text makeSelfContained inp = do let tags = parseTags inp- out' <- convertTags tags+ let html5 = case tags of+ (TagOpen "!DOCTYPE" [("html","")]:_) -> True+ _ -> False+ let convertState = ConvertState { isHtml5 = html5,+ svgMap = mempty }+ out' <- evalStateT (convertTags tags) convertState return $ renderTags' out'
@@ -1,355 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-module Text.Pandoc.Server- ( app- , ServerOpts(..)- , Params(..)- , Blob(..)- , parseServerOpts- ) where--import Data.Aeson-import Network.Wai-import Servant-import Text.DocTemplates as DocTemplates-import Text.Pandoc-import Text.Pandoc.Citeproc (processCitations)-import Text.Pandoc.Highlighting (lookupHighlightingStyle)-import qualified Text.Pandoc.UTF8 as UTF8-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Lazy.Encoding as TLE-import Data.Maybe (fromMaybe)-import Data.Char (isAlphaNum)-import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as BL-import Data.ByteString.Base64 (decodeBase64, encodeBase64)-import Data.Default-import Control.Monad (when, foldM)-import qualified Data.Set as Set-import Skylighting (defaultSyntaxMap)-import qualified Data.Map as M-import System.Console.GetOpt-import System.Environment (getArgs, getProgName)-import qualified Control.Exception as E-import Text.Pandoc.Shared (safeStrRead, headerShift, filterIpynbOutput,- eastAsianLineBreakFilter, stripEmptyParagraphs)-import Text.Pandoc.App.Opt ( IpynbOutput (..), Opt(..), defaultOpts )-import Text.Pandoc.Builder (setMeta)-import Text.Pandoc.SelfContained (makeSelfContained)-import System.Exit--data ServerOpts =- ServerOpts- { serverPort :: Int- , serverTimeout :: Int }- deriving (Show)--defaultServerOpts :: ServerOpts-defaultServerOpts = ServerOpts { serverPort = 3030, serverTimeout = 2 }--cliOptions :: [OptDescr (ServerOpts -> IO ServerOpts)]-cliOptions =- [ Option ['p'] ["port"]- (ReqArg (\s opts -> case safeStrRead s of- Just i -> return opts{ serverPort = i }- Nothing ->- E.throwIO $ PandocOptionError $ T.pack- s <> " is not a number") "NUMBER")- "port number"- , Option ['t'] ["timeout"]- (ReqArg (\s opts -> case safeStrRead s of- Just i -> return opts{ serverTimeout = i }- Nothing ->- E.throwIO $ PandocOptionError $ T.pack- s <> " is not a number") "NUMBER")- "timeout (seconds)"-- , Option ['h'] ["help"]- (NoArg (\_ -> do- prg <- getProgName- let header = "Usage: " <> prg <> " [OPTION...]"- putStrLn $ usageInfo header cliOptions- exitWith ExitSuccess))- "help message"-- , Option ['v'] ["version"]- (NoArg (\_ -> do- prg <- getProgName- putStrLn $ prg <> " " <> T.unpack pandocVersion- exitWith ExitSuccess))- "version info"-- ]--parseServerOpts :: IO ServerOpts-parseServerOpts = do- args <- getArgs- let handleUnknownOpt x = "Unknown option: " <> x- case getOpt' Permute cliOptions args of- (os, ns, unrecognizedOpts, es) -> do- when (not (null es) || not (null unrecognizedOpts)) $- E.throwIO $ PandocOptionError $ T.pack $- concat es ++ unlines (map handleUnknownOpt unrecognizedOpts) ++- ("Try --help for more information.")- when (not (null ns)) $- E.throwIO $ PandocOptionError $ T.pack $- "Unknown arguments: " <> unwords ns- foldM (flip ($)) defaultServerOpts os--newtype Blob = Blob BL.ByteString- deriving (Show, Eq)--instance ToJSON Blob where- toJSON (Blob bs) = toJSON (encodeBase64 $ BL.toStrict bs)--instance FromJSON Blob where- parseJSON = withText "Blob" $ \t -> do- let inp = UTF8.fromText t- case decodeBase64 inp of- Right bs -> return $ Blob $ BL.fromStrict bs- Left _ -> -- treat as regular text- return $ Blob $ BL.fromStrict inp---- This is the data to be supplied by the JSON payload--- of requests. Maybe values may be omitted and will be--- given default values.-data Params = Params- { options :: Opt- , text :: Text- , files :: Maybe (M.Map FilePath Blob)- , citeproc :: Maybe Bool- } deriving (Show)--instance Default Params where- def = Params- { options = defaultOpts- , text = mempty- , files = Nothing- , citeproc = Nothing- }---- Automatically derive code to convert to/from JSON.-instance FromJSON Params where- parseJSON = withObject "Params" $ \o ->- Params- <$> parseJSON (Object o)- <*> o .: "text"- <*> o .:? "files"- <*> o .:? "citeproc"----- This is the API. The "/convert" endpoint takes a request body--- consisting of a JSON-encoded Params structure and responds to--- Get requests with either plain text or JSON, depending on the--- Accept header.-type API =- ReqBody '[JSON] Params :> Post '[PlainText, JSON] Text- :<|>- ReqBody '[JSON] Params :> Post '[OctetStream] BS.ByteString- :<|>- "batch" :> ReqBody '[JSON] [Params] :> Post '[JSON] [Text]- :<|>- "babelmark" :> QueryParam' '[Required] "text" Text :> QueryParam "from" Text :> QueryParam "to" Text :> QueryFlag "standalone" :> Get '[JSON] Value- :<|>- "version" :> Get '[PlainText, JSON] Text--app :: Application-app = serve api server--api :: Proxy API-api = Proxy--server :: Server API-server = convert- :<|> convertBytes- :<|> mapM convert- :<|> babelmark -- for babelmark which expects {"html": "", "version": ""}- :<|> pure pandocVersion- where- babelmark text' from' to' standalone' = do- res <- convert def{ text = text',- options = defaultOpts{- optFrom = from',- optTo = to',- optStandalone = standalone' }- }- return $ toJSON $ object [ "html" .= res, "version" .= pandocVersion ]-- -- We use runPure for the pandoc conversions, which ensures that- -- they will do no IO. This makes the server safe to use. However,- -- it will mean that features requiring IO, like RST includes, will not work.- -- Changing this to- -- handleErr =<< liftIO (runIO (convert' params))- -- will allow the IO operations.- convert params = handleErr $- runPure (convert' id (encodeBase64 . BL.toStrict) params)-- convertBytes params = handleErr $- runPure (convert' UTF8.fromText BL.toStrict params)-- convert' :: (Text -> a) -> (BL.ByteString -> a) -> Params -> PandocPure a- convert' textHandler bsHandler params = do- curtime <- getCurrentTime- -- put files params in ersatz file system- let addFile :: FilePath -> Blob -> FileTree -> FileTree- addFile fp (Blob lbs) =- insertInFileTree fp FileInfo{ infoFileMTime = curtime- , infoFileContents = BL.toStrict lbs }- case files params of- Nothing -> return ()- Just fs -> do- let filetree = M.foldrWithKey addFile mempty fs- modifyPureState $ \st -> st{ stFiles = filetree }-- let opts = options params- let readerFormat = fromMaybe "markdown" $ optFrom opts- let writerFormat = fromMaybe "html" $ optTo opts- (readerSpec, readerExts) <- getReader readerFormat- (writerSpec, writerExts) <- getWriter writerFormat-- let isStandalone = optStandalone opts- let toformat = T.toLower $ T.takeWhile isAlphaNum $ writerFormat- hlStyle <- traverse (lookupHighlightingStyle . T.unpack)- $ optHighlightStyle opts-- mbTemplate <- if isStandalone- then case optTemplate opts of- Nothing -> Just <$>- compileDefaultTemplate toformat- Just t -> Just <$>- compileCustomTemplate toformat t- else return Nothing-- abbrevs <- Set.fromList . filter (not . T.null) . T.lines . UTF8.toText <$>- case optAbbreviations opts of- Nothing -> readDataFile "abbreviations"- Just f -> readFileStrict f-- let readeropts = def{ readerExtensions = readerExts- , readerStandalone = isStandalone- , readerTabStop = optTabStop opts- , readerIndentedCodeClasses =- optIndentedCodeClasses opts- , readerAbbreviations = abbrevs- , readerDefaultImageExtension =- optDefaultImageExtension opts- , readerTrackChanges = optTrackChanges opts- , readerStripComments = optStripComments opts- }- let writeropts =- def{ writerExtensions = writerExts- , writerTabStop = optTabStop opts- , writerWrapText = optWrap opts- , writerColumns = optColumns opts- , writerTemplate = mbTemplate- , writerSyntaxMap = defaultSyntaxMap- , writerVariables = optVariables opts- , writerTableOfContents = optTableOfContents opts- , writerIncremental = optIncremental opts- , writerHTMLMathMethod = optHTMLMathMethod opts- , writerNumberSections = optNumberSections opts- , writerNumberOffset = optNumberOffset opts- , writerSectionDivs = optSectionDivs opts- , writerReferenceLinks = optReferenceLinks opts- , writerDpi = optDpi opts- , writerEmailObfuscation = optEmailObfuscation opts- , writerIdentifierPrefix = optIdentifierPrefix opts- , writerCiteMethod = optCiteMethod opts- , writerHtmlQTags = optHtmlQTags opts- , writerSlideLevel = optSlideLevel opts- , writerTopLevelDivision = optTopLevelDivision opts- , writerListings = optListings opts- , writerHighlightStyle = hlStyle- , writerSetextHeaders = optSetextHeaders opts- , writerEpubSubdirectory = T.pack $ optEpubSubdirectory opts- , writerEpubMetadata = T.pack <$> optEpubMetadata opts- , writerEpubFonts = optEpubFonts opts- , writerEpubChapterLevel = optEpubChapterLevel opts- , writerTOCDepth = optTOCDepth opts- , writerReferenceDoc = optReferenceDoc opts- , writerReferenceLocation = optReferenceLocation opts- , writerPreferAscii = optAscii opts- }- let reader = case readerSpec of- TextReader r -> r readeropts- ByteStringReader r -> \t -> do- let eitherbs = decodeBase64 $ UTF8.fromText t- case eitherbs of- Left errt -> throwError $ PandocSomeError errt- Right bs -> r readeropts $ BL.fromStrict bs- let writer = case writerSpec of- TextWriter w ->- fmap textHandler .- (\d -> w writeropts d >>=- if optEmbedResources opts && htmlFormat (optTo opts)- then makeSelfContained- else return)- ByteStringWriter w -> fmap bsHandler . w writeropts-- let transforms :: Pandoc -> Pandoc- transforms = (case optShiftHeadingLevelBy opts of- 0 -> id- x -> headerShift x) .- (case optStripEmptyParagraphs opts of- True -> stripEmptyParagraphs- False -> id) .- (if extensionEnabled Ext_east_asian_line_breaks- readerExts &&- not (extensionEnabled Ext_east_asian_line_breaks- writerExts &&- optWrap opts == WrapPreserve)- then eastAsianLineBreakFilter- else id) .- (case optIpynbOutput opts of- IpynbOutputAll -> id- IpynbOutputNone -> filterIpynbOutput Nothing- IpynbOutputBest -> filterIpynbOutput (Just $- case optTo opts of- Just "latex" -> Format "latex"- Just "beamer" -> Format "latex"- Nothing -> Format "html"- Just f- | htmlFormat (optTo opts) -> Format "html"- | otherwise -> Format f))-- let meta = (case optBibliography opts of- [] -> id- fs -> setMeta "bibliography" (MetaList- (map (MetaString . T.pack) fs))) .- maybe id (setMeta "csl" . MetaString . T.pack)- (optCSL opts) .- maybe id (setMeta "citation-abbreviations" . MetaString .- T.pack)- (optCitationAbbreviations opts) $- optMetadata opts-- let addMetadata m' (Pandoc m bs) = Pandoc (m <> m') bs-- reader (text params) >>=- return . transforms . addMetadata meta >>=- (case citeproc params of- Just True -> processCitations- _ -> return) >>=- writer-- htmlFormat :: Maybe Text -> Bool- htmlFormat Nothing = True- htmlFormat (Just f) =- any (`T.isPrefixOf` f)- ["html","html4","html5","s5","slidy", "slideous","dzslides","revealjs"]-- handleErr (Right t) = return t- handleErr (Left err) = throwError $- err500 { errBody = TLE.encodeUtf8 $ TL.fromStrict $ renderError err }-- compileCustomTemplate toformat t = do- res <- runWithPartials $ compileTemplate ("custom." <> T.unpack toformat)- (T.pack t)- case res of- Left e -> throwError $ PandocTemplateError (T.pack e)- Right tpl -> return tpl-
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -8,7 +9,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Shared- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -22,13 +23,9 @@ splitBy, splitTextBy, splitTextByIndices,- ordNub,- findM, -- * Text processing inquotes, tshow,- elemText,- notElemText, stripTrailingNewlines, trim, triml,@@ -38,51 +35,44 @@ camelCaseToHyphenated, camelCaseStrToHyphenated, toRomanNumeral,- escapeURI, tabFilter,- crFilter, -- * Date/time normalizeDate, -- * Pandoc block and inline list processing+ addPandocAttributes, orderedListMarkers, extractSpaces, removeFormatting, deNote,- deLink, stringify, capitalize, compactify, compactifyDL, linesToPara,+ figureDiv, makeSections,+ makeSectionsWithOffsets,+ combineAttr, uniqueIdent, inlineListToIdentifier,+ textToIdentifier, isHeaderBlock,- headerShift,- stripEmptyParagraphs,+ hasLineBreaks, onlySimpleTableCells, isTightList, taskListItemFromAscii, taskListItemToAscii, handleTaskListItem, addMetaField,- makeMeta,- eastAsianLineBreakFilter, htmlSpanLikeElements,- filterIpynbOutput, formatCode, -- * TagSoup HTML handling renderTags', -- * File handling inDirectory,+ makeCanonical, collapseFilePath,- uriPathToPath, filteredFilesFromArchive,- -- * URI handling- schemes,- isURI,- -- * Error handling- mapLeft, -- * for squashing blocks blocksToInlines, blocksToInlines',@@ -90,11 +80,7 @@ defaultBlocksSeparator, -- * Safe read safeRead,- safeStrRead,- -- * User data directory- defaultUserDataDir,- -- * Version- pandocVersion+ safeStrRead ) where import Codec.Archive.Zip@@ -102,21 +88,20 @@ import Control.Monad (MonadPlus (..), msum, unless) import qualified Control.Monad.State.Strict as S import qualified Data.ByteString.Lazy as BL-import qualified Data.Bifunctor as Bifunctor+import Data.Containers.ListUtils (nubOrd) import Data.Char (isAlpha, isLower, isSpace, isUpper, toLower, isAlphaNum, generalCategory, GeneralCategory(NonSpacingMark, SpacingCombiningMark, EnclosingMark, ConnectorPunctuation))-import Data.Containers.ListUtils (nubOrd)-import Data.List (find, intercalate, intersperse, sortOn, foldl', groupBy)+import Data.List (find, groupBy, intercalate, intersperse, union)+import qualified Data.List as L import qualified Data.Map as M-import Data.Maybe (mapMaybe, fromMaybe)-import Data.Monoid (Any (..))+import Data.Maybe (mapMaybe)+import Data.Monoid (Any (..) )+import Data.Semigroup (Min (..)) import Data.Sequence (ViewL (..), ViewR (..), viewl, viewr) import qualified Data.Set as Set import qualified Data.Text as T-import Data.Version (showVersion)-import Network.URI (URI (uriScheme), escapeURIString, parseURI)-import Paths_pandoc (version)+import qualified Text.Emoji as Emoji import System.Directory import System.FilePath (isPathSeparator, splitDirectories) import qualified System.FilePath.Posix as Posix@@ -128,13 +113,11 @@ import Text.Pandoc.Asciify (toAsciiText) import Text.Pandoc.Definition import Text.Pandoc.Extensions (Extensions, Extension(..), extensionEnabled)-import Text.Pandoc.Generic (bottomUp) import Text.DocLayout (charWidth) import Text.Pandoc.Walk---- | Version number of pandoc library.-pandocVersion :: T.Text-pandocVersion = T.pack $ showVersion version+-- for addPandocAttributes:+import Commonmark.Pandoc (Cm(..))+import Commonmark (HasAttributes(..)) -- -- List processing@@ -158,40 +141,27 @@ -- /not/ indices but text widths, which will be different for East Asian -- characters, emojis, etc. splitTextByIndices :: [Int] -> T.Text -> [T.Text]-splitTextByIndices ns = splitTextByRelIndices (zipWith (-) ns (0:ns)) . T.unpack+splitTextByIndices ns = splitByRelWidths (zipWith (-) ns (0:ns)) where- splitTextByRelIndices [] cs = [T.pack cs]- splitTextByRelIndices (x:xs) cs =- let (first, rest) = splitAt' x cs- in T.pack first : splitTextByRelIndices xs rest+ splitByRelWidths [] t = [t]+ splitByRelWidths (w:ws) t =+ let (first, rest) = splitAtWidth w t+ in first : splitByRelWidths ws rest --- | Returns a pair whose first element is a prefix of @t@ and that has--- width @n@, and whose second is the remainder of the string.+-- | Split a @Text@ at a given display width, where width is determined+-- by 'charWidth' (East Asian characters, emojis, etc. count as 2). -- -- Note: Do *not* replace this with 'T.splitAt', which is not sensitive -- to character widths!-splitAt' :: Int {-^ n -} -> [Char] {-^ t -} -> ([Char],[Char])-splitAt' _ [] = ([],[])-splitAt' n xs | n <= 0 = ([],xs)-splitAt' n (x:xs) = (x:ys,zs)- where (ys,zs) = splitAt' (n - charWidth x) xs---- | Remove duplicates from a list.-ordNub :: (Ord a) => [a] -> [a]-ordNub = nubOrd-{-# INLINE ordNub #-}---- | Returns the first element in a foldable structure for that the--- monadic predicate holds true, and @Nothing@ if no such element--- exists.-findM :: forall m t a. (Monad m, Foldable t)- => (a -> m Bool) -> t a -> m (Maybe a)-findM p = foldr go (pure Nothing)+splitAtWidth :: Int -> T.Text -> (T.Text, T.Text)+splitAtWidth n t+ | n <= 0 = (T.empty, t)+ | otherwise = T.splitAt (go 0 0 t) t where- go :: a -> m (Maybe a) -> m (Maybe a)- go x acc = do- b <- p x- if b then pure (Just x) else acc+ go !idx !w t'+ | w >= n = idx+ | T.null t' = idx+ | otherwise = go (idx + 1) (w + charWidth (T.head t')) (T.tail t') -- -- Text processing@@ -205,14 +175,6 @@ tshow :: Show a => a -> T.Text tshow = T.pack . show --- | @True@ exactly when the @Char@ appears in the @Text@.-elemText :: Char -> T.Text -> Bool-elemText c = T.any (== c)---- | @True@ exactly when the @Char@ does not appear in the @Text@.-notElemText :: Char -> T.Text -> Bool-notElemText c = T.all (/= c)- -- | Strip trailing newlines from string. stripTrailingNewlines :: T.Text -> T.Text stripTrailingNewlines = T.dropWhileEnd (== '\n')@@ -280,26 +242,23 @@ toRomanNumeral :: Int -> T.Text toRomanNumeral x | x >= 4000 || x < 0 = "?"- | x >= 1000 = "M" <> toRomanNumeral (x - 1000)- | x >= 900 = "CM" <> toRomanNumeral (x - 900)- | x >= 500 = "D" <> toRomanNumeral (x - 500)- | x >= 400 = "CD" <> toRomanNumeral (x - 400)- | x >= 100 = "C" <> toRomanNumeral (x - 100)- | x >= 90 = "XC" <> toRomanNumeral (x - 90)- | x >= 50 = "L" <> toRomanNumeral (x - 50)- | x >= 40 = "XL" <> toRomanNumeral (x - 40)- | x >= 10 = "X" <> toRomanNumeral (x - 10)- | x == 9 = "IX"- | x >= 5 = "V" <> toRomanNumeral (x - 5)- | x == 4 = "IV"- | x >= 1 = "I" <> toRomanNumeral (x - 1)- | otherwise = ""---- | Escape whitespace and some punctuation characters in URI.-escapeURI :: T.Text -> T.Text-escapeURI = T.pack . escapeURIString (not . needsEscaping) . T.unpack- where needsEscaping c = isSpace c || c `elemText` "<>|\"{}[]^`"-+ | otherwise = T.pack (go x)+ where+ go n+ | n >= 1000 = 'M' : go (n - 1000)+ | n >= 900 = 'C' : 'M' : go (n - 900)+ | n >= 500 = 'D' : go (n - 500)+ | n >= 400 = 'C' : 'D' : go (n - 400)+ | n >= 100 = 'C' : go (n - 100)+ | n >= 90 = 'X' : 'C' : go (n - 90)+ | n >= 50 = 'L' : go (n - 50)+ | n >= 40 = 'X' : 'L' : go (n - 40)+ | n >= 10 = 'X' : go (n - 10)+ | n == 9 = "IX"+ | n >= 5 = 'V' : go (n - 5)+ | n == 4 = "IV"+ | n >= 1 = 'I' : go (n - 1)+ | otherwise = [] -- | Convert tabs to spaces. Tabs will be preserved if tab stop is set to 0. tabFilter :: Int -- ^ Tab stop@@ -312,14 +271,9 @@ in if T.null s2 then s1 else s1 <> T.replicate- (tabStop - (T.length s1 `mod` tabStop)) (T.pack " ")+ (tabStop - (T.length s1 `mod` tabStop)) " " <> go (T.drop 1 s2) -{-# DEPRECATED crFilter "readers filter crs automatically" #-}--- | Strip out DOS line endings.-crFilter :: T.Text -> T.Text-crFilter = T.filter (/= '\r')- -- -- Date/time --@@ -346,6 +300,16 @@ -- Pandoc block and inline list processing -- +-- | Add key-value attributes to a pandoc element. If the element+-- does not have a slot for attributes, create an enclosing Span+-- (for Inlines) or Div (for Blocks). Note that both 'Cm () Inlines'+-- and 'Cm () Blocks' are instances of 'HasAttributes'.+addPandocAttributes+ :: forall b . HasAttributes (Cm () b) => [(T.Text, T.Text)] -> b -> b+addPandocAttributes [] bs = bs+addPandocAttributes kvs bs =+ unCm . addAttributes kvs $ (Cm bs :: Cm () b)+ -- | Generate infinite lazy list of markers for an ordered list, -- depending on list attributes. orderedListMarkers :: (Int, ListNumberStyle, ListNumberDelim) -> [T.Text]@@ -401,12 +365,6 @@ deNote (Note _) = Str "" deNote x = x --- {- DEPRECATED deLink "deLink will be removed in a future version" -}--- | Turns links into spans, keeping just the link text.-deLink :: Inline -> Inline-deLink (Link _ ils _) = Span nullAttr ils-deLink x = x- -- | Convert pandoc structure to a string with formatting removed. -- Footnotes are skipped (since we don't want their contents in link -- labels).@@ -459,9 +417,9 @@ let (others, final) = (init items, last items) in case reverse (B.toList final) of (Para a:xs)- | null [Para x | Para x <- xs ++ concatMap B.toList others]+ | not (any isPara xs || any (any isPara . B.toList) others) -> others ++ [B.fromList (reverse (Plain a : xs))]- _ | null [Para x | Para x <- concatMap B.toList items]+ _ | not (any (any isPara . B.toList) items) -> items _ -> map (fmap plainToPara) items @@ -493,16 +451,31 @@ linesToPara :: [[Inline]] -> Block linesToPara = Para . combineLines +-- | Creates a Div block from figure components. The intended use is in+-- writers of formats that do not have markup support for figures.+--+-- The resulting div is given the class @figure@ and contains the figure+-- body and the figure caption. The latter is wrapped in a 'Div' of+-- class @caption@, with the stringified @short-caption@ as attribute.+figureDiv :: Attr -> Caption -> [Block] -> Block+figureDiv (ident, classes, kv) (Caption shortcapt longcapt) body =+ let divattr = ( ident+ , ["figure"] `union` classes+ , kv+ )+ captkv = maybe mempty (\s -> [("short-caption", stringify s)]) shortcapt+ capt = [Div ("", ["caption"], captkv) longcapt | not (null longcapt)]+ in Div divattr (body ++ capt)++-- | Returns 'True' iff the given element is a 'Para'. isPara :: Block -> Bool isPara (Para _) = True isPara _ = False --- | Convert Pandoc inline list to plain text identifier. HTML--- identifiers must start with a letter, and may contain only--- letters, digits, and the characters _-.+-- | Convert Pandoc inline list to plain text identifier. inlineListToIdentifier :: Extensions -> [Inline] -> T.Text inlineListToIdentifier exts =- dropNonLetter . filterAscii . toIdent . stringify . walk unEmojify+ textToIdentifier exts . stringify . unEmojify where unEmojify :: [Inline] -> [Inline] unEmojify@@ -510,7 +483,16 @@ extensionEnabled Ext_ascii_identifiers exts = walk unEmoji | otherwise = id unEmoji (Span ("",["emoji"],[("data-emoji",ename)]) _) = Str ename+ unEmoji (Str t) = Str (Emoji.replaceEmojis emojisToAliases t) unEmoji x = x+ emojisToAliases t [] = t+ emojisToAliases _ (a:_) = a++-- | Convert string to plain text identifier.+textToIdentifier :: Extensions -> T.Text -> T.Text+textToIdentifier exts =+ dropNonLetter . filterAscii . toIdent+ where dropNonLetter | extensionEnabled Ext_gfm_auto_identifiers exts = id | otherwise = T.dropWhile (not . isAlpha)@@ -537,29 +519,36 @@ -- element a Header). If the 'numbering' parameter is True, Header -- numbers are added via the number attribute on the header. -- If the baseLevel parameter is Just n, Header levels are--- adjusted to be gapless starting at level n.+-- adjusted so that the lowest header level is n.+-- (There may still be gaps in header level if the author leaves them.) makeSections :: Bool -> Maybe Int -> [Block] -> [Block]-makeSections numbering mbBaseLevel bs =- S.evalState (go bs) (mbBaseLevel, [])+makeSections = makeSectionsWithOffsets []++-- | Like 'makeSections', but with a parameter for number offsets+-- (a list of 'Int's, the first of which is added to the level 1+-- section number, the second to the level 2, and so on).+makeSectionsWithOffsets :: [Int] -> Bool -> Maybe Int -> [Block] -> [Block]+makeSectionsWithOffsets numoffsets numbering mbBaseLevel bs =+ S.evalState (go bs) numoffsets where- go :: [Block] -> S.State (Maybe Int, [Int]) [Block]+ getLevel (Header level _ _) = Min level+ getLevel _ = Min 99+ minLevel = if all (== 0) numoffsets+ then getMin $ query getLevel bs+ else 1 -- see #5071, for backwards compatibility+ go :: [Block] -> S.State [Int] [Block] go (Header level (ident,classes,kvs) title':xs) = do- (mbLevel, lastnum) <- S.get- let level' = fromMaybe level mbLevel- let lastnum' = take level' lastnum- let newnum =- if level' > 0- then case length lastnum' of- x | "unnumbered" `elem` classes -> []- | x >= level' -> init lastnum' ++ [last lastnum' + 1]- | otherwise -> lastnum ++- replicate (level' - length lastnum - 1) 0 ++ [1]- else []- unless (null newnum) $ S.modify $ \(mbl, _) -> (mbl, newnum)+ lastnum <- S.get+ let level' = maybe level (\n -> n + level - minLevel) mbBaseLevel+ let adjustNum lev numComponent+ | lev < level = numComponent+ | lev == level = numComponent + 1+ | otherwise = 0+ let newnum = zipWith adjustNum [minLevel..level]+ (lastnum ++ repeat 0)+ unless (null newnum || "unnumbered" `elem` classes) $ S.put newnum let (sectionContents, rest) = break (headerLtEq level) xs- S.modify $ \(_, ln) -> (fmap (+ 1) mbLevel, ln) sectionContents' <- go sectionContents- S.modify $ \(_, ln) -> (mbLevel, ln) rest' <- go rest let kvs' = -- don't touch number if already present case lookup "number" kvs of@@ -568,9 +557,14 @@ ("number", T.intercalate "." (map tshow newnum)) : kvs _ -> kvs let divattr = (ident, "section":classes, kvs')- let attr = ("",classes,kvs')+ let isHeadingAttr ("epub:type",_) = False+ isHeadingAttr ("role",v) =+ v `elem` ["tab", "presentation", "none", "treeitem",+ "menuitem", "button", "heading"]+ isHeadingAttr _ = True+ let hattr = ("",classes, filter isHeadingAttr kvs') return $- Div divattr (Header level' attr title' : sectionContents') : rest'+ Div divattr (Header level' hattr title' : sectionContents') : rest' go (Div divattr@(dident,dclasses,_) (Header level hattr title':ys) : xs) | all (\case Header level' _ _ -> level' > level@@ -590,17 +584,18 @@ xs' <- go xs rest' <- go rest return $ Div attr xs' : rest'- go (Null:xs) = go xs go (x:xs) = (x :) <$> go xs go [] = return [] - combineAttr :: Attr -> Attr -> Attr- combineAttr (id1, classes1, kvs1) (id2, classes2, kvs2) =- (if T.null id1 then id2 else id1,- ordNub (classes1 ++ classes2),- foldr (\(k,v) kvs -> case lookup k kvs of- Nothing -> (k,v):kvs- Just _ -> kvs) mempty (kvs1 ++ kvs2))+-- | Combine two 'Attr'. Classes are concatenated. For the id and key-value+-- attributes, the first one takes precedence in case of duplicates.+combineAttr :: Attr -> Attr -> Attr+combineAttr (id1, classes1, kvs1) (id2, classes2, kvs2) =+ (if T.null id1 then id2 else id1,+ nubOrd (classes1 ++ classes2),+ foldr (\(k,v) kvs -> case lookup k kvs of+ Nothing -> (k,v):kvs+ Just _ -> kvs) kvs1 kvs2) headerLtEq :: Int -> Block -> Bool headerLtEq level (Header l _ _) = l <= level@@ -622,34 +617,23 @@ x -> x numIdent n = baseIdent <> "-" <> tshow n +-- | True if inlines include a LineBreak (possibly embedded), with the exception+-- of line breaks in Notes.+hasLineBreaks :: [Inline] -> Bool+hasLineBreaks = getAny . query isLineBreak . walk removeNote+ where+ removeNote :: Inline -> Inline+ removeNote (Note _) = Str ""+ removeNote x = x+ isLineBreak :: Inline -> Any+ isLineBreak LineBreak = Any True+ isLineBreak _ = Any False+ -- | True if block is a Header block. isHeaderBlock :: Block -> Bool isHeaderBlock Header{} = True isHeaderBlock _ = False --- | Shift header levels up or down.-headerShift :: Int -> Pandoc -> Pandoc-headerShift n (Pandoc meta (Header m _ ils : bs))- | n < 0- , m + n == 0 = headerShift n $- B.setTitle (B.fromList ils) $ Pandoc meta bs-headerShift n (Pandoc meta bs) = Pandoc meta (walk shift bs)-- where- shift :: Block -> Block- shift (Header level attr inner)- | level + n > 0 = Header (level + n) attr inner- | otherwise = Para inner- shift x = x---- | Remove empty paragraphs.-stripEmptyParagraphs :: Pandoc -> Pandoc-stripEmptyParagraphs = walk go- where go :: [Block] -> [Block]- go = filter (not . isEmptyParagraph)- isEmptyParagraph (Para []) = True- isEmptyParagraph _ = False- -- | Detect if table rows contain only cells consisting of a single -- paragraph that has no @LineBreak@. onlySimpleTableCells :: [[[Block]]] -> Bool@@ -665,9 +649,13 @@ -- | Detect if a list is tight. isTightList :: [[Block]] -> Bool-isTightList = all (\item -> firstIsPlain item || null item)- where firstIsPlain (Plain _ : _) = True- firstIsPlain _ = False+isTightList = all isPlainItem+ where+ isPlainItem [] = True+ isPlainItem (Plain _ : _) = True+ isPlainItem [BulletList xs] = isTightList xs+ isPlainItem [OrderedList _ xs] = isTightList xs+ isPlainItem _ = False -- | Convert a list item containing tasklist syntax (e.g. @[x]@) -- to using @U+2610 BALLOT BOX@ or @U+2612 BALLOT BOX WITH X@.@@ -715,72 +703,10 @@ tolist (MetaList ys) = ys tolist y = [y] --- | Create 'Meta' from old-style title, authors, date. This is--- provided to ease the transition from the old API.-makeMeta :: [Inline] -> [[Inline]] -> [Inline] -> Meta-makeMeta title authors date =- addMetaField "title" (B.fromList title)- $ addMetaField "author" (map B.fromList authors)- $ addMetaField "date" (B.fromList date) nullMeta---- | Remove soft breaks between East Asian characters.-eastAsianLineBreakFilter :: Pandoc -> Pandoc-eastAsianLineBreakFilter = bottomUp go- where go (x:SoftBreak:y:zs)- | Just (_, b) <- T.unsnoc $ stringify x- , Just (c, _) <- T.uncons $ stringify y- , charWidth b == 2- , charWidth c == 2- = x:y:zs- | otherwise- = x:SoftBreak:y:zs- go xs- = xs- -- | Set of HTML elements that are represented as Span with a class equal as -- the element tag itself. htmlSpanLikeElements :: Set.Set T.Text-htmlSpanLikeElements = Set.fromList ["kbd", "mark", "dfn"]---- | Process ipynb output cells. If mode is Nothing,--- remove all output. If mode is Just format, select--- best output for the format. If format is not ipynb,--- strip out ANSI escape sequences from CodeBlocks (see #5633).-filterIpynbOutput :: Maybe Format -> Pandoc -> Pandoc-filterIpynbOutput mode = walk go- where go (Div (ident, "output":os, kvs) bs) =- case mode of- Nothing -> Div (ident, "output":os, kvs) []- -- "best" for ipynb includes all formats:- Just fmt- | fmt == Format "ipynb"- -> Div (ident, "output":os, kvs) bs- | otherwise -> Div (ident, "output":os, kvs) $- walk removeANSI $- take 1 $ sortOn rank bs- where- rank (RawBlock (Format "html") _)- | fmt == Format "html" = 1 :: Int- | fmt == Format "markdown" = 3- | otherwise = 4- rank (RawBlock (Format "latex") _)- | fmt == Format "latex" = 1- | fmt == Format "markdown" = 3- | otherwise = 4- rank (RawBlock f _)- | fmt == f = 1- | otherwise = 4- rank (Para [Image{}]) = 2- rank _ = 3- removeANSI (CodeBlock attr code) =- CodeBlock attr (removeANSIEscapes code)- removeANSI x = x- removeANSIEscapes t- | Just cs <- T.stripPrefix "\x1b[" t =- removeANSIEscapes $ T.drop 1 $ T.dropWhile (/='m') cs- | Just (c, cs) <- T.uncons t = T.cons c $ removeANSIEscapes cs- | otherwise = ""- go x = x+htmlSpanLikeElements = Set.fromList ["kbd", "mark", "dfn", "abbr"] -- | Reformat 'Inlines' as code, putting the stringlike parts in 'Code' -- elements while bringing other inline formatting outside.@@ -809,10 +735,12 @@ -- | Render HTML tags. renderTags' :: [Tag T.Text] -> T.Text renderTags' = renderTagsOptions- renderOptions{ optMinimize = matchTags ["hr", "br", "img",- "meta", "link", "col"]- , optRawTag = matchTags ["script", "style"] }- where matchTags tags = flip elem tags . T.toLower+ renderOptions{ optMinimize = \t -> T.toLower t `Set.member` minimizeTags+ , optRawTag = \t -> T.toLower t `Set.member` rawTags }+ where+ minimizeTags = Set.fromList ["hr","br","img","meta","link","col",+ "use","path","rect"]+ rawTags = Set.fromList ["script","style"] -- -- File handling@@ -825,12 +753,14 @@ setCurrentDirectory (const $ setCurrentDirectory path >> action) ------ Error reporting-----mapLeft :: (a -> b) -> Either a c -> Either b c-mapLeft = Bifunctor.first+-- | Canonicalizes a file path by removing redundant @.@ and @..@.+makeCanonical :: FilePath -> FilePath+makeCanonical = Posix.joinPath . transformPathParts . splitDirectories+ where transformPathParts = reverse . L.foldl' go []+ go as "." = as+ go ("..":as) ".." = ["..", ".."] <> as+ go (_:as) ".." = as+ go as x = x : as -- | Remove intermediate "." and ".." directories from a path. --@@ -842,7 +772,7 @@ -- > collapseFilePath "parent/foo/.." == "parent" -- > collapseFilePath "/parent/foo/../../bar" == "/bar" collapseFilePath :: FilePath -> FilePath-collapseFilePath = Posix.joinPath . reverse . foldl' go [] . splitDirectories+collapseFilePath = Posix.joinPath . reverse . L.foldl' go [] . splitDirectories where go rs "." = rs go r@(p:rs) ".." = case p of@@ -856,19 +786,6 @@ isSingleton _ = Nothing checkPathSeperator = fmap isPathSeparator . isSingleton --- | Converts the path part of a file: URI to a regular path.--- On windows, @/c:/foo@ should be @c:/foo@.--- On linux, @/foo@ should be @/foo@.-uriPathToPath :: T.Text -> FilePath-uriPathToPath (T.unpack -> path) =-#ifdef _WINDOWS- case path of- '/':ps -> ps- ps -> ps-#else- path-#endif- -- -- File selection from the archive --@@ -879,70 +796,6 @@ fileAndBinary :: Archive -> FilePath -> Maybe (FilePath, BL.ByteString) fileAndBinary a fp = findEntryByPath fp a >>= \e -> Just (fp, fromEntry e) ------ IANA URIs------- | Schemes from http://www.iana.org/assignments/uri-schemes.html plus--- the unofficial schemes doi, javascript, isbn, pmid.-schemes :: Set.Set T.Text-schemes = Set.fromList- -- Official IANA schemes- [ "aaa", "aaas", "about", "acap", "acct", "acr", "adiumxtra", "afp", "afs"- , "aim", "appdata", "apt", "attachment", "aw", "barion", "beshare", "bitcoin"- , "blob", "bolo", "browserext", "callto", "cap", "chrome", "chrome-extension"- , "cid", "coap", "coaps", "com-eventbrite-attendee", "content", "crid", "cvs"- , "data", "dav", "dict", "dis", "dlna-playcontainer", "dlna-playsingle"- , "dns", "dntp", "dtn", "dvb", "ed2k", "example", "facetime", "fax", "feed"- , "feedready", "file", "filesystem", "finger", "fish", "ftp", "geo", "gg"- , "git", "gizmoproject", "go", "gopher", "graph", "gtalk", "h323", "ham"- , "hcp", "http", "https", "hxxp", "hxxps", "hydrazone", "iax", "icap", "icon"- , "im", "imap", "info", "iotdisco", "ipn", "ipp", "ipps", "irc", "irc6"- , "ircs", "iris", "iris.beep", "iris.lwz", "iris.xpc", "iris.xpcs"- , "isostore", "itms", "jabber", "jar", "jms", "keyparc", "lastfm", "ldap"- , "ldaps", "lvlt", "magnet", "mailserver", "mailto", "maps", "market"- , "message", "mid", "mms", "modem", "mongodb", "moz", "ms-access"- , "ms-browser-extension", "ms-drive-to", "ms-enrollment", "ms-excel"- , "ms-gamebarservices", "ms-getoffice", "ms-help", "ms-infopath"- , "ms-media-stream-id", "ms-officeapp", "ms-project", "ms-powerpoint"- , "ms-publisher", "ms-search-repair", "ms-secondary-screen-controller"- , "ms-secondary-screen-setup", "ms-settings", "ms-settings-airplanemode"- , "ms-settings-bluetooth", "ms-settings-camera", "ms-settings-cellular"- , "ms-settings-cloudstorage", "ms-settings-connectabledevices"- , "ms-settings-displays-topology", "ms-settings-emailandaccounts"- , "ms-settings-language", "ms-settings-location", "ms-settings-lock"- , "ms-settings-nfctransactions", "ms-settings-notifications"- , "ms-settings-power", "ms-settings-privacy", "ms-settings-proximity"- , "ms-settings-screenrotation", "ms-settings-wifi", "ms-settings-workplace"- , "ms-spd", "ms-sttoverlay", "ms-transit-to", "ms-virtualtouchpad"- , "ms-visio", "ms-walk-to", "ms-whiteboard", "ms-whiteboard-cmd", "ms-word"- , "msnim", "msrp", "msrps", "mtqp", "mumble", "mupdate", "mvn", "news", "nfs"- , "ni", "nih", "nntp", "notes", "ocf", "oid", "onenote", "onenote-cmd"- , "opaquelocktoken", "pack", "palm", "paparazzi", "pkcs11", "platform", "pop"- , "pres", "prospero", "proxy", "pwid", "psyc", "qb", "query", "redis"- , "rediss", "reload", "res", "resource", "rmi", "rsync", "rtmfp", "rtmp"- , "rtsp", "rtsps", "rtspu", "secondlife", "service", "session", "sftp", "sgn"- , "shttp", "sieve", "sip", "sips", "skype", "smb", "sms", "smtp", "snews"- , "snmp", "soap.beep", "soap.beeps", "soldat", "spotify", "ssh", "steam"- , "stun", "stuns", "submit", "svn", "tag", "teamspeak", "tel", "teliaeid"- , "telnet", "tftp", "things", "thismessage", "tip", "tn3270", "tool", "turn"- , "turns", "tv", "udp", "unreal", "urn", "ut2004", "v-event", "vemmi"- , "ventrilo", "videotex", "vnc", "view-source", "wais", "webcal", "wpid"- , "ws", "wss", "wtai", "wyciwyg", "xcon", "xcon-userid", "xfire"- , "xmlrpc.beep", "xmlrpc.beeps", "xmpp", "xri", "ymsgr", "z39.50", "z39.50r"- , "z39.50s"- -- Unofficial schemes- , "doi", "isbn", "javascript", "pmid"- ]---- | Check if the string is a valid URL with a IANA or frequently used but--- unofficial scheme (see @schemes@).-isURI :: T.Text -> Bool-isURI = maybe False hasKnownScheme . parseURI . T.unpack- where- hasKnownScheme = (`Set.member` schemes) . T.toLower .- T.filter (/= ':') . T.pack . uriScheme- --- --- Squash blocks into inlines ---@@ -974,7 +827,7 @@ unTableBody (TableBody _ _ hd bd) = hd <> bd unTableBodies = concatMap unTableBody blockToInlines (Div _ blks) = blocksToInlines' blks-blockToInlines Null = mempty+blockToInlines (Figure _ _ body) = blocksToInlines' body blocksToInlinesWithSep :: Inlines -> [Block] -> Inlines blocksToInlinesWithSep sep =@@ -992,7 +845,7 @@ defaultBlocksSeparator = -- This is used in the pandoc.utils.blocks_to_inlines function. Docs -- there should be updated if this is changed.- B.space <> B.str "¶" <> B.space+ B.linebreak -- -- Safe read@@ -1006,24 +859,3 @@ (d,x):_ | all isSpace x -> return d _ -> mzero------ User data directory------- | Return appropriate user data directory for platform. We use--- XDG_DATA_HOME (or its default value), but for backwards compatibility,--- we fall back to the legacy user data directory ($HOME/.pandoc on *nix)--- if the XDG_DATA_HOME is missing and this exists. If neither directory--- is present, we return the XDG data directory. If the XDG data directory--- is not defined (e.g. because we are in an environment where $HOME is--- not defined), we return the empty string.-defaultUserDataDir :: IO FilePath-defaultUserDataDir = do- xdgDir <- E.catch (getXdgDirectory XdgData "pandoc")- (\(_ :: E.SomeException) -> return mempty)- legacyDir <- getAppUserDataDirectory "pandoc"- xdgExists <- doesDirectoryExist xdgDir- legacyDirExists <- doesDirectoryExist legacyDir- if not xdgExists && legacyDirExists- then return legacyDir- else return xdgDir
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Slides- Copyright : Copyright (C) 2012-2022 John MacFarlane+ Copyright : Copyright (C) 2012-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -30,7 +30,7 @@ -- | Prepare a block list to be passed to makeSections. prepSlides :: Int -> [Block] -> [Block]-prepSlides slideLevel = ensureStartWithH . splitHrule . extractRefsHeader . filter (/= Null)+prepSlides slideLevel = ensureStartWithH . splitHrule . extractRefsHeader where splitHrule (HorizontalRule : Header n attr xs : ys) | n == slideLevel = Header slideLevel attr xs : splitHrule ys splitHrule (HorizontalRule : xs) = Header slideLevel nullAttr [Str "\0"] :
@@ -6,7 +6,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Sources- Copyright : Copyright (C) 2021-2022 John MacFarlane+ Copyright : Copyright (C) 2021-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -46,6 +46,8 @@ import Text.Parsec.Pos as P import Data.Text (Text) import qualified Data.Text as T+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as BL import Data.Char (isSpace, isLetter, isAlphaNum, isDigit, isHexDigit) import Data.String (IsString(..)) import qualified Data.List.NonEmpty as NonEmpty@@ -110,6 +112,15 @@ updateSourcePos :: SourcePos -> c -> s -> SourcePos instance UpdateSourcePos Text Char where+ updateSourcePos pos c _ = updatePosChar pos c++instance UpdateSourcePos [Char] Char where+ updateSourcePos pos c _ = updatePosChar pos c++instance UpdateSourcePos BS.ByteString Char where+ updateSourcePos pos c _ = updatePosChar pos c++instance UpdateSourcePos BL.ByteString Char where updateSourcePos pos c _ = updatePosChar pos c instance UpdateSourcePos Sources Char where
@@ -0,0 +1,54 @@+{-# LANGUAGE FlexibleInstances #-}+{- |+ Module : Text.Pandoc.TeX+ Copyright : Copyright (C) 2017-2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Types for TeX tokens and macros.+-}+module Text.Pandoc.TeX ( Tok(..)+ , TokType(..)+ , Macro(..)+ , ArgSpec(..)+ , ExpansionPoint(..)+ , MacroScope(..)+ , SourcePos+ )+where+import Data.Text (Text)+import Text.Parsec (SourcePos, sourceName)+import Text.Pandoc.Sources+import Data.List (groupBy)++data TokType = CtrlSeq Text | Spaces | Newline | Symbol | Word | Comment |+ Esc1 | Esc2 | Arg Int | DeferredArg Int+ deriving (Eq, Ord, Show)++data Tok = Tok SourcePos TokType Text+ deriving (Eq, Ord, Show)++instance ToSources [Tok] where+ toSources = Sources+ . map (\ts -> case ts of+ Tok p _ _ : _ -> (p, mconcat $ map tokToText ts)+ _ -> error "toSources [Tok] encountered empty group")+ . groupBy (\(Tok p1 _ _) (Tok p2 _ _) -> sourceName p1 == sourceName p2)++tokToText :: Tok -> Text+tokToText (Tok _ _ t) = t++data ExpansionPoint = ExpandWhenDefined | ExpandWhenUsed+ deriving (Eq, Ord, Show)++data MacroScope = GlobalScope | GroupScope+ deriving (Eq, Ord, Show)++data Macro = Macro MacroScope ExpansionPoint [ArgSpec] (Maybe [Tok]) [Tok]+ deriving Show++data ArgSpec = ArgNum Int | Pattern [Tok]+ deriving Show
@@ -4,7 +4,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Templates- Copyright : Copyright (C) 2009-2022 John MacFarlane+ Copyright : Copyright (C) 2009-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -12,6 +12,22 @@ Portability : portable Utility functions for working with pandoc templates.++'WithDefaultPartials' and 'WithPartials' are Monad wrappers. Wrapping+these around an instance of 'PandocMonad' gives different instances of+'TemplateMonad', with different search behaviors when retrieving+partials.++To compile a template and limit partial search to pandoc’s data files,+use @runWithDefaultPartials (compileTemplate ...)@.++To compile a template and allow partials to be found locally (either on+the file system or via HTTP, in the event that the main template has an+absolute URL), ue @runWithPartials (compileTemplate ...)@.++'getTemplate' seeks a template locally, or via HTTP if the template has+an absolute URL, falling back to the data files if not found.+ -} module Text.Pandoc.Templates ( Template@@ -27,9 +43,10 @@ import System.FilePath ((<.>), (</>), takeFileName) import Text.DocTemplates (Template, TemplateMonad(..), compileTemplate, renderTemplate) import Text.Pandoc.Class.CommonState (CommonState(..))-import Text.Pandoc.Class.PandocMonad (PandocMonad, readDataFile, fetchItem,- getCommonState, modifyCommonState)-import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Class.PandocMonad (PandocMonad, fetchItem,+ getCommonState, modifyCommonState,+ toTextM)+import Text.Pandoc.Data (readDataFile) import Control.Monad.Except (catchError, throwError) import Data.Text (Text) import qualified Data.Text as T@@ -49,14 +66,14 @@ instance PandocMonad m => TemplateMonad (WithDefaultPartials m) where getPartial fp = WithDefaultPartials $- UTF8.toText <$> readDataFile ("templates" </> takeFileName fp)+ readDataFile ("templates" </> takeFileName fp) >>= toTextM fp instance PandocMonad m => TemplateMonad (WithPartials m) where getPartial fp = WithPartials $ getTemplate fp -- | Retrieve text for a template. getTemplate :: PandocMonad m => FilePath -> m Text-getTemplate tp = UTF8.toText <$>+getTemplate tp = ((do surl <- stSourceURL <$> getCommonState -- we don't want to look for templates remotely -- unless the full URL is specified:@@ -74,27 +91,28 @@ PandocIOError _ ioe | isDoesNotExistError ioe -> -- see #5987 on reason for takeFileName readDataFile ("templates" </> takeFileName tp)- _ -> throwError e))+ _ -> throwError e)) >>= toTextM tp -- | Get default template for the specified writer. getDefaultTemplate :: PandocMonad m => Text -- ^ Name of writer -> m Text-getDefaultTemplate writer = do- let format = T.takeWhile (`notElem` ("+-" :: String)) writer -- strip off extensions+getDefaultTemplate format = do case format of "native" -> return "" "csljson" -> return "" "json" -> return ""- "docx" -> return ""+ "xml" -> return "" "fb2" -> return "" "pptx" -> return "" "ipynb" -> return ""+ "asciidoctor" -> getDefaultTemplate "asciidoc"+ "asciidoc_legacy" -> getDefaultTemplate "asciidoc"+ "docx" -> getDefaultTemplate "openxml" "odt" -> getDefaultTemplate "opendocument" "html" -> getDefaultTemplate "html5" "docbook" -> getDefaultTemplate "docbook5" "epub" -> getDefaultTemplate "epub3"- "beamer" -> getDefaultTemplate "latex" "jats" -> getDefaultTemplate "jats_archiving" "markdown_strict" -> getDefaultTemplate "markdown" "multimarkdown" -> getDefaultTemplate "markdown"@@ -103,9 +121,14 @@ "markdown_phpextra" -> getDefaultTemplate "markdown" "gfm" -> getDefaultTemplate "commonmark" "commonmark_x" -> getDefaultTemplate "commonmark"+ "bbcode_phpbb" -> getDefaultTemplate "bbcode"+ "bbcode_fluxbb" -> getDefaultTemplate "bbcode"+ "bbcode_steam" -> getDefaultTemplate "bbcode"+ "bbcode_hubzilla" -> getDefaultTemplate "bbcode"+ "bbcode_xenforo" -> getDefaultTemplate "bbcode" _ -> do let fname = "templates" </> "default" <.> T.unpack format- UTF8.toText <$> readDataFile fname+ readDataFile fname >>= toTextM fname -- | Get and compile default template for the specified writer. -- Raise an error on compilation failure.
@@ -0,0 +1,169 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StrictData #-}+{- |+ Module : Text.Pandoc.Transforms+ Copyright : © 2006-2024 John MacFarlane+ License : GPL-2.0-or-later+ Maintainer : John MacFarlane <jgm@berkeley@edu>++Transformation of a Pandoc document post-parsing+-}+module Text.Pandoc.Transforms+ ( Transform+ , applyTransforms+ , adjustLinksAndIds+ , eastAsianLineBreakFilter+ , filterIpynbOutput+ , headerShift+ ) where++import Data.List (sortOn)+import Data.Text (Text)+import Network.URI (unEscapeString)+import Text.DocLayout (charWidth)+import Text.Pandoc.Definition+ ( Pandoc (..), Attr, Block (..), Format (..), Inline (..) )+import Text.Pandoc.Generic (bottomUp)+import Text.Pandoc.Options (Extensions)+import Text.Pandoc.Shared (stringify, textToIdentifier)+import Text.Pandoc.Walk (walk)+import qualified Data.Text as T+import qualified Text.Pandoc.Builder as B++-- | Transformation of a Pandoc document post-parsing+type Transform = Pandoc -> Pandoc++-- | Apply a list of transforms to a document, in order.+applyTransforms :: Monad m => [Transform] -> Pandoc -> m Pandoc+applyTransforms transforms d = return $ foldr ($) d transforms++-- | Prefixes identifiers with a string derived from the filepath of+-- @thisfile@; fixes links to targets in @allfiles@ accordingly.+adjustLinksAndIds :: Extensions -- ^ defines how IDs are generated+ -> Text -- ^ thisfile+ -> [Text] -- ^ allfiles+ -> Transform+adjustLinksAndIds exts thisfile allfiles+ | length allfiles > 1 = walk fixInline . walk fixBlock+ | otherwise = id+ where+ -- fix ids in blocks+ fixBlock :: Block -> Block+ fixBlock (CodeBlock attr t) = CodeBlock (fixAttrs attr) t+ fixBlock (Header lev attr ils) = Header lev (fixAttrs attr) ils+ fixBlock (Table attr cap cols th tbs tf) =+ Table (fixAttrs attr) cap cols th tbs tf+ fixBlock (Div attr bs) = Div (fixAttrs attr) bs+ fixBlock x = x++ -- fix ids and links in inlines+ fixInline :: Inline -> Inline+ fixInline (Code attr t) = Code (fixAttrs attr) t+ fixInline (Link attr ils (url,tit)) =+ Link (fixAttrs attr) ils (fixURL url,tit)+ fixInline (Image attr ils (url,tit)) =+ Image (fixAttrs attr) ils (fixURL url,tit)+ fixInline (Span attr ils) = Span (fixAttrs attr) ils+ fixInline x = x++ -- add thisfile as prefix of identifier+ fixAttrs :: Attr -> Attr+ fixAttrs (i,cs,kvs)+ | T.null i = (i,cs,kvs)+ | otherwise =+ (T.intercalate "__"+ (filter (not . T.null) [toIdent thisfile, i]),+ cs, kvs)++ -- turns a filepath into an identifier+ toIdent :: Text -> Text+ toIdent = textToIdentifier exts . T.intercalate "__" .+ T.split (\c -> c == '/' || c == '\\')++ -- if URL begins with file from allfiles, convert to+ -- an internal link with the appropriate identifier+ fixURL :: Text -> Text+ fixURL u =+ let (a,b) = T.break (== '#') $ T.pack . unEscapeString . T.unpack $ u+ filepart = if T.null a+ then toIdent thisfile+ else toIdent a+ fragpart = T.dropWhile (== '#') b+ in if T.null a || a `elem` allfiles+ then "#" <> T.intercalate "__"+ (filter (not . T.null) [filepart, fragpart])+ else u++-- | Process ipynb output cells. If mode is Nothing,+-- remove all output. If mode is Just format, select+-- best output for the format. If format is not ipynb,+-- strip out ANSI escape sequences from CodeBlocks (see #5633).+filterIpynbOutput :: Maybe Format -> Pandoc -> Pandoc+filterIpynbOutput mode = walk go+ where go (Div (ident, "output":os, kvs) bs) =+ case mode of+ Nothing -> Div (ident, "output":os, kvs) []+ -- "best" for ipynb includes all formats:+ Just fmt+ | fmt == Format "ipynb"+ -> Div (ident, "output":os, kvs) bs+ | otherwise -> Div (ident, "output":os, kvs) $+ walk removeANSI $+ take 1 $ sortOn rank bs+ where+ rank (RawBlock (Format "html") _)+ | fmt == Format "html" = 1 :: Int+ | fmt == Format "markdown" = 3+ | otherwise = 4+ rank (RawBlock (Format "latex") _)+ | fmt == Format "latex" = 1+ | fmt == Format "markdown" = 3+ | otherwise = 4+ rank (RawBlock f _)+ | fmt == f = 1+ | otherwise = 4+ rank (Para [Image{}]) = 2+ rank _ = 3+ removeANSI (CodeBlock attr code) =+ CodeBlock attr (removeANSIEscapes code)+ removeANSI x = x+ removeANSIEscapes t+ | Just cs <- T.stripPrefix "\x1b[" t =+ removeANSIEscapes $ T.drop 1 $ T.dropWhile (/='m') cs+ | Just (c, cs) <- T.uncons t = T.cons c $ removeANSIEscapes cs+ | otherwise = ""+ go x = x++-- | Remove soft breaks between East Asian characters.+eastAsianLineBreakFilter :: Pandoc -> Pandoc+eastAsianLineBreakFilter = bottomUp go+ where go (x:SoftBreak:y:zs)+ | Just (_, b) <- T.unsnoc $ stringify x+ , Just (c, _) <- T.uncons $ stringify y+ , charWidth b == 2+ , charWidth c == 2+ = x:y:zs+ | otherwise+ = x:SoftBreak:y:zs+ go xs+ = xs++-- | Shift header levels up or down.+headerShift :: Int -> Pandoc -> Pandoc+headerShift n (Pandoc meta (Header m _ ils : bs))+ | n < 0+ , m + n == 0 = headerShift n $+ B.setTitle (B.fromList ils) $ Pandoc meta bs+-- for this case, see #10459:+headerShift n (Pandoc meta (Div attr@(_,"section":_,_) (Header m _ ils : as) : bs))+ | n < 0+ , m + n == 0 = headerShift n $+ B.setTitle (B.fromList ils) $ Pandoc meta (Div attr as : bs)+headerShift n (Pandoc meta bs) = Pandoc meta (walk shift bs)++ where+ shift :: Block -> Block+ shift (Header level attr inner)+ | level + n > 0 = Header (level + n) attr inner+ | otherwise = Para inner+ shift x = x
@@ -1,98 +1,92 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Translations- Copyright : Copyright (C) 2017-2022 John MacFarlane+ Copyright : Copyright (C) 2017-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable -Data types for localization.--Translations are stored in @data/translations/langname.trans@,-where langname can be the full BCP47 language specifier, or-just the language part. File format is:--> # A comment, ignored-> Figure: Figura-> Index: Indeksi-+Functions for getting localized translations of terms. -} module Text.Pandoc.Translations (- Term(..)- , Translations- , lookupTerm+ module Text.Pandoc.Translations.Types , readTranslations+ , getTranslations+ , setTranslations+ , translateTerm ) where-import Data.Aeson.Types (Value(..), FromJSON(..))-import qualified Data.Aeson.Types as Aeson-import qualified Data.Map as M+import Text.Pandoc.Translations.Types+import Text.Pandoc.Class (PandocMonad(..), toTextM, report)+import Text.Pandoc.Class.CommonState (CommonState(..))+import Text.Pandoc.Data (readDataFile)+import Data.Containers.ListUtils (nubOrd)+import Text.Pandoc.Logging (LogMessage(..))+import Control.Monad.Except (catchError) import qualified Data.Text as T import qualified Data.Yaml as Yaml-import GHC.Generics (Generic)-import Text.Pandoc.Shared (safeRead) import qualified Text.Pandoc.UTF8 as UTF8 import Data.Yaml (prettyPrintParseException)--data Term =- Abstract- | Appendix- | Bibliography- | Cc- | Chapter- | Contents- | Encl- | Figure- | Glossary- | Index- | Listing- | ListOfFigures- | ListOfTables- | Page- | Part- | Preface- | Proof- | References- | See- | SeeAlso- | Table- | To- deriving (Show, Eq, Ord, Generic, Enum, Read)--newtype Translations = Translations (M.Map Term T.Text)- deriving (Show, Generic, Semigroup, Monoid)--instance FromJSON Term where- parseJSON (String t) = case safeRead t of- Just t' -> pure t'- Nothing -> Prelude.fail $ "Invalid Term name " ++- show t- parseJSON invalid = Aeson.typeMismatch "Term" invalid--instance FromJSON Translations where- parseJSON o@(Object{}) = do- xs <- parseJSON o >>= mapM addItem . M.toList- return $ Translations (M.fromList xs)- where addItem (k,v) =- case safeRead k of- Nothing -> Prelude.fail $ "Invalid Term name " ++ show k- Just t ->- case v of- (String s) -> return (t, T.strip s)- inv -> Aeson.typeMismatch "String" inv- parseJSON invalid = Aeson.typeMismatch "Translations" invalid--lookupTerm :: Term -> Translations -> Maybe T.Text-lookupTerm t (Translations tm) = M.lookup t tm+import Text.Collate.Lang (Lang(..), renderLang) +-- | Parse YAML translations. readTranslations :: T.Text -> Either T.Text Translations readTranslations s = case Yaml.decodeAllEither' $ UTF8.fromText s of Left err' -> Left $ T.pack $ prettyPrintParseException err' Right (t:_) -> Right t Right [] -> Left "empty YAML document"++-- | Select the language to use with 'translateTerm'.+-- Note that this does not read a translation file;+-- that is only done the first time 'translateTerm' is+-- used.+setTranslations :: PandocMonad m => Lang -> m ()+setTranslations lang =+ modifyCommonState $ \st -> st{ stTranslations = Just (lang, Nothing) }++-- | Load term map.+getTranslations :: PandocMonad m => m Translations+getTranslations = do+ mbtrans <- getsCommonState stTranslations+ case mbtrans of+ Nothing -> return mempty -- no language defined+ Just (_, Just t) -> return t+ Just (lang, Nothing) -> do -- read from file+ let translationFiles = map (\x -> "translations/" <> T.unpack x <> ".yaml")+ (nubOrd [renderLang lang,+ langLanguage lang <> maybe "" ("-" <>) (langScript lang),+ langLanguage lang])+ let getTrans [] = return mempty+ getTrans (fp:fps) = do+ result <- catchError (Right <$> (readDataFile fp >>= toTextM fp))+ (\_ -> pure (Left ""))+ case result >>= readTranslations of+ Left e+ | null fps -> do+ report $ CouldNotLoadTranslations (renderLang lang)+ (T.pack fp <> ": " <> e)+ -- make sure we don't try again...+ modifyCommonState $ \st ->+ st{ stTranslations = Nothing }+ return mempty+ | otherwise -> getTrans fps+ Right t -> do+ modifyCommonState $ \st ->+ st{ stTranslations = Just (lang, Just t) }+ return t+ getTrans translationFiles++-- | Get a translation from the current term map.+-- Issue a warning if the term is not defined.+translateTerm :: PandocMonad m => Term -> m T.Text+translateTerm term = do+ translations <- getTranslations+ case lookupTerm term translations of+ Just s -> return s+ Nothing -> do+ report $ NoTranslation $ T.pack $ show term+ return ""
@@ -0,0 +1,88 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Translations.Types+ Copyright : Copyright (C) 2017-2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Data types for localization.++Translations are stored in @data/translations/langname.trans@,+where langname can be the full BCP47 language specifier, or+just the language part. File format is:++> # A comment, ignored+> Figure: Figura+> Index: Indeksi++-}+module Text.Pandoc.Translations.Types (+ Term(..)+ , Translations+ , lookupTerm+ )+where+import Data.Aeson.Types (Value(..), FromJSON(..))+import qualified Data.Aeson.Types as Aeson+import qualified Data.Map as M+import qualified Data.Text as T+import GHC.Generics (Generic)+import Text.Pandoc.Shared (safeRead)++data Term =+ Abstract+ | Appendix+ | Bibliography+ | Cc+ | Chapter+ | Contents+ | Encl+ | Figure+ | Glossary+ | Index+ | Listing+ | ListOfFigures+ | ListOfTables+ | Page+ | Part+ | Preface+ | Proof+ | References+ | See+ | SeeAlso+ | Table+ | To+ deriving (Show, Eq, Ord, Generic, Enum, Read)++newtype Translations = Translations (M.Map Term T.Text)+ deriving (Show, Generic, Semigroup, Monoid)++instance FromJSON Term where+ parseJSON (String t) = case safeRead t of+ Just t' -> pure t'+ Nothing -> Prelude.fail $ "Invalid Term name " +++ show t+ parseJSON invalid = Aeson.typeMismatch "Term" invalid++instance FromJSON Translations where+ parseJSON o@(Object{}) = do+ xs <- parseJSON o >>= mapM addItem . M.toList+ return $ Translations (M.fromList xs)+ where addItem (k,v) =+ case safeRead k of+ Nothing -> Prelude.fail $ "Invalid Term name " ++ show k+ Just t ->+ case v of+ (String s) -> return (t, T.strip s)+ inv -> Aeson.typeMismatch "String" inv+ parseJSON invalid = Aeson.typeMismatch "Translations" invalid++-- | Lookup a term in a 'Translations'.+lookupTerm :: Term -> Translations -> Maybe T.Text+lookupTerm t (Translations tm) = M.lookup t tm
@@ -0,0 +1,159 @@+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-}+{- |+ Module : Text.Pandoc.URI+ Copyright : Copyright (C) 2006-2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable+-}+module Text.Pandoc.URI ( urlEncode+ , escapeURI+ , isURI+ , schemes+ , uriPathToPath+ , pBase64DataURI+ ) where+import qualified Network.HTTP.Types as HTTP+import Data.ByteString.Base64 (decodeLenient)+import Text.Pandoc.MIME (MimeType)+import qualified Data.ByteString as B+import qualified Text.Pandoc.UTF8 as UTF8+import qualified Data.Text as T+import qualified Data.Set as Set+import Data.Char (isSpace, isAscii, isHexDigit, chr)+import Safe (readMay)+import Network.URI (URI (uriScheme), parseURI, escapeURIString)+import qualified Data.Attoparsec.Text as A+import Data.Text.Encoding (encodeUtf8)+import Control.Applicative (many, (<|>))++urlEncode :: T.Text -> T.Text+urlEncode = UTF8.toText . HTTP.urlEncode True . UTF8.fromText++-- | Escape whitespace and some punctuation characters in URI.+escapeURI :: T.Text -> T.Text+escapeURI = T.pack . escapeURIString (not . needsEscaping) . T.unpack+ where needsEscaping c = isSpace c || T.any (== c) "<>|\"{}[]^`"++--+-- IANA URIs+--++-- | Schemes from http://www.iana.org/assignments/uri-schemes.html plus+-- the unofficial schemes doi, javascript, isbn, pmid.+schemes :: Set.Set T.Text+schemes = Set.fromList+ -- Official IANA schemes+ [ "aaa", "aaas", "about", "acap", "acct", "acr", "adiumxtra", "afp", "afs"+ , "aim", "appdata", "apt", "attachment", "aw", "barion", "beshare", "bitcoin"+ , "blob", "bolo", "browserext", "callto", "cap", "chrome", "chrome-extension"+ , "cid", "coap", "coaps", "com-eventbrite-attendee", "content", "crid", "cvs"+ , "data", "dav", "dict", "dis", "dlna-playcontainer", "dlna-playsingle"+ , "dns", "dntp", "dtn", "dvb", "ed2k", "example", "facetime", "fax", "feed"+ , "feedready", "file", "filesystem", "finger", "fish", "ftp", "geo", "gg"+ , "git", "gizmoproject", "go", "gopher", "graph", "gtalk", "h323", "ham"+ , "hcp", "http", "https", "hxxp", "hxxps", "hydrazone", "iax", "icap", "icon"+ , "im", "imap", "info", "iotdisco", "ipn", "ipp", "ipps", "irc", "irc6"+ , "ircs", "iris", "iris.beep", "iris.lwz", "iris.xpc", "iris.xpcs"+ , "isostore", "itms", "jabber", "jar", "jms", "keyparc", "lastfm", "ldap"+ , "ldaps", "lvlt", "magnet", "mailserver", "mailto", "maps", "market"+ , "message", "mid", "mms", "modem", "mongodb", "moz", "ms-access"+ , "ms-browser-extension", "ms-drive-to", "ms-enrollment", "ms-excel"+ , "ms-gamebarservices", "ms-getoffice", "ms-help", "ms-infopath"+ , "ms-media-stream-id", "ms-officeapp", "ms-project", "ms-powerpoint"+ , "ms-publisher", "ms-search-repair", "ms-secondary-screen-controller"+ , "ms-secondary-screen-setup", "ms-settings", "ms-settings-airplanemode"+ , "ms-settings-bluetooth", "ms-settings-camera", "ms-settings-cellular"+ , "ms-settings-cloudstorage", "ms-settings-connectabledevices"+ , "ms-settings-displays-topology", "ms-settings-emailandaccounts"+ , "ms-settings-language", "ms-settings-location", "ms-settings-lock"+ , "ms-settings-nfctransactions", "ms-settings-notifications"+ , "ms-settings-power", "ms-settings-privacy", "ms-settings-proximity"+ , "ms-settings-screenrotation", "ms-settings-wifi", "ms-settings-workplace"+ , "ms-spd", "ms-sttoverlay", "ms-transit-to", "ms-virtualtouchpad"+ , "ms-visio", "ms-walk-to", "ms-whiteboard", "ms-whiteboard-cmd", "ms-word"+ , "msnim", "msrp", "msrps", "mtqp", "mumble", "mupdate", "mvn", "news", "nfs"+ , "ni", "nih", "nntp", "notes", "ocf", "oid", "onenote", "onenote-cmd"+ , "opaquelocktoken", "pack", "palm", "paparazzi", "pkcs11", "platform", "pop"+ , "pres", "prospero", "proxy", "pwid", "psyc", "qb", "query", "redis"+ , "rediss", "reload", "res", "resource", "rmi", "rsync", "rtmfp", "rtmp"+ , "rtsp", "rtsps", "rtspu", "secondlife", "service", "session", "sftp", "sgn"+ , "shttp", "sieve", "sip", "sips", "skype", "smb", "sms", "smtp", "snews"+ , "snmp", "soap.beep", "soap.beeps", "soldat", "spotify", "ssh", "steam"+ , "stun", "stuns", "submit", "svn", "tag", "teamspeak", "tel", "teliaeid"+ , "telnet", "tftp", "things", "thismessage", "tip", "tn3270", "tool", "turn"+ , "turns", "tv", "udp", "unreal", "urn", "ut2004", "v-event", "vemmi"+ , "ventrilo", "videotex", "vnc", "view-source", "wais", "webcal", "wpid"+ , "ws", "wss", "wtai", "wyciwyg", "xcon", "xcon-userid", "xfire"+ , "xmlrpc.beep", "xmlrpc.beeps", "xmpp", "xri", "ymsgr", "z39.50", "z39.50r"+ , "z39.50s"+ -- Unofficial schemes+ , "doi", "gemini", "isbn", "javascript", "pmid"+ ]++-- | Check if the string is a valid URL with a IANA or frequently used but+-- unofficial scheme (see @schemes@).+isURI :: T.Text -> Bool+isURI t =+ -- If it's a base 64 data: URI, avoid the expensive call to parseURI:+ case A.parseOnly (pBase64DataURI *> A.endOfInput) t of+ Right () -> True+ Left _ ->+ -- we URI-escape non-ASCII characters because otherwise parseURI will choke:+ maybe False hasKnownScheme . parseURI . escapeURIString isAscii . T.unpack $ t+ where+ hasKnownScheme =+ (`Set.member` schemes) . T.toLower . T.filter (/= ':') . T.pack . uriScheme++-- | Converts the path part of a file: URI to a regular path.+-- On windows, @/c:/foo@ should be @c:/foo@.+-- On linux, @/foo@ should be @/foo@.+uriPathToPath :: T.Text -> FilePath+uriPathToPath (T.unpack -> path) =+#ifdef _WINDOWS+ case path of+ '/':ps -> ps+ ps -> ps+#else+ path+#endif++pBase64DataURI :: A.Parser (B.ByteString, MimeType)+pBase64DataURI = base64uri+ where+ base64uri = do+ A.string "data:"+ mime <- do+ n1 <- restrictedName+ A.char '/'+ n2 <- restrictedName+ mps <- many mediaParam+ pure $ n1 <> "/" <> n2 <> mconcat mps+ A.string ";base64,"+ b64 <- mconcat <$> many+ (A.takeWhile1 (A.inClass "A-Za-z0-9/+ \t\r\n") <|> percentOctet)+ A.skipWhile (== '=')+ -- this decode should be lazy:+ pure (decodeLenient (encodeUtf8 b64), mime)+ percentOctet = do+ A.char '%'+ x <- A.satisfy isHexDigit+ y <- A.satisfy isHexDigit+ case readMay ['0','x',x,y] of+ Nothing -> fail $ "Could not read percent encoded byte " <> [x,y]+ Just d -> pure $ T.singleton $ chr d+ restrictedName = do+ c <- A.satisfy (A.inClass "A-Za-z0-9")+ rest <- A.takeWhile (A.inClass "A-Za-z0-9!#$&^_.+-")+ pure $ T.singleton c <> rest+ mediaParam = do+ A.char ';'+ A.skipWhile isSpace+ k <- restrictedName+ A.char '='+ v <- A.takeWhile (/=';')+ pure $ ";" <> k <> "=" <> v
@@ -1,14 +1,14 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.UTF8- Copyright : Copyright (C) 2010-2022 John MacFarlane+ Copyright : Copyright (C) 2010-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable -UTF-8 aware string IO functions that will work with GHC 6.10, 6.12, or 7.+UTF-8 aware string IO functions. -} module Text.Pandoc.UTF8 ( readFile , getContents@@ -140,5 +140,6 @@ encodePath :: FilePath -> FilePath encodePath = id +{-# DEPRECATED decodeArg "decodeArg is now a no-op" #-} decodeArg :: String -> String decodeArg = id
@@ -1,6 +1,6 @@ {- | Module : Text.Pandoc.UUID- Copyright : Copyright (C) 2010-2022 John MacFarlane+ Copyright : Copyright (C) 2010-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -0,0 +1,28 @@+{-# LANGUAGE CPP #-}+{- |+ Module : Text.Pandoc.Version+ Copyright : Copyright (C) 2022-2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Version information.+-}+module Text.Pandoc.Version (+ pandocVersion,+ pandocVersionText+ ) where++import Data.Version (Version, showVersion)+import Paths_pandoc (version)+import qualified Data.Text as T++-- | Version number of pandoc library.+pandocVersion :: Version+pandocVersion = version++-- | Text representation of the library's version number.+pandocVersionText :: T.Text+pandocVersionText = T.pack $ showVersion version
@@ -1,10 +1,11 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-} {- | Module : Text.Pandoc- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -18,17 +19,21 @@ -- * Writers: converting /from/ Pandoc format Writer(..) , writers+ , writeANSI , writeAsciiDoc+ , writeAsciiDocLegacy , writeAsciiDoctor , writeBeamer , writeBibTeX , writeBibLaTeX+ , writeChunkedHTML , writeCommonMark , writeConTeXt , writeCslJson , writeDZSlides- , writeDocbook4- , writeDocbook5+ , writeDjot+ , writeDocBook4+ , writeDocBook5 , writeDocx , writeDokuWiki , writeEPUB2@@ -70,29 +75,39 @@ , writeTEI , writeTexinfo , writeTextile+ , writeTypst+ , writeXML , writeXWiki , writeZimWiki+ , writeVimdoc+ , writeBBCode+ , writeBBCodeSteam+ , writeBBCodeFluxBB+ , writeBBCodePhpBB+ , writeBBCodeHubzilla+ , writeBBCodeXenforo , getWriter ) where import Control.Monad.Except (throwError)-import Control.Monad (unless) import Data.Aeson import qualified Data.ByteString.Lazy as BL import Data.Text (Text)-import qualified Data.Text as T-import Text.Pandoc.Shared (tshow) import Text.Pandoc.Class import Text.Pandoc.Definition+import qualified Text.Pandoc.Format as Format import Text.Pandoc.Options import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Error+import Text.Pandoc.Writers.ANSI import Text.Pandoc.Writers.AsciiDoc import Text.Pandoc.Writers.BibTeX+import Text.Pandoc.Writers.ChunkedHTML import Text.Pandoc.Writers.CommonMark import Text.Pandoc.Writers.ConTeXt import Text.Pandoc.Writers.CslJson-import Text.Pandoc.Writers.Docbook+import Text.Pandoc.Writers.Djot+import Text.Pandoc.Writers.DocBook import Text.Pandoc.Writers.Docx import Text.Pandoc.Writers.DokuWiki import Text.Pandoc.Writers.EPUB@@ -120,8 +135,19 @@ import Text.Pandoc.Writers.TEI import Text.Pandoc.Writers.Texinfo import Text.Pandoc.Writers.Textile+import Text.Pandoc.Writers.Typst+import Text.Pandoc.Writers.XML import Text.Pandoc.Writers.XWiki import Text.Pandoc.Writers.ZimWiki+import Text.Pandoc.Writers.Vimdoc+import Text.Pandoc.Writers.BBCode (+ writeBBCode,+ writeBBCodeFluxBB,+ writeBBCodeHubzilla,+ writeBBCodePhpBB,+ writeBBCodeSteam,+ writeBBCodeXenforo,+ ) data Writer m = TextWriter (WriterOptions -> Pandoc -> m Text) | ByteStringWriter (WriterOptions -> Pandoc -> m BL.ByteString)@@ -148,9 +174,9 @@ ,("slideous" , TextWriter writeSlideous) ,("dzslides" , TextWriter writeDZSlides) ,("revealjs" , TextWriter writeRevealJs)- ,("docbook" , TextWriter writeDocbook5)- ,("docbook4" , TextWriter writeDocbook4)- ,("docbook5" , TextWriter writeDocbook5)+ ,("docbook" , TextWriter writeDocBook5)+ ,("docbook4" , TextWriter writeDocBook4)+ ,("docbook5" , TextWriter writeDocBook5) ,("jats" , TextWriter writeJatsArchiving) ,("jats_articleauthoring", TextWriter writeJatsArticleAuthoring) ,("jats_publishing" , TextWriter writeJatsPublishing)@@ -176,10 +202,12 @@ ,("xwiki" , TextWriter writeXWiki) ,("zimwiki" , TextWriter writeZimWiki) ,("textile" , TextWriter writeTextile)+ ,("typst" , TextWriter writeTypst) ,("rtf" , TextWriter writeRTF) ,("org" , TextWriter writeOrg) ,("asciidoc" , TextWriter writeAsciiDoc)- ,("asciidoctor" , TextWriter writeAsciiDoctor)+ ,("asciidoctor" , TextWriter writeAsciiDoc)+ ,("asciidoc_legacy" , TextWriter writeAsciiDocLegacy) ,("haddock" , TextWriter writeHaddock) ,("commonmark" , TextWriter writeCommonMark) ,("commonmark_x" , TextWriter writeCommonMark)@@ -190,32 +218,27 @@ ,("bibtex" , TextWriter writeBibTeX) ,("biblatex" , TextWriter writeBibLaTeX) ,("markua" , TextWriter writeMarkua)+ ,("chunkedhtml" , ByteStringWriter writeChunkedHTML)+ ,("djot" , TextWriter writeDjot)+ ,("ansi" , TextWriter writeANSI)+ ,("xml" , TextWriter writeXML)+ ,("vimdoc" , TextWriter writeVimdoc)+ ,("bbcode" , TextWriter writeBBCode)+ ,("bbcode_steam" , TextWriter writeBBCodeSteam)+ ,("bbcode_phpbb" , TextWriter writeBBCodePhpBB)+ ,("bbcode_fluxbb", TextWriter writeBBCodeFluxBB)+ ,("bbcode_hubzilla" , TextWriter writeBBCodeHubzilla)+ ,("bbcode_xenforo" , TextWriter writeBBCodeXenforo) ] -- | Retrieve writer, extensions based on formatSpec (format+extensions).-getWriter :: PandocMonad m => Text -> m (Writer m, Extensions)-getWriter s =- case parseFormatSpec s of- Left e -> throwError $ PandocAppError $- "Error parsing writer format " <> tshow s <> ": " <> tshow e- Right (writerName, extsToEnable, extsToDisable) ->- case lookup writerName writers of- Nothing -> throwError $- PandocUnknownWriterError writerName- Just w -> do- let allExts = getAllExtensions writerName- let exts = foldr disableExtension- (foldr enableExtension- (getDefaultExtensions writerName)- extsToEnable) extsToDisable- mapM_ (\ext ->- unless (extensionEnabled ext allExts) $- throwError $- PandocUnsupportedExtensionError- (T.drop 4 $ T.pack $ show ext) writerName)- (extsToEnable ++ extsToDisable)- return (w, exts)-+getWriter :: PandocMonad m => Format.FlavoredFormat -> m (Writer m, Extensions)+getWriter flvrd = do+ let writerName = Format.formatName flvrd+ case lookup writerName writers of+ Nothing -> throwError $ PandocUnknownWriterError writerName+ Just w -> (w,) <$>+ Format.applyExtensionsDiff (Format.getExtensionsConfig writerName) flvrd writeJSON :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeJSON _ = return . UTF8.toText . BL.toStrict . encode
@@ -0,0 +1,394 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Writers.ANSI+ Copyright : © 2024 Evan Silberman+ © 2025 Pandoc contributors+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to Ansi terminal output.+-}+module Text.Pandoc.Writers.ANSI ( writeANSI ) where+import Control.Monad.State.Strict ( StateT, gets, modify, evalStateT )+import Control.Monad (foldM)+import Data.List (intersperse)+import qualified Data.Map as M+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import Text.DocLayout ((<+>), ($$), ($+$))+import Text.DocTemplates (Context(..))+import Text.Pandoc.Class.PandocMonad (PandocMonad, report)+import Text.Pandoc.Definition+import Text.Pandoc.Highlighting (highlight, formatANSI)+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Shared+import Text.Pandoc.Templates (renderTemplate)+import Text.Pandoc.Writers.Math(texMathToInlines)+import Text.Pandoc.Writers.Shared+import qualified Data.Text as T+import Data.Text.Lazy (toStrict)+import qualified Text.DocLayout as D+import qualified Text.Pandoc.Highlighting as HL++hr :: D.HasChars a => D.Doc a+hr = rule 20++rule :: D.HasChars a => Int -> D.Doc a+rule n = D.literal $ D.replicateChar n '─'++data WriterState = WriterState {+ stNotes :: [D.Doc Text] -- Footnotes+ , stColumns :: Int -- Width of the rendered text block+ , stInner :: Bool -- Are we at the document's top-level or in a nested construct?+ , stNextFigureNum :: Int+ , stInFigure :: Bool+ , stInTable :: Bool+ }++type TW = StateT WriterState++withFewerColumns :: PandocMonad m => Int -> TW m a -> TW m a+withFewerColumns n a = do+ cols <- gets stColumns+ inner <- gets stInner+ modify $ \s -> s{stColumns = max (cols - n) 4, stInner = True}+ result <- a+ modify $ \s -> s{stColumns = cols, stInner = inner}+ return result++-- | Convert Pandoc to ANSI+writeANSI :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeANSI opts document =+ evalStateT (pandocToANSI opts document)+ WriterState { stNotes = [],+ stColumns = (writerColumns opts),+ stInner = False,+ stNextFigureNum = 1,+ stInFigure = False,+ stInTable = False+ }++-- | Return ANSI-styled version of document+pandocToANSI :: PandocMonad m+ => WriterOptions -> Pandoc -> TW m Text+pandocToANSI opts (Pandoc meta blocks) = do+ metadata <- metaToContext opts+ (blockListToANSI opts)+ (inlineListToANSI opts) meta+ 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) =+ (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 colwidth main+ Just tpl -> toStrict $ D.renderANSI colwidth+ $ renderTemplate tpl context++titleBlock :: Maybe Int -> Context Text -> D.Doc Text+titleBlock width meta =+ if null most+ then D.empty+ else (maybe id D.cblock width) $ most $+$ hr+ where+ title = D.bold (fromMaybe D.empty $ getField "title" meta)+ subtitle = fromMaybe D.empty $ getField "subtitle" meta+ author = D.vcat $ fromMaybe [] $ getField "author" meta+ date = D.italic (fromMaybe D.empty $ getField "date" meta)+ most = (title $$ subtitle) $+$ author $+$ date++hangMarks :: Int -> [D.Doc Text] -> [D.Doc Text] -> D.Doc Text+hangMarks width markers contents =+ D.vsep (zipWith hangMark markers contents) where+ hangMark m d = D.rblock width m <+> D.nest (width + 1) d++stackMarks :: [D.Doc Text] -> [D.Doc Text] -> D.Doc Text+stackMarks markers contents = D.vsep (zipWith stack markers contents)+ where stack m d = m $$ D.nest 4 d++-- | Convert Pandoc block element to ANSI+blockToANSI :: PandocMonad m+ => WriterOptions -- ^ Options+ -> Block -- ^ Block element+ -> TW m (D.Doc Text)++blockToANSI opts (Div _ bs) = blockListToANSI opts bs++blockToANSI opts (Plain inlines) = inlineListToANSI opts inlines++blockToANSI opts (Para inlines) = inlineListToANSI opts inlines++blockToANSI opts (LineBlock lns) = do+ let go [] = return D.blankline+ go xs = inlineListToANSI opts xs+ lns' <- mapM go lns+ return $ D.vcat lns'++blockToANSI _ b@(RawBlock _ _) = do+ report $ BlockNotRendered b+ return D.empty++blockToANSI _ HorizontalRule = return $ D.blankline $$ hr $$ D.blankline++blockToANSI opts (Header level (_, classes, kvs) inlines) = do+ contents <- inlineListToANSI opts inlines+ let secnum = fromMaybe mempty $ lookup "number" kvs+ let doNumber = writerNumberSections opts && not (T.null secnum) && "unnumbered" `notElem` classes+ let number | doNumber = D.hang (D.realLength secnum + 1) (header level (D.literal secnum) <> D.space)+ | otherwise = id+ return $ number (header level contents) $$ D.blankline where+ header 1 = (fmap T.toUpper) . D.bold+ header 2 = D.bold+ header _ = D.italic++-- The approach to code blocks and highlighting here is a best-effort with+-- existing tools. The Skylighting formatANSI function produces fully-rendered+-- results, and its line numbers are followed by a tab character, which can+-- produce less-than-ideal results depending on your terminal's tab stops. (See+-- tabs(1)). A more ambitious approach here could process SourceLines into a+-- Doc Text.+blockToANSI opts (CodeBlock attr str) = do+ table <- gets stInTable+ 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, 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+ nest True = id++blockToANSI opts (BlockQuote blocks) = do+ contents <- withFewerColumns 2 $ blockListToANSI opts blocks+ return ( D.prefixed "│ " contents $$ D.blankline)++blockToANSI opts (Table _ (Caption _ caption) colSpecs (TableHead _ thead) tbody (TableFoot _ tfoot)) = do+ let captionInlines = blocksToInlines caption+ captionMarkup <-+ if null captionInlines+ then return mempty+ else D.nest 2 <$> inlineListToANSI opts (blocksToInlines caption)+ wasTable <- gets stInTable+ modify $ \s -> s{stInTable = True}+ let tw = writerColumns opts+ let ncol = length colSpecs+ let inWidths = map snd colSpecs+ let spaceForColumns = tw - ncol + 1 -- reserve a 1-char gutter between tcols+ let claimWidth ColWidthDefault = 0+ claimWidth (ColWidth n) = floor (n * fromIntegral spaceForColumns)+ let usedSpace = sum (map claimWidth inWidths)+ let remaining = spaceForColumns - usedSpace+ let defWidth = remaining `div` length (filter (== ColWidthDefault) inWidths)+ let maxWidth ColWidthDefault = defWidth+ maxWidth k = claimWidth k+ let widths = map maxWidth inWidths+ let decor = [D.hsep $ map rule widths]+ head' <- (makeRows widths . map unRow) thead+ body' <- (makeRows widths . map unRow) (tableBodiesToRows tbody)+ foot' <- (makeRows widths . map unRow) tfoot+ modify $ \s -> s{stInTable = wasTable}+ return $ D.vcat (head' <> decor <> body' <> decor <> foot') $+$ captionMarkup+ where+ unRow (Row _ cs) = cs+ makeRows ws rows = do+ (docs, _) <- foldM (goRow ws) ([], M.empty) rows+ return $ reverse docs+ goRow _ (r, spans) [] =+ -- Empty rows are not displayed but previous row spans still apply for them.+ let spans' = M.map decrementPreviousRowSpans spans+ in return (r, spans')+ goRow ws (r, spans) cs = do+ (d, (nextPos, spans'), _) <- foldM goCell ([], (0, spans), ws) cs+ let spans'' = decrementTrailingRowSpans nextPos spans' -- Handle previous row spans next to the end of the current row+ return (D.hcat (intersperse (D.vfill " ") $ reverse d):r, spans'')+ goCell (r, (colPos, spans), ws) cell@(Cell _ aln (RowSpan rspan) (ColSpan cspan) inner)+ | Just (ColSpan previousColSpan, spans') <- takePreviousSpansAtColumn colPos spans = do+ (r', nextPos, ws') <- makeCell r colPos ws AlignDefault previousColSpan []+ goCell (r', (nextPos, spans'), ws') cell+ | otherwise = do+ (r', nextPos, ws') <- makeCell r colPos ws aln cspan inner+ let spans' = insertCurrentSpansAtColumn colPos spans (RowSpan rspan) (ColSpan cspan)+ return (r', (nextPos, spans'), ws')+ decrementPreviousRowSpans spans@(RowSpan rspan, cspan) =+ if rspan >= 1+ then (RowSpan rspan - 1, cspan)+ else spans+ makeCell r colPos ws aln cspan inner = do+ let (ws', render) = next ws aln cspan+ innerDoc <- blockListToANSI opts inner+ return ((render innerDoc):r, colPos + cspan, ws')+ tcell AlignLeft = D.lblock+ tcell AlignRight = D.rblock+ tcell AlignCenter = D.cblock+ tcell AlignDefault = D.lblock+ next ws aln cspan =+ let (this, ws') = splitAt cspan ws+ w = sum this + cspan - 1+ cell = (tcell aln) w+ in (ws', cell)++blockToANSI opts (BulletList items) = do+ contents <- withFewerColumns 2 $ mapM (blockListToANSI opts) items+ return $ D.vsep (fmap hangMark contents) where+ hangMark d = D.hang 2 (D.literal "• ") d++blockToANSI opts (OrderedList attribs items) = do+ let markers = fmap D.literal $ take (length items) $ orderedListMarkers attribs+ let hangWidth = foldr (max . D.offset) 0 markers+ contents <- withFewerColumns hangWidth $ mapM (blockListToANSI opts) items+ return $ hangMarks hangWidth markers contents <> D.cr++blockToANSI opts (DefinitionList items) = do+ labels <- mapM (inlineListToANSI opts . fst) items+ columns <- gets stColumns+ let hangWidth = foldr (max . D.offset) 0 labels+ if hangWidth > floor (toRational columns / 10 * 3)+ then do+ contents <- withFewerColumns 4 $ mapM ((mapM (blockListToANSI opts)) . snd) items+ return $ stackMarks (D.bold <$> labels) (D.vsep <$> contents) <> D.cr+ else do+ contents <- withFewerColumns hangWidth $ mapM ((mapM (blockListToANSI opts)) . snd) items+ return $ hangMarks hangWidth (D.bold <$> labels) (D.vsep <$> contents) <> D.cr++blockToANSI opts (Figure _ (Caption _ caption) body) = do+ let captionInlines = blocksToInlines caption+ figState <- gets stInFigure+ captionMarkup <-+ if null captionInlines+ then return mempty+ else D.nest 2 <$> inlineListToANSI opts (blocksToInlines caption)+ modify $ \s -> s{stInFigure = True}+ contents <- blockListToANSI opts body+ modify $ \s -> s{stInFigure = figState}+ return $ contents $+$ captionMarkup++-- Auxiliary functions for lists:++-- | Convert list of Pandoc block elements to ANSI+blockListToANSI :: PandocMonad m+ => WriterOptions -- ^ Options+ -> [Block] -- ^ List of block elements+ -> TW m (D.Doc Text)+blockListToANSI opts blocks =+ D.vsep <$> mapM (blockToANSI opts) blocks++-- | Convert list of Pandoc inline elements to ANSI+inlineListToANSI :: PandocMonad m+ => WriterOptions -> [Inline] -> TW m (D.Doc Text)+inlineListToANSI opts lst =+ D.hcat <$> mapM (inlineToANSI opts) lst++-- | Convert Pandoc inline element to ANSI+inlineToANSI :: PandocMonad m => WriterOptions -> Inline -> TW m (D.Doc Text)++inlineToANSI opts (Span _ lst) =+ inlineListToANSI opts lst++inlineToANSI opts (Emph lst) = do+ contents <- inlineListToANSI opts lst+ return $ D.italic contents++inlineToANSI opts (Underline lst) = do+ contents <- inlineListToANSI opts lst+ return $ D.underlined contents++inlineToANSI opts (Strong lst) = do+ contents <- inlineListToANSI opts lst+ return $ D.bold contents++inlineToANSI opts (Strikeout lst) = do+ contents <- inlineListToANSI opts lst+ return $ D.strikeout contents++inlineToANSI opts (Superscript lst) = do+ case traverse toSuperscriptInline lst of+ Just xs -> inlineListToANSI opts xs+ Nothing -> D.parens <$> inlineListToANSI opts lst++inlineToANSI opts (Subscript lst) = do+ case traverse toSubscriptInline lst of+ Just xs -> inlineListToANSI opts xs+ Nothing -> D.parens <$> inlineListToANSI opts lst++inlineToANSI opts (SmallCaps lst) = inlineListToANSI opts lst++inlineToANSI opts (Quoted SingleQuote lst) = do+ contents <- inlineListToANSI opts lst+ return $ "‘" <> contents <> "’"++inlineToANSI opts (Quoted DoubleQuote lst) = do+ contents <- inlineListToANSI opts lst+ return $ "“" <> contents <> "”"++inlineToANSI opts (Cite _ lst) = inlineListToANSI opts lst++-- Making a judgment call here that for ANSI-formatted output+-- intended for reading, we want to reflow inline Code on spaces+inlineToANSI _ (Code _ str) =+ return $ D.bg D.white $ D.fg D.red $ " " <> D.hcat flow <> " "+ where flow = intersperse D.space (D.literal <$> T.words str)++inlineToANSI _ (Str str) = return $ D.literal str++inlineToANSI opts (Math t str) = texMathToInlines t str >>= inlineListToANSI opts++inlineToANSI _ il@RawInline{} = do+ report $ InlineNotRendered il+ return ""++inlineToANSI _ LineBreak = return D.cr++inlineToANSI _ SoftBreak = return D.space++inlineToANSI _ Space = return D.space++inlineToANSI opts (Link (_, _, _) txt (src, _)) = do+ label <- inlineListToANSI opts txt+ return $ D.underlined $ D.fg D.cyan $ D.link src label++inlineToANSI opts (Image _ alt _) = do+ infig <- gets stInFigure+ if not infig then do+ alt' <- inlineListToANSI opts alt+ return $ D.brackets $ "image: " <> alt'+ else return $ D.brackets "image"++-- by construction, we should never be lacking in superscript characters+-- for the footnote number, but we'll fall back to square brackets anyway+inlineToANSI opts (Note contents) = do+ curNotes <- gets stNotes+ let newnum = tshow $ length curNotes + 1+ contents' <- blockListToANSI opts contents+ modify $ \s -> s { stNotes = contents' : curNotes }+ let super = T.pack <$> (traverse toSuperscript (T.unpack newnum))+ return $ D.literal $ fromMaybe ("[" <> newnum <> "]") super
@@ -42,7 +42,6 @@ where import Control.Monad.RWS.Strict- hiding ( (<>) ) import Data.Generics ( Data , Typeable )
@@ -1,7 +1,9 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.AsciiDoc- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -18,15 +20,29 @@ AsciiDoc: <http://www.methods.co.nz/asciidoc/> -}-module Text.Pandoc.Writers.AsciiDoc (writeAsciiDoc, writeAsciiDoctor) where+module Text.Pandoc.Writers.AsciiDoc (+ writeAsciiDoc,+ writeAsciiDocLegacy,+ writeAsciiDoctor+ ) where+import Control.Monad (foldM) import Control.Monad.State.Strict+ ( StateT, MonadState(get), gets, modify, evalStateT ) import Data.Char (isPunctuation, isSpace)-import Data.List (delete, intercalate, intersperse)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Maybe (fromMaybe, isJust)+#if MIN_VERSION_base(4,19,0)+import Data.List (delete, intercalate, intersperse, mapAccumL, uncons, sortOn, unsnoc)+#else+import Data.List (delete, intercalate, intersperse, mapAccumL, uncons, sortOn)+#endif+import Data.List.NonEmpty (NonEmpty((:|)), (<|))+import qualified Data.List.NonEmpty as NonEmpty+import Data.Maybe (fromMaybe, isJust, catMaybes)+import qualified Data.Map as M import qualified Data.Set as Set import qualified Data.Text as T import Data.Text (Text)+import Network.URI (parseURI, URI(uriScheme))+import System.FilePath (dropExtension) import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Definition import Text.Pandoc.ImageSize@@ -34,17 +50,24 @@ import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (blankline, space) import Text.DocLayout+import Text.Pandoc.Builder (emptyCell) import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Shared+import Text.Pandoc.Walk (walk) +#if !MIN_VERSION_base(4,19,0)+unsnoc :: [a] -> Maybe ([a], a)+unsnoc = foldr (\x -> Just . maybe ([], x) (\(~(a, b)) -> (x : a, b))) Nothing+#endif data WriterState = WriterState { defListMarker :: Text , orderedListLevel :: Int , bulletListLevel :: Int , intraword :: Bool , autoIds :: Set.Set Text- , asciidoctorVariant :: Bool+ , legacy :: Bool , inList :: Bool , hasMath :: Bool -- |0 is no table@@ -59,7 +82,7 @@ , bulletListLevel = 0 , intraword = False , autoIds = Set.empty- , asciidoctorVariant = False+ , legacy = False , inList = False , hasMath = False , tableNestingLevel = 0@@ -70,11 +93,16 @@ writeAsciiDoc opts document = evalStateT (pandocToAsciiDoc opts document) defaultWriterState --- | Convert Pandoc to AsciiDoctor compatible AsciiDoc.+{-# DEPRECATED writeAsciiDoctor "Use writeAsciiDoc instead" #-}+-- | Deprecated synonym of 'writeAsciiDoc'. writeAsciiDoctor :: PandocMonad m => WriterOptions -> Pandoc -> m Text-writeAsciiDoctor opts document =+writeAsciiDoctor = writeAsciiDoc++-- | Convert Pandoc to legacy AsciiDoc.+writeAsciiDocLegacy :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeAsciiDocLegacy opts document = evalStateT (pandocToAsciiDoc opts document)- defaultWriterState{ asciidoctorVariant = True }+ defaultWriterState{ legacy = True } type ADW = StateT WriterState @@ -90,29 +118,63 @@ (blockListToAsciiDoc opts) (fmap chomp . inlineListToAsciiDoc opts) meta- main <- blockListToAsciiDoc opts $ makeSections False (Just 1) blocks+ main <- blockListToAsciiDoc opts $ makeSections False Nothing blocks st <- get let context = defField "body" main $ defField "toc" (writerTableOfContents opts && isJust (writerTemplate opts))- $ defField "math" (hasMath st)+ $ defField "math" (hasMath st && not (legacy st)) $ defField "titleblock" titleblock metadata return $ render colwidth $ case writerTemplate opts of Nothing -> main Just tpl -> renderTemplate tpl context +data EscContext = Normal | InTable+ deriving (Show, Eq)+ -- | Escape special characters for AsciiDoc.-escapeString :: Text -> Text-escapeString t- | T.any (== '{') t = T.concatMap escChar t- | otherwise = t- where escChar '{' = "\\{"- escChar c = T.singleton c+escapeString :: EscContext -> Text -> Doc Text+escapeString context t+ | T.any needsEscape t+ = literal $+ case T.foldl' go (False, mempty) t of+ (True, x) -> x <> "++" -- close passthrough context+ (False, x) -> x+ | otherwise = literal t+ where+ -- Bool is True when we are in a ++ passthrough context+ go :: (Bool, Text) -> Char -> (Bool, Text)+ go (True, x) '+' = (False, x <> "++" <> "{plus}") -- close context+ go (False, x) '+' = (False, x <> "{plus}")+ go (True, x) '|'+ | context == InTable = (False, x <> "++" <> "{vbar}") -- close context+ go (False, x) '|'+ | context == InTable = (False, x <> "{vbar}")+ go (True, x) c+ | needsEscape c = (True, T.snoc x c)+ | otherwise = (False, T.snoc (x <> "++") c)+ go (False, x) c+ | needsEscape c = (True, x <> "++" <> T.singleton c)+ | otherwise = (False, T.snoc x c) + needsEscape '{' = True+ needsEscape '+' = True+ needsEscape '`' = True+ needsEscape '*' = True+ needsEscape '#' = True+ needsEscape '_' = True+ needsEscape '<' = True+ needsEscape '>' = True+ needsEscape '[' = True+ needsEscape ']' = True+ needsEscape '\\' = True+ needsEscape '|' = True+ needsEscape _ = False+ -- | Ordered list start parser for use in Para below.-olMarker :: Parser Text ParserState Char+olMarker :: Parsec Text ParserState Char olMarker = do (start, style', delim) <- anyOrderedListMarker if delim == Period && (style' == UpperAlpha || (style' == UpperRoman &&@@ -140,7 +202,6 @@ => WriterOptions -- ^ Options -> Block -- ^ Block element -> ADW m (Doc Text)-blockToAsciiDoc _ Null = return empty blockToAsciiDoc opts (Div (id',"section":_,_) (Header level (_,cls,kvs) ils : xs)) = do hdr <- blockToAsciiDoc opts (Header level (id',cls,kvs) ils)@@ -149,10 +210,6 @@ blockToAsciiDoc opts (Plain inlines) = do contents <- inlineListToAsciiDoc opts inlines return $ contents <> blankline-blockToAsciiDoc opts (SimpleFigure attr alternate (src, tit))- -- image::images/logo.png[Company logo, title="blah"]- = (\args -> "image::" <> args <> blankline) <$>- imageArguments opts attr alternate src tit blockToAsciiDoc opts (Para inlines) = do contents <- inlineListToAsciiDoc opts inlines -- escape if para starts with ordered list marker@@ -186,7 +243,27 @@ return $ identifier $$ nowrap (text (replicate (level + 1) '=') <> space <> contents) <> blankline-+blockToAsciiDoc opts (Figure attr (Caption _ longcapt) body) = do+ -- Images in figures all get rendered as individual block-level images+ -- with the given caption. Non-image elements are rendered unchanged.+ capt <- if null longcapt+ then pure mempty+ else ("." <>) . nowrap <$>+ inlineListToAsciiDoc opts (blocksToInlines longcapt)+ let renderFigElement = \case+ Plain [Image imgAttr alternate (src, tit)] -> do+ args <- imageArguments opts imgAttr alternate src tit+ let figAttributes = case attr of+ ("", _, _) -> empty+ (ident, _, _) -> literal $ "[#" <> ident <> "]"+ -- .Figure caption+ -- image::images/logo.png[Company logo, title="blah"]+ return $+ capt $$+ figAttributes $$+ "image::" <> args <> blankline+ blk -> blockToAsciiDoc opts blk+ vcat <$> mapM renderFigElement body blockToAsciiDoc _ (CodeBlock (_,classes,_) str) = return $ flush ( if null classes then "...." $$ literal str $$ "...."@@ -206,9 +283,12 @@ else contents let bar = text "____" return $ bar $$ chomp contents' $$ bar <> blankline-blockToAsciiDoc opts block@(Table _ blkCapt specs thead tbody tfoot) = do- let (caption, aligns, widths, headers, rows) =- toLegacyTable blkCapt specs thead tbody tfoot+blockToAsciiDoc opts block@(Table _ blkCapt specs thead@(TableHead _ originalHeaders) originalTbody tfoot@(TableFoot _ originalFooters)) = do+ let (caption, aligns, widths, _, _) =+ toLegacyTable blkCapt specs thead originalTbody tfoot+ let headers = adjustEmptyRows originalHeaders+ let rows = adjustEmptyRows $ tableBodiesToRows originalTbody+ let footers = adjustEmptyRows originalFooters caption' <- inlineListToAsciiDoc opts caption let caption'' = if null caption then empty@@ -227,15 +307,19 @@ ws -> ws let totalwidth :: Integer totalwidth = floor $ sum widths * 100- let colspec al wi = (case al of- AlignLeft -> "<"- AlignCenter -> "^"- AlignRight -> ">"- AlignDefault -> "") +++ let alignmentOperator AlignLeft = "<"+ alignmentOperator AlignCenter = "^"+ alignmentOperator AlignRight = ">"+ alignmentOperator AlignDefault = ""+ let colspec al wi = (alignmentOperator al) ++ if wi == 0 then "" else show wi ++ "%"- let headerspec = if all null headers+ let optionSpecForRows rowList spec = if allRowsEmpty rowList then Nothing else Just spec+ let headerspec = optionSpecForRows headers "header"+ let footerspec = optionSpecForRows footers "footer"+ let optionsList = catMaybes [headerspec, footerspec]+ let optionsspec = if null optionsList then empty- else text "options=\"header\","+ else text "options=\"" <> text (intercalate "," optionsList) <> text "\"," let widthspec = if totalwidth == 0 then empty else text "width="@@ -247,7 +331,7 @@ <> doubleQuotes (text $ intercalate "," $ zipWith colspec aligns widths') <> text ","- <> headerspec <> text "]"+ <> optionsspec <> text "]" -- construct cells and recurse in case of nested tables parentTableLevel <- gets tableNestingLevel@@ -272,19 +356,48 @@ d <- blockListToAsciiDoc opts bs return $ (text "a" <> separator) $$ d - let makeRow cells = hsep `fmap` mapM makeCell cells- rows' <- mapM makeRow rows- head' <- makeRow headers+ let colSpanFactor (ColSpan colSpan) = if colSpan > 1+ then text $ show colSpan+ else empty+ let rowSpanFactor (RowSpan rowSpan) = if rowSpan > 1+ then text $ "." ++ show rowSpan+ else empty++ let makeCellWithSpansAndAlignment (Cell _ alignment rowSpan colSpan blocks) = do+ let spanFactor = colSpanFactor colSpan <> rowSpanFactor rowSpan+ cell <- makeCell blocks+ let alignedCell = alignmentOperator alignment <> cell++ return $ if null spanFactor+ then alignedCell+ else spanFactor <> text "+" <> alignedCell++ let makeRow (Row attr []) = makeRow $ Row attr $ replicate (length widths') emptyCell+ makeRow (Row _ cells) = hsep `fmap` mapM makeCellWithSpansAndAlignment cells++ -- AsciiDoc only supports 1 header row and 1 footer row.+ let headerRow = Data.List.uncons $ adjustHeaders headers+ let footerRow = unsnoc $ adjustFooters footers+ let tailHeaderRows = if allRowsEmpty headers then [] else maybe [] snd headerRow+ let initFooterRows = if allRowsEmpty footers then [] else maybe [] fst footerRow+ rows' <- mapM makeRow $ tailHeaderRows ++ rows ++ initFooterRows+ head' <- case headerRow of+ Nothing -> return empty+ Just (headerRow', _) -> makeRow headerRow'+ foot <- case footerRow of+ Nothing -> return empty+ Just (_, footerRow') -> makeRow footerRow' modify $ \st -> st{ tableNestingLevel = parentTableLevel }- let head'' = if all null headers then empty else head'+ let head'' = if allRowsEmpty headers then empty else head'+ let foot' = if allRowsEmpty footers then empty else foot let colwidth = if writerWrapText opts == WrapAuto then writerColumns opts else 100000- let maxwidth = maximum $ fmap offset (head' :| rows')+ let maxwidth = maximum $ fmap offset (foot <| (head' :| rows')) let body = if maxwidth > colwidth then vsep rows' else vcat rows' let border = separator <> text "===" return $- caption'' $$ tablespec $$ border $$ head'' $$ body $$ border $$ blankline+ caption'' $$ tablespec $$ border $$ head'' $$ body $$ foot' $$ border $$ blankline blockToAsciiDoc opts (BulletList items) = do inlist <- gets inList modify $ \st -> st{ inList = True }@@ -312,27 +425,34 @@ contents <- mapM (definitionListItemToAsciiDoc opts) items modify $ \st -> st{ inList = inlist } return $ mconcat contents <> blankline++-- convert admonition and sidebar divs to asicidoc blockToAsciiDoc opts (Div (ident,classes,_) bs) = do let identifier = if T.null ident then empty else "[[" <> literal ident <> "]]"- let admonitions = ["attention","caution","danger","error","hint",+ let admonition_classes = ["attention","caution","danger","error","hint", "important","note","tip","warning"]+ let sidebar_class = "sidebar"+ contents <- case classes of- (l:_) | l `elem` admonitions -> do+ (l:_) | l `elem` admonition_classes || T.toLower l == sidebar_class -> do let (titleBs, bodyBs) = case bs of (Div (_,["title"],_) ts : rest) -> (ts, rest) _ -> ([], bs)- admonitionTitle <- if null titleBs+ let fence = if l == "sidebar" then "****" else "===="+ elemTitle <- if null titleBs ||+ -- If title matches class, omit+ (T.toLower (T.strip (stringify titleBs))) == l then return mempty else ("." <>) <$> blockListToAsciiDoc opts titleBs- admonitionBody <- blockListToAsciiDoc opts bodyBs+ elemBody <- blockListToAsciiDoc opts bodyBs return $ "[" <> literal (T.toUpper l) <> "]" $$- chomp admonitionTitle $$- "====" $$- chomp admonitionBody $$- "===="+ chomp elemTitle $$+ fence $$+ chomp elemBody $$+ fence _ -> blockListToAsciiDoc opts bs return $ identifier $$ contents $$ blankline @@ -342,11 +462,11 @@ bulletListItemToAsciiDoc opts blocks = do lev <- gets bulletListLevel modify $ \s -> s{ bulletListLevel = lev + 1 }- isAsciidoctor <- gets asciidoctorVariant- let blocksWithTasks = if isAsciidoctor- then (taskListItemToAsciiDoc blocks)- else blocks- contents <- foldM (addBlock opts) empty blocksWithTasks+ isLegacy <- gets legacy+ let blocksWithTasks = if isLegacy+ then blocks+ else (taskListItemToAsciiDoc blocks)+ contents <- snd <$> foldM (addBlock opts) (False, empty) blocksWithTasks modify $ \s -> s{ bulletListLevel = lev } let marker = text (replicate (lev + 1) '*') return $ marker <> text " " <> listBegin blocksWithTasks <>@@ -355,26 +475,32 @@ -- | Convert a list item containing text starting with @U+2610 BALLOT BOX@ -- or @U+2612 BALLOT BOX WITH X@ to asciidoctor checkbox syntax (e.g. @[x]@). taskListItemToAsciiDoc :: [Block] -> [Block]-taskListItemToAsciiDoc = handleTaskListItem toOrg listExt+taskListItemToAsciiDoc = handleTaskListItem toAd listExt where- toOrg (Str "☐" : Space : is) = Str "[ ]" : Space : is- toOrg (Str "☒" : Space : is) = Str "[x]" : Space : is- toOrg is = is+ toAd (Str "☐" : Space : is) = RawInline (Format "asciidoc") "[ ]" : Space : is+ toAd (Str "☒" : Space : is) = RawInline (Format "asciidoc") "[x]" : Space : is+ toAd is = is 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 =@@ -394,7 +520,7 @@ orderedListItemToAsciiDoc opts blocks = do lev <- gets orderedListLevel modify $ \s -> s{ orderedListLevel = lev + 1 }- contents <- foldM (addBlock opts) empty blocks+ contents <- snd <$> foldM (addBlock opts) (False, empty) blocks modify $ \s -> s{ orderedListLevel = lev } let marker = text (replicate (lev + 1) '.') return $ marker <> text " " <> listBegin blocks <> contents <> cr@@ -468,7 +594,9 @@ _ -> False isSpacy Start (Str xs) | Just (c, _) <- T.uncons xs = isPunctuation c || isSpace c- isSpacy _ _ = True+ isSpacy End (Link{}) = True+ isSpacy End (Image{}) = True+ isSpacy _ _ = False setIntraword :: PandocMonad m => Bool -> ADW m () setIntraword b = modify $ \st -> st{ intraword = b }@@ -484,58 +612,63 @@ contents <- inlineListToAsciiDoc opts lst isIntraword <- gets intraword let marker = if isIntraword then "__" else "_"- return $ marker <> contents <> marker+ return $ delimited marker marker contents inlineToAsciiDoc opts (Underline lst) = do contents <- inlineListToAsciiDoc opts lst- return $ "[.underline]#" <> contents <> "#"+ return $ delimited "[.underline]#" "#" contents inlineToAsciiDoc opts (Strong lst) = do contents <- inlineListToAsciiDoc opts lst isIntraword <- gets intraword let marker = if isIntraword then "**" else "*"- return $ marker <> contents <> marker+ return $ delimited marker marker contents inlineToAsciiDoc opts (Strikeout lst) = do contents <- inlineListToAsciiDoc opts lst- return $ "[line-through]*" <> contents <> "*"+ return $ delimited "[line-through]#" "#" contents inlineToAsciiDoc opts (Superscript lst) = do contents <- inlineListToAsciiDoc opts lst- return $ "^" <> contents <> "^"+ return $ delimited "^" "^" contents inlineToAsciiDoc opts (Subscript lst) = do contents <- inlineListToAsciiDoc opts lst- return $ "~" <> contents <> "~"-inlineToAsciiDoc opts (SmallCaps lst) = inlineListToAsciiDoc opts lst+ return $ delimited "~" "~" contents+inlineToAsciiDoc opts (SmallCaps lst) = do+ contents <- inlineListToAsciiDoc opts lst+ return $ delimited "[smallcaps]#" "#" contents inlineToAsciiDoc opts (Quoted qt lst) = do- isAsciidoctor <- gets asciidoctorVariant- inlineListToAsciiDoc opts $- case qt of- SingleQuote- | isAsciidoctor -> [Str "'`"] ++ lst ++ [Str "`'"]- | otherwise -> [Str "`"] ++ lst ++ [Str "'"]- DoubleQuote- | isAsciidoctor -> [Str "\"`"] ++ lst ++ [Str "`\""]- | otherwise -> [Str "``"] ++ lst ++ [Str "''"]+ isLegacy <- gets legacy+ contents <- inlineListToAsciiDoc opts lst+ pure $ case qt of+ SingleQuote+ | isLegacy -> "`" <> contents <> "'"+ | otherwise -> "'`" <> contents <> "`'"+ DoubleQuote+ | isLegacy -> "``" <> contents <> "''"+ | otherwise -> "\"`" <> contents <> "`\"" inlineToAsciiDoc _ (Code _ str) = do- isAsciidoctor <- gets asciidoctorVariant+ isLegacy <- gets legacy let escChar '`' = "\\'" escChar c = T.singleton c- let contents = literal (T.concatMap escChar str)- return $- if isAsciidoctor- then text "`+" <> contents <> "+`"- else text "`" <> contents <> "`"-inlineToAsciiDoc _ (Str str) = return $ literal $ escapeString str+ parentTableLevel <- gets tableNestingLevel+ let content+ | isLegacy = literal (T.concatMap escChar str)+ | otherwise = escapeString+ (if parentTableLevel > 0 then InTable else Normal) str+ return $ text "`" <> content <> "`"+inlineToAsciiDoc _ (Str str) = do+ parentTableLevel <- gets tableNestingLevel+ pure $ escapeString (if parentTableLevel > 0 then InTable else Normal) str inlineToAsciiDoc _ (Math InlineMath str) = do- isAsciidoctor <- gets asciidoctorVariant+ isLegacy <- gets legacy modify $ \st -> st{ hasMath = True }- let content = if isAsciidoctor- then literal str- else "$" <> literal str <> "$"+ let content = if isLegacy+ then "$" <> literal str <> "$"+ else literal str return $ "latexmath:[" <> content <> "]" inlineToAsciiDoc _ (Math DisplayMath str) = do- isAsciidoctor <- gets asciidoctorVariant+ isLegacy <- gets legacy modify $ \st -> st{ hasMath = True }- let content = if isAsciidoctor- then literal str- else "\\[" <> literal str <> "\\]"+ let content = if isLegacy+ then "\\[" <> literal str <> "\\]"+ else literal str inlist <- gets inList let sepline = if inlist then text "+"@@ -560,11 +693,19 @@ -- relative: link:downloads/foo.zip[download foo.zip] -- abs: http://google.cod[Google] -- or my@email.com[email john]- let fixCommas = T.replace "," "," -- see #8070- linktext <- fmap fixCommas <$> inlineListToAsciiDoc opts txt- let isRelative = T.all (/= ':') src+ let fixCommas (Str t) =+ intersperse (RawInline (Format "asciidoc") ",")+ $ map Str $ T.splitOn "," t -- see #8070+ fixCommas x = [x]++ linktext <- inlineListToAsciiDoc opts $ walk (concatMap fixCommas) txt+ let needsLinkPrefix = case parseURI (T.unpack src) of+ Just u -> uriScheme u `notElem` ["http:","https:",+ "ftp:", "irc:",+ "mailto:"]+ _ -> True let needsPassthrough = "--" `T.isInfixOf` src- let prefix = if isRelative+ let prefix = if needsLinkPrefix then text "link:" else empty let srcSuffix = fromMaybe src (T.stripPrefix "mailto:" src)@@ -594,9 +735,10 @@ contents <- inlineListToAsciiDoc opts ils isIntraword <- gets intraword let marker = if isIntraword then "##" else "#"- if T.null ident && null classes- then return contents- else do+ case classes of+ [] | T.null ident -> return contents+ ["mark"] | T.null ident -> return $ marker <> contents <> marker+ _ -> do let modifier = brackets $ literal $ T.unwords $ [ "#" <> ident | not (T.null ident)] ++ map ("." <>) classes return $ modifier <> marker <> contents <> marker@@ -608,7 +750,7 @@ ADW m (Doc Text) imageArguments opts attr altText src title = do let txt = if null altText || (altText == [Str ""])- then [Str "image"]+ then [Str . T.pack . dropExtension $ T.unpack src] else altText linktext <- inlineListToAsciiDoc opts txt let linktitle = if T.null title@@ -627,3 +769,144 @@ then empty else "," <> mconcat (intersperse "," dimList) return $ literal src <> "[" <> linktext <> linktitle <> dims <> "]"++-- | Adjust header rows for the fact that AsciiDoc only supports a single header row.+--+-- The first header row will become the single header row in AsciiDoc with the+-- other rows becoming the top body rows.+-- All cells of the first header row with a RowSpan > 1 will be mapped to+-- RowSpan 1 and the remaining RowSpans of those cells wll be added as empty+-- columns into the second row beneath them to preserve the original layout.+adjustHeaders :: [Row] -> [Row]+adjustHeaders [] = []+adjustHeaders [row] = [row]+adjustHeaders (Row attr firstHeaderCells:secondRow:remainingRows) =+ let ((_, emptyHeaderCells), headerRow) = mapAccumL adjustHeaderRowCell (0, []) firstHeaderCells+ secondRow' = applyEmptyCells secondRow emptyHeaderCells+ in Row attr headerRow:secondRow':remainingRows+ where+ adjustHeaderRowCell (columnPosition, emptyCells) cell@(Cell cellAttr alignment (RowSpan rowSpan) (ColSpan colSpan) blocks) =+ let nextColumnPosition = columnPosition + colSpan+ adjustedHeaderCell = Cell cellAttr alignment (RowSpan 1) (ColSpan colSpan) blocks+ emptyHeaderRowCell = Cell nullAttr AlignDefault (RowSpan rowSpan - 1) (ColSpan colSpan) []+ emptyCellPosition = (columnPosition, emptyHeaderRowCell)+ in if rowSpan > 1+ then ((nextColumnPosition, emptyCellPosition:emptyCells), adjustedHeaderCell)+ else ((nextColumnPosition, emptyCells), cell)++-- | Adjust footer rows for the fact that AsciiDoc only supports a single footer row.+--+-- The last footer row will become the single footer row in AsciiDoc with the+-- previous footer rows becoming the bottom body rows.+-- All column indices of cells whose RowSpans would reach that last footer row+-- are collected and subtracted by 1. Those collected column indices will then+-- be applied as empty columns into the last footer row to preserve the original+-- layout.+adjustFooters :: [Row] -> [Row]+adjustFooters [] = []+adjustFooters [row] = [row]+adjustFooters rows = adjustFooters' [] (0, length rows) M.empty rows+ where+ adjustFooters' _ _ _ [] = []+ adjustFooters' columnIndices _ _ [row] = [applyEmptyCells row columnIndices]+ adjustFooters' columnIndices rowInfo@(rowIndex, footerLength) previousRowSpans (row:rest) =+ -- Need to keep track of RowSpans from previous rows and how they occupy+ -- space in rows beneath them to be able to apply the correct column+ -- position of RowSpans that would reach the last footer row.+ let (previousRowSpans', row', columnIndices') = adjustFooterRow rowInfo previousRowSpans row+ rows' = adjustFooters' (columnIndices ++ columnIndices') (rowIndex + 1, footerLength) previousRowSpans' rest+ in row':rows'++ adjustFooterRow rowInfo previousRowSpans (Row attr cells) =+ let ((nextColumnPosition, previousRowSpans'), cells') = mapAccumL (adjustFooterCell rowInfo) (0, previousRowSpans) cells+ (cells'', columnIndices) = unzip cells'++ -- Apply row spans from a previous row that are next to the end of the+ -- current row's cells to keep track of the correct column position.+ previousRowSpans'' = decrementTrailingRowSpans nextColumnPosition previousRowSpans'+ in (previousRowSpans'', Row attr cells'', catMaybes columnIndices)++-- | Adjust footer cell for the fact that AsciiDoc only supports a single footer row.+--+-- Collects cells whose RowSpan would reach to the last footer row and applies+-- them as empty cells to that last footer row.+adjustFooterCell :: (Int, Int) -> (Int, M.Map Int (RowSpan, ColSpan)) -> Cell -> ((Int, M.Map Int (RowSpan, ColSpan)), (Cell, Maybe (Int, Cell)))+adjustFooterCell rowInfo@(rowIndex, footerLength) (columnPosition, previousSpans) cell@(Cell _ _ (RowSpan rowSpan) (ColSpan colSpan) _)+ | Just (ColSpan previousColSpan, previousSpans') <- takePreviousSpansAtColumn columnPosition previousSpans =+ -- Apply row span from a previous row that occupies this column to keep+ -- track of the correct column position.+ adjustFooterCell rowInfo (columnPosition + previousColSpan, previousSpans') cell+ | rowSpan > 1 && rowIndex + rowSpan >= footerLength =+ -- Adjust row span that would reach all the way to the last footer row and+ -- keep track of that to apply it to the last footer row.+ ((nextColumnPosition, previousRowSpans'), (decrementRowSpanInCell cell, Just (columnPosition, emptyCellWithColSpan)))+ | otherwise = ((nextColumnPosition, previousRowSpans'), (cell, Nothing))+ where+ -- Keep track of this cell's RowSpan for the rows following it.+ previousRowSpans' = insertCurrentSpansAtColumn columnPosition previousSpans (RowSpan rowSpan) (ColSpan colSpan)+ nextColumnPosition = columnPosition + colSpan+ emptyCellWithColSpan = Cell nullAttr AlignDefault (RowSpan 1) (ColSpan colSpan) []++-- | Adjust empty rows for AsciiDoc.+--+-- An empty row without any cells decrements RowSpans that cover it and is+-- removed by them to adjust for being unable to express empty rows with no+-- cells in AsciiDoc.+adjustEmptyRows :: [Row] -> [Row]+adjustEmptyRows = adjustEmptyRows' . map applyInitialRowsLeft+ where+ adjustEmptyRows' [] = []+ adjustEmptyRows' (row:rest)+ | maxRowSpan' <- maxRowSpan row+ , maxRowSpan' > 1 =+ -- Consume empty rows within the row's span.+ let followingRows = take (maxRowSpan' - 1) rest+ rows = consumeEmptyRows (row :| []) followingRows+ rest' = drop (length followingRows) rest+ in rowFromCellsWithRowsLeft (NonEmpty.head rows) : adjustEmptyRows' (NonEmpty.tail rows ++ rest')+ | otherwise = rowFromCellsWithRowsLeft row : adjustEmptyRows' rest++ rowFromCellsWithRowsLeft (attr, cellsWithRowsLeft) = Row attr $ map fst cellsWithRowsLeft+ cellRowSpan (Cell _ _ (RowSpan rowSpan) _ _) = rowSpan++ consumeEmptyRows rows [] = NonEmpty.reverse rows+ consumeEmptyRows rows (followingRow:restRows) =+ if null (snd followingRow) && any rowHasRowSpanAndRowsLeft rows+ then consumeEmptyRows (fmap (subtractRowsLeft decrementRowSpanInCell) rows) restRows -- Consume empty row for RowSpan and remove it+ else consumeEmptyRows (followingRow <| fmap (subtractRowsLeft id) rows) restRows++ rowHasRowSpanAndRowsLeft (_, cells) = any cellHasRowSpanAndRowsLeft cells+ cellHasRowSpanAndRowsLeft (cell, rowsLeft) = cellRowSpan cell > 1 && rowsLeft >= 1++ subtractRowsLeft changeCell (attr, cells) = (attr, map (subtractRowsLeftCell changeCell) cells)++ subtractRowsLeftCell changeCell cellPair@(cell, rowsLeft)+ | rowsLeft >= 1 = (changeCell cell, rowsLeft - 1)+ | otherwise = cellPair++ applyInitialRowsLeft (Row attr cells) = (attr, map applyInitialRowsLeftCell cells)++ applyInitialRowsLeftCell cell+ | rowSpan <- cellRowSpan cell, rowSpan > 1 = (cell, rowSpan - 1) -- Minus its own row+ | otherwise = (cell, 0)++ maxRowSpan (_, []) = 0+ maxRowSpan (_, cells) = maximum $ map (cellRowSpan . fst) cells++-- | Decrement the RowSpan of a Cell if that RowSpan > 1.+decrementRowSpanInCell :: Cell -> Cell+decrementRowSpanInCell cell@(Cell attr alignment (RowSpan rowSpan) colSpan blocks) =+ if rowSpan > 1+ then Cell attr alignment (RowSpan rowSpan - 1) colSpan blocks+ else cell++-- | Apply empty table cells at the given positions inside a Row.+applyEmptyCells :: Row -> [(Int, Cell)] -> Row+applyEmptyCells (Row attr cells) = Row attr . applyEmptyCells' 0 cells . sortOn fst+ where+ applyEmptyCells' _ cells' [] = cells'+ applyEmptyCells' currentPosition cells' ((columnPosition, columnEmptyCell@(Cell _ _ _ (ColSpan colSpan) _)):rest)+ | columnPosition == currentPosition = columnEmptyCell : applyEmptyCells' (currentPosition + colSpan) cells' rest+ applyEmptyCells' _ [] _ = []+ applyEmptyCells' currentPosition (cell@(Cell _ _ _ (ColSpan currentCellColSpan) _):restCells) emptyCellList =+ cell : applyEmptyCells' (currentPosition + currentCellColSpan) restCells emptyCellList
@@ -0,0 +1,1089 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE Strict #-}+{-# LANGUAGE TypeApplications #-}+{- |+ Module : Text.Pandoc.Writers.BBCode+ Copyright : © 2025 Aleksey Myshko <git@crii.xyz>+ License : GNU GPL, version 2 or above++ Maintainer : Aleksey Myshko <git@crii.xyz>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to various BBCode flavors.+-}++module Text.Pandoc.Writers.BBCode (+ -- * Predefined writers+ -- Writers for different flavors of BBCode. 'writeBBCode' is a synonym for+ -- 'writeBBCode_official'+ writeBBCode,+ writeBBCodeOfficial,+ writeBBCodeSteam,+ writeBBCodePhpBB,+ writeBBCodeFluxBB,+ writeBBCodeHubzilla,+ writeBBCodeXenforo,++ -- * Extending the writer+ -- $extending+ FlavorSpec (..),+ WriterState (..),+ RR,+ writeBBCodeCustom,+ inlineToBBCode,+ inlineListToBBCode,+ blockToBBCode,+ blockListToBBCode,++ -- ** Handling attributes+ -- $wrapping_spans_divs+ attrToMap,++ -- * Predefined flavor specifications+ officialSpec,+ steamSpec,+ phpbbSpec,+ fluxbbSpec,+ hubzillaSpec,+ xenforoSpec,+) where++import Control.Applicative (some)+import Control.Monad (forM)+import Control.Monad.Reader (MonadReader (..), ReaderT (..), asks)+import Control.Monad.State (MonadState (..), StateT, evalStateT, gets, modify)+import Data.Default (Default (..))+import Data.Either (isRight)+import Data.Foldable (toList)+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as Map+import Data.Maybe (fromMaybe, isJust)+import Data.Sequence (Seq, (|>))+import qualified Data.Sequence as Seq+import Data.Text (Text)+import qualified Data.Text as T+import Text.DocLayout hiding (char, link, text)+import Text.Pandoc.Class.PandocMonad (PandocMonad, report)+import Text.Pandoc.Definition+import Text.Pandoc.Logging (LogMessage (..))+import Text.Pandoc.Options (WriterOptions (..))+import Text.Pandoc.Parsing (char, digit, eof, readWith)+import Text.Pandoc.Shared (inquotes, onlySimpleTableCells, removeFormatting, trim, tshow)+import Text.Pandoc.Templates (renderTemplate)+import Text.Pandoc.URI (escapeURI)+import Text.Pandoc.Writers.Shared (defField, metaToContext, toLegacyTable, unsmartify)+import Text.Read (readMaybe)++-- Type synonym to prevent haddock-generated HTML from overflowing+type PandocTable =+ (Attr, Caption, [ColSpec], TableHead, [TableBody], TableFoot)++-- $extending+-- If you want to support more Pandoc elements (or render some of them+-- differently) you can do so by creating your own 'FlavorSpec'+--+-- The module exports the @'FlavorSpec'@s underlying @writeBBCode_*@ functions,+-- namely 'officialSpec', 'steamSpec', 'phpbbSpec', 'fluxbbSpec',+-- 'hubzillaSpec'.+--+-- You can create and use your own renderers, for instance here we define a+-- renderer for 'CodeBlock' and use it to create a derivative format:+--+-- > renderCodeBlockCustom :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+-- > renderCodeBlockCustom (_, cls, _) code = do+-- > let opening = case cls of+-- > (lang : _) -> "[code=" <> lang <> "]"+-- > ("c++" : _) -> "[code=cpp]"+-- > _ -> "[code]"+-- > pure $ mconcat [literal opening, literal code, cr, "[/code]"]+-- >+-- > specCustom = officialSpec{renderCodeBlock = renderCodeBlockCustom}+--+-- Then we can use it to render 'Pandoc' document via 'writeBBCode_custom'++{- | Data type that is a collection of renderers for most elements in a Pandoc+AST (see 'Block' and 'Inline')++The intention here is to allow inheritance between formats, for instance if+format A and format @B@ differ only in rendering tables, @B@ can be implemented+as @A{'renderTable' = renderTableB}@+-}+data FlavorSpec = FlavorSpec+ { renderBlockQuote ::+ forall m.+ (PandocMonad m) =>+ [Block] ->+ RR m (Doc Text)+ -- ^ Render 'BlockQuote'+ , renderBulletList ::+ forall m.+ (PandocMonad m) =>+ [[Block]] ->+ RR m (Doc Text)+ -- ^ Render 'BulletList'+ , renderCodeBlock ::+ forall m.+ (PandocMonad m) =>+ Attr ->+ Text ->+ RR m (Doc Text)+ -- ^ Render 'CodeBlock'+ , renderDefinitionList ::+ forall m.+ (PandocMonad m) =>+ [([Inline], [[Block]])] ->+ RR m (Doc Text)+ -- ^ Render 'DefinitionList'+ , renderHeader ::+ forall m.+ (PandocMonad m) =>+ Int ->+ Attr ->+ [Inline] ->+ RR m (Doc Text)+ -- ^ Render 'Header'+ , renderInlineCode ::+ forall m.+ (PandocMonad m) =>+ Attr ->+ Text ->+ RR m (Doc Text)+ -- ^ Render 'Code'+ , renderLink ::+ forall m.+ (PandocMonad m) =>+ Attr ->+ [Inline] ->+ Target ->+ RR m (Doc Text)+ -- ^ Render 'Link'+ , renderOrderedList ::+ forall m.+ (PandocMonad m) =>+ ListAttributes ->+ [[Block]] ->+ RR m (Doc Text)+ -- ^ Render 'OrderedList'+ , renderStrikeout ::+ forall m.+ (PandocMonad m) =>+ [Inline] ->+ RR m (Doc Text)+ -- ^ Render 'Strikeout'+ , renderTable :: forall m. (PandocMonad m) => PandocTable -> RR m (Doc Text)+ -- ^ Render 'Table'+ , renderHorizontalRule ::+ forall m.+ (PandocMonad m) =>+ RR m (Doc Text)+ -- ^ Render 'HorizontalRule'+ , renderLineBlock ::+ forall m.+ (PandocMonad m) =>+ [[Inline]] ->+ RR m (Doc Text)+ -- ^ Render 'LineBlock'+ , renderPara ::+ forall m.+ (PandocMonad m) =>+ [Inline] ->+ RR m (Doc Text)+ -- ^ Render 'Para'+ , renderSuperscript ::+ forall m.+ (PandocMonad m) =>+ [Inline] ->+ RR m (Doc Text)+ -- ^ Render 'Superscript'+ , renderSubscript :: forall m. (PandocMonad m) => [Inline] -> RR m (Doc Text)+ -- ^ Render 'Subscript'+ , renderSmallCaps :: forall m. (PandocMonad m) => [Inline] -> RR m (Doc Text)+ -- ^ Render 'SmallCaps'+ , renderCite ::+ forall m.+ (PandocMonad m) =>+ [Citation] ->+ [Inline] ->+ RR m (Doc Text)+ -- ^ Render 'Cite'+ , renderNote :: forall m. (PandocMonad m) => [Block] -> RR m (Doc Text)+ -- ^ Render 'Note'+ , renderFigure ::+ forall m.+ (PandocMonad m) =>+ Attr ->+ Caption ->+ [Block] ->+ RR m (Doc Text)+ -- ^ Render 'Figure'+ , renderQuoted ::+ forall m.+ (PandocMonad m) =>+ QuoteType ->+ [Inline] ->+ RR m (Doc Text)+ -- ^ Render 'Quoted'+ , renderMath ::+ forall m.+ (PandocMonad m) =>+ MathType ->+ Text ->+ RR m (Doc Text)+ -- ^ Render 'Math'+ , renderImage ::+ forall m.+ (PandocMonad m) =>+ Attr ->+ [Inline] ->+ Target ->+ RR m (Doc Text)+ -- ^ Render 'Image'+ , wrapSpanDiv :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+ -- ^ Wrap document in bbcode tags based on attributes/classes. Boolean flag+ -- indicates whether passed argument is a Div or a Span (True means Div)+ }++data WriterState = WriterState+ { writerOptions :: WriterOptions+ , flavorSpec :: FlavorSpec+ , inList :: Bool+ }++instance Default WriterState where+ def =+ WriterState+ { writerOptions = def+ , flavorSpec = officialSpec+ , inList = False+ }++-- | The base of a renderer monad.+type RR m a = StateT (Seq (Doc Text)) (ReaderT WriterState m) a++pandocToBBCode :: (PandocMonad m) => Pandoc -> RR m Text+pandocToBBCode (Pandoc meta body) = do+ opts <- asks writerOptions+ -- Run the rendering that mutates the state by producing footnotes+ bodyContents <- blockListToBBCode body+ -- Get the footnotes+ footnotes <- get+ -- Separate footnotes (if any) with a horizontal rule+ footnotesSep <-+ if null footnotes+ then pure empty+ else+ (\hr -> blankline <> hr <> blankline)+ <$> blockToBBCode HorizontalRule+ -- Put footnotes after the main text+ let docText = bodyContents <> footnotesSep <> vsep (toList footnotes)+ metadata <- metaToContext opts blockListToBBCode inlineListToBBCode meta+ let context = defField "body" docText metadata+ case writerTemplate opts of+ Just tpl -> pure $ render Nothing (renderTemplate tpl context)+ Nothing -> pure $ render Nothing docText++writeBBCode+ , writeBBCodeOfficial+ , writeBBCodeSteam+ , writeBBCodePhpBB+ , writeBBCodeFluxBB+ , writeBBCodeHubzilla+ , writeBBCodeXenforo ::+ (PandocMonad m) => WriterOptions -> Pandoc -> m Text+writeBBCode = writeBBCodeOfficial+writeBBCodeOfficial = writeBBCodeCustom officialSpec+writeBBCodeSteam = writeBBCodeCustom steamSpec+writeBBCodePhpBB = writeBBCodeCustom phpbbSpec+writeBBCodeFluxBB = writeBBCodeCustom fluxbbSpec+writeBBCodeHubzilla = writeBBCodeCustom hubzillaSpec+writeBBCodeXenforo = writeBBCodeCustom xenforoSpec++{- | Convert a 'Pandoc' document to BBCode using the given 'FlavorSpec' and+'WriterOptions'.+-}+writeBBCodeCustom ::+ (PandocMonad m) => FlavorSpec -> WriterOptions -> Pandoc -> m Text+writeBBCodeCustom spec opts document =+ runRR mempty def{writerOptions = opts, flavorSpec = spec} $+ pandocToBBCode document+ where+ runRR :: (Monad m) => Seq (Doc Text) -> WriterState -> RR m a -> m a+ runRR footnotes writerState action =+ runReaderT (evalStateT action footnotes) writerState++blockListToBBCode :: (PandocMonad m) => [Block] -> RR m (Doc Text)+blockListToBBCode blocks =+ chomp . vsep . filter (not . null)+ <$> mapM blockToBBCode blocks++blockToBBCode :: (PandocMonad m) => Block -> RR m (Doc Text)+blockToBBCode block = do+ spec <- asks flavorSpec+ case block of+ Plain inlines -> inlineListToBBCode inlines+ Para inlines -> renderPara spec inlines+ LineBlock inliness -> renderLineBlock spec inliness+ CodeBlock attr code -> renderCodeBlock spec attr code+ RawBlock format raw -> case format of+ "bbcode" -> pure $ literal raw+ _ -> "" <$ report (BlockNotRendered block)+ BlockQuote blocks -> renderBlockQuote spec blocks+ OrderedList attr items -> renderOrderedList spec attr items+ BulletList items -> renderBulletList spec items+ DefinitionList items -> renderDefinitionList spec items+ Header level attr inlines -> renderHeader spec level attr inlines+ HorizontalRule -> renderHorizontalRule spec+ Table attr blkCapt specs thead tbody tfoot ->+ renderTable spec (attr, blkCapt, specs, thead, tbody, tfoot)+ Figure attr caption blocks -> renderFigure spec attr caption blocks+ Div attr blocks -> do+ contents <- blockListToBBCode blocks+ let kvcMap = attrToMap attr+ -- whether passed contents is a Div (Block) element+ -- vvvv+ pure $ wrapSpanDiv spec True kvcMap contents++inlineToBBCode :: (PandocMonad m) => Inline -> RR m (Doc Text)+inlineToBBCode inline = do+ spec <- asks flavorSpec+ case inline of+ Str str -> do+ opts <- asks writerOptions+ pure . literal $ unsmartify opts str+ Emph inlines -> do+ contents <- inlineListToBBCode inlines+ pure $ mconcat ["[i]", contents, "[/i]"]+ Underline inlines -> do+ contents <- inlineListToBBCode inlines+ pure $ mconcat ["[u]", contents, "[/u]"]+ Strong inlines -> do+ contents <- inlineListToBBCode inlines+ pure $ mconcat ["[b]", contents, "[/b]"]+ Strikeout inlines -> renderStrikeout spec inlines+ Superscript inlines -> renderSuperscript spec inlines+ Subscript inlines -> renderSubscript spec inlines+ SmallCaps inlines -> renderSmallCaps spec inlines+ Quoted typ inlines -> renderQuoted spec typ inlines+ Cite cits inlines -> renderCite spec cits inlines+ Code attr code -> renderInlineCode spec attr code+ Space -> pure space+ SoftBreak -> pure space+ LineBreak -> pure cr+ Math typ math -> renderMath spec typ math+ RawInline (Format format) text -> case format of+ "bbcode" -> pure $ literal text+ _ -> "" <$ report (InlineNotRendered inline)+ Link attr txt target -> renderLink spec attr txt target+ Image attr alt target -> renderImage spec attr alt target+ Note blocks -> renderNote spec blocks+ Span attr inlines -> do+ contents <- inlineListToBBCode inlines+ let kvcMap = attrToMap attr+ -- whether passed contents is a Div (Block element)+ -- vvvvv+ pure $ wrapSpanDiv spec False kvcMap contents++renderImageDefault ::+ (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderImageDefault (_, _, kvList) alt (source, title) = do+ altText <-+ trim . render Nothing+ <$> inlineListToBBCode (removeFormatting alt)+ let kvMap = Map.fromList kvList+ -- No BBCode flavor supported by the Writer has local images support, but we+ -- still allow source to be plain path or anything else+ pure . literal $+ mconcat+ [ "[img"+ , if T.null altText+ then ""+ else " alt=" <> inquotes altText+ , if T.null title+ then ""+ else " title=" <> inquotes title+ , case Map.lookup "width" kvMap of+ Just w+ | isJust (readMaybe @Int $ T.unpack w) ->+ " width=" <> inquotes w+ _ -> ""+ , case Map.lookup "height" kvMap of+ Just h+ | isJust (readMaybe @Int $ T.unpack h) ->+ " height=" <> inquotes h+ _ -> ""+ , "]"+ , source+ , "[/img]"+ ]++renderImageOmit ::+ (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderImageOmit _ _ _ = pure ""++{- | Basic phpBB doesn't support any attributes, although+@[img src=https://example.com]whatever[/img]@ is supported, but text in tag has+no effect+-}+renderImagePhpBB ::+ (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderImagePhpBB _ _ (source, _) =+ pure . literal $ mconcat ["[img]", source, "[/img]"]++renderImageXenforo ::+ (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderImageXenforo (_, _, kvList) alt (source, title) = do+ altText <-+ trim . render Nothing+ <$> inlineListToBBCode (removeFormatting alt)+ let kvMap = Map.fromList kvList+ -- No BBCode flavor supported by the Writer has local images support, but we+ -- still allow source to be plain path or anything else+ pure . literal $+ mconcat+ [ "[img"+ , if T.null altText+ then ""+ else " alt=" <> inquotes altText+ , if T.null title+ then ""+ else " title=" <> inquotes title+ , case Map.lookup "width" kvMap of+ Just w+ | isRight (readWith sizeP Nothing w) ->+ " width=" <> w+ _ -> ""+ , "]"+ , source+ , "[/img]"+ ]+ where+ sizeP = some digit >> char '%' >> eof++{- | Check whether character is a bracket++>>> T.filter notBracket "[a]b[[ó]qü]]n®"+"ab\243q\252n\174"+-}+notBracket :: Char -> Bool+notBracket = \case+ '[' -> False+ ']' -> False+ _ -> True++-- FluxBB uses [img=alt text] instead of [img alt="alt text"]+renderImageFluxBB ::+ (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderImageFluxBB _ alt (source, _) = do+ alt' <- T.filter notBracket . render Nothing <$> inlineListToBBCode alt+ pure . literal $+ mconcat+ [ "[img"+ , if T.null alt'+ then ""+ else "=" <> alt'+ , "]"+ , source+ , "[/img]"+ ]++inlineListToBBCode :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+inlineListToBBCode inlines = mconcat <$> mapM inlineToBBCode inlines++-- Taken from Data.Ord+clamp :: (Ord a) => (a, a) -> a -> a+clamp (low, high) a = min high (max a low)++renderHeaderDefault ::+ (PandocMonad m) => Int -> Attr -> [Inline] -> RR m (Doc Text)+renderHeaderDefault level _attr inlines =+ case clamp (1, 4) level of+ 1 -> inlineToBBCode $ Underline [Strong inlines]+ 2 -> inlineToBBCode $ Strong inlines+ 3 -> inlineToBBCode $ Underline inlines+ _ -> inlineListToBBCode inlines++-- Adapted from Text.Pandoc.Writers.Org+renderLinkDefault ::+ (PandocMonad m) => Attr -> [Inline] -> Target -> RR m (Doc Text)+renderLinkDefault _ txt (src, _) =+ case txt of+ [Str x]+ | escapeURI x == src ->+ pure $ "[url]" <> literal x <> "[/url]"+ _ -> do+ contents <- inlineListToBBCode txt+ let suffix = if T.null src then "" else "=" <> src+ pure $ "[url" <> literal suffix <> "]" <> contents <> "[/url]"++renderCodeBlockDefault :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderCodeBlockDefault (_, cls, _) code = do+ let opening = case cls of+ (lang : _) -> "[code=" <> lang <> "]"+ _ -> "[code]"+ pure $ mconcat [literal opening, literal code, cr, "[/code]"]++renderCodeBlockSimple :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderCodeBlockSimple _ code = do+ pure $ mconcat [literal "[code]", literal code, cr, "[/code]"]++renderInlineCodeLiteral :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderInlineCodeLiteral _ code = pure $ literal code++renderInlineCodeNoParse :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderInlineCodeNoParse _ code =+ pure $ mconcat [literal "[noparse]", literal code, "[/noparse]"]++renderInlineCodeHubzilla :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderInlineCodeHubzilla _ code =+ pure $ mconcat [literal "[code]", literal code, "[/code]"]++renderInlineCodeXenforo :: (PandocMonad m) => Attr -> Text -> RR m (Doc Text)+renderInlineCodeXenforo _ code =+ pure $ mconcat [literal "[icode]", literal code, "[/icode]"]++renderStrikeoutDefault :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderStrikeoutDefault inlines = do+ contents <- inlineListToBBCode inlines+ pure $ mconcat ["[s]", contents, "[/s]"]++renderStrikeoutSteam :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderStrikeoutSteam inlines = do+ contents <- inlineListToBBCode inlines+ pure $ mconcat ["[strike]", contents, "[/strike]"]++renderDefinitionListDefault ::+ (PandocMonad m) => [([Inline], [[Block]])] -> RR m (Doc Text)+renderDefinitionListDefault items = do+ items' <- forM items $ \(term, definitions) -> do+ term' <- inlineListToBBCode term+ definitions' <- blockToBBCode (BulletList definitions)+ pure $ term' $$ definitions'+ pure $ vcat items'++renderDefinitionListHubzilla ::+ (PandocMonad m) => [([Inline], [[Block]])] -> RR m (Doc Text)+renderDefinitionListHubzilla items = do+ items' <- forM items $ \(term, definitions) -> do+ term' <- inlineListToBBCode term+ let term'' = "[*= " <> term' <> "]"+ definitions' <- forM definitions blockListToBBCode+ pure $ vcat (term'' : definitions')+ pure $ vcat (literal "[dl terms=\"b\"]" : items' ++ [literal "[/dl]"])++listWithTags ::+ (PandocMonad m) =>+ Text ->+ Text ->+ ([[Block]] -> RR m [Doc Text]) ->+ [[Block]] ->+ RR m (Doc Text)+listWithTags open close renderItems items = do+ contents <- local (\s -> s{inList = True}) (renderItems items)+ pure $ vcat $ literal open : contents ++ [literal close]++starListItems :: (PandocMonad m) => [[Block]] -> RR m [Doc Text]+starListItems items = forM items $ \item -> do+ item' <- blockListToBBCode item+ pure $ literal "[*]" <> item'++listStyleCode :: ListNumberStyle -> Maybe Text+listStyleCode = \case+ Decimal -> Just "1"+ DefaultStyle -> Just "1"+ LowerAlpha -> Just "a"+ UpperAlpha -> Just "A"+ LowerRoman -> Just "i"+ UpperRoman -> Just "I"+ Example -> Nothing++renderBulletListOfficial :: (PandocMonad m) => [[Block]] -> RR m (Doc Text)+renderBulletListOfficial = listWithTags "[list]" "[/list]" starListItems++renderBulletListHubzilla :: (PandocMonad m) => [[Block]] -> RR m (Doc Text)+renderBulletListHubzilla = listWithTags "[ul]" "[/ul]" starListItems++renderOrderedListHubzilla ::+ (PandocMonad m) => ListAttributes -> [[Block]] -> RR m (Doc Text)+renderOrderedListHubzilla (_, style, _) = case style of+ DefaultStyle -> listWithTags "[ol]" "[/ol]" starListItems+ Example -> listWithTags "[ol]" "[/ol]" starListItems+ _ -> listWithTags ("[list=" <> suffix <> "]") "[/list]" starListItems+ where+ suffix = fromMaybe "1" $ listStyleCode style++renderOrderedListOfficial ::+ (PandocMonad m) => ListAttributes -> [[Block]] -> RR m (Doc Text)+renderOrderedListOfficial (_, style, _) = do+ let suffix = maybe "" ("=" <>) (listStyleCode style)+ listWithTags ("[list" <> suffix <> "]") "[/list]" starListItems++renderOrderedListSteam ::+ (PandocMonad m) => ListAttributes -> [[Block]] -> RR m (Doc Text)+renderOrderedListSteam _ =+ listWithTags "[olist]" "[/olist]" starListItems++renderHeaderSteam ::+ (PandocMonad m) => Int -> Attr -> [Inline] -> RR m (Doc Text)+renderHeaderSteam level _ inlines = do+ body <- inlineListToBBCode inlines+ let capped = clamp (1, 3) level+ open = "[h" <> tshow capped <> "]"+ close = "[/h" <> tshow capped <> "]"+ pure $ literal open <> body <> literal close++renderHeaderHubzilla ::+ (PandocMonad m) => Int -> Attr -> [Inline] -> RR m (Doc Text)+renderHeaderHubzilla level _ inlines = do+ body <- inlineListToBBCode inlines+ let capped = clamp (1, 6) level+ open = "[h" <> tshow capped <> "]"+ close = "[/h" <> tshow capped <> "]"+ pure $ literal open <> body <> literal close++-- xenForo supports levels 1--3, but levels other than 1--3 become div with+-- .bbHeading class which can be linked to.+renderHeaderXenforo ::+ (PandocMonad m) => Int -> Attr -> [Inline] -> RR m (Doc Text)+renderHeaderXenforo level _ inlines = do+ body <- inlineListToBBCode inlines+ let capped = max 1 level+ open = "[heading=" <> tshow capped <> "]"+ close = "[/heading]"+ pure $ literal open <> body <> literal close++renderTableGeneric ::+ (PandocMonad m) =>+ Text ->+ Text ->+ Text ->+ (Attr, Caption, [ColSpec], TableHead, [TableBody], TableFoot) ->+ RR m (Doc Text)+renderTableGeneric tableTag headerCellTag bodyCellTag table = do+ caption' <- inlineListToBBCode caption+ table' <-+ if not simpleCells+ then "" <$ report (BlockNotRendered tableBlock)+ else do+ headerDocs <-+ if null headers+ then pure []+ else pure <$> renderTableRow headerCellTag headers+ rowDocs <- mapM (renderTableRow bodyCellTag) rows+ pure $ renderTable' headerDocs rowDocs+ pure $ caption' $$ table'+ where+ (attr, blkCapt, specs, thead, tbody, tfoot) = table+ (caption, _, _, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot+ tableBlock = Table attr blkCapt specs thead tbody tfoot+ simpleCells = onlySimpleTableCells (headers : rows)+ renderTable' headerDocs rowDocs =+ vcat+ [ literal ("[" <> tableTag <> "]")+ , vcat headerDocs+ , vcat rowDocs+ , literal ("[/" <> tableTag <> "]")+ ]+ renderCell cellTag cellDoc =+ mconcat+ [ literal ("[" <> cellTag <> "]")+ , cellDoc+ , literal ("[/" <> cellTag <> "]")+ ]+ renderTableRow cellTag cells = do+ renderedCells <- mapM blockListToBBCode cells+ let cellsDoc = mconcat $ map (renderCell cellTag) renderedCells+ pure $ literal "[tr]" <> cellsDoc <> literal "[/tr]"++renderTableDefault ::+ (PandocMonad m) =>+ ( Attr+ , Caption+ , [ColSpec]+ , TableHead+ , [TableBody]+ , TableFoot+ ) ->+ RR m (Doc Text)+renderTableDefault = renderTableGeneric "table" "th" "td"++renderTableOmit ::+ (PandocMonad m) =>+ ( Attr+ , Caption+ , [ColSpec]+ , TableHead+ , [TableBody]+ , TableFoot+ ) ->+ RR m (Doc Text)+renderTableOmit (_, blkCapt, specs, thead, tbody, tfoot) = do+ let (caption, _, _, _, _) = toLegacyTable blkCapt specs thead tbody tfoot+ caption' <- inlineListToBBCode caption+ pure $ caption' $$ "(TABLE)"++-- $wrapping_spans_divs+-- Consider attribute a key-value pair with a Just value, and respectively+-- class is key-value pair with Nothing value.+-- For instance, given @("", ["cl1"], [("k", "v")]) :: 'Attr'@, respective Map+-- should look like @'Map.fromList' [("cl1", 'Nothing'), ("k", 'Just' "v")]@+--+-- This transformation is handled by 'attrToMap'+--+-- Example definition of a wrapSpanDiv:+--+-- > {-# LANGUAGE OverloadedStrings #-}+-- > import Data.Map (Map)+-- > import qualified Data.Map as Map+-- > import Text.DocLayout+-- > import Data.Text (Text)+-- > import qualified Data.Text as T+-- >+-- > wrapSpanDivSteam :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+-- > wrapSpanDivSteam isDiv kvc doc = Map.foldrWithKey wrap doc kvc+-- > where+-- > wrap "spoiler" (Just _) acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+-- > wrap "spoiler" Nothing acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+-- > wrap _ _ acc = acc+--+-- To verify it works, wrap some text in unnamed spoiler+--+-- >>> render Nothing $ wrapSpanDivSteam True (attrToMap ("", ["spoiler"], [])) "I am text"+-- "[spoiler]I am text[/spoiler]"++{- | The goal of the transformation is to treat classes and key-value pairs+uniformly.++Class list becomes Map where all values are Nothing, and list of key-value+pairs is converted to Map via 'Map.toList'. Both Maps are then merged.+-}+attrToMap :: Attr -> Map Text (Maybe Text)+attrToMap (_, classes, kvList) =+ Map.fromList kvList' `Map.union` Map.fromList classes'+ where+ kvList' = map (\(k, v) -> (k, Just v)) kvList+ classes' = map (\k -> (k, Nothing)) classes++wrapSpanDivOfficial :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivOfficial isDiv kvc doc = Map.foldrWithKey wrap doc kvc+ where+ wrap "left" Nothing acc | isDiv = "[left]" <> acc <> "[/left]"+ wrap "center" Nothing acc | isDiv = "[center]" <> acc <> "[/center]"+ wrap "right" Nothing acc | isDiv = "[right]" <> acc <> "[/right]"+ wrap "spoiler" Nothing acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+ wrap "spoiler" (Just v) acc+ | isDiv =+ literal ("[spoiler=" <> T.filter notBracket v <> "]")+ <> acc+ <> "[/spoiler]"+ wrap "size" (Just v) acc+ | Just v' <- readMaybe @Int (T.unpack v)+ , v' > 0 =+ literal ("[size=" <> v <> "]") <> acc <> "[/size]"+ wrap "color" (Just v) acc =+ literal ("[color=" <> v <> "]") <> acc <> "[/color]"+ wrap _ _ acc = acc++wrapSpanDivSteam :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivSteam isDiv kvc doc = Map.foldrWithKey wrap doc kvc+ where+ wrap "spoiler" (Just _) acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+ wrap "spoiler" Nothing acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+ wrap _ _ acc = acc++wrapSpanDivPhpBB :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivPhpBB _ kvc doc = Map.foldrWithKey wrap doc kvc+ where+ wrap "color" (Just v) acc =+ literal ("[color=" <> v <> "]") <> acc <> "[/color]"+ wrap _ _ acc = acc++wrapSpanDivFluxBB :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivFluxBB _ kvc doc = Map.foldrWithKey wrap doc kvc+ where+ wrap "color" (Just v) acc =+ literal ("[color=" <> v <> "]") <> acc <> "[/color]"+ wrap _ _ acc = acc++wrapSpanDivHubzilla :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivHubzilla isDiv kvc doc = Map.foldrWithKey wrap doc kvc+ where+ wrap "center" Nothing acc | isDiv = "[center]" <> acc <> "[/center]"+ wrap "spoiler" Nothing acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+ wrap "spoiler" (Just v) acc+ | isDiv =+ literal ("[spoiler=" <> T.filter notBracket v <> "]")+ <> acc+ <> "[/spoiler]"+ wrap "size" (Just v) acc+ | Just v' <- readMaybe @Int (T.unpack v)+ , v' > 0 =+ literal ("[size=" <> v <> "]") <> acc <> "[/size]"+ wrap "color" (Just v) acc =+ literal ("[color=" <> v <> "]") <> acc <> "[/color]"+ wrap "font" (Just v) acc = literal ("[font=" <> v <> "]") <> acc <> "[/font]"+ wrap _ _ acc = acc++wrapSpanDivXenforo :: Bool -> Map Text (Maybe Text) -> Doc Text -> Doc Text+wrapSpanDivXenforo isDiv kvc doc = Map.foldrWithKey wrap doc kvc+ where+ wrap "left" Nothing acc | isDiv = "[left]" <> acc <> "[/left]"+ wrap "center" Nothing acc | isDiv = "[center]" <> acc <> "[/center]"+ wrap "right" Nothing acc | isDiv = "[right]" <> acc <> "[/right]"+ wrap "spoiler" _ acc | not isDiv = "[ispoiler]" <> acc <> "[/ispoiler]"+ wrap "spoiler" Nothing acc | isDiv = "[spoiler]" <> acc <> "[/spoiler]"+ wrap "spoiler" (Just v) acc+ | isDiv =+ literal ("[spoiler=" <> T.filter notBracket v <> "]")+ <> acc+ <> "[/spoiler]"+ wrap "size" (Just v) acc+ | Just v' <- readMaybe @Int (T.unpack v)+ , v' > 0 =+ literal ("[size=" <> v <> "]") <> acc <> "[/size]"+ wrap "color" (Just v) acc =+ literal ("[color=" <> v <> "]") <> acc <> "[/color]"+ wrap "font" (Just v) acc = literal ("[font=" <> v <> "]") <> acc <> "[/font]"+ wrap _ _ acc = acc++renderOrderedListFluxbb ::+ (PandocMonad m) =>+ ListAttributes ->+ [[Block]] ->+ RR m (Doc Text)+renderOrderedListFluxbb (_, style, _) =+ let suffix = case style of+ LowerAlpha -> "=a"+ UpperAlpha -> "=a"+ _ -> "=1"+ in listWithTags ("[list" <> suffix <> "]") "[/list]" starListItems++renderOrderedListXenforo ::+ (PandocMonad m) =>+ ListAttributes ->+ [[Block]] ->+ RR m (Doc Text)+renderOrderedListXenforo _ =+ listWithTags "[list=1]" "[/list]" starListItems++renderLinkEmailAware ::+ (PandocMonad m) =>+ Attr ->+ [Inline] ->+ Target ->+ RR m (Doc Text)+renderLinkEmailAware attr txt target@(src, _) = do+ case T.stripPrefix "mailto:" src of+ Just address -> do+ linkText <- inlineListToBBCode txt+ let isAutoEmail = case txt of+ [Str x] -> x == address+ _ -> False+ pure $+ if isAutoEmail+ then literal "[email]" <> literal address <> "[/email]"+ else literal ("[email=" <> address <> "]") <> linkText <> "[/email]"+ Nothing -> renderLinkDefault attr txt target++renderBlockQuoteDefault :: (PandocMonad m) => [Block] -> RR m (Doc Text)+renderBlockQuoteDefault blocks = do+ contents <- blockListToBBCode blocks+ pure $ vcat ["[quote]", contents, "[/quote]"]++renderBlockQuoteFluxBB :: (PandocMonad m) => [Block] -> RR m (Doc Text)+renderBlockQuoteFluxBB blocks = do+ contents <- blockListToBBCode blocks+ isInList <- asks inList+ if isInList+ then "" <$ report (BlockNotRendered $ BlockQuote blocks)+ else pure $ vcat ["[quote]", contents, "[/quote]"]++renderHorizontalRuleDefault :: (PandocMonad m) => RR m (Doc Text)+renderHorizontalRuleDefault = pure "* * *"++renderHorizontalRuleHR :: (PandocMonad m) => RR m (Doc Text)+renderHorizontalRuleHR = pure "[hr]"++renderLineBlockDefault :: (PandocMonad m) => [[Inline]] -> RR m (Doc Text)+renderLineBlockDefault inliness = vcat <$> mapM inlineListToBBCode inliness++renderParaDefault :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderParaDefault inlines = inlineListToBBCode inlines++renderSuperscriptDefault :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderSuperscriptDefault = inlineListToBBCode++renderSubscriptDefault :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderSubscriptDefault = inlineListToBBCode++renderSmallCapsDefault :: (PandocMonad m) => [Inline] -> RR m (Doc Text)+renderSmallCapsDefault = inlineListToBBCode++renderCiteDefault ::+ (PandocMonad m) => [Citation] -> [Inline] -> RR m (Doc Text)+renderCiteDefault _ = inlineListToBBCode++renderNoteDefault :: (PandocMonad m) => [Block] -> RR m (Doc Text)+renderNoteDefault blocks = do+ -- NOTE: no BBCode flavor has native syntax for footnotes.+ newN <- gets (succ . Seq.length)+ contents <- blockListToBBCode blocks+ let pointer = "(" <> tshow newN <> ")"+ let contents' = literal pointer <> space <> contents+ modify (|> contents')+ pure $ literal pointer++renderFigureDefault ::+ (PandocMonad m) => Attr -> Caption -> [Block] -> RR m (Doc Text)+renderFigureDefault _ (Caption _ caption) blocks = do+ caption' <- blockListToBBCode caption+ contents <- blockListToBBCode blocks+ pure $ contents $$ caption'++renderQuotedDefault ::+ (PandocMonad m) => QuoteType -> [Inline] -> RR m (Doc Text)+renderQuotedDefault typ inlines = do+ let quote = case typ of SingleQuote -> "'"; DoubleQuote -> "\""+ contents <- inlineListToBBCode inlines+ pure $ mconcat [quote, contents, quote]++renderMathDefault :: (PandocMonad m) => MathType -> Text -> RR m (Doc Text)+renderMathDefault typ math = case typ of+ InlineMath ->+ inlineToBBCode $+ Code ("", ["latex"], []) ("$" <> math <> "$")+ DisplayMath ->+ blockToBBCode $+ CodeBlock ("", ["latex"], []) ("$$" <> math <> "$$")++{- | Format documentation: <https://www.bbcode.org/reference.php>++There is no such thing as «Official» bbcode format, nonetheless this spec+implements what is described on bbcode.org, which is a reasonable base that can+be extended/contracted as needed.+-}+officialSpec :: FlavorSpec+officialSpec =+ FlavorSpec+ { renderOrderedList = renderOrderedListOfficial+ , renderBulletList = renderBulletListOfficial+ , renderDefinitionList = renderDefinitionListDefault+ , renderHeader = renderHeaderDefault+ , renderTable = renderTableDefault+ , renderLink = renderLinkEmailAware+ , renderCodeBlock = renderCodeBlockDefault+ , renderInlineCode = renderInlineCodeLiteral+ , renderStrikeout = renderStrikeoutDefault+ , renderBlockQuote = renderBlockQuoteDefault+ , renderHorizontalRule = renderHorizontalRuleDefault+ , renderLineBlock = renderLineBlockDefault+ , renderPara = renderParaDefault+ , renderSuperscript = renderSuperscriptDefault+ , renderSubscript = renderSubscriptDefault+ , renderSmallCaps = renderSmallCapsDefault+ , renderCite = renderCiteDefault+ , renderNote = renderNoteDefault+ , renderFigure = renderFigureDefault+ , renderMath = renderMathDefault+ , renderQuoted = renderQuotedDefault+ , renderImage = renderImageDefault+ , wrapSpanDiv = wrapSpanDivOfficial+ }++{- | Format documentation: <https://steamcommunity.com/comment/ForumTopic/formattinghelp>++Used at: <https://steamcommunity.com/discussions/forum>++Quirks:++- There seems to be no way to show external images on steam.+ https://steamcommunity.com/sharedfiles/filedetails/?id=2807121939 shows [img]+ and [previewimg] can (could?) be used to show images, although it is likely+ reserved for steam urls only.+-}+steamSpec :: FlavorSpec+steamSpec =+ officialSpec+ { renderOrderedList = renderOrderedListSteam+ , renderHeader = renderHeaderSteam+ , renderLink = renderLinkDefault+ , renderInlineCode = renderInlineCodeNoParse+ , renderStrikeout = renderStrikeoutSteam+ , renderImage = renderImageOmit+ , wrapSpanDiv = wrapSpanDivSteam+ , renderHorizontalRule = renderHorizontalRuleHR+ }++{- | Format documentation: <https://www.phpbb.com/community/help/bbcode>++Used at: <https://www.phpbb.com/community>++Quirks:++- PhpBB docs don't mention strikeout support, but their+ [support forum](https://www.phpbb.com/community) does support it.+- Same for named code blocks.+- @[email=example\@example.com]the email[/url]@ is a valid use of [email]+ tag on the phpBB community forum despite not being in the docs.+-}+phpbbSpec :: FlavorSpec+phpbbSpec =+ officialSpec+ { renderTable = renderTableOmit+ , renderImage = renderImagePhpBB+ , wrapSpanDiv = wrapSpanDivPhpBB+ }++{- | Format documentation: <https://web.archive.org/web/20210623155046/https://fluxbb.org/forums/help.php#bbcode>++Used at: https://bbs.archlinux.org+-}+fluxbbSpec :: FlavorSpec+fluxbbSpec =+ officialSpec+ { renderOrderedList = renderOrderedListFluxbb+ , renderCodeBlock = renderCodeBlockSimple+ , renderTable = renderTableOmit+ , renderBlockQuote = renderBlockQuoteFluxBB+ , renderImage = renderImageFluxBB+ , wrapSpanDiv = wrapSpanDivFluxBB+ }++{- | Format documentation: <https://hubzilla.org/help/member/bbcode>++Used at: <https://hub.netzgemeinde.eu> (see [other hubs](https://hubzilla.org/pubsites))++Quirks:++- If link target is not a URI, it simply points to https://$BASEURL/ when+ rendered by a hub.+-}+hubzillaSpec :: FlavorSpec+hubzillaSpec =+ officialSpec+ { renderOrderedList = renderOrderedListHubzilla+ , renderBulletList = renderBulletListHubzilla+ , renderDefinitionList = renderDefinitionListHubzilla+ , renderHeader = renderHeaderHubzilla+ , renderInlineCode = renderInlineCodeHubzilla+ , renderLink = renderLinkDefault+ , wrapSpanDiv = wrapSpanDivHubzilla+ , renderHorizontalRule = renderHorizontalRuleHR+ }++{- | Format documentation: <https://www.xenfocus.com/community/help/bb-codes/>++Used at: see <https://xenforo.com/>+-}+xenforoSpec :: FlavorSpec+xenforoSpec =+ officialSpec+ { wrapSpanDiv = wrapSpanDivXenforo+ , renderHeader = renderHeaderXenforo+ , renderInlineCode = renderInlineCodeXenforo+ , renderHorizontalRule = renderHorizontalRuleHR+ , renderOrderedList = renderOrderedListXenforo+ , renderImage = renderImageXenforo+ }
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.BibTeX- Copyright : Copyright (C) 2021-2022 John MacFarlane+ Copyright : Copyright (C) 2021-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -57,5 +57,3 @@ case writerTemplate opts of Nothing -> main Just tpl -> renderTemplate tpl context--
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.Blaze- Copyright : Copyright (C) 2021-2022 John MacFarlane+ Copyright : Copyright (C) 2021-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -0,0 +1,173 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Writers.ChunkedHTML+ Copyright : Copyright (C) 2023 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to "chunked" HTML (a folder of+linked HTML documents, split by sections.+-}+module Text.Pandoc.Writers.ChunkedHTML (+ writeChunkedHTML+ ) where+import Text.Pandoc.Definition+import Text.Pandoc.Options (WriterOptions(..))+import Text.Pandoc.Shared (stringify, tshow)+import Text.Pandoc.Class (PandocMonad, getPOSIXTime, runPure,+ fetchItem, insertMedia, getMediaBag)+import Text.Pandoc.MediaBag (mediaItems)+import qualified Data.ByteString.Lazy as BL+import Text.Pandoc.Chunks (splitIntoChunks, Chunk(..), ChunkedDoc(..),+ SecInfo(..), tocToList)+import Text.Pandoc.URI (isURI)+import Data.Text (Text)+import Data.Tree+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+import Text.Pandoc.Writers.HTML (writeHtml5String)+import Codec.Archive.Zip (Entry, addEntryToArchive, emptyArchive, toEntry,+ fromArchive)+import qualified Data.Map as M+import Text.DocTemplates (Context(..), Val(..))+import Text.DocLayout (literal)+import Text.Pandoc.Writers.Shared (defField)+import Data.Aeson (toJSON, encode)+import System.FilePath (isRelative, normalise)+import Data.List (isInfixOf)+import Text.Pandoc.Walk (walkM)+import Text.Pandoc.Builder (setMeta)+import Text.Pandoc.Templates (compileTemplate, WithDefaultPartials(..))+import Control.Monad.Except (throwError)+import Text.Pandoc.Error++-- | Splits document into HTML chunks, dividing them by section,+-- and returns a zip archive of a folder of files.+writeChunkedHTML :: PandocMonad m+ => WriterOptions -> Pandoc -> m BL.ByteString+writeChunkedHTML opts (Pandoc meta blocks) = do+ walkM addMedia (Pandoc meta blocks)+ epochtime <- floor <$> getPOSIXTime+ let toMediaEntry (fp, _mt, bs) = toEntry fp epochtime bs+ mediaEntries <- map toMediaEntry . mediaItems <$> getMediaBag+ let chunkedDoc = splitIntoChunks (writerChunkTemplate opts)+ True+ (Just 1)+ (writerSplitLevel opts)+ (Pandoc meta blocks)+ let topChunk =+ Chunk+ { chunkHeading = docTitle meta+ , chunkId = "top"+ , chunkLevel = 0+ , chunkNumber = 0+ , chunkSectionNumber = Nothing+ , chunkPath = "index.html"+ , chunkUp = Nothing+ , chunkPrev = Nothing+ , chunkNext = case chunkedChunks chunkedDoc of+ [] -> Nothing+ (x:_) -> Just x+ , chunkUnlisted = True+ , chunkContents = mempty+ }++ let chunks = map (\x -> case chunkUp x of+ Nothing -> x{ chunkUp = Just topChunk }+ _ -> x)+ $ case chunkedChunks chunkedDoc of+ [] -> []+ (x:xs) -> x{ chunkPrev = Just topChunk } : xs++ let Node secinfo secs = chunkedTOC chunkedDoc+ let tocTree = Node secinfo{ secTitle = docTitle meta,+ secPath = "index.html" } secs+ let tree = buildTOC opts tocTree+ renderedTOC <- writeHtml5String opts{ writerTemplate = Nothing }+ (Pandoc nullMeta [tree])+ -- see #8915 -- we need to set the math variable in the top chunk:+ res <- runWithDefaultPartials $ compileTemplate "mathvar" "$math$"+ mathVar <- case res of+ Left e -> throwError $ PandocTemplateError (T.pack e)+ Right t -> return t+ tocMathVariable <- writeHtml5String opts{ writerTemplate = Just mathVar }+ (Pandoc meta (tree:blocks))+ let opts' = opts{ writerVariables =+ defField "table-of-contents" renderedTOC+ . defField "math" tocMathVariable+ $ writerVariables opts }+ entries <- mapM (chunkToEntry opts' meta topChunk) (topChunk : chunks)+ let sitemap = toEntry "sitemap.json" epochtime+ (encode $ toJSON $ tocTreeToContext tocTree)+ let archive = foldr addEntryToArchive emptyArchive+ (sitemap : entries ++ mediaEntries)+ return $ fromArchive archive+++-- We include in the zip only local media that is in the working directory+-- or below.+addMedia :: PandocMonad m => Inline -> m Inline+addMedia il@(Image _ _ (src,_))+ | not (isURI src)+ , fp <- normalise (T.unpack src)+ , isRelative fp+ , not (".." `isInfixOf` fp) = do+ (bs, mbMime) <- fetchItem (T.pack fp)+ insertMedia fp mbMime (BL.fromStrict bs)+ return il+addMedia il = return il++buildTOC :: WriterOptions -> Tree SecInfo -> Block+buildTOC opts = tocToList (writerNumberSections opts) (writerTOCDepth opts)++chunkToEntry :: PandocMonad m+ => WriterOptions -> Meta -> Chunk -> Chunk -> m Entry+chunkToEntry opts meta topChunk chunk = do+ html <- writeHtml5String opts' (Pandoc meta' blocks)+ epochtime <- floor <$> getPOSIXTime+ let htmlLBS = BL.fromStrict $ TE.encodeUtf8 html+ return $ toEntry (chunkPath chunk) epochtime htmlLBS+ where+ opts' = opts{ writerVariables =+ addContextVars opts' topChunk chunk $ writerVariables opts }+ meta' = setMeta "pagetitle" (MetaString (stringify $ chunkHeading chunk)) meta+ blocks = chunkContents chunk++tocTreeToContext :: Tree SecInfo -> Context Text+tocTreeToContext (Node secinfo subs) =+ Context $ M.fromList+ [ ("section", MapVal $ secInfoToContext secinfo)+ , ("subsections", ListVal $ map (MapVal . tocTreeToContext) subs)+ ]++secInfoToContext :: SecInfo -> Context Text+secInfoToContext sec =+ Context $ M.fromList+ [ ("title", SimpleVal $ literal $ stringify $ secTitle sec)+ , ("number", maybe NullVal (SimpleVal . literal) (secNumber sec))+ , ("id", SimpleVal $ literal $ secId sec)+ , ("path", SimpleVal $ literal $ secPath sec)+ , ("level", SimpleVal $ literal $ tshow $ secLevel sec)+ ]++addContextVars+ :: WriterOptions -> Chunk -> Chunk -> Context Text -> Context Text+addContextVars opts topChunk chunk context =+ maybe id (defField "next" . navlinks) (chunkNext chunk)+ . maybe id (defField "previous" . navlinks) (chunkPrev chunk)+ . maybe id (defField "up" . navlinks) (chunkUp chunk)+ . maybe id (defField "top" . navlinks) (if chunk == topChunk+ then Nothing+ else Just topChunk)+ . defField "toc" (chunk == topChunk && writerTableOfContents opts)+ $ context+ where+ navlinks ch = toMapVal [("url", formatPath ch), ("title", formatHeading ch)]+ toMapVal = MapVal . Context . M.fromList+ formatPath = SimpleVal . literal . T.pack . chunkPath+ formatHeading ch = SimpleVal . literal . either (const "") id . runPure $+ writeHtml5String opts{ writerTemplate = Nothing }+ (Pandoc nullMeta [Plain $ chunkHeading ch])
@@ -1,6 +1,6 @@ {- | Module : Text.Pandoc.Writers.CommonMark- Copyright : Copyright (C) 2015-2022 John MacFarlane+ Copyright : Copyright (C) 2015-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -14,4 +14,3 @@ module Text.Pandoc.Writers.CommonMark (writeCommonMark) where import Text.Pandoc.Writers.Markdown (writeCommonMark)-
@@ -4,7 +4,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Writers.ConTeXt- Copyright : Copyright (C) 2007-2022 John MacFarlane+ Copyright : Copyright (C) 2007-2025 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -14,37 +14,47 @@ Conversion of 'Pandoc' format into ConTeXt. -} module Text.Pandoc.Writers.ConTeXt ( writeConTeXt ) where+import Control.Monad (liftM, unless) import Control.Monad.State.Strict+ ( StateT, MonadState(put, get), gets, modify, evalStateT ) import Data.Char (ord, isDigit) import Data.List (intersperse) import Data.List.NonEmpty (NonEmpty ((:|))) import Data.Maybe (mapMaybe, catMaybes)+import Data.Monoid (Any (Any, getAny)) import Data.Text (Text) import qualified Data.Text as T import Network.URI (unEscapeString) import Text.Collate.Lang (Lang(..)) import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang) import Text.Pandoc.Definition+import Text.Pandoc.Highlighting+ (formatConTeXtBlock, formatConTeXtInline, highlight, styleToConTeXt) import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options import Text.DocLayout import Text.Pandoc.Shared+import Text.Pandoc.URI (isURI) import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Walk (query) import Text.Pandoc.Writers.Shared import Text.Printf (printf) import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Map.Strict as Map import qualified Text.Pandoc.Writers.AnnotatedTable as Ann data WriterState =- WriterState { stNextRef :: Int -- number of next URL reference- , stOrderedListLevel :: Int -- level of ordered list- , stOptions :: WriterOptions -- writer options- , stHasCslRefs :: Bool -- has CSL citations- , stCslHangingIndent :: Bool -- CSL hanging indent- }+ WriterState+ { stCslHangingIndent :: Bool -- CSL hanging indent+ , stHasCslRefs :: Bool -- has CSL citations+ , stHighlighting :: Bool -- has syntax-highlighted code blocks+ , stNextRef :: Int -- number of next URL reference+ , stOptions :: WriterOptions -- writer options+ , stOrderedListLevel :: Int -- level of ordered list+ , stEmphasisCommands :: Map.Map Text (Doc Text)+ } -- | Table type data Tabl = Xtb -- ^ Extreme tables@@ -60,12 +70,15 @@ -- | Convert Pandoc to ConTeXt. writeConTeXt :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeConTeXt options document =- let defaultWriterState = WriterState { stNextRef = 1- , stOrderedListLevel = 0- , stOptions = options- , stHasCslRefs = False- , stCslHangingIndent = False- }+ let defaultWriterState = WriterState+ { stCslHangingIndent = False+ , stHasCslRefs = False+ , stHighlighting = False+ , stNextRef = 1+ , stOptions = options+ , stOrderedListLevel = 0+ , stEmphasisCommands = mempty+ } in evalStateT (pandocToConTeXt options document) defaultWriterState type WM = StateT WriterState@@ -91,6 +104,8 @@ mblang <- fromBCP47 (getLang options meta) st <- get let context = defField "toc" (writerTableOfContents options)+ $ defField "lof" (writerListOfFigures options)+ $ defField "lot" (writerListOfTables options) $ defField "placelist" (mconcat . intersperse ("," :: Doc Text) $ take (writerTOCDepth options +@@ -102,6 +117,7 @@ "subsubsubsection","subsubsubsubsection"]) $ defField "body" main $ defField "layout" layoutFromMargins+ $ defField "tagging" (isEnabled Ext_tagging options) $ defField "number-sections" (writerNumberSections options) $ defField "csl-refs" (stHasCslRefs st) $ defField "csl-hanging-indent" (stCslHangingIndent st)@@ -113,6 +129,12 @@ | all isDigit (d:ds) -> resetField "papersize" (T.pack ('A':d:ds)) _ -> id)+ $ defField "emphasis-commands"+ (mconcat $ Map.elems (stEmphasisCommands st))+ $ (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@@ -165,25 +187,26 @@ -- | Convert Pandoc block element to ConTeXt. blockToConTeXt :: PandocMonad m => Block -> WM m (Doc Text)-blockToConTeXt Null = return empty blockToConTeXt (Div attr@(_,"section":_,_) (Header level _ title' : xs)) = do header' <- sectionHeader attr level title' SectionHeading footer' <- sectionFooter attr level innerContents <- blockListToConTeXt xs return $ header' $$ innerContents $$ footer'-blockToConTeXt (Plain lst) = inlineListToConTeXt lst-blockToConTeXt (SimpleFigure attr txt (src, _)) = do- capt <- inlineListToConTeXt txt- img <- inlineToConTeXt (Image attr txt (src, ""))- let (ident, _, _) = attr- label = if T.null ident- then empty- else "[]" <> brackets (literal $ toLabel ident)- return $ blankline $$ "\\placefigure" <> label <> braces capt <> img <> blankline+blockToConTeXt (Plain lst) = do+ opts <- gets stOptions+ contents <- inlineListToConTeXt lst+ return $+ if isEnabled Ext_tagging opts+ then "\\bpar{}" <> contents <> "\\epar{}"+ else contents blockToConTeXt (Para lst) = do+ opts <- gets stOptions contents <- inlineListToConTeXt lst- return $ contents <> blankline+ return $+ if isEnabled Ext_tagging opts+ then "\\bpar" $$ contents $$ "\\epar" <> blankline+ else contents <> blankline blockToConTeXt (LineBlock lns) = do let emptyToBlankline doc = if isEmpty doc then blankline@@ -194,9 +217,25 @@ blockToConTeXt (BlockQuote lst) = do contents <- blockListToConTeXt lst return $ "\\startblockquote" $$ nest 0 contents $$ "\\stopblockquote" <> blankline-blockToConTeXt (CodeBlock _ str) =- return $ flush ("\\starttyping" <> cr <> literal str <> cr <> "\\stoptyping") $$ blankline+blockToConTeXt (CodeBlock (_ident, classes, kv) str) = do+ opts <- gets stOptions+ let syntaxMap = writerSyntaxMap opts+ let attr' = ("", classes, kv)+ let unhighlighted = vcat ["\\starttyping", literal str, "\\stoptyping"]+ let highlighted =+ case highlight syntaxMap formatConTeXtBlock attr' str of+ Left msg -> do+ unless (T.null msg) $+ report (CouldNotHighlight msg)+ return unhighlighted+ Right h -> do+ modify (\s -> s{ stHighlighting = True })+ return (literal h) -- blankline because \stoptyping can't have anything after it, inc. '}'+ ($$ blankline) . flush <$>+ 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)@@ -264,7 +303,25 @@ sectionHeader attr level lst NonSectionHeading blockToConTeXt (Table attr caption colspecs thead tbody tfoot) = tableToConTeXt (Ann.toTable attr caption colspecs thead tbody tfoot)+blockToConTeXt (Figure (ident, _, _) (Caption cshort clong) body) = do+ title <- inlineListToConTeXt (blocksToInlines clong)+ list <- maybe (pure empty) inlineListToConTeXt cshort+ content <- blockListToConTeXt body + let options =+ ["reference=" <> literal (toLabel ident) | not (T.null ident)]+ ++ ["title=" <> braces title | not (isEmpty title)]+ ++ ["list=" <> braces list | not (isEmpty list)]+ let hasSubfigures = getAny $+ query (Any . \case {Figure {} -> True; _ -> False}) body+ return+ $ "\\startplacefigure" <> brackets (mconcat $ intersperse "," options)+ $$ (if hasSubfigures then "\\startfloatcombination" else empty)+ $$ content+ $$ (if hasSubfigures then "\\stopfloatcombination" else empty)+ $$ "\\stopplacefigure"+ $$ blankline+ tableToConTeXt :: PandocMonad m => Ann.Table -> WM m (Doc Text) tableToConTeXt (Ann.Table attr caption colspecs thead tbodies tfoot) = do opts <- gets stOptions@@ -309,9 +366,9 @@ ] setupCols :: [ColSpec] -> Doc Text-setupCols = vcat . map toColSetup . zip [1::Int ..]+setupCols = vcat . zipWith toColSetup [1::Int ..] where- toColSetup (i, (align, width)) =+ toColSetup i (align, width) = let opts = filter (not . isEmpty) [ case align of AlignLeft -> "align=right"@@ -512,19 +569,31 @@ isSpacey (Str (T.uncons -> Just ('\160',_))) = True isSpacey _ = False +highlightInlines :: PandocMonad m+ => Text -> (Doc Text) -> [Inline]+ -> WM m (Doc Text)+highlightInlines name style inlines = do+ opts <- gets stOptions+ contents <- inlineListToConTeXt inlines+ if not (isEnabled Ext_tagging opts)+ then return $ braces (style <> space <> contents)+ else do+ let cmd = "\\definehighlight " <> brackets (literal name) <>+ brackets ("style=" <> braces style)+ modify (\st -> st{ stEmphasisCommands =+ Map.insert name cmd (stEmphasisCommands st) })+ return $ "\\" <> literal name <> braces contents+ -- | Convert inline element to ConTeXt inlineToConTeXt :: PandocMonad m => Inline -- ^ Inline to convert -> WM m (Doc Text)-inlineToConTeXt (Emph lst) = do- contents <- inlineListToConTeXt lst- return $ braces $ "\\em " <> contents+inlineToConTeXt (Emph lst) = highlightInlines "emph" "\\em" lst+inlineToConTeXt (Strong lst) = highlightInlines "strong" "\\bf" lst+inlineToConTeXt (SmallCaps lst) = highlightInlines "smallcaps" "\\setsmallcaps" lst inlineToConTeXt (Underline lst) = do contents <- inlineListToConTeXt lst return $ "\\underbar" <> braces contents-inlineToConTeXt (Strong lst) = do- contents <- inlineListToConTeXt lst- return $ braces $ "\\bf " <> contents inlineToConTeXt (Strikeout lst) = do contents <- inlineListToConTeXt lst return $ "\\overstrikes" <> braces contents@@ -534,14 +603,31 @@ inlineToConTeXt (Subscript lst) = do contents <- inlineListToConTeXt lst return $ "\\low" <> braces contents-inlineToConTeXt (SmallCaps lst) = do- contents <- inlineListToConTeXt lst- return $ braces $ "\\sc " <> contents-inlineToConTeXt (Code _ str) | not ('{' `elemText` str || '}' `elemText` str) =- return $ "\\type" <> braces (literal str)-inlineToConTeXt (Code _ str) = do+inlineToConTeXt (Code (_ident, classes, _kv) str) = do+ let rawCode =+ pure . literal $+ case typeDelim str of+ Just (open, close) ->+ "\\type" <> (open `T.cons` str) `T.snoc` close+ Nothing ->+ "\\type[escape=yes]{" <>+ (T.replace "{" "/BTEX\\letteropenbrace /ETEX" .+ T.replace "}" "/BTEX\\letterclosebrace /ETEX" $+ str) `T.snoc` '}' opts <- gets stOptions- return $ "\\mono" <> braces (literal $ stringToConTeXt opts str)+ let syntaxMap = writerSyntaxMap opts+ let attr' = ("", classes, [])+ let highlightCode =+ case highlight syntaxMap formatConTeXtInline attr' str of+ Left msg -> do+ unless (T.null msg) $ report (CouldNotHighlight msg)+ rawCode+ Right h -> do+ modify (\st -> st{ stHighlighting = True })+ return (text (T.unpack h))+ case writerHighlightMethod opts of+ Skylighting _ | not (null classes) -> highlightCode+ _ -> rawCode inlineToConTeXt (Quoted SingleQuote lst) = do contents <- inlineListToConTeXt lst return $ "\\quote" <> braces contents@@ -613,9 +699,9 @@ dims = if null dimList then empty else brackets $ mconcat (intersperse "," dimList)- clas = if null cls- then empty- else brackets $ literal $ toLabel $ head cls+ clas = case cls of+ [] -> empty+ (cl:_) -> brackets $ literal $ toLabel cl -- Use / for path separators on Windows; see #4918 fixPathSeparators = T.map $ \c -> case c of '\\' -> '/'@@ -624,7 +710,7 @@ if isURI src then src else T.pack $ unEscapeString $ T.unpack src- return $ braces $ "\\externalfigure" <> brackets (literal src') <> dims <> clas+ return $ braces $ "\\externalfigure" <> brackets (literal src') <> clas <> dims inlineToConTeXt (Note contents) = do contents' <- blockListToConTeXt contents let codeBlock x@(CodeBlock _ _) = [x]@@ -661,20 +747,18 @@ opts <- gets stOptions contents <- inlineListToConTeXt lst levelText <- sectionLevelToText opts (ident,classes,kvs) hdrLevel secenv- let ident' = if T.null ident- then empty- else "reference=" <> braces (literal (toLabel ident))- let contents' = if isEmpty contents- then empty- else "title=" <> braces contents- let options = if isEmpty keys || isEmpty levelText- then empty- else brackets keys- where keys = hcat $ intersperse "," $- filter (not . isEmpty) [contents', ident']+ let optsList = mconcat . filter (not . null) $+ [ ["title=" <> braces contents | not (isEmpty contents)]+ , ["reference=" <> braces (literal (toLabel ident)) | not (T.null ident)]+ , ["number=no" | "unnumbered" `elem` classes]+ , ["incrementnumber=no" | "unnumbered" `elem` classes]+ ] let starter = case secenv of SectionHeading -> "\\start" NonSectionHeading -> "\\"+ let options = if null optsList || isEmpty levelText+ then empty+ else brackets $ hcat (intersperse "," optsList) return $ starter <> levelText <> options <> blankline -- | Craft the section footer@@ -689,8 +773,9 @@ => WriterOptions -> Attr -> Int -> HeadingType -> WM m (Doc Text) sectionLevelToText opts (_,classes,_) hdrLevel headingType = do+ let unlisted = "unlisted" `elem` classes let semanticSection shift = do- let (section, chapter) = if "unnumbered" `elem` classes+ let (section, chapter) = if unlisted then (literal "subject", literal "title") else (literal "section", literal "chapter") return $ case hdrLevel + shift of@@ -704,11 +789,24 @@ TopLevelPart -> semanticSection (-2) TopLevelChapter -> semanticSection (-1) TopLevelSection -> semanticSection 0- TopLevelDefault -> return . literal $- case headingType of- SectionHeading -> "sectionlevel"- NonSectionHeading -> ""+ TopLevelDefault -> if unlisted+ then semanticSection 0+ else return . literal $+ case headingType of+ SectionHeading -> "sectionlevel"+ NonSectionHeading -> "" +-- | Finds a pair of symbols that can be used as delimiters.+typeDelim :: Text -> Maybe (Char, Char)+typeDelim t =+ let delimChars = "{\"'`()-+=%,.:;"+ go delims '}' = go delims '{'+ go delims c = T.filter (/= c) delims+ in case fmap fst . T.uncons $ T.foldl' go delimChars t of+ Just '{' -> Just ('{', '}')+ Just c -> Just (c, c)+ Nothing -> Nothing+ fromBCP47 :: PandocMonad m => Maybe Text -> WM m (Maybe Text) fromBCP47 mbs = fromBCP47' <$> toLang mbs @@ -734,7 +832,6 @@ fromBCP47' (Just (Lang "el" _ _ _ _ _)) = Just "gr" fromBCP47' (Just (Lang "eu" _ _ _ _ _)) = Just "ba" fromBCP47' (Just (Lang "he" _ _ _ _ _)) = Just "il"-fromBCP47' (Just (Lang "jp" _ _ _ _ _)) = Just "ja" fromBCP47' (Just (Lang "uk" _ _ _ _ _)) = Just "ua" fromBCP47' (Just (Lang "vi" _ _ _ _ _)) = Just "vn" fromBCP47' (Just (Lang "zh" _ _ _ _ _)) = Just "cn"
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.CslJson- Copyright : Copyright (C) 2020-2022 John MacFarlane+ Copyright : Copyright (C) 2020-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -71,7 +71,8 @@ fromInline Space = CslText " " fromInline SoftBreak = CslText " " fromInline LineBreak = CslText "\n"-fromInline (Math _ t) = CslText t+fromInline (Math InlineMath t) = CslText $ "$" <> t <> "$"+fromInline (Math DisplayMath t) = CslText $ "$$" <> t <> "$$" fromInline (RawInline _ _) = CslEmpty fromInline (Link _ ils _) = fromInlines ils fromInline (Image _ ils _) = fromInlines ils
@@ -1,58 +0,0 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Writers.Custom- Copyright : 2012-2022 John MacFarlane,- License : GNU GPL, version 2 or above- Maintainer : John MacFarlane <jgm@berkeley.edu>--Conversion of 'Pandoc' documents to custom markup using-a Lua writer.--}-module Text.Pandoc.Writers.Custom ( writeCustom ) where-import Control.Exception-import Control.Monad ((<=<))-import Data.Maybe (fromMaybe)-import Data.Text (Text)-import HsLua-import Control.Monad.IO.Class (MonadIO)-import Text.Pandoc.Class (PandocMonad, findFileWithDataFallback)-import Text.Pandoc.Definition (Pandoc (..))-import Text.Pandoc.Lua (Global (..), runLua, setGlobals)-import Text.Pandoc.Options (WriterOptions)--import qualified Text.Pandoc.Lua.Writer.Classic as Classic---- | Convert Pandoc to custom markup.-writeCustom :: (PandocMonad m, MonadIO m)- => FilePath -> WriterOptions -> Pandoc -> m Text-writeCustom luaFile opts doc = do- luaFile' <- fromMaybe luaFile <$> findFileWithDataFallback "writers" luaFile- either throw pure <=< runLua $ do- setGlobals [ PANDOC_DOCUMENT doc- , PANDOC_SCRIPT_FILE luaFile'- , PANDOC_WRITER_OPTIONS opts- ]- dofileTrace luaFile' >>= \case- OK -> pure ()- _ -> throwErrorAsException- -- Most classic writers contain code that throws an error if a global- -- is not present. This would break our check for the existence of a- -- "Writer" function. We resort to raw access for that reason, but- -- could also catch the error instead.- let rawgetglobal x = do- pushglobaltable- pushName x- rawget (nth 2) <* remove (nth 2) -- remove global table-- rawgetglobal "Writer" >>= \case- TypeNil -> do- pop 1 -- remove nil- Classic.runCustom opts doc- _ -> do- -- Writer on top of the stack. Call it with document and writer- -- options as arguments.- push doc- push opts- callTrace 2 1- forcePeek $ peekText top
@@ -0,0 +1,300 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{- |+ Module : Text.Pandoc.Writers.Djot+ Copyright : Copyright (C) 2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' format into Djot markup (<https://djot.net>).+-}+module Text.Pandoc.Writers.Djot (+ writeDjot+ ) where+import Text.Pandoc.Definition+import Text.Pandoc.Logging+import Text.Pandoc.Class ( PandocMonad , report )+import Text.Pandoc.Options ( WriterOptions(..), WrapOption(..))+import Data.Text (Text)+import Data.Set (Set)+import qualified Data.Set as Set+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as B8+import Data.List (intersperse)+import qualified Data.Text as T+import qualified Data.Map as M+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Writers.Shared ( metaToContext, defField, toLegacyTable )+import Text.Pandoc.Shared (isTightList, tshow, stringify, onlySimpleTableCells,+ makeSections)+import Text.DocLayout+import Text.DocTemplates (renderTemplate)++import Control.Monad.State (StateT(..), gets, modify)+import Control.Monad (zipWithM, when)+import Data.Maybe (fromMaybe)+import qualified Djot.AST as D+import Djot (renderDjot, RenderOptions(..), toIdentifier)+import Text.Pandoc.UTF8 (fromText)++-- | Convert Pandoc to Djot.+writeDjot :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeDjot opts (Pandoc meta blocks) = do+ let colwidth = if writerWrapText opts == WrapAuto+ then Just $ writerColumns opts+ else Nothing+ let ropts = RenderOptions{ preserveSoftBreaks =+ writerWrapText opts == WrapPreserve }+ metadata <- metaToContext opts+ (fmap (renderDjot ropts) . bodyToDjot opts)+ (fmap (chomp . renderDjot ropts) . bodyToDjot opts .+ (:[]) . Plain)+ meta+ main <- renderDjot ropts <$>+ bodyToDjot opts (makeSections False Nothing blocks)+ let context = defField "body" main metadata+ return $ render colwidth $+ case writerTemplate opts of+ Nothing -> main+ Just tpl -> renderTemplate tpl context++data DjotState =+ DjotState+ { footnotes :: D.NoteMap+ , references :: D.ReferenceMap+ , autoReferences :: D.ReferenceMap+ , autoIds :: Set B.ByteString+ , options :: WriterOptions }++bodyToDjot :: PandocMonad m => WriterOptions -> [Block] -> m D.Doc+bodyToDjot opts bls = do+ (bs, st) <- runStateT (blocksToDjot bls)+ (DjotState mempty mempty mempty mempty opts)+ let D.ReferenceMap autos = autoReferences st+ let D.ReferenceMap refs = references st+ pure $ D.Doc{ D.docBlocks = bs+ , D.docFootnotes = footnotes st+ , D.docReferences = D.ReferenceMap $ M.difference refs autos+ , D.docAutoReferences = D.ReferenceMap autos+ , D.docAutoIdentifiers = autoIds st+ }++blocksToDjot :: PandocMonad m => [Block] -> StateT DjotState m D.Blocks+blocksToDjot = fmap mconcat . mapM blockToDjot++blockToDjot :: PandocMonad m => Block -> StateT DjotState m D.Blocks+blockToDjot (Para ils) = D.para <$> inlinesToDjot ils+blockToDjot (Plain ils) = D.para <$> inlinesToDjot ils+blockToDjot (LineBlock ls) =+ D.para . mconcat . intersperse D.hardBreak <$> mapM inlinesToDjot ls+blockToDjot (CodeBlock attr@(_,_,kvs) t) = do+ let lang = fromMaybe mempty $ lookup "lang" kvs+ pure $ D.addAttr (toDjotAttr attr)+ <$> D.codeBlock (fromText lang) (fromText t)+blockToDjot (RawBlock (Format f) t) =+ pure $ D.rawBlock (D.Format (fromText f)) (fromText t)+blockToDjot (BlockQuote bls) = D.blockQuote <$> blocksToDjot bls+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)+ (Header lev (_,hcls,hkvs) ils : bls)) = do+ ilsBs <- D.inlinesToByteString <$> inlinesToDjot ils+ let ident' = toIdentifier ilsBs+ let label = D.normalizeLabel ilsBs+ let autoid = UTF8.toText ident' == ident+ when autoid $+ modify $ \st -> st{ autoIds = Set.insert ident' (autoIds st) }+ modify $ \st -> st{ autoReferences = D.insertReference label+ (B8.cons '#' ident', mempty) (autoReferences st) }+ fmap+ (D.addAttr (toDjotAttr (if autoid then "" else ident,+ filter (/= "section") cls,+ 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+ (toDjotAttr (ident,cls,filter (\(k,_) -> k /= "wrapper") kvs)))+ <$> blocksToDjot bls+ | otherwise+ = fmap (D.addAttr (toDjotAttr attr)) . D.div <$> blocksToDjot bls+blockToDjot (BulletList items) =+ D.bulletList spacing <$> mapM blocksToDjot items+ where+ spacing = if isTightList items then D.Tight else D.Loose+blockToDjot (OrderedList (start, sty, delim) items) =+ D.orderedList listAttr spacing <$> mapM blocksToDjot items+ where+ spacing = if isTightList items then D.Tight else D.Loose+ listAttr = D.OrderedListAttributes {+ D.orderedListStyle =+ case sty of+ DefaultStyle -> D.Decimal+ Example -> D.Decimal+ Decimal -> D.Decimal+ LowerRoman -> D.RomanLower+ UpperRoman -> D.RomanUpper+ LowerAlpha -> D.LetterLower+ UpperAlpha -> D.LetterUpper,+ D.orderedListDelim =+ case delim of+ DefaultDelim -> D.RightPeriod+ Period -> D.RightPeriod+ OneParen -> D.RightParen+ TwoParens -> D.LeftRightParen,+ D.orderedListStart = start }+blockToDjot (DefinitionList items) =+ D.definitionList spacing <$> mapM toDLItem items+ where+ spacing = if isTightList (map (concat . snd) items)+ then D.Tight+ else D.Loose+ toDLItem (term, defs) = do+ term' <- inlinesToDjot term+ def' <- mconcat <$> mapM blocksToDjot defs+ pure (term', def')+blockToDjot (Figure attr (Caption _ capt) bls) = do+ content <- blocksToDjot bls+ caption <- fmap (D.addAttr (D.Attr [("class","caption")])) . D.div <$>+ blocksToDjot capt+ pure $ fmap (D.addAttr (toDjotAttr attr)) $ D.div $ content <> caption+blockToDjot (Table attr capt' colspecs thead tbodies tfoot) = do+ let (capt, aligns, _, headRow, bodyRows) =+ toLegacyTable capt' colspecs thead tbodies tfoot+ if onlySimpleTableCells (headRow : bodyRows)+ then do+ let alignToAlign al = case al of+ AlignDefault -> D.AlignDefault+ AlignLeft -> D.AlignLeft+ AlignRight -> D.AlignRight+ AlignCenter -> D.AlignCenter+ let defAligns = map alignToAlign aligns+ let cellToCell isHeader bls al =+ D.Cell (if isHeader then D.HeadCell else D.BodyCell) al+ <$> case bls of+ [Para ils] -> inlinesToDjot ils+ [Plain ils] -> inlinesToDjot ils+ [] -> pure mempty+ bs -> do+ mapM_ (report . BlockNotRendered) bs+ pure $ D.str "((omitted))"+ let rowToRow isHeader cells = zipWithM (cellToCell isHeader) cells defAligns+ hrows <- if null headRow+ then pure []+ else (:[]) <$> rowToRow True headRow+ rows <- mapM (rowToRow False) bodyRows+ caption <- case capt of+ [] -> pure Nothing+ _ -> Just . D.Caption . D.para <$> inlinesToDjot capt+ pure $ D.addAttr (toDjotAttr attr) <$> D.table caption (hrows <> rows)+ else do -- table can't be represented as a simple pipe table, use list+ tableList <- D.bulletList D.Loose <$> mapM+ (fmap (D.bulletList D.Loose) . mapM blocksToDjot)+ (headRow:bodyRows)+ pure $ D.addAttr (D.Attr [("class", "table")]) <$> tableList++inlinesToDjot :: PandocMonad m => [Inline] -> StateT DjotState m D.Inlines+inlinesToDjot = fmap mconcat . mapM inlineToDjot++inlineToDjot :: PandocMonad m => Inline -> StateT DjotState m D.Inlines+inlineToDjot (Str t) = pure $ D.str (fromText t)+inlineToDjot Space = pure $ D.str " "+inlineToDjot SoftBreak = pure D.softBreak+inlineToDjot LineBreak = pure D.hardBreak+inlineToDjot (Emph ils) = D.emph <$> inlinesToDjot ils+inlineToDjot (Underline ils) =+ fmap (D.addAttr (D.Attr [("class","underline")])) . D.span_+ <$> inlinesToDjot ils+inlineToDjot (Strong ils) = D.strong <$> inlinesToDjot ils+inlineToDjot (Strikeout ils) = D.delete <$> inlinesToDjot ils+inlineToDjot (Subscript ils) = D.subscript <$> inlinesToDjot ils+inlineToDjot (Superscript ils) = D.superscript <$> inlinesToDjot ils+inlineToDjot (Span ("",["mark"],[]) ils) = D.highlight <$> inlinesToDjot ils+inlineToDjot (Span attr@(ident,cls,kvs) ils)+ | Just "1" <- lookup "wrapper" kvs+ = fmap (D.addAttr+ (toDjotAttr (ident,cls,filter (\(k,_) -> k /= "wrapper") kvs)))+ <$> inlinesToDjot ils+ | otherwise+ = fmap (D.addAttr (toDjotAttr attr)) . D.span_ <$> inlinesToDjot ils+inlineToDjot (SmallCaps ils) =+ fmap (D.addAttr (D.Attr [("class","smallcaps")])) . D.span_+ <$> inlinesToDjot ils+inlineToDjot (Quoted DoubleQuote ils) = D.doubleQuoted <$> inlinesToDjot ils+inlineToDjot (Quoted SingleQuote ils) = D.singleQuoted <$> inlinesToDjot ils+inlineToDjot (Cite _cs ils) = inlinesToDjot ils+inlineToDjot (Code attr t) =+ pure $ D.addAttr (toDjotAttr attr) <$> D.verbatim (fromText t)+inlineToDjot (Math mt t) =+ pure $ (if mt == InlineMath+ then D.inlineMath+ else D.displayMath) (fromText t)+inlineToDjot (RawInline (Format f) t) =+ pure $ D.rawInline (D.Format (fromText f)) (fromText t)+inlineToDjot (Link attr ils (src,tit)) = do+ opts <- gets options+ description <- inlinesToDjot ils+ let ilstring = stringify ils+ let autolink = ilstring == src+ let email = ("mailto:" <> ilstring) == src+ let removeClass name (ident, cls, kvs) = (ident, filter (/= name) cls, kvs)+ let attr' = D.Attr [("title", fromText tit) | not (T.null tit)] <>+ toDjotAttr ( (if autolink+ then removeClass "uri"+ else id) .+ (if email+ then removeClass "email"+ else id) $ attr)+ case () of+ _ | autolink -> pure $ D.addAttr attr' <$> D.urlLink (fromText ilstring)+ | email -> pure $ D.addAttr attr' <$> D.emailLink (fromText ilstring)+ | writerReferenceLinks opts+ -> do refs@(D.ReferenceMap m) <- gets references+ autoRefs <- gets autoReferences+ let lab' = D.inlinesToByteString description+ lab <- case D.lookupReference lab' (refs <> autoRefs) of+ Just _ -> pure lab'+ Nothing -> do+ let refnum = M.size m + 1+ let lab = fromText $ tshow refnum+ modify $ \st -> st{ references =+ D.insertReference lab+ (fromText src, attr') refs }+ pure lab+ pure $ D.addAttr attr' <$> D.link description (D.Reference lab)+ | otherwise+ -> pure $ D.addAttr attr' <$> D.link description (D.Direct (fromText src))+inlineToDjot (Image attr ils (src,tit)) = do+ opts <- gets options+ description <- inlinesToDjot ils+ let attr' = D.Attr [("title", fromText tit) | not (T.null tit)] <>+ toDjotAttr attr+ if writerReferenceLinks opts+ then do+ refs@(D.ReferenceMap m) <- gets references+ let refnum = M.size m + 1+ let lab = fromText $ tshow refnum+ modify $ \st -> st{ references =+ D.insertReference lab+ (fromText src, attr') refs }+ pure $ D.addAttr attr' <$> D.image description (D.Reference lab)+ else pure $ D.addAttr attr' <$> D.image description (D.Direct (fromText src))+inlineToDjot (Note bs) = do+ notes@(D.NoteMap m) <- gets footnotes+ let notenum = M.size m + 1+ let lab = fromText $ tshow notenum+ contents <- blocksToDjot bs+ modify $ \st -> st{ footnotes = D.insertNote lab contents notes }+ pure $ D.footnoteReference lab++toDjotAttr :: (Text, [Text], [(Text, Text)]) -> D.Attr+toDjotAttr (ident, classes, kvs) =+ D.Attr $ [("id", fromText ident) | not (T.null ident)] +++ [("class", fromText (T.unwords classes)) | not (null classes)] +++ map (\(k,v) -> (fromText k, fromText v)) kvs
@@ -0,0 +1,525 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{- |+ Module : Text.Pandoc.Writers.DocBook+ Copyright : Copyright (C) 2006-2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to DocBook XML.+-}+module Text.Pandoc.Writers.DocBook ( writeDocBook4, writeDocBook5 ) where+import Control.Monad.Reader+import Data.Generics (everywhere, mkT)+import Data.List (nub, partition)+import Data.Maybe (isNothing)+import Data.Monoid (All (..))+import Data.Text (Text)+import qualified Data.Text as T+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class.PandocMonad (PandocMonad, report)+import Text.Pandoc.Definition+import Text.Pandoc.Highlighting (languages, languagesByExtension)+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.DocLayout+import Text.Pandoc.Shared+import Text.Pandoc.URI+import Text.Pandoc.Templates (renderTemplate)+import Text.Pandoc.Writers.Shared+import Text.Pandoc.Walk+import Text.Pandoc.Writers.Math+import Text.Pandoc.XML+import Text.TeXMath+import qualified Text.XML.Light as Xml++data DocBookVersion = DocBook4 | DocBook5+ deriving (Eq, Show)++type DB = ReaderT DocBookVersion++-- | Get level of the top-level headers based on the configured top-level division.+-- The header level can then be used to determine appropriate DocBook element+-- for each subdivision associated with a header.+-- The numbering here follows LaTeX's internal numbering+getStartLvl :: WriterOptions -> Int+getStartLvl opts =+ case writerTopLevelDivision opts of+ TopLevelPart -> -1+ TopLevelChapter -> 0+ TopLevelSection -> 1+ TopLevelDefault -> 1++-- | Get correct name for the id attribute based on DocBook version.+-- DocBook 4 used custom id attribute but DocBook 5 adopted the xml:id specification.+-- https://www.w3.org/TR/xml-id/+idName :: DocBookVersion -> Text+idName DocBook5 = "xml:id"+idName DocBook4 = "id"++-- | Convert list of authors to a docbook <author> section+authorToDocBook :: PandocMonad m => WriterOptions -> [Inline] -> DB m B.Inlines+authorToDocBook opts name' = do+ name <- render Nothing <$> inlinesToDocBook opts name'+ let colwidth = if writerWrapText opts == WrapAuto+ then Just $ writerColumns opts+ else Nothing+ return $ B.rawInline "docbook" $+ render colwidth $ inTags True "personname" [] $+ if T.any (== ',') name+ then -- last name first+ let (lastname, rest) = T.break (==',') name+ firstname = triml rest in+ inTagsSimple "firstname" (literal $ escapeStringForXML firstname) <>+ inTagsSimple "surname" (literal $ escapeStringForXML lastname)+ else -- last name last+ let namewords = T.words name+ lengthname = length namewords+ (firstname, lastname) = case lengthname of+ 0 -> ("","")+ 1 -> ("", name)+ n -> (T.unwords (take (n-1) namewords), last namewords)+ in inTagsSimple "firstname" (literal $ escapeStringForXML firstname) $$+ inTagsSimple "surname" (literal $ escapeStringForXML lastname)++writeDocBook4 :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeDocBook4 opts d =+ runReaderT (writeDocBook opts d) DocBook4++writeDocBook5 :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeDocBook5 opts d =+ runReaderT (writeDocBook opts d) DocBook5++-- | Convert Pandoc document to string in DocBook format.+writeDocBook :: PandocMonad m => WriterOptions -> Pandoc -> DB m Text+writeDocBook opts doc = do+ let Pandoc meta blocks = ensureValidXmlIdentifiers doc+ let colwidth = if writerWrapText opts == WrapAuto+ then Just $ writerColumns opts+ else Nothing+ let startLvl = getStartLvl opts+ let fromBlocks = blocksToDocBook opts .+ makeSections False (Just startLvl)+ auths' <- mapM (authorToDocBook opts) $ docAuthors meta+ let meta' = B.setMeta "author" auths' meta+ metadata <- metaToContext opts+ fromBlocks+ (inlinesToDocBook opts)+ meta'+ main <- fromBlocks blocks+ let context = defField "body" main+ $ defField "mathml" (case writerHTMLMathMethod opts of+ MathML -> True+ _ -> False) metadata+ return $ render colwidth $+ (if writerPreferAscii opts then fmap toEntities else id) $+ case writerTemplate opts of+ Nothing -> main+ Just tpl -> renderTemplate tpl context++-- | Convert a list of Pandoc blocks to DocBook.+blocksToDocBook :: PandocMonad m => WriterOptions -> [Block] -> DB m (Doc Text)+blocksToDocBook opts = fmap vcat . mapM (blockToDocBook opts)++-- | Auxiliary function to convert Plain block to Para.+plainToPara :: Block -> Block+plainToPara (Plain x) = Para x+plainToPara x = x++-- | Convert a list of pairs of terms and definitions into a list of+-- DocBook varlistentrys.+deflistItemsToDocBook :: PandocMonad m+ => WriterOptions -> [([Inline],[[Block]])]+ -> DB m (Doc Text)+deflistItemsToDocBook opts items =+ vcat <$> mapM (uncurry (deflistItemToDocBook opts)) items++-- | Convert a term and a list of blocks into a DocBook varlistentry.+deflistItemToDocBook :: PandocMonad m+ => WriterOptions -> [Inline] -> [[Block]]+ -> DB m (Doc Text)+deflistItemToDocBook opts term defs = do+ term' <- inlinesToDocBook opts term+ def' <- blocksToDocBook opts $ concatMap (map plainToPara) defs+ return $ inTagsIndented "varlistentry" $+ inTagsIndented "term" term' $$+ inTagsIndented "listitem" def'++-- | Convert a list of lists of blocks to a list of DocBook list items.+listItemsToDocBook :: PandocMonad m+ => WriterOptions -> [[Block]] -> DB m (Doc Text)+listItemsToDocBook opts items = vcat <$> mapM (listItemToDocBook opts) items++-- | Convert a list of blocks into a DocBook list item.+listItemToDocBook :: PandocMonad m+ => WriterOptions -> [Block] -> DB m (Doc Text)+listItemToDocBook opts item =+ inTagsIndented "listitem" <$> blocksToDocBook opts (map plainToPara item)++imageToDocBook :: WriterOptions -> Attr -> Text -> Doc Text+imageToDocBook _ attr src = selfClosingTag "imagedata" $+ ("fileref", src) : idAndRole attr <> dims+ where+ dims = go Width "width" <> go Height "depth"+ go dir dstr = case dimension dir attr of+ Just a -> [(dstr, tshow a)]+ Nothing -> []++-- | Convert a Pandoc block element to DocBook.+blockToDocBook :: PandocMonad m => WriterOptions -> Block -> DB m (Doc Text)+-- Add ids to paragraphs in divs with ids - this is needed for+-- pandoc-citeproc to get link anchors in bibliographies:+blockToDocBook opts (Div (id',"section":_classes,divattrs)+ (Header lvl (_,hclasses,_) ils : xs)) = do+ version <- ask+ -- DocBook doesn't allow sections with no content, so insert some if needed+ let bs = if null xs+ then [Para []]+ else xs+ tag = case lvl of+ -1 -> "part"+ 0 -> "chapter"+ n | n >= 1 && n <= 5 -> if version == DocBook5+ then "section"+ else "sect" <> tshow n+ _ -> "simplesect"+ idAttr = [(idName version, writerIdentifierPrefix opts <> id') | not (T.null id')]+ -- We want to add namespaces to the root (top-level) element.+ nsAttr = if version == DocBook5 && lvl == getStartLvl opts && isNothing (writerTemplate opts)+ -- Though, DocBook 4 does not support namespaces and+ -- standalone documents will include them in the template.+ then [("xmlns", "http://docbook.org/ns/docbook")+ ,("xmlns:xlink", "http://www.w3.org/1999/xlink")]+ else []++ -- Populate miscAttr with Header.Attr.attributes, filtering out non-valid DocBook section attributes, id, and xml:id+ -- Also enrich the role attribute with certain class tokens+ miscAttr = enrichRole (filter (isSectionAttr version) divattrs) hclasses+ attribs = nsAttr <> idAttr <> miscAttr+ title' <- inlinesToDocBook opts ils+ contents <- blocksToDocBook opts bs+ return $ inTags True tag attribs $ inTagsSimple "title" title' $$ contents+blockToDocBook opts (Div (ident,classes,_) bs) = do+ version <- ask+ let identAttribs = [(idName version, ident) | not (T.null ident)]+ admonitions = ["caution","danger","important","note","tip","warning"]+ case classes of+ (l:_) | l `elem` admonitions -> do+ let (mTitleBs, bodyBs) =+ case bs of+ -- Matches AST produced by the DocBook reader → Markdown writer → Markdown reader chain.+ (Div (_,["title"],_) [Para ts] : rest) -> (Just (inlinesToDocBook opts ts), rest)+ -- Matches AST produced by the DocBook reader.+ (Div (_,["title"],_) ts : rest) -> (Just (blocksToDocBook opts ts), rest)+ _ -> (Nothing, bs)+ admonitionTitle <- case mTitleBs of+ Nothing -> return mempty+ -- id will be attached to the admonition so let’s pass empty identAttrs.+ Just titleBs -> inTagsSimple "title" <$> titleBs+ admonitionBody <- handleDivBody [] bodyBs+ return (inTags True l identAttribs (admonitionTitle $$ admonitionBody))+ _ -> handleDivBody identAttribs bs+ where+ handleDivBody identAttribs [Para lst] =+ if hasLineBreaks lst+ then flush . nowrap . inTags False "literallayout" identAttribs+ <$> inlinesToDocBook opts lst+ else inTags True "para" identAttribs <$> inlinesToDocBook opts lst+ handleDivBody identAttribs bodyBs = do+ contents <- blocksToDocBook opts (map plainToPara bodyBs)+ return $+ (if null identAttribs+ then mempty+ else selfClosingTag "anchor" identAttribs) $$ contents+blockToDocBook _ h@Header{} = do+ -- should be handled by Div section above, except inside lists/blockquotes+ report $ BlockNotRendered h+ return empty+blockToDocBook opts (Plain lst) = inlinesToDocBook opts lst+blockToDocBook opts (Para lst)+ | hasLineBreaks lst = flush . nowrap . inTagsSimple "literallayout"+ <$> inlinesToDocBook opts lst+ | otherwise = inTagsIndented "para" <$> inlinesToDocBook opts lst+blockToDocBook opts (LineBlock lns) =+ inTags False "literallayout" [] . vcat <$> mapM (inlinesToDocBook opts) lns+blockToDocBook opts (BlockQuote blocks) =+ inTagsIndented "blockquote" <$> blocksToDocBook opts blocks+blockToDocBook opts (CodeBlock (_,classes,_) str) = return $+ literal ("<programlisting" <> lang <> ">") <> cr <>+ flush (literal (escapeStringForXML str) <> cr <> literal "</programlisting>")+ where lang = case langs of+ [] -> ""+ (l:_) -> " language=\"" <> escapeStringForXML l <> "\""+ syntaxMap = writerSyntaxMap opts+ isLang l = T.toLower l `elem` map T.toLower (languages syntaxMap)+ langsFrom s = if isLang s+ then [s]+ else (languagesByExtension syntaxMap) . T.toLower $ s+ langs = concatMap langsFrom classes+blockToDocBook opts (BulletList lst) = do+ let attribs = [("spacing", "compact") | isTightList lst]+ inTags True "itemizedlist" attribs <$> listItemsToDocBook opts lst+blockToDocBook _ (OrderedList _ []) = return empty+blockToDocBook opts (OrderedList (start, numstyle, _) items) = do+ let numeration = case numstyle of+ DefaultStyle -> []+ Decimal -> [("numeration", "arabic")]+ Example -> [("numeration", "arabic")]+ UpperAlpha -> [("numeration", "upperalpha")]+ LowerAlpha -> [("numeration", "loweralpha")]+ UpperRoman -> [("numeration", "upperroman")]+ LowerRoman -> [("numeration", "lowerroman")]+ 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+blockToDocBook _ b@(RawBlock f str)+ | f == "docbook" = return $ literal str -- raw XML block+ | f == "html" = do+ version <- ask+ if version == DocBook5+ then return empty -- No html in DocBook5+ else return $ literal str -- allow html for backwards+ -- compatibility+ | otherwise = do+ report $ BlockNotRendered b+ return empty+blockToDocBook _ HorizontalRule = return empty -- not semantic+blockToDocBook opts (Table _ blkCapt specs thead tbody tfoot) = do+ let (caption, aligns, widths, headers, rows) =+ toLegacyTable blkCapt specs thead tbody tfoot+ captionDoc <- if null caption+ then return empty+ else inTagsSimple "title" <$>+ inlinesToDocBook opts caption+ let tableType = if isEmpty captionDoc then "informaltable" else "table"+ percent w = tshow (truncate (100*w) :: Integer) <> "*"+ coltags = vcat $ zipWith (\w al -> selfClosingTag "colspec"+ ([("colwidth", percent w) | w > 0] <>+ [("align", alignmentToString al)])) widths aligns+ head' <- if all null headers+ then return empty+ else inTagsIndented "thead" <$> tableRowToDocBook opts headers+ body' <- inTagsIndented "tbody" . vcat <$>+ mapM (tableRowToDocBook opts) rows+ return $ inTagsIndented tableType $ captionDoc $$+ inTags True "tgroup" [("cols", tshow (length aligns))] (+ coltags $$ head' $$ body')+blockToDocBook opts (Figure attr capt@(Caption _ caption) body) = do+ -- TODO: probably better to handle nested figures as mediaobject+ let isAcceptable = \case+ Table {} -> All False+ Figure {} -> All False+ _ -> All True+ if not . getAll $ query isAcceptable body+ -- Fallback to a div if the content cannot be included in a figure+ then blockToDocBook opts $ figureDiv attr capt body+ else do+ title <- inlinesToDocBook opts (blocksToInlines caption)+ let toMediaobject = \case+ Plain [Image imgAttr inlns (src, _)] -> do+ alt <- inlinesToDocBook opts inlns+ pure $ inTagsIndented "mediaobject" (+ inTagsIndented "imageobject"+ (imageToDocBook opts imgAttr src) $$+ if isEmpty alt+ then empty+ else inTagsSimple "textobject" (inTagsSimple "phrase" alt))+ _ -> ask >>= \case+ DocBook4 -> pure mempty -- docbook4 requires media+ DocBook5 -> blocksToDocBook opts body+ mediaobjects <- mapM toMediaobject body+ return $+ if isEmpty $ mconcat mediaobjects+ then mempty -- figures must have at least some content+ else inTagsIndented "figure" $+ inTagsSimple "title" title $$+ mconcat mediaobjects++alignmentToString :: Alignment -> Text+alignmentToString alignment = case alignment of+ AlignLeft -> "left"+ AlignRight -> "right"+ AlignCenter -> "center"+ AlignDefault -> "left"++tableRowToDocBook :: PandocMonad m+ => WriterOptions+ -> [[Block]]+ -> DB m (Doc Text)+tableRowToDocBook opts cols =+ inTagsIndented "row" . vcat <$> mapM (tableItemToDocBook opts) cols++tableItemToDocBook :: PandocMonad m+ => WriterOptions+ -> [Block]+ -> DB m (Doc Text)+tableItemToDocBook opts item =+ inTags True "entry" [] . vcat <$> mapM (blockToDocBook opts) item++-- | Convert a list of inline elements to DocBook.+inlinesToDocBook :: PandocMonad m => WriterOptions -> [Inline] -> DB m (Doc Text)+inlinesToDocBook opts lst = hcat <$> mapM (inlineToDocBook opts) lst++-- | Convert an inline element to DocBook.+inlineToDocBook :: PandocMonad m => WriterOptions -> Inline -> DB m (Doc Text)+inlineToDocBook _ (Str str) = return $ literal $ escapeStringForXML str+inlineToDocBook opts (Emph lst) =+ inTagsSimple "emphasis" <$> inlinesToDocBook opts lst+inlineToDocBook opts (Underline lst) =+ inTags False "emphasis" [("role", "underline")] <$> inlinesToDocBook opts lst+inlineToDocBook opts (Strong lst) =+ inTags False "emphasis" [("role", "strong")] <$> inlinesToDocBook opts lst+inlineToDocBook opts (Strikeout lst) =+ inTags False "emphasis" [("role", "strikethrough")] <$>+ inlinesToDocBook opts lst+inlineToDocBook opts (Superscript lst) =+ inTagsSimple "superscript" <$> inlinesToDocBook opts lst+inlineToDocBook opts (Subscript lst) =+ inTagsSimple "subscript" <$> inlinesToDocBook opts lst+inlineToDocBook opts (SmallCaps lst) =+ inTags False "emphasis" [("role", "smallcaps")] <$>+ inlinesToDocBook opts lst+inlineToDocBook opts (Quoted _ lst) =+ inTagsSimple "quote" <$> inlinesToDocBook opts lst+inlineToDocBook opts (Cite _ lst) =+ inlinesToDocBook opts lst+inlineToDocBook opts (Span (ident,_,_) ils) = do+ version <- ask+ ((if T.null ident+ then mempty+ else selfClosingTag "anchor" [(idName version, ident)]) <>) <$>+ inlinesToDocBook opts ils+inlineToDocBook _ (Code _ str) =+ return $ inTagsSimple "literal" $ literal (escapeStringForXML str)+inlineToDocBook opts (Math t str)+ | isMathML (writerHTMLMathMethod opts) = do+ res <- convertMath writeMathML t str+ case res of+ Right r -> return $ inTagsSimple tagtype+ $ literal $ T.pack $ Xml.ppcElement conf+ $ fixNS+ $ removeAttr r+ Left il -> inlineToDocBook opts il+ | otherwise =+ texMathToInlines t str >>= inlinesToDocBook opts+ where tagtype = case t of+ InlineMath -> "inlineequation"+ DisplayMath -> "informalequation"+ conf = Xml.useShortEmptyTags (const False) Xml.defaultConfigPP+ removeAttr e = e{ Xml.elAttribs = [] }+ fixNS' qname = qname{ Xml.qPrefix = Just "mml" }+ fixNS = everywhere (mkT fixNS')+inlineToDocBook _ il@(RawInline f x)+ | f == "html" || f == "docbook" = return $ literal x+ | otherwise = do+ report $ InlineNotRendered il+ return empty+inlineToDocBook _ LineBreak = return $ literal "\n"+-- currently ignore, would require the option to add custom+-- styles to the document+inlineToDocBook _ Space = return space+-- because we use \n for LineBreak, we can't do soft breaks:+inlineToDocBook _ SoftBreak = return space+inlineToDocBook opts (Link attr txt (src, _))+ | Just email <- T.stripPrefix "mailto:" src =+ let emailLink = inTagsSimple "email" $ literal $+ escapeStringForXML email+ in case txt of+ [Str s] | escapeURI s == email -> return emailLink+ _ -> do contents <- inlinesToDocBook opts txt+ return $ contents <+>+ char '(' <> emailLink <> char ')'+ | otherwise = do+ version <- ask+ (if "#" `T.isPrefixOf` src+ then let tag = if null txt then "xref" else "link"+ in inTags False tag $+ ("linkend", writerIdentifierPrefix opts <> T.drop 1 src) :+ idAndRole attr+ else if version == DocBook5+ then inTags False "link" $ ("xlink:href", src) : idAndRole attr+ else inTags False "ulink" $ ("url", src) : idAndRole attr )+ <$> inlinesToDocBook opts txt+inlineToDocBook opts (Image attr ils (src, tit)) = return $+ let titleDoc = if T.null tit+ then empty+ else inTagsIndented "objectinfo" $+ inTagsSimple "title" (literal $ escapeStringForXML tit)+ alt = if null ils+ then mempty+ else inTagsIndented "textobject" $+ inTagsSimple "phrase" $ literal (stringify ils)+ in inTagsIndented "inlinemediaobject" $+ inTagsIndented "imageobject"+ (titleDoc $$ imageToDocBook opts attr src)+ $$ alt+inlineToDocBook opts (Note contents) =+ inTagsIndented "footnote" <$> blocksToDocBook opts contents++isMathML :: HTMLMathMethod -> Bool+isMathML MathML = True+isMathML _ = False++idAndRole :: Attr -> [(Text, Text)]+idAndRole (id',cls,_) = ident <> role+ where+ ident = [("id", id') | not (T.null id')]+ role = [("role", T.unwords cls) | not (null cls)]++-- Used in blockToDocBook for Header (section) to create or extend+-- the role attribute with candidate class tokens+enrichRole :: [(Text, Text)] -> [Text] -> [(Text, Text)]+enrichRole mattrs cls = [("role", T.unwords roles) | roles /= []] <> nonRole+ where+ (roleAttr, nonRole) = partition (\(key, _v) -> key == "role") mattrs+ roles = nub $ filter (`elem` cand) cls <> map snd roleAttr+ cand = ["unnumbered"]++isSectionAttr :: DocBookVersion -> (Text, Text) -> Bool+isSectionAttr _ ("label",_) = True+isSectionAttr _ ("status",_) = True+isSectionAttr DocBook5 ("annotations",_) = True+isSectionAttr DocBook5 ("dir","ltr") = True+isSectionAttr DocBook5 ("dir","rtl") = True+isSectionAttr DocBook5 ("dir","lro") = True+isSectionAttr DocBook5 ("dir","rlo") = True+isSectionAttr _ ("remap",_) = True+isSectionAttr _ ("revisionflag","changed") = True+isSectionAttr _ ("revisionflag","added") = True+isSectionAttr _ ("revisionflag","deleted") = True+isSectionAttr _ ("revisionflag","off") = True+isSectionAttr _ ("role",_) = True+isSectionAttr DocBook5 ("version",_) = True+isSectionAttr DocBook5 ("xml:base",_) = True+isSectionAttr DocBook5 ("xml:lang",_) = True+isSectionAttr _ ("xreflabel",_) = True+isSectionAttr DocBook5 ("linkend",_) = True+isSectionAttr DocBook5 ("linkends",_) = True+isSectionAttr DocBook5 ("xlink:actuate",_) = True+isSectionAttr DocBook5 ("xlink:arcrole",_) = True+isSectionAttr DocBook5 ("xlink:from",_) = True+isSectionAttr DocBook5 ("xlink:href",_) = True+isSectionAttr DocBook5 ("xlink:label",_) = True+isSectionAttr DocBook5 ("xlink:role",_) = True+isSectionAttr DocBook5 ("xlink:show",_) = True+isSectionAttr DocBook5 ("xlink:title",_) = True+isSectionAttr DocBook5 ("xlink:to",_) = True+isSectionAttr DocBook5 ("xlink:type",_) = True+isSectionAttr DocBook4 ("arch",_) = True+isSectionAttr DocBook4 ("condition",_) = True+isSectionAttr DocBook4 ("conformance",_) = True+isSectionAttr DocBook4 ("lang",_) = True+isSectionAttr DocBook4 ("os",_) = True+isSectionAttr DocBook4 ("revision",_) = True+isSectionAttr DocBook4 ("security",_) = True+isSectionAttr DocBook4 ("vendor",_) = True+isSectionAttr _ (_,_) = False
@@ -1,498 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PatternGuards #-}-{- |- Module : Text.Pandoc.Writers.Docbook- Copyright : Copyright (C) 2006-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Conversion of 'Pandoc' documents to Docbook XML.--}-module Text.Pandoc.Writers.Docbook ( writeDocbook4, writeDocbook5 ) where-import Control.Monad.Reader-import Data.Generics (everywhere, mkT)-import Data.Maybe (isNothing)-import Data.Monoid (Any (..))-import Data.Text (Text)-import qualified Data.Text as T-import qualified Text.Pandoc.Builder as B-import Text.Pandoc.Class.PandocMonad (PandocMonad, report)-import Text.Pandoc.Definition-import Text.Pandoc.Highlighting (languages, languagesByExtension)-import Text.Pandoc.ImageSize-import Text.Pandoc.Logging-import Text.Pandoc.Options-import Text.DocLayout-import Text.Pandoc.Shared-import Text.Pandoc.Templates (renderTemplate)-import Text.Pandoc.Writers.Shared-import Text.Pandoc.Walk-import Text.Pandoc.Writers.Math-import Text.Pandoc.XML-import Text.TeXMath-import qualified Text.XML.Light as Xml--data DocBookVersion = DocBook4 | DocBook5- deriving (Eq, Show)--type DB = ReaderT DocBookVersion---- | Get level of the top-level headers based on the configured top-level division.--- The header level can then be used to determine appropriate DocBook element--- for each subdivision associated with a header.--- The numbering here follows LaTeX's internal numbering-getStartLvl :: WriterOptions -> Int-getStartLvl opts =- case writerTopLevelDivision opts of- TopLevelPart -> -1- TopLevelChapter -> 0- TopLevelSection -> 1- TopLevelDefault -> 1---- | Get correct name for the id attribute based on DocBook version.--- DocBook 4 used custom id attribute but DocBook 5 adopted the xml:id specification.--- https://www.w3.org/TR/xml-id/-idName :: DocBookVersion -> Text-idName DocBook5 = "xml:id"-idName DocBook4 = "id"---- | Convert list of authors to a docbook <author> section-authorToDocbook :: PandocMonad m => WriterOptions -> [Inline] -> DB m B.Inlines-authorToDocbook opts name' = do- name <- render Nothing <$> inlinesToDocbook opts name'- let colwidth = if writerWrapText opts == WrapAuto- then Just $ writerColumns opts- else Nothing- return $ B.rawInline "docbook" $- render colwidth $ inTags True "personname" [] $- if T.any (== ',') name- then -- last name first- let (lastname, rest) = T.break (==',') name- firstname = triml rest in- inTagsSimple "firstname" (literal $ escapeStringForXML firstname) <>- inTagsSimple "surname" (literal $ escapeStringForXML lastname)- else -- last name last- let namewords = T.words name- lengthname = length namewords- (firstname, lastname) = case lengthname of- 0 -> ("","")- 1 -> ("", name)- n -> (T.unwords (take (n-1) namewords), last namewords)- in inTagsSimple "firstname" (literal $ escapeStringForXML firstname) $$- inTagsSimple "surname" (literal $ escapeStringForXML lastname)--writeDocbook4 :: PandocMonad m => WriterOptions -> Pandoc -> m Text-writeDocbook4 opts d =- runReaderT (writeDocbook opts d) DocBook4--writeDocbook5 :: PandocMonad m => WriterOptions -> Pandoc -> m Text-writeDocbook5 opts d =- runReaderT (writeDocbook opts d) DocBook5---- | Convert Pandoc document to string in Docbook format.-writeDocbook :: PandocMonad m => WriterOptions -> Pandoc -> DB m Text-writeDocbook opts doc = do- let Pandoc meta blocks = ensureValidXmlIdentifiers doc- let colwidth = if writerWrapText opts == WrapAuto- then Just $ writerColumns opts- else Nothing- let startLvl = getStartLvl opts- let fromBlocks = blocksToDocbook opts .- makeSections False (Just startLvl)- auths' <- mapM (authorToDocbook opts) $ docAuthors meta- let meta' = B.setMeta "author" auths' meta- metadata <- metaToContext opts- fromBlocks- (inlinesToDocbook opts)- meta'- main <- fromBlocks blocks- let context = defField "body" main- $ defField "mathml" (case writerHTMLMathMethod opts of- MathML -> True- _ -> False) metadata- return $ render colwidth $- (if writerPreferAscii opts then fmap toEntities else id) $- case writerTemplate opts of- Nothing -> main- Just tpl -> renderTemplate tpl context---- | Convert a list of Pandoc blocks to Docbook.-blocksToDocbook :: PandocMonad m => WriterOptions -> [Block] -> DB m (Doc Text)-blocksToDocbook opts = fmap vcat . mapM (blockToDocbook opts)---- | Auxiliary function to convert Plain block to Para.-plainToPara :: Block -> Block-plainToPara (Plain x) = Para x-plainToPara x = x---- | Convert a list of pairs of terms and definitions into a list of--- Docbook varlistentrys.-deflistItemsToDocbook :: PandocMonad m- => WriterOptions -> [([Inline],[[Block]])] -> DB m (Doc Text)-deflistItemsToDocbook opts items =- vcat <$> mapM (uncurry (deflistItemToDocbook opts)) items---- | Convert a term and a list of blocks into a Docbook varlistentry.-deflistItemToDocbook :: PandocMonad m- => WriterOptions -> [Inline] -> [[Block]] -> DB m (Doc Text)-deflistItemToDocbook opts term defs = do- term' <- inlinesToDocbook opts term- def' <- blocksToDocbook opts $ concatMap (map plainToPara) defs- return $ inTagsIndented "varlistentry" $- inTagsIndented "term" term' $$- inTagsIndented "listitem" def'---- | Convert a list of lists of blocks to a list of Docbook list items.-listItemsToDocbook :: PandocMonad m => WriterOptions -> [[Block]] -> DB m (Doc Text)-listItemsToDocbook opts items = vcat <$> mapM (listItemToDocbook opts) items---- | Convert a list of blocks into a Docbook list item.-listItemToDocbook :: PandocMonad m => WriterOptions -> [Block] -> DB m (Doc Text)-listItemToDocbook opts item =- inTagsIndented "listitem" <$> blocksToDocbook opts (map plainToPara item)--imageToDocbook :: WriterOptions -> Attr -> Text -> Doc Text-imageToDocbook _ attr src = selfClosingTag "imagedata" $- ("fileref", src) : idAndRole attr <> dims- where- dims = go Width "width" <> go Height "depth"- go dir dstr = case dimension dir attr of- Just a -> [(dstr, tshow a)]- Nothing -> []---- | Convert a Pandoc block element to Docbook.-blockToDocbook :: PandocMonad m => WriterOptions -> Block -> DB m (Doc Text)-blockToDocbook _ Null = return empty--- Add ids to paragraphs in divs with ids - this is needed for--- pandoc-citeproc to get link anchors in bibliographies:-blockToDocbook opts (Div (id',"section":_,_) (Header lvl (_,_,attrs) ils : xs)) = do- version <- ask- -- Docbook doesn't allow sections with no content, so insert some if needed- let bs = if null xs- then [Para []]- else xs- tag = case lvl of- -1 -> "part"- 0 -> "chapter"- n | n >= 1 && n <= 5 -> if version == DocBook5- then "section"- else "sect" <> tshow n- _ -> "simplesect"- idAttr = [(idName version, writerIdentifierPrefix opts <> id') | not (T.null id')]- -- We want to add namespaces to the root (top-level) element.- nsAttr = if version == DocBook5 && lvl == getStartLvl opts && isNothing (writerTemplate opts)- -- Though, DocBook 4 does not support namespaces and- -- standalone documents will include them in the template.- then [("xmlns", "http://docbook.org/ns/docbook"),("xmlns:xlink", "http://www.w3.org/1999/xlink")]- else []-- -- Populate miscAttr with Header.Attr.attributes, filtering out non-valid DocBook section attributes, id, and xml:id- miscAttr = filter (isSectionAttr version) attrs- attribs = nsAttr <> idAttr <> miscAttr- title' <- inlinesToDocbook opts ils- contents <- blocksToDocbook opts bs- return $ inTags True tag attribs $ inTagsSimple "title" title' $$ contents-blockToDocbook opts (Div (ident,classes,_) bs) = do- version <- ask- let identAttribs = [(idName version, ident) | not (T.null ident)]- admonitions = ["caution","danger","important","note","tip","warning"]- case classes of- (l:_) | l `elem` admonitions -> do- let (mTitleBs, bodyBs) =- case bs of- -- Matches AST produced by the DocBook reader → Markdown writer → Markdown reader chain.- (Div (_,["title"],_) [Para ts] : rest) -> (Just (inlinesToDocbook opts ts), rest)- -- Matches AST produced by the Docbook reader.- (Div (_,["title"],_) ts : rest) -> (Just (blocksToDocbook opts ts), rest)- _ -> (Nothing, bs)- admonitionTitle <- case mTitleBs of- Nothing -> return mempty- -- id will be attached to the admonition so let’s pass empty identAttrs.- Just titleBs -> inTags False "title" [] <$> titleBs- admonitionBody <- handleDivBody [] bodyBs- return (inTags True l identAttribs (admonitionTitle $$ admonitionBody))- _ -> handleDivBody identAttribs bs- where- handleDivBody identAttribs [Para lst] =- if hasLineBreaks lst- then flush . nowrap . inTags False "literallayout" identAttribs- <$> inlinesToDocbook opts lst- else inTags True "para" identAttribs <$> inlinesToDocbook opts lst- handleDivBody identAttribs bodyBs = do- contents <- blocksToDocbook opts (map plainToPara bodyBs)- return $- (if null identAttribs- then mempty- else selfClosingTag "anchor" identAttribs) $$ contents-blockToDocbook _ h@Header{} = do- -- should be handled by Div section above, except inside lists/blockquotes- report $ BlockNotRendered h- return empty-blockToDocbook opts (Plain lst) = inlinesToDocbook opts lst--- title beginning with fig: indicates that the image is a figure-blockToDocbook opts (SimpleFigure attr txt (src, _)) = do- alt <- inlinesToDocbook opts txt- let capt = if null txt- then empty- else inTagsSimple "title" alt- return $ inTagsIndented "figure" $- capt $$- inTagsIndented "mediaobject" (- inTagsIndented "imageobject"- (imageToDocbook opts attr src) $$- inTagsSimple "textobject" (inTagsSimple "phrase" alt))-blockToDocbook opts (Para lst)- | hasLineBreaks lst = flush . nowrap . inTagsSimple "literallayout"- <$> inlinesToDocbook opts lst- | otherwise = inTagsIndented "para" <$> inlinesToDocbook opts lst-blockToDocbook opts (LineBlock lns) =- blockToDocbook opts $ linesToPara lns-blockToDocbook opts (BlockQuote blocks) =- inTagsIndented "blockquote" <$> blocksToDocbook opts blocks-blockToDocbook opts (CodeBlock (_,classes,_) str) = return $- literal ("<programlisting" <> lang <> ">") <> cr <>- flush (literal (escapeStringForXML str) <> cr <> literal "</programlisting>")- where lang = if null langs- then ""- else " language=\"" <> escapeStringForXML (head langs) <>- "\""- syntaxMap = writerSyntaxMap opts- isLang l = T.toLower l `elem` map T.toLower (languages syntaxMap)- langsFrom s = if isLang s- then [s]- else (languagesByExtension syntaxMap) . T.toLower $ s- langs = concatMap langsFrom classes-blockToDocbook opts (BulletList lst) = do- 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- let numeration = case numstyle of- DefaultStyle -> []- Decimal -> [("numeration", "arabic")]- Example -> [("numeration", "arabic")]- UpperAlpha -> [("numeration", "upperalpha")]- 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-blockToDocbook opts (DefinitionList lst) = do- let attribs = [("spacing", "compact") | isTightList $ concatMap snd lst]- inTags True "variablelist" attribs <$> deflistItemsToDocbook opts lst-blockToDocbook _ b@(RawBlock f str)- | f == "docbook" = return $ literal str -- raw XML block- | f == "html" = do- version <- ask- if version == DocBook5- then return empty -- No html in Docbook5- else return $ literal str -- allow html for backwards compatibility- | otherwise = do- report $ BlockNotRendered b- return empty-blockToDocbook _ HorizontalRule = return empty -- not semantic-blockToDocbook opts (Table _ blkCapt specs thead tbody tfoot) = do- let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot- captionDoc <- if null caption- then return empty- else inTagsIndented "title" <$>- inlinesToDocbook opts caption- let tableType = if isEmpty captionDoc then "informaltable" else "table"- percent w = tshow (truncate (100*w) :: Integer) <> "*"- coltags = vcat $ zipWith (\w al -> selfClosingTag "colspec"- ([("colwidth", percent w) | w > 0] <>- [("align", alignmentToString al)])) widths aligns- head' <- if all null headers- then return empty- else inTagsIndented "thead" <$> tableRowToDocbook opts headers- body' <- inTagsIndented "tbody" . vcat <$>- mapM (tableRowToDocbook opts) rows- return $ inTagsIndented tableType $ captionDoc $$- inTags True "tgroup" [("cols", tshow (length aligns))] (- coltags $$ head' $$ body')--hasLineBreaks :: [Inline] -> Bool-hasLineBreaks = getAny . query isLineBreak . walk removeNote- where- removeNote :: Inline -> Inline- removeNote (Note _) = Str ""- removeNote x = x- isLineBreak :: Inline -> Any- isLineBreak LineBreak = Any True- isLineBreak _ = Any False--alignmentToString :: Alignment -> Text-alignmentToString alignment = case alignment of- AlignLeft -> "left"- AlignRight -> "right"- AlignCenter -> "center"- AlignDefault -> "left"--tableRowToDocbook :: PandocMonad m- => WriterOptions- -> [[Block]]- -> DB m (Doc Text)-tableRowToDocbook opts cols =- inTagsIndented "row" . vcat <$> mapM (tableItemToDocbook opts) cols--tableItemToDocbook :: PandocMonad m- => WriterOptions- -> [Block]- -> DB m (Doc Text)-tableItemToDocbook opts item =- inTags True "entry" [] . vcat <$> mapM (blockToDocbook opts) item---- | Convert a list of inline elements to Docbook.-inlinesToDocbook :: PandocMonad m => WriterOptions -> [Inline] -> DB m (Doc Text)-inlinesToDocbook opts lst = hcat <$> mapM (inlineToDocbook opts) lst---- | Convert an inline element to Docbook.-inlineToDocbook :: PandocMonad m => WriterOptions -> Inline -> DB m (Doc Text)-inlineToDocbook _ (Str str) = return $ literal $ escapeStringForXML str-inlineToDocbook opts (Emph lst) =- inTagsSimple "emphasis" <$> inlinesToDocbook opts lst-inlineToDocbook opts (Underline lst) =- inTags False "emphasis" [("role", "underline")] <$> inlinesToDocbook opts lst-inlineToDocbook opts (Strong lst) =- inTags False "emphasis" [("role", "strong")] <$> inlinesToDocbook opts lst-inlineToDocbook opts (Strikeout lst) =- inTags False "emphasis" [("role", "strikethrough")] <$>- inlinesToDocbook opts lst-inlineToDocbook opts (Superscript lst) =- inTagsSimple "superscript" <$> inlinesToDocbook opts lst-inlineToDocbook opts (Subscript lst) =- inTagsSimple "subscript" <$> inlinesToDocbook opts lst-inlineToDocbook opts (SmallCaps lst) =- inTags False "emphasis" [("role", "smallcaps")] <$>- inlinesToDocbook opts lst-inlineToDocbook opts (Quoted _ lst) =- inTagsSimple "quote" <$> inlinesToDocbook opts lst-inlineToDocbook opts (Cite _ lst) =- inlinesToDocbook opts lst-inlineToDocbook opts (Span (ident,_,_) ils) = do- version <- ask- ((if T.null ident- then mempty- else selfClosingTag "anchor" [(idName version, ident)]) <>) <$>- inlinesToDocbook opts ils-inlineToDocbook _ (Code _ str) =- return $ inTagsSimple "literal" $ literal (escapeStringForXML str)-inlineToDocbook opts (Math t str)- | isMathML (writerHTMLMathMethod opts) = do- res <- convertMath writeMathML t str- case res of- Right r -> return $ inTagsSimple tagtype- $ literal $ T.pack $ Xml.ppcElement conf- $ fixNS- $ removeAttr r- Left il -> inlineToDocbook opts il- | otherwise =- texMathToInlines t str >>= inlinesToDocbook opts- where tagtype = case t of- InlineMath -> "inlineequation"- DisplayMath -> "informalequation"- conf = Xml.useShortEmptyTags (const False) Xml.defaultConfigPP- removeAttr e = e{ Xml.elAttribs = [] }- fixNS' qname = qname{ Xml.qPrefix = Just "mml" }- fixNS = everywhere (mkT fixNS')-inlineToDocbook _ il@(RawInline f x)- | f == "html" || f == "docbook" = return $ literal x- | otherwise = do- report $ InlineNotRendered il- return empty-inlineToDocbook _ LineBreak = return $ literal "\n"--- currently ignore, would require the option to add custom--- styles to the document-inlineToDocbook _ Space = return space--- because we use \n for LineBreak, we can't do soft breaks:-inlineToDocbook _ SoftBreak = return space-inlineToDocbook opts (Link attr txt (src, _))- | Just email <- T.stripPrefix "mailto:" src =- let emailLink = inTagsSimple "email" $ literal $- escapeStringForXML email- in case txt of- [Str s] | escapeURI s == email -> return emailLink- _ -> do contents <- inlinesToDocbook opts txt- return $ contents <+>- char '(' <> emailLink <> char ')'- | otherwise = do- version <- ask- (if "#" `T.isPrefixOf` src- then let tag = if null txt then "xref" else "link"- in inTags False tag $- ("linkend", writerIdentifierPrefix opts <> T.drop 1 src) : idAndRole attr- else if version == DocBook5- then inTags False "link" $ ("xlink:href", src) : idAndRole attr- else inTags False "ulink" $ ("url", src) : idAndRole attr )- <$> inlinesToDocbook opts txt-inlineToDocbook opts (Image attr _ (src, tit)) = return $- let titleDoc = if T.null tit- then empty- else inTagsIndented "objectinfo" $- inTagsIndented "title" (literal $ escapeStringForXML tit)- in inTagsIndented "inlinemediaobject" $ inTagsIndented "imageobject" $- titleDoc $$ imageToDocbook opts attr src-inlineToDocbook opts (Note contents) =- inTagsIndented "footnote" <$> blocksToDocbook opts contents--isMathML :: HTMLMathMethod -> Bool-isMathML MathML = True-isMathML _ = False--idAndRole :: Attr -> [(Text, Text)]-idAndRole (id',cls,_) = ident <> role- where- ident = [("id", id') | not (T.null id')]- role = [("role", T.unwords cls) | not (null cls)]--isSectionAttr :: DocBookVersion -> (Text, Text) -> Bool-isSectionAttr _ ("label",_) = True-isSectionAttr _ ("status",_) = True-isSectionAttr DocBook5 ("annotations",_) = True-isSectionAttr DocBook5 ("dir","ltr") = True-isSectionAttr DocBook5 ("dir","rtl") = True-isSectionAttr DocBook5 ("dir","lro") = True-isSectionAttr DocBook5 ("dir","rlo") = True-isSectionAttr _ ("remap",_) = True-isSectionAttr _ ("revisionflag","changed") = True-isSectionAttr _ ("revisionflag","added") = True-isSectionAttr _ ("revisionflag","deleted") = True-isSectionAttr _ ("revisionflag","off") = True-isSectionAttr _ ("role",_) = True-isSectionAttr DocBook5 ("version",_) = True-isSectionAttr DocBook5 ("xml:base",_) = True-isSectionAttr DocBook5 ("xml:lang",_) = True-isSectionAttr _ ("xreflabel",_) = True-isSectionAttr DocBook5 ("linkend",_) = True-isSectionAttr DocBook5 ("linkends",_) = True-isSectionAttr DocBook5 ("xlink:actuate",_) = True-isSectionAttr DocBook5 ("xlink:arcrole",_) = True-isSectionAttr DocBook5 ("xlink:from",_) = True-isSectionAttr DocBook5 ("xlink:href",_) = True-isSectionAttr DocBook5 ("xlink:label",_) = True-isSectionAttr DocBook5 ("xlink:role",_) = True-isSectionAttr DocBook5 ("xlink:show",_) = True-isSectionAttr DocBook5 ("xlink:title",_) = True-isSectionAttr DocBook5 ("xlink:to",_) = True-isSectionAttr DocBook5 ("xlink:type",_) = True-isSectionAttr DocBook4 ("arch",_) = True-isSectionAttr DocBook4 ("condition",_) = True-isSectionAttr DocBook4 ("conformance",_) = True-isSectionAttr DocBook4 ("lang",_) = True-isSectionAttr DocBook4 ("os",_) = True-isSectionAttr DocBook4 ("revision",_) = True-isSectionAttr DocBook4 ("security",_) = True-isSectionAttr DocBook4 ("vendor",_) = True-isSectionAttr _ (_,_) = False
@@ -3,1446 +3,853 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.Writers.Docx- Copyright : Copyright (C) 2012-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Conversion of 'Pandoc' documents to docx.--}-module Text.Pandoc.Writers.Docx ( writeDocx ) where-import Codec.Archive.Zip-import Control.Applicative ((<|>))-import Control.Monad.Except (catchError, throwError)-import Control.Monad.Reader-import Control.Monad.State.Strict-import qualified Data.ByteString.Lazy as BL-import Data.Char (isSpace, isLetter)-import Data.List (intercalate, isPrefixOf, isSuffixOf)-import Data.String (fromString)-import qualified Data.Map as M-import Data.Maybe (fromMaybe, isNothing, mapMaybe, maybeToList, isJust)-import qualified Data.Set as Set-import qualified Data.Text as T-import Data.Text (Text)-import qualified Data.Text.Lazy as TL-import Data.Time.Clock.POSIX-import Data.Digest.Pure.SHA (sha1, showDigest)-import Skylighting-import Text.Collate.Lang (renderLang)-import Text.Pandoc.Class (PandocMonad, report, toLang, translateTerm,- getMediaBag)-import Text.Pandoc.MediaBag (lookupMedia, MediaItem(..))-import qualified Text.Pandoc.Translations as Term-import qualified Text.Pandoc.Class.PandocMonad as P-import Data.Time-import Text.Pandoc.UTF8 (fromTextLazy)-import Text.Pandoc.Definition-import Text.Pandoc.Generic-import Text.Pandoc.Highlighting (highlight)-import Text.Pandoc.Error-import Text.Pandoc.ImageSize-import Text.Pandoc.Logging-import Text.Pandoc.MIME (extensionFromMimeType, getMimeType, getMimeTypeDef)-import Text.Pandoc.Options-import Text.Pandoc.Writers.Docx.StyleMap-import Text.Pandoc.Writers.Docx.Table-import Text.Pandoc.Writers.Docx.Types-import Text.Pandoc.Shared-import Text.Pandoc.Walk-import qualified Text.Pandoc.Writers.GridTable as Grid-import Text.Pandoc.Writers.Math-import Text.Pandoc.Writers.Shared-import Text.TeXMath-import Text.Pandoc.Writers.OOXML-import Text.Pandoc.XML.Light as XML-import Data.Generics (mkT, everywhere)--squashProps :: EnvProps -> [Element]-squashProps (EnvProps Nothing es) = es-squashProps (EnvProps (Just e) es) = e : es--renumIdMap :: Int -> [Element] -> M.Map Text Text-renumIdMap _ [] = M.empty-renumIdMap n (e:es)- | Just oldId <- findAttr (QName "Id" Nothing Nothing) e =- M.insert oldId ("rId" <> tshow n) (renumIdMap (n+1) es)- | otherwise = renumIdMap n es--replaceAttr :: (QName -> Bool) -> Text -> [XML.Attr] -> [XML.Attr]-replaceAttr f val = map $- \a -> if f (attrKey a) then XML.Attr (attrKey a) val else a--renumId :: (QName -> Bool) -> M.Map Text Text -> Element -> Element-renumId f renumMap e- | Just oldId <- findAttrBy f e- , Just newId <- M.lookup oldId renumMap =- let attrs' = replaceAttr f newId (elAttribs e)- in- e { elAttribs = attrs' }- | otherwise = e--renumIds :: (QName -> Bool) -> M.Map Text Text -> [Element] -> [Element]-renumIds f renumMap = map (renumId f renumMap)---- | Certain characters are invalid in XML even if escaped.--- See #1992-stripInvalidChars :: Text -> Text-stripInvalidChars = T.filter isValidChar---- | See XML reference-isValidChar :: Char -> Bool-isValidChar '\t' = True-isValidChar '\n' = True-isValidChar '\r' = True-isValidChar '\xFFFE' = False-isValidChar '\xFFFF' = False-isValidChar c = (' ' <= c && c <= '\xD7FF') || ('\xE000' <= c)--writeDocx :: (PandocMonad m)- => WriterOptions -- ^ Writer options- -> Pandoc -- ^ Document to convert- -> m BL.ByteString-writeDocx opts doc = do- let Pandoc meta blocks = walk fixDisplayMath doc- let blocks' = makeSections True Nothing blocks- let doc' = Pandoc meta blocks'-- username <- P.lookupEnv "USERNAME"- utctime <- P.getTimestamp- oldUserDataDir <- P.getUserDataDir- P.setUserDataDir Nothing- res <- P.readDefaultDataFile "reference.docx"- P.setUserDataDir oldUserDataDir- let distArchive = toArchive $ BL.fromStrict res- refArchive <- case writerReferenceDoc opts of- Just f -> toArchive <$> P.readFileLazy f- Nothing -> toArchive . BL.fromStrict <$>- P.readDataFile "reference.docx"-- parsedDoc <- parseXml refArchive distArchive "word/document.xml"- let wname f qn = qPrefix qn == Just "w" && f (qName qn)- let mbsectpr = filterElementName (wname (=="sectPr")) parsedDoc-- -- Gets the template size- let mbpgsz = mbsectpr >>= filterElementName (wname (=="pgSz"))- let mbAttrSzWidth = mbpgsz >>= lookupAttrBy ((=="w") . qName) . elAttribs-- let mbpgmar = mbsectpr >>= filterElementName (wname (=="pgMar"))- let mbAttrMarLeft = mbpgmar >>= lookupAttrBy ((=="left") . qName) . elAttribs- let mbAttrMarRight = mbpgmar >>= lookupAttrBy ((=="right") . qName) . elAttribs-- -- Get the available area (converting the size and the margins to int and- -- doing the difference- let pgContentWidth = do- w <- mbAttrSzWidth >>= safeRead- r <- mbAttrMarRight >>= safeRead- l <- mbAttrMarLeft >>= safeRead- pure $ w - r - l-- -- styles- mblang <- toLang $ getLang opts meta- -- TODO FIXME avoid this generic traversal!- -- lang is in w:docDefaults / w:rPr / w:lang- let addLang :: Element -> Element- addLang = case mblang of- Nothing -> id- Just l -> everywhere (mkT (go (renderLang l)))- where- go :: Text -> Element -> Element- go l e'- | qName (elName e') == "lang"- = e'{ elAttribs = map (setvalattr l) $ elAttribs e' }- | otherwise = e'-- setvalattr l (XML.Attr qn@(QName "val" _ _) _) = XML.Attr qn l- setvalattr _ x = x-- let stylepath = "word/styles.xml"- styledoc <- addLang <$> parseXml refArchive distArchive stylepath-- -- parse styledoc for heading styles- let styleMaps = getStyleMaps refArchive-- let tocTitle = case lookupMetaInlines "toc-title" meta of- [] -> stTocTitle defaultWriterState- ls -> ls-- let initialSt = defaultWriterState {- stStyleMaps = styleMaps- , stTocTitle = tocTitle- , stCurId = 20- }-- let isRTLmeta = case lookupMeta "dir" meta of- Just (MetaString "rtl") -> True- Just (MetaInlines [Str "rtl"]) -> True- _ -> False-- let env = defaultWriterEnv {- envRTL = isRTLmeta- , envChangesAuthor = fromMaybe "unknown" username- , envChangesDate = T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime- , envPrintWidth = maybe 420 (`quot` 20) pgContentWidth- }--- ((contents, footnotes, comments), st) <- runStateT- (runReaderT- (writeOpenXML opts{writerWrapText = WrapNone} doc')- env)- initialSt- let epochtime = floor $ utcTimeToPOSIXSeconds utctime- let imgs = M.elems $ stImages st-- -- create entries for images in word/media/...- let toImageEntry (_,path,_,img) = toEntry ("word/" ++ path) epochtime $ toLazy img- let imageEntries = map toImageEntry imgs-- let stdAttributes =- [("xmlns:w","http://schemas.openxmlformats.org/wordprocessingml/2006/main")- ,("xmlns:m","http://schemas.openxmlformats.org/officeDocument/2006/math")- ,("xmlns:r","http://schemas.openxmlformats.org/officeDocument/2006/relationships")- ,("xmlns:o","urn:schemas-microsoft-com:office:office")- ,("xmlns:v","urn:schemas-microsoft-com:vml")- ,("xmlns:w10","urn:schemas-microsoft-com:office:word")- ,("xmlns:a","http://schemas.openxmlformats.org/drawingml/2006/main")- ,("xmlns:pic","http://schemas.openxmlformats.org/drawingml/2006/picture")- ,("xmlns:wp","http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing")]--- parsedRels <- parseXml refArchive distArchive "word/_rels/document.xml.rels"- let isHeaderNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header"- let isFooterNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"- let headers = filterElements isHeaderNode parsedRels- let footers = filterElements isFooterNode parsedRels-- let extractTarget = findAttr (QName "Target" Nothing Nothing)-- -- we create [Content_Types].xml and word/_rels/document.xml.rels- -- from scratch rather than reading from reference.docx,- -- because Word sometimes changes these files when a reference.docx is modified,- -- e.g. deleting the reference to footnotes.xml or removing default entries- -- for image content types.-- -- [Content_Types].xml- let mkOverrideNode (part', contentType') = mknode "Override"- [("PartName", T.pack part')- ,("ContentType", contentType')] ()- let mkImageOverride (_, imgpath, mbMimeType, _) =- mkOverrideNode ("/word/" <> imgpath,- fromMaybe "application/octet-stream" mbMimeType)- let mkMediaOverride imgpath =- mkOverrideNode ("/" <> imgpath, getMimeTypeDef imgpath)- let overrides = map mkOverrideNode (- [("/word/webSettings.xml",- "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml")- ,("/word/numbering.xml",- "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml")- ,("/word/settings.xml",- "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml")- ,("/word/theme/theme1.xml",- "application/vnd.openxmlformats-officedocument.theme+xml")- ,("/word/fontTable.xml",- "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml")- ,("/docProps/app.xml",- "application/vnd.openxmlformats-officedocument.extended-properties+xml")- ,("/docProps/core.xml",- "application/vnd.openxmlformats-package.core-properties+xml")- ,("/docProps/custom.xml",- "application/vnd.openxmlformats-officedocument.custom-properties+xml")- ,("/word/styles.xml",- "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml")- ,("/word/document.xml",- "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")- ,("/word/comments.xml",- "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml")- ,("/word/footnotes.xml",- "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml")- ] ++- map (\x -> (maybe "" (T.unpack . ("/word/" <>)) (extractTarget x),- "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml")) headers ++- map (\x -> (maybe "" (T.unpack . ("/word/" <>)) (extractTarget x),- "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml")) footers) ++- map mkImageOverride imgs ++- [ mkMediaOverride (eRelativePath e)- | e <- zEntries refArchive- , "word/media/" `isPrefixOf` eRelativePath e ]-- let defaultnodes = [mknode "Default"- [("Extension","xml"),("ContentType","application/xml")] (),- mknode "Default"- [("Extension","rels"),("ContentType","application/vnd.openxmlformats-package.relationships+xml")] ()]- let contentTypesDoc = mknode "Types" [("xmlns","http://schemas.openxmlformats.org/package/2006/content-types")] $ defaultnodes ++ overrides- let contentTypesEntry = toEntry "[Content_Types].xml" epochtime- $ renderXml contentTypesDoc-- -- word/_rels/document.xml.rels- let toBaseRel (url', id', target') = mknode "Relationship"- [("Type",url')- ,("Id",id')- ,("Target",target')] ()- let baserels' = map toBaseRel- [("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",- "rId1",- "numbering.xml")- ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",- "rId2",- "styles.xml")- ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",- "rId3",- "settings.xml")- ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",- "rId4",- "webSettings.xml")- ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",- "rId5",- "fontTable.xml")- ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",- "rId6",- "theme/theme1.xml")- ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",- "rId7",- "footnotes.xml")- ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",- "rId8",- "comments.xml")- ]-- let idMap = renumIdMap (length baserels' + 1) (headers ++ footers)- let renumHeaders = renumIds (\q -> qName q == "Id") idMap headers- let renumFooters = renumIds (\q -> qName q == "Id") idMap footers- let baserels = baserels' ++ renumHeaders ++ renumFooters- let toImgRel (ident,path,_,_) = mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"),("Id",T.pack ident),("Target",T.pack path)] ()- let imgrels = map toImgRel imgs- let toLinkRel (src,ident) = mknode "Relationship" [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"),("Id",ident),("Target",src),("TargetMode","External") ] ()- let linkrels = map toLinkRel $ M.toList $ stExternalLinks st- let reldoc = mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")] $ baserels ++ imgrels ++ linkrels- let relEntry = toEntry "word/_rels/document.xml.rels" epochtime- $ renderXml reldoc--- -- adjust contents to add sectPr from reference.docx- let sectpr = case mbsectpr of- Just sectpr' -> let cs = renumIds- (\q -> qName q == "id" && qPrefix q == Just "r")- idMap- (elChildren sectpr')- in- add_attrs (elAttribs sectpr') $ mknode "w:sectPr" [] cs- Nothing -> mknode "w:sectPr" [] ()-- -- let sectpr = fromMaybe (mknode "w:sectPr" [] ()) mbsectpr'- let contents' = contents ++ [Elem sectpr]- let docContents = mknode "w:document" stdAttributes- $ mknode "w:body" [] contents'---- -- word/document.xml- let contentEntry = toEntry "word/document.xml" epochtime- $ renderXml docContents-- -- footnotes- let notes = mknode "w:footnotes" stdAttributes footnotes- let footnotesEntry = toEntry "word/footnotes.xml" epochtime $ renderXml notes-- -- footnote rels- let footnoteRelEntry = toEntry "word/_rels/footnotes.xml.rels" epochtime- $ renderXml $ mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]- linkrels-- -- comments- let commentsEntry = toEntry "word/comments.xml" epochtime- $ renderXml $ mknode "w:comments" stdAttributes comments-- -- styles-- -- We only want to inject paragraph and text properties that- -- are not already in the style map. Note that keys in the stylemap- -- are normalized as lowercase.- let newDynamicParaProps = filter- (\sty -> not $ hasStyleName sty $ smParaStyle styleMaps)- (Set.toList $ stDynamicParaProps st)-- newDynamicTextProps = filter- (\sty -> not $ hasStyleName sty $ smCharStyle styleMaps)- (Set.toList $ stDynamicTextProps st)-- let newstyles = map newParaPropToOpenXml newDynamicParaProps ++- map newTextPropToOpenXml newDynamicTextProps ++- maybe [] (styleToOpenXml styleMaps) (writerHighlightStyle opts)- let styledoc' = styledoc{ elContent = elContent styledoc ++- map Elem newstyles }- let styleEntry = toEntry stylepath epochtime $ renderXml styledoc'-- -- construct word/numbering.xml- let numpath = "word/numbering.xml"- numbering <- parseXml refArchive distArchive numpath- let newNumElts = mkNumbering (stLists st)- let pandocAdded e =- case findAttrBy ((== "abstractNumId") . qName) e >>= safeRead of- Just numid -> numid >= (990 :: Int)- Nothing ->- case findAttrBy ((== "numId") . qName) e >>= safeRead of- Just numid -> numid >= (1000 :: Int)- Nothing -> False- let oldElts = filter (not . pandocAdded) $ onlyElems (elContent numbering)- let allElts = oldElts ++ newNumElts- let numEntry = toEntry numpath epochtime $ renderXml numbering{ elContent =- -- we want all the abstractNums first, then the nums,- -- otherwise things break:- [Elem e | e <- allElts- , qName (elName e) == "abstractNum" ] ++- [Elem e | e <- allElts- , qName (elName e) == "num" ] }-- let keywords = case lookupMeta "keywords" meta of- Just (MetaList xs) -> map stringify xs- _ -> []-- -- docProps/core.xml- let docPropsPath = "docProps/core.xml"- let extraCoreProps = ["subject","lang","category","description"]- let extraCorePropsMap = M.fromList $ zip extraCoreProps- ["dc:subject","dc:language","cp:category","dc:description"]- let lookupMetaString' :: Text -> Meta -> Text- lookupMetaString' key' meta' =- case key' of- "description" -> T.intercalate "_x000d_\n" (map stringify $ lookupMetaBlocks "description" meta')- key'' -> lookupMetaString key'' meta'-- let docProps = mknode "cp:coreProperties"- [("xmlns:cp","http://schemas.openxmlformats.org/package/2006/metadata/core-properties")- ,("xmlns:dc","http://purl.org/dc/elements/1.1/")- ,("xmlns:dcterms","http://purl.org/dc/terms/")- ,("xmlns:dcmitype","http://purl.org/dc/dcmitype/")- ,("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")]- $ mktnode "dc:title" [] (stringify $ docTitle meta)- : mktnode "dc:creator" [] (T.intercalate "; " (map stringify $ docAuthors meta))- : [ mktnode (M.findWithDefault "" k extraCorePropsMap) [] (lookupMetaString' k meta)- | k <- M.keys (unMeta meta), k `elem` extraCoreProps]- ++ mknode "cp:keywords" [] (T.intercalate ", " keywords)- : (\x -> [ mknode "dcterms:created" [("xsi:type","dcterms:W3CDTF")] x- , mknode "dcterms:modified" [("xsi:type","dcterms:W3CDTF")] x- ]) (T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime)- let docPropsEntry = toEntry docPropsPath epochtime $ renderXml docProps-- -- docProps/custom.xml- let customProperties :: [(Text, Text)]- customProperties = [ (k, lookupMetaString k meta)- | k <- M.keys (unMeta meta)- , k `notElem` (["title", "author", "keywords"]- ++ extraCoreProps)]- let mkCustomProp (k, v) pid = mknode "property"- [("fmtid","{D5CDD505-2E9C-101B-9397-08002B2CF9AE}")- ,("pid", tshow pid)- ,("name", k)] $ mknode "vt:lpwstr" [] v- let customPropsPath = "docProps/custom.xml"- let customProps = mknode "Properties"- [("xmlns","http://schemas.openxmlformats.org/officeDocument/2006/custom-properties")- ,("xmlns:vt","http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes")- ] $ zipWith mkCustomProp customProperties [(2 :: Int)..]- let customPropsEntry = toEntry customPropsPath epochtime $ renderXml customProps-- let relsPath = "_rels/.rels"- let rels = mknode "Relationships" [("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")]- $ map (\attrs -> mknode "Relationship" attrs ())- [ [("Id","rId1")- ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")- ,("Target","word/document.xml")]- , [("Id","rId4")- ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties")- ,("Target","docProps/app.xml")]- , [("Id","rId3")- ,("Type","http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties")- ,("Target","docProps/core.xml")]- , [("Id","rId5")- ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties")- ,("Target","docProps/custom.xml")]- ]- let relsEntry = toEntry relsPath epochtime $ renderXml rels-- -- we use dist archive for settings.xml, because Word sometimes- -- adds references to footnotes or endnotes we don't have...- -- we do, however, copy some settings over from reference- let settingsPath = "word/settings.xml"- settingsList = [ "zoom"- , "embedSystemFonts"- , "doNotTrackMoves"- , "defaultTabStop"- , "drawingGridHorizontalSpacing"- , "drawingGridVerticalSpacing"- , "displayHorizontalDrawingGridEvery"- , "displayVerticalDrawingGridEvery"- , "characterSpacingControl"- , "savePreviewPicture"- , "mathPr"- , "themeFontLang"- , "decimalSymbol"- , "listSeparator"- , "autoHyphenation"- , "consecutiveHyphenLimit"- , "hyphenationZone"- , "doNotHyphenateCap"- , "evenAndOddHeaders"- , "proofState"- , "compat"- ]- settingsEntry <- copyChildren refArchive distArchive settingsPath epochtime settingsList-- let entryFromArchive arch path =- maybe (throwError $ PandocSomeError- $ T.pack $ path ++ " missing in reference docx")- return- (findEntryByPath path arch `mplus` findEntryByPath path distArchive)- docPropsAppEntry <- entryFromArchive refArchive "docProps/app.xml"- themeEntry <- entryFromArchive refArchive "word/theme/theme1.xml"- fontTableEntry <- entryFromArchive refArchive "word/fontTable.xml"- webSettingsEntry <- entryFromArchive refArchive "word/webSettings.xml"- headerFooterEntries <- mapM (entryFromArchive refArchive . ("word/" ++)) $- mapMaybe (fmap T.unpack . extractTarget)- (headers ++ footers)- let miscRelEntries = [ e | e <- zEntries refArchive- , "word/_rels/" `isPrefixOf` eRelativePath e- , ".xml.rels" `isSuffixOf` eRelativePath e- , eRelativePath e /= "word/_rels/document.xml.rels"- , eRelativePath e /= "word/_rels/footnotes.xml.rels" ]- let otherMediaEntries = [ e | e <- zEntries refArchive- , "word/media/" `isPrefixOf` eRelativePath e ]-- -- Create archive- let archive = foldr addEntryToArchive emptyArchive $- contentTypesEntry : relsEntry : contentEntry : relEntry :- footnoteRelEntry : numEntry : styleEntry : footnotesEntry :- commentsEntry :- docPropsEntry : docPropsAppEntry : customPropsEntry :- themeEntry :- fontTableEntry : settingsEntry : webSettingsEntry :- imageEntries ++ headerFooterEntries ++- miscRelEntries ++ otherMediaEntries- return $ fromArchive archive--newParaPropToOpenXml :: ParaStyleName -> Element-newParaPropToOpenXml (fromStyleName -> s) =- let styleId = T.filter (not . isSpace) s- in mknode "w:style" [ ("w:type", "paragraph")- , ("w:customStyle", "1")- , ("w:styleId", styleId)]- [ mknode "w:name" [("w:val", s)] ()- , mknode "w:basedOn" [("w:val","BodyText")] ()- , mknode "w:qFormat" [] ()- ]--newTextPropToOpenXml :: CharStyleName -> Element-newTextPropToOpenXml (fromStyleName -> s) =- let styleId = T.filter (not . isSpace) s- in mknode "w:style" [ ("w:type", "character")- , ("w:customStyle", "1")- , ("w:styleId", styleId)]- [ mknode "w:name" [("w:val", s)] ()- , mknode "w:basedOn" [("w:val","BodyTextChar")] ()- ]--styleToOpenXml :: StyleMaps -> Style -> [Element]-styleToOpenXml sm style =- maybeToList parStyle ++ mapMaybe toStyle alltoktypes- where alltoktypes = enumFromTo KeywordTok NormalTok- toStyle toktype | hasStyleName (fromString $ show toktype) (smCharStyle sm) = Nothing- | otherwise = Just $- mknode "w:style" [("w:type","character"),- ("w:customStyle","1"),("w:styleId", tshow toktype)]- [ mknode "w:name" [("w:val", tshow toktype)] ()- , mknode "w:basedOn" [("w:val","VerbatimChar")] ()- , mknode "w:rPr" [] $- [ mknode "w:color" [("w:val", tokCol toktype)] ()- | tokCol toktype /= "auto" ] ++- [ mknode "w:shd" [("w:val","clear")- ,("w:fill",tokBg toktype)] ()- | tokBg toktype /= "auto" ] ++- [ mknode "w:b" [] () | tokFeature tokenBold toktype ] ++- [ mknode "w:i" [] () | tokFeature tokenItalic toktype ] ++- [ mknode "w:u" [] () | tokFeature tokenUnderline toktype ]- ]- tokStyles = tokenStyles style- tokFeature f toktype = maybe False f $ M.lookup toktype tokStyles- tokCol toktype = maybe "auto" (T.pack . drop 1 . fromColor)- $ (tokenColor =<< M.lookup toktype tokStyles)- `mplus` defaultColor style- tokBg toktype = maybe "auto" (T.pack . drop 1 . fromColor)- $ (tokenBackground =<< M.lookup toktype tokStyles)- `mplus` backgroundColor style- parStyle | hasStyleName "Source Code" (smParaStyle sm) = Nothing- | otherwise = Just $- mknode "w:style" [("w:type","paragraph"),- ("w:customStyle","1"),("w:styleId","SourceCode")]- [ mknode "w:name" [("w:val","Source Code")] ()- , mknode "w:basedOn" [("w:val","Normal")] ()- , mknode "w:link" [("w:val","VerbatimChar")] ()- , mknode "w:pPr" []- $ mknode "w:wordWrap" [("w:val","off")] ()- :- maybe [] (\col -> [mknode "w:shd" [("w:val","clear"),("w:fill", T.pack $ drop 1 $ fromColor col)] ()]) (backgroundColor style)- ]--copyChildren :: (PandocMonad m)- => Archive -> Archive -> String -> Integer -> [Text] -> m Entry-copyChildren refArchive distArchive path timestamp elNames = do- ref <- parseXml refArchive distArchive path- dist <- parseXml distArchive distArchive path- let elsToCopy =- map cleanElem $ filterChildrenName (\e -> qName e `elem` elNames) ref- let elsToKeep =- [e | Elem e <- elContent dist, not (any (hasSameNameAs e) elsToCopy)]- return $ toEntry path timestamp $ renderXml dist{- elContent = map Elem elsToKeep ++ map Elem elsToCopy- }- where- hasSameNameAs (Element {elName = n1}) (Element {elName = n2}) =- qName n1 == qName n2- cleanElem el@Element{elName=name} = el{elName=name{qURI=Nothing}}---- this is the lowest number used for a list numId-baseListId :: Int-baseListId = 1000--mkNumbering :: [ListMarker] -> [Element]-mkNumbering lists =- elts ++ zipWith mkNum lists [baseListId..(baseListId + length lists - 1)]- where elts = map mkAbstractNum (ordNub lists)--maxListLevel :: Int-maxListLevel = 8--mkNum :: ListMarker -> Int -> Element-mkNum marker numid =- mknode "w:num" [("w:numId",tshow numid)]- $ mknode "w:abstractNumId" [("w:val",listMarkerToId marker)] ()- : case marker of- NoMarker -> []- BulletMarker -> []- NumberMarker _ _ start ->- map (\lvl -> mknode "w:lvlOverride" [("w:ilvl",tshow (lvl :: Int))]- $ mknode "w:startOverride" [("w:val",tshow start)] ())- [0..maxListLevel]--mkAbstractNum :: ListMarker -> Element-mkAbstractNum marker =- mknode "w:abstractNum" [("w:abstractNumId",listMarkerToId marker)]- $ mknode "w:nsid" [("w:val", "A" <> listMarkerToId marker)] ()- : mknode "w:multiLevelType" [("w:val","multilevel")] ()- : map (mkLvl marker)- [0..maxListLevel]--mkLvl :: ListMarker -> Int -> Element-mkLvl marker lvl =- mknode "w:lvl" [("w:ilvl",tshow lvl)] $- [ mknode "w:start" [("w:val",start)] ()- | marker /= NoMarker && marker /= BulletMarker ] ++- [ mknode "w:numFmt" [("w:val",fmt)] ()- , mknode "w:lvlText" [("w:val", lvltxt)] ()- , mknode "w:lvlJc" [("w:val","left")] ()- , mknode "w:pPr" []- [ mknode "w:ind" [ ("w:left",tshow $ lvl * step + step)- , ("w:hanging",tshow (hang :: Int))- ] ()- ]- ]- where (fmt, lvltxt, start) =- case marker of- NoMarker -> ("bullet"," ","1")- BulletMarker -> ("bullet",bulletFor lvl,"1")- NumberMarker st de n -> (styleFor st lvl- ,patternFor de ("%" <> tshow (lvl + 1))- ,tshow n)- step = 720- hang = 480- bulletFor 0 = "\x2022" -- filled circle- bulletFor 1 = "\x2013" -- en dash- bulletFor 2 = "\x2022" -- hyphen bullet- bulletFor 3 = "\x2013"- bulletFor 4 = "\x2022"- bulletFor 5 = "\x2013"- bulletFor x = bulletFor (x `mod` 6)- styleFor UpperAlpha _ = "upperLetter"- styleFor LowerAlpha _ = "lowerLetter"- styleFor UpperRoman _ = "upperRoman"- styleFor LowerRoman _ = "lowerRoman"- styleFor Decimal _ = "decimal"- styleFor DefaultStyle 0 = "decimal"- styleFor DefaultStyle 1 = "lowerLetter"- styleFor DefaultStyle 2 = "lowerRoman"- styleFor DefaultStyle 3 = "decimal"- styleFor DefaultStyle 4 = "lowerLetter"- styleFor DefaultStyle 5 = "lowerRoman"- styleFor DefaultStyle x = styleFor DefaultStyle (x `mod` 6)- styleFor _ _ = "decimal"- patternFor OneParen s = s <> ")"- patternFor TwoParens s = "(" <> s <> ")"- patternFor _ s = s <> "."--getNumId :: (PandocMonad m) => WS m Int-getNumId = (((baseListId - 1) +) . length) `fmap` gets stLists---makeTOC :: (PandocMonad m) => WriterOptions -> WS m [Element]-makeTOC opts = do- let depth = "1-" <> tshow (writerTOCDepth opts)- let tocCmd = "TOC \\o \"" <> depth <> "\" \\h \\z \\u"- tocTitle <- gets stTocTitle- title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para tocTitle])- return- [mknode "w:sdt" [] [- mknode "w:sdtPr" [] (- mknode "w:docPartObj" []- [mknode "w:docPartGallery" [("w:val","Table of Contents")] (),- mknode "w:docPartUnique" [] ()]- -- w:docPartObj- ), -- w:sdtPr- mknode "w:sdtContent" [] (title ++ [ Elem $- mknode "w:p" [] (- mknode "w:r" [] [- mknode "w:fldChar" [("w:fldCharType","begin"),("w:dirty","true")] (),- mknode "w:instrText" [("xml:space","preserve")] tocCmd,- mknode "w:fldChar" [("w:fldCharType","separate")] (),- mknode "w:fldChar" [("w:fldCharType","end")] ()- ] -- w:r- ) -- w:p- ])- ]] -- w:sdt---- | Convert Pandoc document to two lists of--- OpenXML elements (the main document and footnotes).-writeOpenXML :: (PandocMonad m)- => WriterOptions -> Pandoc- -> WS m ([Content], [Element], [Element])-writeOpenXML opts (Pandoc meta blocks) = do- let tit = docTitle meta- let auths = docAuthors meta- let dat = docDate meta- let abstract' = lookupMetaBlocks "abstract" meta- let subtitle' = lookupMetaInlines "subtitle" meta- let includeTOC = writerTableOfContents opts || lookupMetaBool "toc" meta- title <- withParaPropM (pStyleM "Title") $ blocksToOpenXML opts [Para tit | not (null tit)]- subtitle <- withParaPropM (pStyleM "Subtitle") $ blocksToOpenXML opts [Para subtitle' | not (null subtitle')]- authors <- withParaPropM (pStyleM "Author") $ blocksToOpenXML opts $- map Para auths- date <- withParaPropM (pStyleM "Date") $ blocksToOpenXML opts [Para dat | not (null dat)]- abstract <- if null abstract'- then return []- else withParaPropM (pStyleM "Abstract") $ blocksToOpenXML opts abstract'- let convertSpace (Str x : Space : Str y : xs) = Str (x <> " " <> y) : xs- convertSpace (Str x : Str y : xs) = Str (x <> y) : xs- convertSpace xs = xs- let blocks' = bottomUp convertSpace blocks- doc' <- setFirstPara >> blocksToOpenXML opts blocks'- notes' <- reverse <$> gets stFootnotes- comments <- reverse <$> gets stComments- let toComment (kvs, ils) = do- annotation <- inlinesToOpenXML opts ils- return $- mknode "w:comment" [("w:" <> k, v) | (k,v) <- kvs]- [ mknode "w:p" [] $- map Elem- [ mknode "w:pPr" []- [ mknode "w:pStyle" [("w:val", "CommentText")] () ]- , mknode "w:r" []- [ mknode "w:rPr" []- [ mknode "w:rStyle" [("w:val", "CommentReference")] ()- , mknode "w:annotationRef" [] ()- ]- ]- ] ++ annotation- ]- comments' <- mapM toComment comments- toc <- if includeTOC- then makeTOC opts- else return []- let meta' = title ++ subtitle ++ authors ++ date ++ abstract ++ map Elem toc- return (meta' ++ doc', notes', comments')---- | 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)--isForeignRawBlock :: Block -> Bool-isForeignRawBlock (RawBlock format _) = format /= "openxml"-isForeignRawBlock _ = False---- Word combines adjacent tables unless you put an empty paragraph between--- them. See #4315.-separateTables :: [Block] -> [Block]-separateTables [] = []-separateTables (x@Table{}:xs@(Table{}:_)) =- x : RawBlock (Format "openxml") "<w:p />" : separateTables xs-separateTables (x:xs) = x : separateTables xs--rStyleM :: (PandocMonad m) => CharStyleName -> WS m XML.Element-rStyleM styleName = do- cStyleMap <- gets (smCharStyle . stStyleMaps)- let sty' = getStyleIdFromName styleName cStyleMap- return $ mknode "w:rStyle" [("w:val", fromStyleId sty')] ()--getUniqueId :: (PandocMonad m) => WS m Text-getUniqueId = do- n <- gets stCurId- modify $ \st -> st{stCurId = n + 1}- return $ tshow n---- | Key for specifying user-defined docx styles.-dynamicStyleKey :: Text-dynamicStyleKey = "custom-style"---- | Convert a Pandoc block element to OpenXML.-blockToOpenXML :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]-blockToOpenXML opts blk = withDirection $ blockToOpenXML' opts blk--blockToOpenXML' :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]-blockToOpenXML' _ Null = return []-blockToOpenXML' opts (Div (ident,_classes,kvs) bs) = do- stylemod <- case lookup dynamicStyleKey kvs of- Just (fromString . T.unpack -> sty) -> do- modify $ \s ->- s{stDynamicParaProps = Set.insert sty- (stDynamicParaProps s)}- return $ withParaPropM (pStyleM sty)- _ -> return id- dirmod <- case lookup "dir" kvs of- Just "rtl" -> return $ local (\env -> env { envRTL = True })- Just "ltr" -> return $ local (\env -> env { envRTL = False })- _ -> return id- let (hs, bs') = if ident == "refs"- then span isHeaderBlock bs- else ([], bs)- let bibmod = if ident == "refs"- then withParaPropM (pStyleM "Bibliography")- else id- let langmod = case lookup "lang" kvs of- Nothing -> id- Just lang -> local (\env -> env{envLang = Just lang})- header <- dirmod $ stylemod $ blocksToOpenXML opts hs- contents <- dirmod $ bibmod $ stylemod $ langmod $ blocksToOpenXML opts bs'- wrapBookmark ident $ header <> contents-blockToOpenXML' opts (Header lev (ident,_,kvs) lst) = do- setFirstPara- paraProps <- withParaPropM (pStyleM (fromString $ "Heading "++show lev)) $- getParaProps False- number <-- if writerNumberSections opts- then- case lookup "number" kvs of- Just n -> do- num <- withTextPropM (rStyleM "SectionNumber")- (inlineToOpenXML opts (Str n))- return $ num ++ [Elem $ mknode "w:r" [] [mknode "w:tab" [] ()]]- Nothing -> return []- else return []- contents <- (number ++) <$> inlinesToOpenXML opts lst- if T.null ident- then return [Elem $ mknode "w:p" [] (map Elem paraProps ++ contents)]- else do- let bookmarkName = ident- modify $ \s -> s{ stSectionIds = Set.insert bookmarkName- $ stSectionIds s }- bookmarkedContents <- wrapBookmark bookmarkName contents- return [Elem $ mknode "w:p" [] (map Elem paraProps ++ bookmarkedContents)]-blockToOpenXML' opts (Plain lst) = do- isInTable <- gets stInTable- isInList <- gets stInList- let block = blockToOpenXML opts (Para lst)- prop <- pStyleM "Compact"- if isInTable || isInList- then withParaProp prop block- else block--- title beginning with fig: indicates that the image is a figure-blockToOpenXML' opts (SimpleFigure attr@(imgident, _, _) alt (src, tit)) = do- setFirstPara- fignum <- gets stNextFigureNum- unless (null alt) $ modify $ \st -> st{ stNextFigureNum = fignum + 1 }- let refid = if T.null imgident- then "ref_fig" <> tshow fignum- else "ref_" <> imgident- figname <- translateTerm Term.Figure- prop <- pStyleM $- if null alt- then "Figure"- else "Captioned Figure"- paraProps <- local (\env -> env { envParaProperties = EnvProps (Just prop) [] <> envParaProperties env }) (getParaProps False)- contents <- inlinesToOpenXML opts [Image attr alt (src,tit)]- captionNode <- if null alt- then return []- else withParaPropM (pStyleM "Image Caption")- $ blockToOpenXML opts- $ Para- $ if isEnabled Ext_native_numbering opts- then Span (refid,[],[])- [Str (figname <> "\160"),- RawInline (Format "openxml")- ("<w:fldSimple w:instr=\"SEQ Figure"- <> " \\* ARABIC \"><w:r><w:t>"- <> tshow fignum- <> "</w:t></w:r></w:fldSimple>")] : Str ": " : alt- else alt- return $- Elem (mknode "w:p" [] (map Elem paraProps ++ contents))- : captionNode-blockToOpenXML' opts (Para lst)- | null lst && not (isEnabled Ext_empty_paragraphs opts) = return []- | otherwise = do- isFirstPara <- gets stFirstPara- let displayMathPara = case lst of- [x] -> isDisplayMath x- _ -> False- paraProps <- getParaProps displayMathPara- bodyTextStyle <- pStyleM $ if isFirstPara- then "First Paragraph"- else "Body Text"- let paraProps' = case paraProps of- [] -> [mknode "w:pPr" [] [bodyTextStyle]]- ps -> ps- modify $ \s -> s { stFirstPara = False }- contents <- inlinesToOpenXML opts lst- return [Elem $ mknode "w:p" [] (map Elem paraProps' ++ contents)]-blockToOpenXML' opts (LineBlock lns) = blockToOpenXML opts $ linesToPara lns-blockToOpenXML' _ b@(RawBlock format str)- | format == Format "openxml" = return [- Text (CData CDataRaw str Nothing)- ]- | otherwise = do- report $ BlockNotRendered b- return []-blockToOpenXML' opts (BlockQuote blocks) = do- p <- withParaPropM (pStyleM "Block Text")- $ blocksToOpenXML opts blocks- setFirstPara- return p-blockToOpenXML' opts (CodeBlock attrs@(ident, _, _) str) = do- p <- withParaPropM (pStyleM "Source Code") (blockToOpenXML opts $ Para [Code attrs str])- setFirstPara- wrapBookmark ident p-blockToOpenXML' _ HorizontalRule = do- setFirstPara- return [ Elem $- mknode "w:p" [] $ mknode "w:r" [] $ mknode "w:pict" []- $ mknode "v:rect" [("style","width:0;height:1.5pt"),- ("o:hralign","center"),- ("o:hrstd","t"),("o:hr","t")] () ]-blockToOpenXML' opts (Table attr caption colspecs thead tbodies tfoot) = do- content <- tableToOpenXML opts- (blocksToOpenXML opts)- (Grid.toTable attr caption colspecs thead tbodies tfoot)- let (tableId, _, _) = attr- wrapBookmark tableId content-blockToOpenXML' opts el- | BulletList lst <- el = addOpenXMLList BulletMarker lst- | OrderedList (start, numstyle, numdelim) lst <- el- = addOpenXMLList (NumberMarker numstyle numdelim start) lst- where- addOpenXMLList marker lst = do- addList marker- numid <- getNumId- exampleid <- case marker of- NumberMarker Example _ _ -> gets stExampleId- _ -> return Nothing- l <- asList $ concat `fmap` mapM (listItemToOpenXML opts $ fromMaybe numid exampleid) lst- setFirstPara- return l-blockToOpenXML' opts (DefinitionList items) = do- l <- concat `fmap` mapM (definitionListItemToOpenXML opts) items- setFirstPara- return l--definitionListItemToOpenXML :: (PandocMonad m)- => WriterOptions -> ([Inline],[[Block]])- -> WS m [Content]-definitionListItemToOpenXML opts (term,defs) = do- term' <- withParaPropM (pStyleM "Definition Term")- $ blockToOpenXML opts (Para term)- defs' <- withParaPropM (pStyleM "Definition")- $ concat `fmap` mapM (blocksToOpenXML opts) defs- return $ term' ++ defs'--addList :: (PandocMonad m) => ListMarker -> WS m ()-addList marker = do- lists <- gets stLists- lastExampleId <- gets stExampleId- modify $ \st -> st{ stLists = lists ++ case marker of- -- Use only first occurrence of Example for list declaration to avoid overhead- NumberMarker Example _ _ | isJust lastExampleId -> []- _ -> [marker]- , stExampleId = case marker of- -- Reuse the same identifier for all other occurrences of Example- NumberMarker Example _ _ -> lastExampleId <|> Just (baseListId + length lists)- _ -> lastExampleId- }--listItemToOpenXML :: (PandocMonad m)- => WriterOptions- -> Int -> [Block]- -> WS m [Content]-listItemToOpenXML opts numid bs = do- oldInList <- gets stInList- modify $ \st -> st{ stInList = True }- let isListBlock = \case- BulletList{} -> True- OrderedList{} -> True- _ -> False- -- Prepend an empty string if the first entry is another- -- list. Otherwise the outer bullet will disappear.- let bs' = case bs of- [] -> []- first:rest -> if isListBlock first- then Plain [Str ""]:first:rest- else first:rest- modify $ \st -> st{ stNumIdUsed = False }- contents <- withNumId numid $ blocksToOpenXML opts bs'- modify $ \st -> st{ stInList = oldInList }- return contents---- | Convert a list of inline elements to OpenXML.-inlinesToOpenXML :: PandocMonad m => WriterOptions -> [Inline] -> WS m [Content]-inlinesToOpenXML opts lst = concat `fmap` mapM (inlineToOpenXML opts) lst--withNumId :: (PandocMonad m) => Int -> WS m a -> WS m a-withNumId numid = local $ \env -> env{ envListNumId = numid }--asList :: (PandocMonad m) => WS m a -> WS m a-asList = local $ \env -> env{ envListLevel = envListLevel env + 1 }--getTextProps :: (PandocMonad m) => WS m [Element]-getTextProps = do- props <- asks envTextProperties- mblang <- asks envLang- let langnode = case mblang of- Nothing -> mempty- Just l -> EnvProps Nothing- [mknode "w:lang" [("w:val", l)] ()]- let squashed = squashProps (props <> langnode)- return [mknode "w:rPr" [] squashed | (not . null) squashed]--withTextProp :: PandocMonad m => Element -> WS m a -> WS m a-withTextProp d p =- local (\env -> env {envTextProperties = ep <> envTextProperties env}) p- where ep = if isStyle d then EnvProps (Just d) [] else EnvProps Nothing [d]--withTextPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a-withTextPropM md p = do- d <- md- withTextProp d p--getParaProps :: PandocMonad m => Bool -> WS m [Element]-getParaProps displayMathPara = do- props <- asks envParaProperties- listLevel <- asks envListLevel- numid <- asks envListNumId- numIdUsed <- gets stNumIdUsed- -- clear numId after first use to support multiple paragraphs in the same bullet- -- baseListId is the code for no list marker- let numid' = if numIdUsed then baseListId else numid- modify $ \st -> st{ stNumIdUsed = True }- let listPr = [mknode "w:numPr" []- [ mknode "w:ilvl" [("w:val",tshow listLevel)] ()- , mknode "w:numId" [("w:val",tshow numid')] () ] | listLevel >= 0 && not displayMathPara]- return $ case listPr ++ squashProps props of- [] -> []- ps -> [mknode "w:pPr" [] ps]--formattedString :: PandocMonad m => Text -> WS m [Element]-formattedString str =- -- properly handle soft hyphens- case splitTextBy (=='\173') str of- [w] -> formattedString' w- ws -> do- sh <- formattedRun [mknode "w:softHyphen" [] ()]- intercalate sh <$> mapM formattedString' ws--formattedString' :: PandocMonad m => Text -> WS m [Element]-formattedString' str = do- inDel <- asks envInDel- formattedRun [ mktnode (if inDel then "w:delText" else "w:t")- [("xml:space","preserve")] (stripInvalidChars str) ]--formattedRun :: PandocMonad m => [Element] -> WS m [Element]-formattedRun els = do- props <- getTextProps- return [ mknode "w:r" [] $ props ++ els ]---- | Convert an inline element to OpenXML.-inlineToOpenXML :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]-inlineToOpenXML opts il = withDirection $ inlineToOpenXML' opts il--inlineToOpenXML' :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]-inlineToOpenXML' _ (Str str) =- map Elem <$> formattedString str-inlineToOpenXML' opts Space = inlineToOpenXML opts (Str " ")-inlineToOpenXML' opts SoftBreak = inlineToOpenXML opts (Str " ")-inlineToOpenXML' opts (Span ("",["csl-block"],[]) ils) =- inlinesToOpenXML opts ils-inlineToOpenXML' opts (Span ("",["csl-left-margin"],[]) ils) =- inlinesToOpenXML opts ils-inlineToOpenXML' opts (Span ("",["csl-right-inline"],[]) ils) =- ([Elem $- mknode "w:r" []- (mknode "w:t"- [("xml:space","preserve")]- ("\t" :: Text))] ++)- <$> inlinesToOpenXML opts ils-inlineToOpenXML' opts (Span ("",["csl-indent"],[]) ils) =- inlinesToOpenXML opts ils-inlineToOpenXML' _ (Span (ident,["comment-start"],kvs) ils) = do- -- prefer the "id" in kvs, since that is the one produced by the docx- -- reader.- let ident' = fromMaybe ident (lookup "id" kvs)- kvs' = filter (("id" /=) . fst) kvs- modify $ \st -> st{ stComments = (("id",ident'):kvs', ils) : stComments st }- return [ Elem $ mknode "w:commentRangeStart" [("w:id", ident')] () ]-inlineToOpenXML' _ (Span (ident,["comment-end"],kvs) _) =- -- prefer the "id" in kvs, since that is the one produced by the docx- -- reader.- let ident' = fromMaybe ident (lookup "id" kvs)- in return . map Elem $- [ mknode "w:commentRangeEnd" [("w:id", ident')] ()- , mknode "w:r" []- [ mknode "w:rPr" []- [ mknode "w:rStyle" [("w:val", "CommentReference")] () ]- , mknode "w:commentReference" [("w:id", ident')] () ]- ]-inlineToOpenXML' opts (Span (ident,classes,kvs) ils) = do- stylemod <- case lookup dynamicStyleKey kvs of- Just (fromString . T.unpack -> sty) -> do- modify $ \s ->- s{stDynamicTextProps = Set.insert sty- (stDynamicTextProps s)}- return $ withTextPropM (rStyleM sty)- _ -> return id- let dirmod = case lookup "dir" kvs of- Just "rtl" -> local (\env -> env { envRTL = True })- Just "ltr" -> local (\env -> env { envRTL = False })- _ -> id- off x = withTextProp (mknode x [("w:val","0")] ())- pmod = (if "csl-no-emph" `elem` classes then off "w:i" else id) .- (if "csl-no-strong" `elem` classes then off "w:b" else id) .- (if "csl-no-smallcaps" `elem` classes- then off "w:smallCaps"- else id)- getChangeAuthorDate = do- defaultAuthor <- asks envChangesAuthor- let author = fromMaybe defaultAuthor (lookup "author" kvs)- let mdate = lookup "date" kvs- return $ ("w:author", author) :- maybe [] (\date -> [("w:date", date)]) mdate- insmod <- if "insertion" `elem` classes- then do- changeAuthorDate <- getChangeAuthorDate- insId <- gets stInsId- modify $ \s -> s{stInsId = insId + 1}- return $ \f -> do- x <- f- return [Elem $- mknode "w:ins"- (("w:id", tshow insId) : changeAuthorDate) x]- else return id- delmod <- if "deletion" `elem` classes- then do- changeAuthorDate <- getChangeAuthorDate- delId <- gets stDelId- modify $ \s -> s{stDelId = delId + 1}- return $ \f -> local (\env->env{envInDel=True}) $ do- x <- f- return [Elem $ mknode "w:del"- (("w:id", tshow delId) : changeAuthorDate) x]- else return id- let langmod = case lookup "lang" kvs of- Nothing -> id- Just lang -> local (\env -> env{envLang = Just lang})- contents <- insmod $ delmod $ dirmod $ stylemod $ pmod $- langmod $ inlinesToOpenXML opts ils- wrapBookmark ident contents-inlineToOpenXML' opts (Strong lst) =- withTextProp (mknode "w:b" [] ()) $- withTextProp (mknode "w:bCs" [] ()) $ -- needed for LTR, #6911- inlinesToOpenXML opts lst-inlineToOpenXML' opts (Emph lst) =- withTextProp (mknode "w:i" [] ()) $- withTextProp (mknode "w:iCs" [] ()) $ -- needed for LTR, #6911- inlinesToOpenXML opts lst-inlineToOpenXML' opts (Underline lst) =- withTextProp (mknode "w:u" [("w:val","single")] ()) $- inlinesToOpenXML opts lst-inlineToOpenXML' opts (Subscript lst) =- withTextProp (mknode "w:vertAlign" [("w:val","subscript")] ())- $ inlinesToOpenXML opts lst-inlineToOpenXML' opts (Superscript lst) =- withTextProp (mknode "w:vertAlign" [("w:val","superscript")] ())- $ inlinesToOpenXML opts lst-inlineToOpenXML' opts (SmallCaps lst) =- withTextProp (mknode "w:smallCaps" [] ())- $ inlinesToOpenXML opts lst-inlineToOpenXML' opts (Strikeout lst) =- withTextProp (mknode "w:strike" [] ())- $ inlinesToOpenXML opts lst-inlineToOpenXML' _ LineBreak = return [Elem br]-inlineToOpenXML' _ il@(RawInline f str)- | f == Format "openxml" = return- [Text (CData CDataRaw str Nothing)]- | otherwise = do- report $ InlineNotRendered il- return []-inlineToOpenXML' opts (Quoted quoteType lst) =- inlinesToOpenXML opts $ [Str open] ++ lst ++ [Str close]- where (open, close) = case quoteType of- SingleQuote -> ("\x2018", "\x2019")- DoubleQuote -> ("\x201C", "\x201D")-inlineToOpenXML' opts (Math mathType str) = do- when (mathType == DisplayMath) setFirstPara- res <- (lift . lift) (convertMath writeOMML mathType str)- case res of- Right r -> return [Elem $ fromXLElement r]- Left il -> inlineToOpenXML' opts il-inlineToOpenXML' opts (Cite _ lst) = inlinesToOpenXML opts lst-inlineToOpenXML' opts (Code attrs str) = do- let alltoktypes = [KeywordTok ..]- tokTypesMap <- mapM (\tt -> (,) tt <$> rStyleM (fromString $ show tt)) alltoktypes- let unhighlighted = (map Elem . intercalate [br]) `fmap`- mapM formattedString (T.lines str)- formatOpenXML _fmtOpts = intercalate [br] . map (map toHlTok)- toHlTok (toktype,tok) =- mknode "w:r" []- [ mknode "w:rPr" [] $- 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-inlineToOpenXML' opts (Note bs) = do- notes <- gets stFootnotes- notenum <- getUniqueId- footnoteStyle <- rStyleM "Footnote Reference"- let notemarker = mknode "w:r" []- [ mknode "w:rPr" [] footnoteStyle- , mknode "w:footnoteRef" [] () ]- let notemarkerXml = RawInline (Format "openxml") $ ppElement notemarker- let insertNoteRef (Plain ils : xs) = Plain (notemarkerXml : Space : ils) : xs- insertNoteRef (Para ils : xs) = Para (notemarkerXml : Space : ils) : xs- insertNoteRef xs = Para [notemarkerXml] : xs-- contents <- local (\env -> env{ envListLevel = -1- , envParaProperties = mempty- , envTextProperties = mempty })- (withParaPropM (pStyleM "Footnote Text") $ blocksToOpenXML opts- $ insertNoteRef bs)- let newnote = mknode "w:footnote" [("w:id", notenum)] contents- modify $ \s -> s{ stFootnotes = newnote : notes }- return [ Elem $ mknode "w:r" []- [ mknode "w:rPr" [] footnoteStyle- , mknode "w:footnoteReference" [("w:id", notenum)] () ] ]--- internal link:-inlineToOpenXML' opts (Link _ txt (T.uncons -> Just ('#', xs),_)) = do- contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt- return- [ Elem $ mknode "w:hyperlink" [("w:anchor", toBookmarkName xs)] contents ]--- external link:-inlineToOpenXML' opts (Link _ txt (src,_)) = do- contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt- extlinks <- gets stExternalLinks- id' <- case M.lookup src extlinks of- Just i -> return i- Nothing -> do- i <- ("rId" <>) <$> getUniqueId- modify $ \st -> st{ stExternalLinks =- M.insert src i extlinks }- return i- return [ Elem $ mknode "w:hyperlink" [("r:id",id')] contents ]-inlineToOpenXML' opts (Image attr@(imgident, _, _) alt (src, title)) = do- pageWidth <- asks envPrintWidth- imgs <- gets stImages- let- stImage = M.lookup (T.unpack src) imgs- generateImgElt (ident, _fp, mt, img) = do- docprid <- getUniqueId- nvpicprid <- getUniqueId- (blipAttrs, blipContents) <-- case T.takeWhile (/=';') <$> mt of- Just "image/svg+xml" -> do- -- get fallback png- mediabag <- getMediaBag- mbFallback <-- case lookupMedia (T.unpack (src <> ".png")) mediabag of- Just item -> do- id' <- T.unpack . ("rId" <>) <$> getUniqueId- let fp' = "media/" <> id' <> ".png"- let imgdata = (id',- fp',- Just (mediaMimeType item),- BL.toStrict $ mediaContents item)- modify $ \st -> st { stImages =- M.insert fp' imgdata $ stImages st }- return $ Just id'- Nothing -> return Nothing- let extLst = mknode "a:extLst" []- [ mknode "a:ext"- [("uri","{28A0092B-C50C-407E-A947-70E740481C1C}")]- [ mknode "a14:useLocalDpi"- [("xmlns:a14","http://schemas.microsoft.com/office/drawing/2010/main"),- ("val","0")] () ]- , mknode "a:ext"- [("uri","{96DAC541-7B7A-43D3-8B79-37D633B846F1}")]- [ mknode "asvg:svgBlip"- [("xmlns:asvg", "http://schemas.microsoft.com/office/drawing/2016/SVG/main"),- ("r:embed",T.pack ident)] () ]- ]- return (maybe [] (\id'' -> [("r:embed", T.pack id'')]) mbFallback,- [extLst])- _ -> return ([("r:embed", T.pack ident)], [])- let- (xpt,ypt) = desiredSizeInPoints opts attr- (either (const def) id (imageSize opts img))- -- 12700 emu = 1 pt- (xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700)- (pageWidth * 12700)- cNvPicPr = mknode "pic:cNvPicPr" [] $- mknode "a:picLocks" [("noChangeArrowheads","1")- ,("noChangeAspect","1")] ()- nvPicPr = mknode "pic:nvPicPr" []- [ mknode "pic:cNvPr"- [("descr",src)- ,("id", nvpicprid)- ,("name","Picture")] ()- , cNvPicPr ]- blipFill = mknode "pic:blipFill" []- [ mknode "a:blip" blipAttrs blipContents- , mknode "a:stretch" [] $- mknode "a:fillRect" [] ()- ]- xfrm = mknode "a:xfrm" []- [ mknode "a:off" [("x","0"),("y","0")] ()- , mknode "a:ext" [("cx",tshow xemu)- ,("cy",tshow yemu)] () ]- prstGeom = mknode "a:prstGeom" [("prst","rect")] $- mknode "a:avLst" [] ()- ln = mknode "a:ln" [("w","9525")]- [ mknode "a:noFill" [] ()- , mknode "a:headEnd" [] ()- , mknode "a:tailEnd" [] () ]- spPr = mknode "pic:spPr" [("bwMode","auto")]- [xfrm, prstGeom, mknode "a:noFill" [] (), ln]- graphic = mknode "a:graphic" [] $- mknode "a:graphicData"- [("uri","http://schemas.openxmlformats.org/drawingml/2006/picture")]- [ mknode "pic:pic" []- [ nvPicPr- , blipFill- , spPr- ]- ]- imgElt = mknode "w:r" [] $- mknode "w:drawing" [] $- mknode "wp:inline" []- [ mknode "wp:extent" [("cx",tshow xemu),("cy",tshow yemu)] ()- , mknode "wp:effectExtent"- [("b","0"),("l","0"),("r","0"),("t","0")] ()- , mknode "wp:docPr"- [ ("descr", stringify alt)- , ("title", title)- , ("id", docprid)- , ("name","Picture")- ] ()- , graphic- ]- return [Elem imgElt]-- wrapBookmark imgident =<< case stImage of- Just imgData -> generateImgElt imgData- Nothing -> ( do --try- (img, mt) <- P.fetchItem src- ident <- ("rId" <>) <$> getUniqueId-- let- imgext = case mt >>= extensionFromMimeType of- Just x -> "." <> x- Nothing -> case imageType img of- Just Png -> ".png"- Just Jpeg -> ".jpeg"- Just Gif -> ".gif"- Just Pdf -> ".pdf"- Just Eps -> ".eps"- Just Svg -> ".svg"- Just Emf -> ".emf"- Just Tiff -> ".tiff"- Nothing -> ""- imgpath = "media/" <> ident <> imgext- mbMimeType = mt <|> getMimeType (T.unpack imgpath)-- imgData = (T.unpack ident, T.unpack imgpath, mbMimeType, img)-- if T.null imgext- then -- without an extension there is no rule for content type- inlinesToOpenXML opts alt -- return alt to avoid corrupted docx- else do- -- insert mime type to use in constructing [Content_Types].xml- modify $ \st -> st { stImages = M.insert (T.unpack src) imgData $ stImages st }- generateImgElt imgData- )- `catchError` ( \e -> do- report $ CouldNotFetchResource src $ T.pack (show e)- -- emit alt text- inlinesToOpenXML opts alt- )--br :: Element-br = mknode "w:r" [] [mknode "w:br" [] ()]---withDirection :: PandocMonad m => WS m a -> WS m a-withDirection x = do- isRTL <- asks envRTL- paraProps <- asks envParaProperties- textProps <- asks envTextProperties- -- We want to clean all bidirection (bidi) and right-to-left (rtl)- -- properties from the props first. This is because we don't want- -- them to stack up.- let paraProps' = filter (\e -> (qName . elName) e /= "bidi") (otherElements paraProps)- textProps' = filter (\e -> (qName . elName) e /= "rtl") (otherElements textProps)- paraStyle = styleElement paraProps- textStyle = styleElement textProps- if isRTL- -- if we are going right-to-left, we (re?)add the properties.- then flip local x $- \env -> env { envParaProperties = EnvProps paraStyle $ mknode "w:bidi" [] () : paraProps'- , envTextProperties = EnvProps textStyle $ mknode "w:rtl" [] () : textProps'- }- else flip local x $ \env -> env { envParaProperties = EnvProps paraStyle paraProps'- , envTextProperties = EnvProps textStyle textProps'- }--wrapBookmark :: (PandocMonad m) => Text -> [Content] -> WS m [Content]-wrapBookmark "" contents = return contents-wrapBookmark ident contents = do- id' <- getUniqueId- let bookmarkStart = mknode "w:bookmarkStart"- [("w:id", id')- ,("w:name", toBookmarkName ident)] ()- bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()- return $ Elem bookmarkStart : contents ++ [Elem bookmarkEnd]---- Word imposes a 40 character limit on bookmark names and requires--- that they begin with a letter. So we just use a hash of the--- identifier when otherwise we'd have an illegal bookmark name.-toBookmarkName :: Text -> Text-toBookmarkName s- | Just (c, _) <- T.uncons s- , isLetter c- , T.length s <= 40 = s- | otherwise = T.pack $ 'X' : drop 1 (showDigest (sha1 (fromTextLazy $ TL.fromStrict s)))+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.Writers.Docx+ Copyright : Copyright (C) 2012-2025 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to docx.+-}+module Text.Pandoc.Writers.Docx ( writeDocx ) where+import Codec.Archive.Zip+ ( Archive(zEntries),+ addEntryToArchive,+ emptyArchive,+ findEntryByPath,+ fromArchive,+ toArchive,+ toEntry,+ Entry(eRelativePath) )+import Control.Monad (MonadPlus(mplus), foldM)+import Control.Monad.Except (throwError)+import Control.Monad.Reader ( ReaderT(runReaderT) )+import Control.Monad.State.Strict ( StateT(runStateT) )+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import Data.Containers.ListUtils (nubOrd)+import Data.Char (isSpace)+import Data.List (isPrefixOf, isSuffixOf)+import Data.String (fromString)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, mapMaybe, maybeToList)+import qualified Data.Set as Set+import qualified Data.Text as T+import Data.Text (Text)+import Data.Time.Clock.POSIX+import Skylighting+import Text.Pandoc.Class (PandocMonad, toLang)+import qualified Text.Pandoc.Class.PandocMonad as P+import Text.Pandoc.Data (readDataFile, readDefaultDataFile)+import Data.Time+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Definition+import Text.Pandoc.Error+import Text.Pandoc.Highlighting (defaultStyle)+import Text.Pandoc.MIME (MimeType, getMimeTypeDef)+import Text.Pandoc.Options+import Text.Pandoc.Writers.Docx.StyleMap+import Text.Pandoc.Writers.Docx.Types+import Text.Pandoc.Writers.Docx.OpenXML (writeOpenXML, maxListLevel)+import Text.Pandoc.Shared+import Text.Pandoc.Walk+import Text.Pandoc.Writers.Shared+import Text.Pandoc.Writers.OOXML+import Text.Pandoc.XML.Light as XML+import Text.Collate.Lang (renderLang, Lang(..))++writeDocx :: (PandocMonad m)+ => WriterOptions -- ^ Writer options+ -> Pandoc -- ^ Document to convert+ -> m BL.ByteString+writeDocx opts doc = do+ -- Phase 1: Document preprocessing+ let Pandoc meta blocks = walk fixDisplayMath doc+ setupTranslations meta+ let blocks' = makeSectionsWithOffsets (writerNumberOffset opts)+ True Nothing blocks+ let doc' = Pandoc meta blocks'++ -- Phase 2: Archive loading+ (refArchive, distArchive, username, utctime) <- loadArchives opts+ let epochtime = floor $ utcTimeToPOSIXSeconds utctime++ -- Phase 3: Page layout extraction+ (mbsectpr, pgContentWidth) <- extractPageLayout refArchive distArchive++ -- Phase 4: Language & style setup+ mblang <- toLang $ getLang opts meta+ let addLang = mkLangTransformer mblang+ styledoc <- addLang <$> parseXml refArchive distArchive "word/styles.xml"+ let styleMaps = getStyleMaps refArchive++ let tocTitle = case lookupMetaInlines "toc-title" meta of+ [] -> stTocTitle defaultWriterState+ ls -> ls++ let isRTLmeta = case lookupMeta "dir" meta of+ Just (MetaString "rtl") -> True+ Just (MetaInlines [Str "rtl"]) -> True+ _ -> False++ let env = defaultWriterEnv {+ envRTL = isRTLmeta+ , envChangesAuthor = fromMaybe "unknown" username+ , envChangesDate = T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime+ , envPrintWidth = maybe 420 (`quot` 20) pgContentWidth+ }++ -- Phase 5: Relationship extraction+ (baserels, headers, footers, newMaxRelId) <- extractRelationships refArchive distArchive++ let initialSt = defaultWriterState {+ stStyleMaps = styleMaps+ , stTocTitle = tocTitle+ , stCurId = newMaxRelId + 1+ }++ -- Phase 6: Core content generation+ -- adjust contents to add sectPr from reference.docx+ let sectpr = case mbsectpr of+ Just sectpr' -> add_attrs (elAttribs sectpr') $ mknode "w:sectPr" []+ (elChildren sectpr')+ Nothing -> mknode "w:sectPr" []+ [ mknode "w:footnotePr" []+ [ mknode "w:numRestart" [("w:val","eachSect")] () ]+ ]++ ((contents, footnotes, comments), st) <- runStateT+ (runReaderT+ (writeOpenXML opts{ writerWrapText = WrapNone }+ doc')+ env{ envSectPr = Just sectpr })+ initialSt+ let imgs = M.elems $ stImages st++ -- Phase 7: XML document construction+ -- We create [Content_Types].xml and word/_rels/document.xml.rels+ -- from scratch rather than reading from reference.docx,+ -- because Word sometimes changes these files when a reference.docx is modified,+ -- e.g. deleting the reference to footnotes.xml or removing default entries+ -- for image content types.+ let contentTypesEntry = mkContentTypesEntry epochtime imgs headers footers refArchive+ let relEntry = mkDocumentRelsEntry epochtime baserels imgs (stExternalLinks st)+ let contentEntry = toEntry "word/document.xml" epochtime+ (BL.fromStrict $ UTF8.fromText contents)+ let footnotesEntry = mkFootnotesEntry epochtime footnotes+ let footnoteRelEntry = mkFootnoteRelsEntry epochtime (stExternalLinks st)+ let commentsEntry = mkCommentsEntry epochtime comments+ let styleEntry = mkStylesEntry epochtime styledoc styleMaps st opts+ numEntry <- mkNumberingEntry refArchive distArchive epochtime (stLists st)+ let docPropsEntry = mkCorePropsEntry epochtime utctime meta+ let customPropsEntry = mkCustomPropsEntry epochtime meta+ let relsEntry = mkPackageRelsEntry epochtime++ -- we use dist archive for settings.xml, because Word sometimes+ -- adds references to footnotes or endnotes we don't have...+ -- we do, however, copy some settings over from reference+ settingsEntry <- copyChildren refArchive distArchive "word/settings.xml"+ epochtime settingsElementNames++ -- Phase 8: Archive assembly+ let toImageEntry (_, path, _, img) = toEntry ("word/" ++ path) epochtime $ toLazy img+ let imageEntries = map toImageEntry imgs++ refEntries <- collectReferenceEntries refArchive distArchive headers footers++ let archive = foldr addEntryToArchive emptyArchive $+ contentTypesEntry : relsEntry : contentEntry : relEntry :+ footnoteRelEntry : numEntry : styleEntry : footnotesEntry :+ commentsEntry :+ docPropsEntry : customPropsEntry :+ settingsEntry :+ imageEntries ++ refEntries+ return $ fromArchive archive++newParaPropToOpenXml :: ParaStyleName -> Element+newParaPropToOpenXml (fromStyleName -> s) =+ let styleId = T.filter (not . isSpace) s+ in mknode "w:style" [ ("w:type", "paragraph")+ , ("w:customStyle", "1")+ , ("w:styleId", styleId)]+ [ mknode "w:name" [("w:val", s)] ()+ , mknode "w:basedOn" [("w:val","BodyText")] ()+ , mknode "w:qFormat" [] ()+ ]++newTextPropToOpenXml :: CharStyleName -> Element+newTextPropToOpenXml (fromStyleName -> s) =+ let styleId = T.filter (not . isSpace) s+ in mknode "w:style" [ ("w:type", "character")+ , ("w:customStyle", "1")+ , ("w:styleId", styleId)]+ [ mknode "w:name" [("w:val", s)] ()+ , mknode "w:basedOn" [("w:val","BodyTextChar")] ()+ ]++styleToOpenXml :: StyleMaps -> Style -> [Element]+styleToOpenXml sm style =+ maybeToList parStyle ++ mapMaybe toStyle alltoktypes+ where alltoktypes = enumFromTo KeywordTok NormalTok+ toStyle toktype | hasStyleName (fromString $ show toktype) (smCharStyle sm) = Nothing+ | otherwise = Just $+ mknode "w:style" [("w:type","character"),+ ("w:customStyle","1"),("w:styleId", tshow toktype)]+ [ mknode "w:name" [("w:val", tshow toktype)] ()+ , mknode "w:basedOn" [("w:val","VerbatimChar")] ()+ , mknode "w:rPr" [] $+ [ mknode "w:b" [] () | tokFeature tokenBold toktype ] +++ [ mknode "w:i" [] () | tokFeature tokenItalic toktype ] +++ [ mknode "w:color" [("w:val", tokCol toktype)] ()+ | tokCol toktype /= "auto" ] +++ [ mknode "w:u" [] () | tokFeature tokenUnderline toktype ] +++ [ mknode "w:shd" [("w:val","clear")+ ,("w:fill",tokBg toktype)] ()+ | tokBg toktype /= "auto" ]+ ]+ tokStyles = tokenStyles style+ tokFeature f toktype = maybe False f $ M.lookup toktype tokStyles+ tokCol toktype = maybe "auto" (T.pack . drop 1 . fromColor)+ $ (tokenColor =<< M.lookup toktype tokStyles)+ `mplus` defaultColor style+ tokBg toktype = maybe "auto" (T.pack . drop 1 . fromColor)+ $ (tokenBackground =<< M.lookup toktype tokStyles)+ `mplus` backgroundColor style+ parStyle | hasStyleName "Source Code" (smParaStyle sm) = Nothing+ | otherwise = Just $+ mknode "w:style" [("w:type","paragraph"),+ ("w:customStyle","1"),("w:styleId","SourceCode")]+ [ mknode "w:name" [("w:val","Source Code")] ()+ , mknode "w:basedOn" [("w:val","Normal")] ()+ , mknode "w:link" [("w:val","VerbatimChar")] ()+ , mknode "w:pPr" []+ $ mknode "w:wordWrap" [("w:val","off")] ()+ :+ maybe [] (\col -> [mknode "w:shd" [("w:val","clear"),("w:fill", T.pack $ drop 1 $ fromColor col)] ()]) (backgroundColor style)+ ]++copyChildren :: (PandocMonad m)+ => Archive -> Archive -> String -> Integer -> [Text] -> m Entry+copyChildren refArchive distArchive path timestamp elNames = do+ ref <- parseXml refArchive distArchive path+ dist <- parseXml distArchive distArchive path+ els <- foldM (addEl ref dist) [] (reverse elNames)+ return $ toEntry path timestamp+ $ renderXml dist{ elContent = map cleanElem els }+ where+ addEl ref dist els name =+ case filterChildName (hasName name) ref `mplus`+ filterChildName (hasName name) dist of+ Just el -> pure (el : els)+ Nothing -> pure els+ hasName name = (== name) . qName+ cleanElem el@Element{elName=name} = Elem el{elName=name{qURI=Nothing}}++-- this is the lowest number used for a list numId+baseListId :: Int+baseListId = 1000++-- | Standard XML namespace attributes for docx elements+stdAttributes :: [(Text, Text)]+stdAttributes =+ [("xmlns:w","http://schemas.openxmlformats.org/wordprocessingml/2006/main")+ ,("xmlns:m","http://schemas.openxmlformats.org/officeDocument/2006/math")+ ,("xmlns:r","http://schemas.openxmlformats.org/officeDocument/2006/relationships")+ ,("xmlns:o","urn:schemas-microsoft-com:office:office")+ ,("xmlns:v","urn:schemas-microsoft-com:vml")+ ,("xmlns:w10","urn:schemas-microsoft-com:office:word")+ ,("xmlns:a","http://schemas.openxmlformats.org/drawingml/2006/main")+ ,("xmlns:pic","http://schemas.openxmlformats.org/drawingml/2006/picture")+ ,("xmlns:wp","http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing")]++-- | Settings elements to copy from reference.docx (order matters)+settingsElementNames :: [Text]+settingsElementNames =+ [ "writeProtection"+ , "view"+ , "zoom"+ , "removePersonalInformation"+ , "removeDateAndTime"+ , "doNotDisplayPageBoundaries"+ , "displayBackgroundShape"+ , "printPostScriptOverText"+ , "printFractionalCharacterWidth"+ , "printFormsData"+ , "embedTrueTypeFonts"+ , "embedSystemFonts"+ , "saveSubsetFonts"+ , "saveFormsData"+ , "mirrorMargins"+ , "alignBordersAndEdges"+ , "bordersDoNotSurroundHeader"+ , "bordersDoNotSurroundFooter"+ , "gutterAtTop"+ , "hideSpellingErrors"+ , "hideGrammaticalErrors"+ , "activeWritingStyle"+ , "proofState"+ , "formsDesign"+ , "attachedTemplate"+ , "linkStyles"+ , "stylePaneFormatFilter"+ , "stylePaneSortMethod"+ , "documentType"+ , "mailMerge"+ , "revisionView"+ , "trackRevisions"+ , "doNotTrackMoves"+ , "doNotTrackFormatting"+ , "documentProtection"+ , "autoFormatOverride"+ , "styleLockTheme"+ , "styleLockQFSet"+ , "defaultTabStop"+ , "autoHyphenation"+ , "consecutiveHyphenLimit"+ , "hyphenationZone"+ , "doNotHyphenateCaps"+ , "showEnvelope"+ , "summaryLength"+ , "clickAndTypeStyle"+ , "defaultTableStyle"+ , "evenAndOddHeaders"+ , "bookFoldRevPrinting"+ , "bookFoldPrinting"+ , "bookFoldPrintingSheets"+ , "drawingGridHorizontalSpacing"+ , "drawingGridVerticalSpacing"+ , "displayHorizontalDrawingGridEvery"+ , "displayVerticalDrawingGridEvery"+ , "doNotUseMarginsForDrawingGridOrigin"+ , "drawingGridHorizontalOrigin"+ , "drawingGridVerticalOrigin"+ , "doNotShadeFormData"+ , "noPunctuationKerning"+ , "characterSpacingControl"+ , "printTwoOnOne"+ , "strictFirstAndLastChars"+ , "noLineBreaksAfter"+ , "noLineBreaksBefore"+ , "savePreviewPicture"+ , "doNotValidateAgainstSchema"+ , "saveInvalidXml"+ , "ignoreMixedContent"+ , "alwaysShowPlaceholderText"+ , "doNotDemarcateInvalidXml"+ , "saveXmlDataOnly"+ , "useXSLTWhenSaving"+ , "saveThroughXslt"+ , "showXMLTags"+ , "alwaysMergeEmptyNamespace"+ , "updateFields"+ , "hdrShapeDefaults"+ -- , "footnotePr" -- this can cause problems, see #9522+ -- , "endnotePr"+ , "compat"+ , "docVars"+ , "rsids"+ , "attachedSchema"+ , "themeFontLang"+ , "clrSchemeMapping"+ , "doNotIncludeSubdocsInStats"+ , "doNotAutoCompressPictures"+ , "forceUpgrade"+ , "captions"+ , "readModeInkLockDown"+ , "smartTagType"+ , "shapeDefaults"+ , "doNotEmbedSmartTags"+ , "decimalSymbol"+ , "listSeparator" ]++mkNumbering :: [ListMarker] -> [Element]+mkNumbering lists =+ elts ++ zipWith mkNum lists [baseListId..(baseListId + length lists - 1)]+ where elts = map mkAbstractNum (nubOrd lists)++mkNum :: ListMarker -> Int -> Element+mkNum marker numid =+ mknode "w:num" [("w:numId",tshow numid)]+ $ mknode "w:abstractNumId" [("w:val",listMarkerToId marker)] ()+ : case marker of+ NoMarker -> []+ BulletMarker -> []+ CheckboxMarker _ -> []+ NumberMarker _ _ start ->+ map (\lvl -> mknode "w:lvlOverride" [("w:ilvl",tshow (lvl :: Int))]+ $ mknode "w:startOverride" [("w:val",tshow start)] ())+ [0..maxListLevel]++mkAbstractNum :: ListMarker -> Element+mkAbstractNum marker =+ mknode "w:abstractNum" [("w:abstractNumId",listMarkerToId marker)]+ $ mknode "w:nsid" [("w:val", T.justifyRight 8 '0' ("A" <> listMarkerToId marker))] ()+ : mknode "w:multiLevelType" [("w:val","multilevel")] ()+ : map (mkLvl marker)+ [0..maxListLevel]++mkLvl :: ListMarker -> Int -> Element+mkLvl marker lvl =+ mknode "w:lvl" [("w:ilvl",tshow lvl)] $+ (case marker of+ NumberMarker{} -> [mknode "w:start" [("w:val",start)] ()]+ _ -> []) +++ [ mknode "w:numFmt" [("w:val",fmt)] ()+ , mknode "w:lvlText" [("w:val", lvltxt)] ()+ , mknode "w:lvlJc" [("w:val","left")] ()+ , mknode "w:pPr" [] $+ mknode "w:ind" [ ("w:left",tshow $ lvl * step + step)+ , ("w:hanging",tshow hang)+ ] ()+ ] +++ maybe [] (\font ->+ [ mknode "w:rPr" []+ [ mknode "w:rFonts" [ ("w:ascii", font)+ , ("w:hAnsi", font)+ , ("w:cs", font)+ , ("w:hint", "default") ] () ]]) mbfont+ where (fmt, lvltxt, mbfont, start) =+ case marker of+ NoMarker -> ("bullet"," ", Nothing, "1")+ BulletMarker -> bulletFor lvl+ CheckboxMarker False -> ("bullet","\9744", Nothing, "1")+ CheckboxMarker True -> ("bullet","\9746", Nothing, "1")+ NumberMarker st de n -> (styleFor st lvl+ ,patternFor de ("%" <> tshow (lvl + 1))+ ,Nothing+ ,tshow n)+ step = 720+ hang :: Int+ hang = 360+ bulletFor 0 = ("bullet", "\xf0b7", Just "Symbol", "1") -- filled circle+ bulletFor 1 = ("bullet", "o", Just "Courier New", "1") -- open o+ bulletFor 2 = ("bullet", "\xf0a7", Just "Wingdings", "1") -- closed box+ bulletFor x = bulletFor (x `mod` 3)+ styleFor UpperAlpha _ = "upperLetter"+ styleFor LowerAlpha _ = "lowerLetter"+ styleFor UpperRoman _ = "upperRoman"+ styleFor LowerRoman _ = "lowerRoman"+ styleFor Decimal _ = "decimal"+ styleFor DefaultStyle 0 = "decimal"+ styleFor DefaultStyle 1 = "lowerLetter"+ styleFor DefaultStyle 2 = "lowerRoman"+ styleFor DefaultStyle 3 = "decimal"+ styleFor DefaultStyle 4 = "lowerLetter"+ styleFor DefaultStyle 5 = "lowerRoman"+ styleFor DefaultStyle x = styleFor DefaultStyle (x `mod` 6)+ styleFor _ _ = "decimal"+ patternFor OneParen s = s <> ")"+ patternFor TwoParens s = "(" <> s <> ")"+ patternFor _ s = s <> "."++-- | Build language transformer function for modifying XML elements.+-- Navigates directly to w:docDefaults/w:rPr/w:lang instead of generic traversal.+mkLangTransformer :: Maybe Lang -> (Element -> Element)+mkLangTransformer Nothing = id+mkLangTransformer (Just lang) = modifyAtPath path updateLangAttrs+ where+ -- Path is: w:docDefaults / w:rPrDefault / w:rPr / w:lang+ path = [named "docDefaults", named "rPrDefault", named "rPr", named "lang"]+ named n = (== n) . qName++ updateLangAttrs e+ | isEastAsianLang lang = e{ elAttribs = map (setattr "eastAsia") $ elAttribs e }+ | isBidiLang lang = e{ elAttribs = map (setattr "bidi") $ elAttribs e }+ | otherwise = e{ elAttribs = map (setattr "val") $ elAttribs e }++ setattr attrname (XML.Attr qn@(QName s _ _) _)+ | s == attrname = XML.Attr qn (renderLang lang)+ setattr _ x = x++ isEastAsianLang Lang{ langLanguage = l } = l == "zh" || l == "ja" || l == "ko"+ isBidiLang Lang{ langLanguage = l } = l == "he" || l == "ar"++-- | Modify an element at a specific path in the XML tree.+-- The path is a list of predicates that match element names at each level.+modifyAtPath :: [(QName -> Bool)] -> (Element -> Element) -> Element -> Element+modifyAtPath [] f e = f e+modifyAtPath (p:ps) f e = e{ elContent = map go (elContent e) }+ where+ go (Elem el) | p (elName el) = Elem (modifyAtPath ps f el)+ go c = c++-- | Load reference and distribution archives+loadArchives :: PandocMonad m+ => WriterOptions+ -> m (Archive, Archive, Maybe Text, UTCTime)+loadArchives opts = do+ username <- P.lookupEnv "USERNAME"+ utctime <- P.getTimestamp+ oldUserDataDir <- P.getUserDataDir+ P.setUserDataDir Nothing+ res <- readDefaultDataFile "reference.docx"+ P.setUserDataDir oldUserDataDir+ let distArchive = toArchive $ BL.fromStrict res+ refArchive <- case writerReferenceDoc opts of+ Just f -> toArchive . BL.fromStrict . fst+ <$> P.fetchItem (T.pack f)+ Nothing -> toArchive . BL.fromStrict <$>+ readDataFile "reference.docx"+ return (refArchive, distArchive, username, utctime)++-- | Extract page dimensions from template+extractPageLayout :: PandocMonad m+ => Archive -> Archive -> m (Maybe Element, Maybe Integer)+extractPageLayout refArchive distArchive = do+ parsedDoc <- parseXml refArchive distArchive "word/document.xml"+ let wname f qn = qPrefix qn == Just "w" && f (qName qn)+ let mbsectpr = filterElementName (wname (=="sectPr")) parsedDoc++ -- Gets the template size+ let mbpgsz = mbsectpr >>= filterElementName (wname (=="pgSz"))+ let mbAttrSzWidth = mbpgsz >>= lookupAttrBy ((=="w") . qName) . elAttribs++ let mbpgmar = mbsectpr >>= filterElementName (wname (=="pgMar"))+ let mbAttrMarLeft = mbpgmar >>= lookupAttrBy ((=="left") . qName) . elAttribs+ let mbAttrMarRight = mbpgmar >>= lookupAttrBy ((=="right") . qName) . elAttribs++ -- Get the available area (converting the size and the margins to int and+ -- doing the difference+ let pgContentWidth = do+ w <- mbAttrSzWidth >>= safeRead+ r <- mbAttrMarRight >>= safeRead+ l <- mbAttrMarLeft >>= safeRead+ pure $ w - r - l++ return (mbsectpr, pgContentWidth)++-- | Parse and augment relationships from reference.docx+extractRelationships :: PandocMonad m+ => Archive -> Archive+ -> m ([Element], [Element], [Element], Int)+extractRelationships refArchive distArchive = do+ let isImageNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"+ let isHeaderNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header"+ let isFooterNode e = findAttr (QName "Type" Nothing Nothing) e == Just "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"+ parsedRels <- filterElements+ (\e -> isImageNode e || isHeaderNode e || isFooterNode e)+ <$> parseXml refArchive distArchive "word/_rels/document.xml.rels"+ let getRelId e =+ case findAttr (QName "Id" Nothing Nothing) e of+ Just ident -> T.stripPrefix "rId" ident >>= safeRead+ Nothing -> Nothing+ let relIds = mapMaybe getRelId parsedRels+ let maxRelId = if null relIds then 0 else maximum relIds++ let headers = filter isHeaderNode parsedRels+ let footers = filter isFooterNode parsedRels+ -- word/_rels/document.xml.rels+ let addBaseRel (url', target') (maxId, rels) =+ case [e | e <- rels+ , findAttr (QName "Target" Nothing Nothing) e ==+ Just target'] of+ [] -> (maxId + 1, mknode "Relationship"+ [("Type",url')+ ,("Id","rId" <> tshow (maxId + 1))+ ,("Target",target')] () : rels)+ _ -> (maxId, rels)++ let (newMaxRelId, baserels) = foldr addBaseRel (maxRelId, parsedRels)+ [("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",+ "numbering.xml")+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",+ "styles.xml")+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",+ "settings.xml")+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",+ "webSettings.xml")+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",+ "fontTable.xml")+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",+ "theme/theme1.xml")+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",+ "footnotes.xml")+ ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",+ "comments.xml")+ ]++ return (baserels, headers, footers, newMaxRelId)++-- | Create footnotes XML entry+mkFootnotesEntry :: Integer -> [Element] -> Entry+mkFootnotesEntry epochtime footnotes =+ let notes = mknode "w:footnotes" stdAttributes footnotes+ in toEntry "word/footnotes.xml" epochtime $ renderXml notes++-- | Create footnote relationships entry+mkFootnoteRelsEntry :: Integer -> M.Map Text Text -> Entry+mkFootnoteRelsEntry epochtime externalLinks =+ let linkrels = map toLinkRel $ M.toList externalLinks+ toLinkRel (src, ident) = mknode "Relationship"+ [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink")+ ,("Id",ident)+ ,("Target",src)+ ,("TargetMode","External")] ()+ in toEntry "word/_rels/footnotes.xml.rels" epochtime+ $ renderXml $ mknode "Relationships"+ [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]+ linkrels++-- | Create comments XML entry+mkCommentsEntry :: Integer -> [Element] -> Entry+mkCommentsEntry epochtime comments =+ toEntry "word/comments.xml" epochtime+ $ renderXml $ mknode "w:comments" stdAttributes comments++-- | Create package-level relationships entry+mkPackageRelsEntry :: Integer -> Entry+mkPackageRelsEntry epochtime =+ let rels = mknode "Relationships"+ [("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")]+ $ map (\attrs -> mknode "Relationship" attrs ())+ [ [("Id","rId1")+ ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")+ ,("Target","word/document.xml")]+ , [("Id","rId4")+ ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties")+ ,("Target","docProps/app.xml")]+ , [("Id","rId3")+ ,("Type","http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties")+ ,("Target","docProps/core.xml")]+ , [("Id","rId5")+ ,("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties")+ ,("Target","docProps/custom.xml")]+ ]+ in toEntry "_rels/.rels" epochtime $ renderXml rels++-- | Create content types manifest entry+mkContentTypesEntry :: Integer+ -> [(String, String, Maybe MimeType, B.ByteString)] -- imgs+ -> [Element] -- headers+ -> [Element] -- footers+ -> Archive -- refArchive+ -> Entry+mkContentTypesEntry epochtime imgs headers footers refArchive =+ let mkOverrideNode (part', contentType') = mknode "Override"+ [("PartName", T.pack part')+ ,("ContentType", contentType')] ()+ mkImageOverride (_, imgpath, mbMimeType, _) =+ mkOverrideNode ("/word/" <> imgpath,+ fromMaybe "application/octet-stream" mbMimeType)+ mkMediaOverride imgpath =+ mkOverrideNode ("/" <> imgpath, getMimeTypeDef imgpath)+ unrelativize ('/':xs) = '/':xs+ unrelativize xs = "/word/" ++ xs+ overrides = map mkOverrideNode (+ [("/word/webSettings.xml",+ "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml")+ ,("/word/numbering.xml",+ "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml")+ ,("/word/settings.xml",+ "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml")+ ,("/word/theme/theme1.xml",+ "application/vnd.openxmlformats-officedocument.theme+xml")+ ,("/word/fontTable.xml",+ "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml")+ ,("/docProps/app.xml",+ "application/vnd.openxmlformats-officedocument.extended-properties+xml")+ ,("/docProps/core.xml",+ "application/vnd.openxmlformats-package.core-properties+xml")+ ,("/docProps/custom.xml",+ "application/vnd.openxmlformats-officedocument.custom-properties+xml")+ ,("/word/styles.xml",+ "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml")+ ,("/word/document.xml",+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")+ ,("/word/comments.xml",+ "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml")+ ,("/word/footnotes.xml",+ "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml")+ ] +++ map (\x -> (maybe "" (unrelativize . T.unpack) (extractTarget x),+ "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml")) headers +++ map (\x -> (maybe "" (unrelativize . T.unpack) (extractTarget x),+ "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml")) footers) +++ map mkImageOverride imgs +++ [ mkMediaOverride (eRelativePath e)+ | e <- zEntries refArchive+ , "word/media/" `isPrefixOf` eRelativePath e+ , not ("/" `isSuffixOf` eRelativePath e) ]+ mkDefaultNode (ext, mt) =+ mknode "Default" [("Extension",ext),("ContentType",mt)] ()+ defaultnodes = map mkDefaultNode+ [("xml", "application/xml"),+ ("rels", "application/vnd.openxmlformats-package.relationships+xml"),+ ("odttf",+ "application/vnd.openxmlformats-officedocument.obfuscatedFont")]+ contentTypesDoc = mknode "Types"+ [("xmlns","http://schemas.openxmlformats.org/package/2006/content-types")]+ $ defaultnodes ++ overrides+ in toEntry "[Content_Types].xml" epochtime $ renderXml contentTypesDoc++-- | Create document relationships entry+mkDocumentRelsEntry :: Integer+ -> [Element] -- baserels+ -> [(String, String, Maybe MimeType, B.ByteString)] -- imgs+ -> M.Map Text Text -- externalLinks+ -> Entry+mkDocumentRelsEntry epochtime baserels imgs externalLinks =+ let toImgRel (ident, path, _, _) = mknode "Relationship"+ [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/image")+ ,("Id",T.pack ident)+ ,("Target",T.pack path)] ()+ imgrels = map toImgRel imgs+ toLinkRel (src, ident) = mknode "Relationship"+ [("Type","http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink")+ ,("Id",ident)+ ,("Target",src)+ ,("TargetMode","External")] ()+ linkrels = map toLinkRel $ M.toList externalLinks+ reldoc = mknode "Relationships"+ [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]+ $ baserels ++ imgrels ++ linkrels+ in toEntry "word/_rels/document.xml.rels" epochtime $ renderXml reldoc++-- | Create styles entry with dynamic additions+mkStylesEntry :: Integer -> Element -> StyleMaps -> WriterState -> WriterOptions -> Entry+mkStylesEntry epochtime styledoc styleMaps st opts =+ let stylepath = "word/styles.xml"+ -- We only want to inject paragraph and text properties that+ -- are not already in the style map. Note that keys in the stylemap+ -- are normalized as lowercase.+ newDynamicParaProps = filter+ (\sty -> not $ hasStyleName sty $ smParaStyle styleMaps)+ (Set.toList $ stDynamicParaProps st)++ newDynamicTextProps = filter+ (\sty -> not $ hasStyleName sty $ smCharStyle styleMaps)+ (Set.toList $ stDynamicTextProps st)++ newstyles = map newParaPropToOpenXml newDynamicParaProps +++ map newTextPropToOpenXml newDynamicTextProps +++ (case writerHighlightMethod opts of+ Skylighting sty -> styleToOpenXml styleMaps sty+ DefaultHighlighting -> styleToOpenXml styleMaps+ defaultStyle+ _ -> [])+ styledoc' = styledoc{ elContent = elContent styledoc +++ map Elem newstyles }+ in toEntry stylepath epochtime $ renderXml styledoc'++-- | Create core document properties entry+mkCorePropsEntry :: Integer -> UTCTime -> Meta -> Entry+mkCorePropsEntry epochtime utctime meta =+ let metaValueToText (MetaString s) = s+ metaValueToText (MetaInlines ils) = stringify ils+ metaValueToText (MetaBlocks bs) = stringify bs+ metaValueToText (MetaBool b) = T.pack (show b)+ metaValueToText _ = ""+ keywords = case lookupMeta "keywords" meta of+ Just (MetaList xs) -> map metaValueToText xs+ _ -> []+ docPropsPath = "docProps/core.xml"+ extraCoreProps = ["subject","lang","category","description"]+ extraCorePropsMap = M.fromList $ zip extraCoreProps+ ["dc:subject","dc:language","cp:category","dc:description"]+ lookupMetaString' :: Text -> Meta -> Text+ lookupMetaString' key' meta' =+ case key' of+ "description" -> T.intercalate "_x000d_\n"+ (map stringify $ lookupMetaBlocks "description" meta')+ key'' -> lookupMetaString key'' meta'++ docProps = mknode "cp:coreProperties"+ [("xmlns:cp","http://schemas.openxmlformats.org/package/2006/metadata/core-properties")+ ,("xmlns:dc","http://purl.org/dc/elements/1.1/")+ ,("xmlns:dcterms","http://purl.org/dc/terms/")+ ,("xmlns:dcmitype","http://purl.org/dc/dcmitype/")+ ,("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")]+ $ mktnode "dc:title" [] (stringify $ docTitle meta)+ : mktnode "dc:creator" [] (T.intercalate "; " (map stringify $ docAuthors meta))+ : [ mktnode (M.findWithDefault "" k extraCorePropsMap) [] (lookupMetaString' k meta)+ | k <- M.keys (unMeta meta), k `elem` extraCoreProps]+ ++ mknode "cp:keywords" [] (T.intercalate ", " keywords)+ : (\x -> [ mknode "dcterms:created" [("xsi:type","dcterms:W3CDTF")] x+ , mknode "dcterms:modified" [("xsi:type","dcterms:W3CDTF")] x+ ]) (T.pack $ formatTime defaultTimeLocale "%FT%XZ" utctime)+ in toEntry docPropsPath epochtime $ renderXml docProps++-- | Create custom document properties entry+mkCustomPropsEntry :: Integer -> Meta -> Entry+mkCustomPropsEntry epochtime meta =+ let extraCoreProps = ["subject","lang","category","description"]+ customProperties :: [(Text, Text)]+ customProperties = [ (k, lookupMetaString k meta)+ | k <- M.keys (unMeta meta)+ , k `notElem` (["title", "author", "keywords"]+ ++ extraCoreProps)]+ mkCustomProp (k, v) pid = mknode "property"+ [("fmtid","{D5CDD505-2E9C-101B-9397-08002B2CF9AE}")+ ,("pid", tshow pid)+ ,("name", k)] $ mknode "vt:lpwstr" [] v+ customPropsPath = "docProps/custom.xml"+ customProps = mknode "Properties"+ [("xmlns","http://schemas.openxmlformats.org/officeDocument/2006/custom-properties")+ ,("xmlns:vt","http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes")+ ] $ zipWith mkCustomProp customProperties [(2 :: Int)..]+ in toEntry customPropsPath epochtime $ renderXml customProps++-- | Create numbering entry+mkNumberingEntry :: PandocMonad m+ => Archive -> Archive -> Integer -> [ListMarker] -> m Entry+mkNumberingEntry refArchive distArchive epochtime lists = do+ let numpath = "word/numbering.xml"+ numbering <- parseXml refArchive distArchive numpath+ let newNumElts = mkNumbering lists+ let pandocAdded e =+ case findAttrBy ((== "abstractNumId") . qName) e >>= safeRead of+ Just numid -> numid >= (990 :: Int)+ Nothing ->+ case findAttrBy ((== "numId") . qName) e >>= safeRead of+ Just numid -> numid >= (1000 :: Int)+ Nothing -> False+ let oldElts = filter (not . pandocAdded) $ onlyElems (elContent numbering)+ let allElts = oldElts ++ newNumElts+ return $ toEntry numpath epochtime $ renderXml numbering{ elContent =+ -- we want all the abstractNums first, then the nums,+ -- otherwise things break:+ [Elem e | e <- allElts+ , qName (elName e) == "abstractNum" ] +++ [Elem e | e <- allElts+ , qName (elName e) == "num" ] }++-- | Collect auxiliary entries from reference archive+collectReferenceEntries :: PandocMonad m+ => Archive -> Archive -> [Element] -> [Element]+ -> m [Entry]+collectReferenceEntries refArchive distArchive headers footers = do+ let entryFromArchive arch path =+ maybe (throwError $ PandocSomeError+ $ T.pack $ path ++ " missing in reference docx")+ return+ (findEntryByPath path arch `mplus` findEntryByPath path distArchive)+ docPropsAppEntry <- entryFromArchive refArchive "docProps/app.xml"+ themeEntry <- entryFromArchive refArchive "word/theme/theme1.xml"+ fontTableEntry <- entryFromArchive refArchive "word/fontTable.xml"+ let fontTableRelsEntries = maybeToList $+ findEntryByPath "word/_rels/fontTable.xml.rels" refArchive+ let fontEntries = [entry | entry <- zEntries refArchive+ , "word/fonts/" `isPrefixOf` (eRelativePath entry)]+ webSettingsEntry <- entryFromArchive refArchive "word/webSettings.xml"+ let unrelativize ('/':xs) = xs+ unrelativize xs = "word/" ++ xs+ headerFooterEntries <- mapM (entryFromArchive refArchive . unrelativize) $+ mapMaybe (fmap T.unpack . extractTarget)+ (headers ++ footers)+ let miscRelEntries = [ e | e <- zEntries refArchive+ , "word/_rels/" `isPrefixOf` eRelativePath e+ , ".xml.rels" `isSuffixOf` eRelativePath e+ , eRelativePath e /= "word/_rels/document.xml.rels"+ , eRelativePath e /= "word/_rels/footnotes.xml.rels" ]+ let otherMediaEntries = [ e | e <- zEntries refArchive+ , "word/media/" `isPrefixOf` eRelativePath e ]+ return $ docPropsAppEntry : themeEntry : fontTableEntry : webSettingsEntry+ : fontTableRelsEntries ++ fontEntries ++ headerFooterEntries+ ++ miscRelEntries ++ otherMediaEntries++extractTarget :: Element -> Maybe Text+extractTarget = findAttr (QName "Target" Nothing Nothing)
@@ -0,0 +1,1146 @@+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-}+{- |+ Module : Text.Pandoc.Writers.Docx+ Copyright : Copyright (C) 2012-2025 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' documents to docx.+-}+module Text.Pandoc.Writers.Docx.OpenXML ( writeOpenXML, maxListLevel ) where++import Control.Monad (when, unless)+import Control.Applicative ((<|>))+import Control.Monad.Except (catchError)+import Crypto.Hash (hashWith, SHA1(SHA1))+import qualified Data.ByteString.Lazy as BL+import Data.Char (isLetter, isSpace)+import Text.Pandoc.Char (isCJK)+import Data.Ord (comparing)+import Data.String (fromString)+import qualified Data.Map as M+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+import qualified Data.Text as T+import Data.Text (Text)+import Skylighting+import Text.DocLayout (hcat, vcat, literal, render)+import Text.Pandoc.Class (PandocMonad, report, getMediaBag)+import Text.Pandoc.Translations (Term(Abstract), translateTerm)+import Text.Pandoc.MediaBag (lookupMedia, MediaItem(..))+import qualified Text.Pandoc.Translations as Term+import qualified Text.Pandoc.Class.PandocMonad as P+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.UTF8 (fromText)+import Text.Pandoc.Definition+import Text.Pandoc.Highlighting (highlight)+import Text.Pandoc.Templates (compileDefaultTemplate, renderTemplate)+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging+import Text.Pandoc.MIME (extensionFromMimeType, getMimeType)+import Text.Pandoc.Options+import Text.Pandoc.Writers.Docx.StyleMap+import Text.Pandoc.Writers.Docx.Table as Table+import Text.Pandoc.Writers.Docx.Types+import Text.Pandoc.Shared+import Text.Pandoc.Walk+import qualified Text.Pandoc.Writers.GridTable as Grid+import Text.Pandoc.Writers.Math+import Text.Pandoc.Writers.Shared+import Text.TeXMath+import Text.Pandoc.Writers.OOXML+import Text.Pandoc.XML.Light as XML+import Data.List (sortBy, intercalate, groupBy)++-- from wml.xsd EG_RPrBase+rPrTagOrder :: M.Map Text Int+rPrTagOrder =+ M.fromList+ (zip [ "rStyle"+ , "rFonts"+ , "b"+ , "bCs"+ , "i"+ , "iCs"+ , "caps"+ , "smallCaps"+ , "strike"+ , "dstrike"+ , "outline"+ , "shadow"+ , "emboss"+ , "imprint"+ , "noProof"+ , "snapToGrid"+ , "vanish"+ , "webHidden"+ , "color"+ , "spacing"+ , "w"+ , "kern"+ , "position"+ , "sz"+ , "szCs"+ , "highlight"+ , "u"+ , "effect"+ , "bdr"+ , "shd"+ , "fitText"+ , "vertAlign"+ , "rtl"+ , "cs"+ , "em"+ , "lang"+ , "eastAsianLayout"+ , "specVanish"+ , "oMath"+ ] [0..])++sortSquashed :: [Element] -> [Element]+sortSquashed l =+ sortBy (comparing tagIndex) l+ where+ tagIndex :: Element -> Int+ tagIndex el =+ fromMaybe 0 (M.lookup tag rPrTagOrder)+ where tag = (qName . elName) el++squashProps :: EnvProps -> [Element]+squashProps (EnvProps Nothing es) = sortSquashed es+squashProps (EnvProps (Just e) es) = sortSquashed (e : es)++-- | Certain characters are invalid in XML even if escaped.+-- See #1992+stripInvalidChars :: Text -> Text+stripInvalidChars = T.filter isValidChar++-- | See XML reference+isValidChar :: Char -> Bool+isValidChar '\t' = True+isValidChar '\n' = True+isValidChar '\r' = True+isValidChar '\xFFFE' = False+isValidChar '\xFFFF' = False+isValidChar c = (' ' <= c && c <= '\xD7FF') || ('\xE000' <= c)++-- this is the lowest number used for a list numId+baseListId :: Int+baseListId = 1000++getNumId :: (PandocMonad m) => WS m Int+getNumId = gets (((baseListId - 1) +) . length . stLists)++makeTOC :: (PandocMonad m) => WriterOptions -> WS m [Element]+makeTOC opts = do+ let depth = "1-" <> tshow (writerTOCDepth opts)+ let tocCmd = "TOC \\o \"" <> depth <> "\" \\h \\z \\u"+ tocTitle <- gets stTocTitle+ title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para tocTitle])+ return+ [mknode "w:sdt" [] [+ mknode "w:sdtPr" [] (+ mknode "w:docPartObj" []+ [mknode "w:docPartGallery" [("w:val","Table of Contents")] (),+ mknode "w:docPartUnique" [] ()]+ -- w:docPartObj+ ), -- w:sdtPr+ mknode "w:sdtContent" [] (title ++ [ Elem $+ mknode "w:p" [] (+ mknode "w:r" [] [+ mknode "w:fldChar" [("w:fldCharType","begin"),("w:dirty","true")] (),+ mknode "w:instrText" [("xml:space","preserve")] tocCmd,+ mknode "w:fldChar" [("w:fldCharType","separate")] (),+ mknode "w:fldChar" [("w:fldCharType","end")] ()+ ] -- w:r+ ) -- w:p+ ])+ ]] -- w:sdt++makeLOF :: (PandocMonad m) => WriterOptions -> WS m [Element]+makeLOF opts = do+ let lofCmd = "TOC \\h \\z \\t \"Image Caption\" \\c" :: Text+ lofTitle <- B.toList <$> B.text <$> translateTerm Term.ListOfFigures+ title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para lofTitle])+ return+ [mknode "w:sdt" [] [+ mknode "w:sdtPr" [] (+ mknode "w:docPartObj" []+ [mknode "w:docPartGallery" [("w:val","List of Figures")] (),+ mknode "w:docPartUnique" [] ()]+ -- w:docPartObj+ ), -- w:sdtPr+ mknode "w:sdtContent" [] (title ++ [ Elem $+ mknode "w:p" [] (+ mknode "w:r" [] [+ mknode "w:fldChar" [("w:fldCharType","begin"),("w:dirty","true")] (),+ mknode "w:instrText" [("xml:space","preserve")] lofCmd,+ mknode "w:fldChar" [("w:fldCharType","separate")] (),+ mknode "w:fldChar" [("w:fldCharType","end")] ()+ ] -- w:r+ ) -- w:p+ ]) -- w:sdtContent+ ]] -- w:sdt++makeLOT :: (PandocMonad m) => WriterOptions -> WS m [Element]+makeLOT opts = do+ let lotCmd = "TOC \\h \\z \\t \"Table Caption\" \\c" :: Text+ lotTitle <- B.toList <$> B.text <$> translateTerm Term.ListOfTables+ title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para lotTitle])+ return+ [mknode "w:sdt" [] [+ mknode "w:sdtPr" [] (+ mknode "w:docPartObj" []+ [mknode "w:docPartGallery" [("w:val","List of Tables")] (),+ mknode "w:docPartUnique" [] ()]+ -- w:docPartObj+ ), -- w:sdtPr+ mknode "w:sdtContent" [] (title ++ [ Elem $+ mknode "w:p" [] (+ mknode "w:r" [] [+ mknode "w:fldChar" [("w:fldCharType","begin"),("w:dirty","true")] (),+ mknode "w:instrText" [("xml:space","preserve")] lotCmd,+ mknode "w:fldChar" [("w:fldCharType","separate")] (),+ mknode "w:fldChar" [("w:fldCharType","end")] ()+ ] -- w:r+ ) -- w:p+ ]) -- 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+ => WriterOptions -> Pandoc+ -> WS m (Text, [Element], [Element])+writeOpenXML opts (Pandoc meta blocks) = do+ setupTranslations meta+ let includeTOC = writerTableOfContents opts || lookupMetaBool "toc" meta+ let includeLOF = writerListOfFigures opts || lookupMetaBool "lof" meta+ let includeLOT = writerListOfTables opts || lookupMetaBool "lot" meta+ abstractTitle <- case lookupMeta "abstract-title" meta of+ Just (MetaBlocks bs) -> pure $ stringify bs+ Just (MetaInlines ils) -> pure $ stringify ils+ Just (MetaString s) -> pure s+ _ -> translateTerm Abstract+ abstract <-+ case lookupMetaBlocks "abstract" meta of+ [] -> return mempty+ xs -> vcat . map (literal . showContent) <$>+ withParaPropM (pStyleM "Abstract") (blocksToOpenXML opts xs)++ let toInlineMeta field = hcat . map (literal . showContent) <$>+ inlinesToOpenXML opts (lookupMetaInlines field meta)++ title <- toInlineMeta "title"+ subtitle <- toInlineMeta "subtitle"+ date <- toInlineMeta "date"++ author <- mapM+ (fmap (hcat . map (literal . showContent)) . inlinesToOpenXML opts)+ (docAuthors meta)++ doc' <- setFirstPara >> blocksToOpenXML opts blocks+ let body = vcat $ map (literal . showContent) doc'+ notes' <- gets (reverse . stFootnotes)+ comments <- gets (reverse . stComments)+ let toComment (kvs, ils) = do+ annotation <- inlinesToOpenXML opts ils+ return $+ mknode "w:comment" [("w:" <> k, v) | (k,v) <- kvs]+ [ mknode "w:p" [] $+ map Elem+ [ mknode "w:pPr" []+ [ mknode "w:pStyle" [("w:val", "CommentText")] () ]+ , mknode "w:r" []+ [ mknode "w:rPr" []+ [ mknode "w:rStyle" [("w:val", "CommentReference")] ()+ ]+ , mknode "w:annotationRef" [] ()+ ]+ ] ++ annotation+ ]+ comments' <- mapM toComment comments+ toc <- if includeTOC+ then makeTOC opts+ else return []+ lof <- if includeLOF+ then makeLOF opts+ else return []+ lot <- if includeLOT+ then makeLOT opts+ else return []+ metadata <- metaToContext opts+ (fmap (vcat . map (literal . showContent)) . blocksToOpenXML opts)+ (fmap (hcat . map (literal . showContent)) . inlinesToOpenXML opts)+ meta+ cStyleMap <- gets (smParaStyle . stStyleMaps)+ let styleIdOf name = fromStyleId $ getStyleIdFromName name cStyleMap+ renderedSectPr <- maybe mempty ppElement <$> asks envSectPr++ let context = resetField "body" body+ . resetField "toc"+ (vcat (map (literal . showElement) toc))+ . resetField "lof"+ (vcat (map (literal . showElement) lof))+ . resetField "lot"+ (vcat (map (literal . showElement) lot))+ . resetField "title" title+ . resetField "subtitle" subtitle+ . resetField "author" author+ . resetField "date" date+ . resetField "abstract-title" abstractTitle+ . resetField "abstract" abstract+ . resetField "title-style-id" (styleIdOf "Title")+ . resetField "subtitle-style-id" (styleIdOf "Subtitle")+ . resetField "author-style-id" (styleIdOf "Author")+ . resetField "date-style-id" (styleIdOf "Date")+ . resetField "abstract-title-style-id" (styleIdOf "AbstractTitle")+ . resetField "abstract-style-id" (styleIdOf "Abstract")+ . resetField "sectpr" renderedSectPr+ $ metadata+ tpl <- maybe (lift $ compileDefaultTemplate "openxml") pure $ writerTemplate opts+ let rendered = render Nothing $ renderTemplate tpl context+ return (rendered, notes', comments')++-- | 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)++isForeignRawBlock :: Block -> Bool+isForeignRawBlock (RawBlock format _) = format /= "openxml"+isForeignRawBlock _ = False++-- Word combines adjacent tables unless you put an empty paragraph between+-- them. See #4315.+separateTables :: [Block] -> [Block]+separateTables [] = []+separateTables (x@Table{}:xs@(Table{}:_)) =+ x : RawBlock (Format "openxml") "<w:p />" : separateTables xs+separateTables (x:xs) = x : separateTables xs++rStyleM :: (PandocMonad m) => CharStyleName -> WS m XML.Element+rStyleM styleName = do+ cStyleMap <- gets (smCharStyle . stStyleMaps)+ let sty' = getStyleIdFromName styleName cStyleMap+ return $ mknode "w:rStyle" [("w:val", fromStyleId sty')] ()++getUniqueId :: (PandocMonad m) => WS m Text+getUniqueId = do+ n <- gets stCurId+ modify $ \st -> st{stCurId = n + 1}+ return $ tshow n++-- | Key for specifying user-defined docx styles.+dynamicStyleKey :: Text+dynamicStyleKey = "custom-style"++-- | Convert a Pandoc block element to OpenXML.+blockToOpenXML :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]+blockToOpenXML opts blk = withDirection $ blockToOpenXML' opts blk++blockToOpenXML' :: (PandocMonad m) => WriterOptions -> Block -> WS m [Content]+blockToOpenXML' opts (Div (ident,_classes,kvs) bs) = do+ stylemod <- case lookup dynamicStyleKey kvs of+ Just (fromString . T.unpack -> sty) -> do+ modify $ \s ->+ s{stDynamicParaProps = Set.insert sty+ (stDynamicParaProps s)}+ return $ withParaPropM (pStyleM sty)+ _ -> return id+ dirmod <- case lookup "dir" kvs of+ Just "rtl" -> return $ local (\env -> env { envRTL = True })+ Just "ltr" -> return $ local (\env -> env { envRTL = False })+ _ -> return id+ let (hs, bs') = if ident == "refs"+ then span isHeaderBlock bs+ else ([], bs)+ let bibmod = if ident == "refs"+ then withParaPropM (pStyleM "Bibliography")+ else id+ let langmod = case lookup "lang" kvs of+ Nothing -> id+ Just lang -> local (\env -> env{envLang = Just lang})+ header <- dirmod $ stylemod $ blocksToOpenXML opts hs+ contents <- dirmod $ bibmod $ stylemod $ langmod $ blocksToOpenXML opts bs'+ wrapBookmark ident $ header <> contents+blockToOpenXML' opts (Header lev (ident,_,kvs) lst) = do+ setFirstPara+ let isSection = case writerTopLevelDivision opts of+ TopLevelChapter -> lev == 1+ TopLevelPart -> lev <= 2+ _ -> False+ paraProps <- withParaPropM (pStyleM (fromString $ "Heading "++show lev)) $+ getParaProps False+ number <-+ if writerNumberSections opts+ then+ case lookup "number" kvs of+ Just n -> do+ num <- withTextPropM (rStyleM "SectionNumber")+ (inlineToOpenXML opts (Str n))+ return $ num ++ [Elem $ mknode "w:r" [] [mknode "w:tab" [] ()]]+ Nothing -> return []+ else return []+ contents <- (number ++) <$> inlinesToOpenXML opts lst+ -- Add section break before section-level headers, but not for the first one+ -- to avoid a blank first page (#10578, #11482).+ addSectionBreak <- if isSection+ then do+ isFirst <- gets stFirstSectionHeader+ if isFirst+ then do+ modify $ \s -> s { stFirstSectionHeader = False }+ pure id+ else sectionSeparator >>= \case+ Just sep -> pure (sep:)+ Nothing -> pure id+ else pure id+ addSectionBreak <$>+ if T.null ident+ then return [Elem $ mknode "w:p" [] (map Elem paraProps ++ contents)]+ else do+ let bookmarkName = ident+ modify $ \s -> s{ stSectionIds = Set.insert bookmarkName+ $ stSectionIds s }+ bookmarkedContents <- wrapBookmark bookmarkName contents+ return [Elem $ mknode "w:p" [] (map Elem paraProps ++ bookmarkedContents)]+blockToOpenXML' opts (Plain lst) = do+ isInTable <- gets stInTable+ isInList <- gets stInList+ let block = blockToOpenXML opts (Para lst)+ prop <- pStyleM "Compact"+ if isInTable || isInList+ then withParaProp prop block+ else block+blockToOpenXML' opts (Para lst)+ | null lst && not (isEnabled Ext_empty_paragraphs opts) = return []+ | [Math InlineMath _] <- lst+ = blockToOpenXML' opts (Para (lst ++ [Str "\x200B"])) -- see #11674+ -- we add a space to prevent Word from displaying the single+ -- inline math element with display math style+ | otherwise = do+ isFirstPara <- gets stFirstPara+ let displayMathPara = case lst of+ [x] -> isDisplayMath x+ _ -> False+ paraProps <- getParaProps displayMathPara+ bodyTextStyle <- pStyleM $ if isFirstPara+ then "First Paragraph"+ else "Body Text"+ let paraProps' = case paraProps of+ [] -> [mknode "w:pPr" [] [bodyTextStyle]]+ ps -> ps+ modify $ \s -> s { stFirstPara = False }+ contents <- inlinesToOpenXML opts lst+ return [Elem $ mknode "w:p" [] (map Elem paraProps' ++ contents)]+blockToOpenXML' opts (LineBlock lns) = blockToOpenXML opts $ linesToPara lns+blockToOpenXML' _ b@(RawBlock format str)+ | format == Format "openxml" = return [+ Text (CData CDataRaw str Nothing)+ ]+ | otherwise = do+ report $ BlockNotRendered b+ return []+blockToOpenXML' opts (BlockQuote blocks) = do+ inNote <- asks envInNote+ p <- withParaPropM (pStyleM+ (if inNote+ then "Footnote Block Text"+ else "Block Text"))+ $ blocksToOpenXML opts blocks+ setFirstPara+ return p+blockToOpenXML' opts (CodeBlock attrs@(ident, _, _) str) = do+ p <- withParaPropM (pStyleM "Source Code") (blockToOpenXML opts $ Para [Code attrs str])+ setFirstPara+ wrapBookmark ident p+blockToOpenXML' _ HorizontalRule = do+ setFirstPara+ return [ Elem $+ mknode "w:p" [] $ mknode "w:r" [] $ mknode "w:pict" []+ $ mknode "v:rect" [("style","width:0;height:1.5pt"),+ ("o:hralign","center"),+ ("o:hrstd","t"),("o:hr","t")] () ]+blockToOpenXML' opts (Table attr caption colspecs thead tbodies tfoot) = do+ -- Remove extra paragraph indentation due to list items (#5947).+ -- This means that tables in lists will not be indented, but it+ -- avoids unwanted indentation in each cell.+ content <- tableToOpenXML opts+ (local (\env -> env{ envListLevel = -1 }) . blocksToOpenXML opts)+ (Grid.toTable attr caption colspecs thead tbodies tfoot)+ let (tableId, _, _) = attr+ wrapBookmark tableId content+blockToOpenXML' opts el+ | BulletList lst <- el+ = case mapM toTaskListItem lst of+ Just items -> mconcat <$>+ mapM (\(checked, bs) -> addOpenXMLList (CheckboxMarker checked) [bs]) items+ Nothing -> addOpenXMLList BulletMarker lst+ | OrderedList (start, numstyle, numdelim) lst <- el+ = addOpenXMLList (NumberMarker numstyle numdelim start) lst+ where+ addOpenXMLList marker items = do+ addList marker+ numid <- getNumId+ exampleid <- case marker of+ NumberMarker Example _ _ -> gets stExampleId+ _ -> return Nothing+ l <- asList $ concat <$>+ mapM (listItemToOpenXML opts $ fromMaybe numid exampleid) items+ setFirstPara+ return l+blockToOpenXML' opts (DefinitionList items) = do+ l <- concat `fmap` mapM (definitionListItemToOpenXML opts) items+ setFirstPara+ return l+blockToOpenXML' opts (Figure (ident, _, _) (Caption _ longcapt) body) = do+ setFirstPara+ fignum <- gets stNextFigureNum+ unless (null longcapt) $ modify $ \st -> st{ stNextFigureNum = fignum + 1 }+ let refid = if T.null ident+ then "ref_fig" <> tshow fignum+ else "ref_" <> ident+ figname <- translateTerm Term.Figure+ prop <- pStyleM $+ if null longcapt+ then "Figure"+ else "Captioned Figure"+ paraProps <- local+ (\env -> env { envParaProperties = EnvProps (Just prop) [] <>+ envParaProperties env })+ (getParaProps False)++ -- Figure contents+ let simpleImage x = do+ imgXML <- inlineToOpenXML opts x+ pure $ Elem (mknode "w:p" [] (map Elem paraProps ++ imgXML))+ contentsNode <- case body of+ [Plain [img@Image {}]] -> simpleImage img+ [Para [img@Image {}]] -> simpleImage img+ _ -> toFigureTable opts body+ -- Caption+ let imageCaption = withParaPropM (pStyleM "Image Caption")+ . blocksToOpenXML opts+ let fstCaptionPara inlns = Para $+ if not $ isEnabled Ext_native_numbering opts+ then inlns+ else let rawfld = RawInline (Format "openxml") $ mconcat+ [ "<w:fldSimple w:instr=\"SEQ Figure"+ , " \\* ARABIC \"><w:r><w:t>"+ , tshow fignum+ , "</w:t></w:r></w:fldSimple>"+ ]+ in Span (refid,[],[]) [Str (figname <> "\160") , rawfld]+ : Str ": " : inlns+ captionNode <- case longcapt of+ [] -> return []+ (Para xs : bs) -> imageCaption (fstCaptionPara xs : bs)+ (Plain xs : bs) -> imageCaption (fstCaptionPara xs : bs)+ _ -> imageCaption longcapt+ wrapBookmark ident $+ case writerFigureCaptionPosition opts of+ CaptionBelow -> contentsNode : captionNode+ CaptionAbove -> captionNode ++ [contentsNode]++toFigureTable :: PandocMonad m+ => WriterOptions -> [Block] -> WS m Content+toFigureTable opts blks = do+ modify $ \s -> s { stInTable = True }+ let ncols = length blks+ let textwidth = 7920 -- 5.5 in in twips (1 twip == 1/20 pt)+ let cellfrac = 1 / fromIntegral ncols+ let colwidth = tshow @Integer $ floor (textwidth * cellfrac) -- twips+ let gridCols = replicate ncols $ mknode "w:gridCol" [("w:w", colwidth)] ()+ let scaleImage = \case+ Image attr@(ident, classes, attribs) alt tgt ->+ let dimWidth = case dimension Width attr of+ Nothing -> Percent (cellfrac * 100)+ Just d -> scaleDimension cellfrac d+ dimHeight = scaleDimension cellfrac <$> dimension Height attr+ attribs' = (tshow Width, tshow dimWidth) :+ (case dimHeight of+ Nothing -> id+ Just h -> ((tshow Height, tshow h) :))+ [ (k, v) | (k, v) <- attribs+ , k `notElem` ["width", "height"]+ ]+ in Image (ident, classes, attribs') alt tgt+ x -> x+ let blockToCell = Table.OOXMLCell nullAttr AlignCenter 1 1 . (:[])+ . walk scaleImage+ tblBody <- Table.rowToOpenXML (blocksToOpenXML opts) .+ Table.OOXMLRow Table.BodyRow nullAttr $+ map blockToCell blks+ let tbl = mknode "w:tbl" []+ ( mknode "w:tblPr" []+ [ mknode "w:tblStyle" [("w:val","FigureTable")] (),+ mknode "w:tblW" [ ("w:type", "auto"), ("w:w", "0") ] (),+ mknode "w:jc" [("w:val","center")] (),+ mknode "w:tblLook" [ ("w:firstRow", "0")+ , ("w:lastRow", "0")+ , ("w:firstColumn", "0")+ , ("w:lastColumn", "0")+ ] ()+ ]+ : mknode "w:tblGrid" [] gridCols+ : maybeToList tblBody+ )+ modify $ \s -> s { stInTable = False }+ return $ Elem tbl+++definitionListItemToOpenXML :: (PandocMonad m)+ => WriterOptions -> ([Inline],[[Block]])+ -> WS m [Content]+definitionListItemToOpenXML opts (term,defs) = do+ term' <- withParaPropM (pStyleM "Definition Term")+ $ blockToOpenXML opts (Para term)+ defs' <- withParaPropM (pStyleM "Definition")+ $ concat `fmap` mapM (blocksToOpenXML opts) defs+ return $ term' ++ defs'++addList :: (PandocMonad m) => ListMarker -> WS m ()+addList marker = do+ lists <- gets stLists+ lastExampleId <- gets stExampleId+ modify $ \st -> st{ stLists = lists ++ case marker of+ -- Use only first occurrence of Example for list declaration to avoid overhead+ NumberMarker Example _ _ | isJust lastExampleId -> []+ _ -> [marker]+ , stExampleId = case marker of+ -- Reuse the same identifier for all other occurrences of Example+ NumberMarker Example _ _ -> lastExampleId <|> Just (baseListId + length lists)+ _ -> lastExampleId+ }++listItemToOpenXML :: (PandocMonad m)+ => WriterOptions+ -> Int -> [Block]+ -> WS m [Content]+listItemToOpenXML opts numid bs = do+ oldInList <- gets stInList+ modify $ \st -> st{ stInList = True }+ let isListBlock = \case+ BulletList{} -> True+ OrderedList{} -> True+ _ -> False+ -- Prepend an empty string if the first entry is another+ -- list. Otherwise the outer bullet will disappear.+ let bs' = case bs of+ [] -> []+ x:xs -> if isListBlock x+ then Plain [Str ""]:x:xs+ else x:xs+ modify $ \st -> st{ stNumIdUsed = False }+ contents <- withNumId numid $ blocksToOpenXML opts bs'+ modify $ \st -> st{ stInList = oldInList }+ return contents++-- | Convert a list of inline elements to OpenXML.+inlinesToOpenXML :: PandocMonad m => WriterOptions -> [Inline] -> WS m [Content]+inlinesToOpenXML opts lst = concat `fmap` mapM (inlineToOpenXML opts) (convertSpace lst)++withNumId :: (PandocMonad m) => Int -> WS m a -> WS m a+withNumId numid = local $ \env -> env{ envListNumId = numid }++asList :: (PandocMonad m) => WS m a -> WS m a+asList = local $ \env -> env{ envListLevel = envListLevel env + 1 }++getTextProps :: (PandocMonad m) => WS m [Element]+getTextProps = do+ props <- asks envTextProperties+ mblang <- asks envLang+ let langnode = case mblang of+ Nothing -> mempty+ Just l -> EnvProps Nothing+ [mknode "w:lang" [("w:val", l)] ()]+ let squashed = squashProps (props <> langnode)+ return [mknode "w:rPr" [] squashed | (not . null) squashed]++withTextProp :: PandocMonad m => Element -> WS m a -> WS m a+withTextProp d p =+ local (\env -> env {envTextProperties = ep <> envTextProperties env}) p+ where ep = if isStyle d then EnvProps (Just d) [] else EnvProps Nothing [d]++withTextPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a+withTextPropM md p = do+ d <- md+ withTextProp d p++getParaProps :: PandocMonad m => Bool -> WS m [Element]+getParaProps displayMathPara = do+ props <- asks envParaProperties+ listLevel <- asks envListLevel+ numid <- asks envListNumId+ numIdUsed <- gets stNumIdUsed+ -- clear numId after first use to support multiple paragraphs in the same bullet+ -- baseListId is the code for no list marker+ let numid' = if numIdUsed then baseListId else numid+ modify $ \st -> st{ stNumIdUsed = True }+ let listPr = [mknode "w:numPr" []+ [ mknode "w:ilvl" [("w:val",tshow listLevel)] ()+ , mknode "w:numId" [("w:val",tshow numid')] () ] | listLevel >= 0 && not displayMathPara]+ return $ case squashProps (EnvProps Nothing listPr <> props) of+ [] -> []+ ps -> [mknode "w:pPr" [] ps]++formattedString :: PandocMonad m => Text -> WS m [Element]+formattedString str =+ -- properly handle soft hyphens+ case splitTextBy (=='\173') str of+ [w] -> formattedString' w+ ws -> do+ sh <- formattedRun [mknode "w:softHyphen" [] ()]+ intercalate [sh] <$> mapM formattedString' ws++formattedString' :: PandocMonad m => Text -> WS m [Element]+formattedString' str = do+ inDel <- asks envInDel+ let mkrun s =+ (if T.any isCJK s+ then withTextProp (mknode "w:rFonts" [("w:hint","eastAsia")] ())+ else id) $ formattedRun+ [ mktnode (if inDel then "w:delText" else "w:t")+ [("xml:space","preserve")] $ s ]+ mapM mkrun $ breakIntoChunks $ stripInvalidChars str++-- For motivation see #9817.+breakIntoChunks :: Text -> [Text]+breakIntoChunks t+ | T.null t = []+ | T.any isCJK t+ = let cs = T.groupBy (\c d -> (isSpace c && isSpace d) ||+ not (isSpace c || isSpace d)) t+ css = groupBy (\x y -> not (T.any isCJK x || T.any isCJK y)+ || (T.all isSpace x && not (T.any isCJK y))+ || (T.all isSpace y && not (T.any isCJK x)))+ cs+ in map mconcat css+ | otherwise = [t]++formattedRun :: PandocMonad m => [Element] -> WS m Element+formattedRun els = do+ props <- getTextProps+ return $ mknode "w:r" [] $ props ++ els++-- | Convert an inline element to OpenXML.+inlineToOpenXML :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]+inlineToOpenXML opts il = withDirection $ inlineToOpenXML' opts il++inlineToOpenXML' :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]+inlineToOpenXML' _ (Str str) =+ map Elem <$> formattedString str+inlineToOpenXML' opts Space = inlineToOpenXML opts (Str " ")+inlineToOpenXML' opts SoftBreak = inlineToOpenXML opts (Str " ")+inlineToOpenXML' opts (Span ("",["mark"],[]) ils) =+ withTextProp (mknode "w:highlight" [("w:val","yellow")] ()) $+ inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-block"],[]) ils) =+ inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-left-margin"],[]) ils) =+ inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-right-inline"],[]) ils) =+ ([Elem $+ mknode "w:r" []+ (mknode "w:t"+ [("xml:space","preserve")]+ ("\t" :: Text))] ++)+ <$> inlinesToOpenXML opts ils+inlineToOpenXML' opts (Span ("",["csl-indent"],[]) ils) =+ inlinesToOpenXML opts ils+inlineToOpenXML' _ (Span (ident,["comment-start"],kvs) ils) = do+ -- prefer the "id" in kvs, since that is the one produced by the docx+ -- reader.+ let ident' = fromMaybe ident (lookup "id" kvs)+ kvs' = filter (("id" /=) . fst) kvs+ modify $ \st -> st{ stComments = (("id",ident'):kvs', ils) : stComments st }+ return [ Elem $ mknode "w:commentRangeStart" [("w:id", ident')] () ]+inlineToOpenXML' opts (Span (ident,["comment-end"],kvs) content) = do+ -- prefer the "id" in kvs, since that is the one produced by the docx+ -- reader.+ let ident' = fromMaybe ident (lookup "id" kvs)+ -- process nested content: see #8189+ nestedContent <- inlinesToOpenXML opts content+ let thisCommentEnd =+ [ mknode "w:commentRangeEnd" [("w:id", ident')] ()+ , mknode "w:r" []+ [ mknode "w:rPr" []+ [ mknode "w:rStyle" [("w:val", "CommentReference")] () ]+ , mknode "w:commentReference" [("w:id", ident')] () ]+ ]+ return $ map Elem thisCommentEnd ++ nestedContent+inlineToOpenXML' opts (Span (ident,classes,kvs) ils) = do+ stylemod <- case lookup dynamicStyleKey kvs of+ Just (fromString . T.unpack -> sty) -> do+ modify $ \s ->+ s{stDynamicTextProps = Set.insert sty+ (stDynamicTextProps s)}+ return $ withTextPropM (rStyleM sty)+ _ -> return id+ let dirmod = case lookup "dir" kvs of+ Just "rtl" -> local (\env -> env { envRTL = True })+ Just "ltr" -> local (\env -> env { envRTL = False })+ _ -> id+ off x = withTextProp (mknode x [("w:val","0")] ())+ pmod = (if "csl-no-emph" `elem` classes then off "w:i" else id) .+ (if "csl-no-strong" `elem` classes then off "w:b" else id) .+ (if "csl-no-smallcaps" `elem` classes+ then off "w:smallCaps"+ else id)+ getChangeAuthorDate = do+ defaultAuthor <- asks envChangesAuthor+ let author = fromMaybe defaultAuthor (lookup "author" kvs)+ let mdate = lookup "date" kvs+ return $ ("w:author", author) :+ maybe [] (\date -> [("w:date", date)]) mdate+ insmod <- if "insertion" `elem` classes+ then do+ changeAuthorDate <- getChangeAuthorDate+ insId <- gets stInsId+ modify $ \s -> s{stInsId = insId + 1}+ return $ \f -> do+ x <- f+ return [Elem $+ mknode "w:ins"+ (("w:id", tshow insId) : changeAuthorDate) x]+ else return id+ delmod <- if "deletion" `elem` classes+ then do+ changeAuthorDate <- getChangeAuthorDate+ delId <- gets stDelId+ modify $ \s -> s{stDelId = delId + 1}+ return $ \f -> local (\env->env{envInDel=True}) $ do+ x <- f+ return [Elem $ mknode "w:del"+ (("w:id", tshow delId) : changeAuthorDate) x]+ else return id+ let langmod = case lookup "lang" kvs of+ Nothing -> id+ Just lang -> local (\env -> env{envLang = Just lang})+ contents <- insmod $ delmod $ dirmod $ stylemod $ pmod $+ langmod $ inlinesToOpenXML opts ils+ wrapBookmark ident contents+inlineToOpenXML' opts (Strong lst) =+ withTextProp (mknode "w:bCs" [] ()) $ -- needed for LTR, #6911+ withTextProp (mknode "w:b" [] ()) $+ inlinesToOpenXML opts lst+inlineToOpenXML' opts (Emph lst) =+ withTextProp (mknode "w:iCs" [] ()) $ -- needed for LTR, #6911+ withTextProp (mknode "w:i" [] ()) $+ inlinesToOpenXML opts lst+inlineToOpenXML' opts (Underline lst) =+ withTextProp (mknode "w:u" [("w:val","single")] ()) $+ inlinesToOpenXML opts lst+inlineToOpenXML' opts (Subscript lst) =+ withTextProp (mknode "w:vertAlign" [("w:val","subscript")] ())+ $ inlinesToOpenXML opts lst+inlineToOpenXML' opts (Superscript lst) =+ withTextProp (mknode "w:vertAlign" [("w:val","superscript")] ())+ $ inlinesToOpenXML opts lst+inlineToOpenXML' opts (SmallCaps lst) =+ withTextProp (mknode "w:smallCaps" [] ())+ $ inlinesToOpenXML opts lst+inlineToOpenXML' opts (Strikeout lst) =+ withTextProp (mknode "w:strike" [] ())+ $ inlinesToOpenXML opts lst+inlineToOpenXML' _ LineBreak = return [Elem br]+inlineToOpenXML' _ il@(RawInline f str)+ | f == Format "openxml" = return+ [Text (CData CDataRaw str Nothing)]+ | otherwise = do+ report $ InlineNotRendered il+ return []+inlineToOpenXML' opts (Quoted quoteType lst) =+ inlinesToOpenXML opts $ [Str open] ++ lst ++ [Str close]+ where (open, close) = case quoteType of+ SingleQuote -> ("\x2018", "\x2019")+ DoubleQuote -> ("\x201C", "\x201D")+inlineToOpenXML' opts (Math mathType str) = do+ when (mathType == DisplayMath) setFirstPara+ res <- (lift . lift) (convertMath writeOMML mathType str)+ case res of+ Right r -> return [Elem $ fromXLElement r]+ Left il -> inlineToOpenXML' opts il+inlineToOpenXML' opts (Cite _ lst) = inlinesToOpenXML opts lst+inlineToOpenXML' opts (Code attrs str) = do+ let alltoktypes = [KeywordTok ..]+ tokTypesMap <- mapM (\tt -> (,) tt <$> rStyleM (fromString $ show tt)) alltoktypes+ let unhighlighted = (map Elem . intercalate [br]) `fmap`+ mapM formattedString (T.lines str)+ formatOpenXML _fmtOpts = intercalate [br] . map (map toHlTok)+ toHlTok (toktype,tok) =+ mknode "w:r" []+ [ mknode "w:rPr" [] $+ maybeToList (lookup toktype tokTypesMap)+ , mknode "w:t" [("xml:space","preserve")] tok ]+ let highlighted =+ case highlight (writerSyntaxMap opts) formatOpenXML attrs str of+ Right h -> return (map Elem h)+ Left msg -> do+ unless (T.null msg) $ report $ CouldNotHighlight msg+ unhighlighted+ withTextPropM (rStyleM "Verbatim Char")+ $ case writerHighlightMethod opts of+ DefaultHighlighting -> highlighted+ Skylighting _ -> highlighted+ _ -> unhighlighted+inlineToOpenXML' opts (Note bs) = do+ notes <- gets stFootnotes+ notenum <- getUniqueId+ oldFirstPara <- gets stFirstPara+ footnoteStyle <- rStyleM "Footnote Reference"+ let notemarker = mknode "w:r" []+ [ mknode "w:rPr" [] footnoteStyle+ , mknode "w:footnoteRef" [] () ]+ let notemarkerXml = RawInline (Format "openxml") $ ppElement notemarker+ let insertNoteRef (Plain ils : xs) = Plain (notemarkerXml : Space : ils) : xs+ insertNoteRef (Para ils : xs) = Para (notemarkerXml : Space : ils) : xs+ insertNoteRef xs = Para [notemarkerXml] : xs++ contents <- local (\env -> env{ envListLevel = -1+ , envParaProperties = mempty+ , envTextProperties = mempty+ , envInNote = True })+ (withParaPropM (pStyleM "Footnote Text") $+ blocksToOpenXML opts $ insertNoteRef bs)+ modify $ \s -> s{ stFirstPara = oldFirstPara }+ let newnote = mknode "w:footnote" [("w:id", notenum)] contents+ modify $ \s -> s{ stFootnotes = newnote : notes }+ return [ Elem $ mknode "w:r" []+ [ mknode "w:rPr" [] footnoteStyle+ , mknode "w:footnoteReference" [("w:id", notenum)] () ] ]+-- internal link:+inlineToOpenXML' opts (Link _ txt (T.uncons -> Just ('#', xs),_)) = do+ contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt+ return+ [ Elem $ mknode "w:hyperlink" [("w:anchor", toBookmarkName xs)] contents ]+-- external link:+inlineToOpenXML' opts (Link _ txt (src,_)) = do+ contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt+ extlinks <- gets stExternalLinks+ id' <- case M.lookup src extlinks of+ Just i -> return i+ Nothing -> do+ i <- ("rId" <>) <$> getUniqueId+ modify $ \st -> st{ stExternalLinks =+ M.insert src i extlinks }+ return i+ return [ Elem $ mknode "w:hyperlink" [("r:id",id')] contents ]+inlineToOpenXML' opts (Image attr@(imgident, _, _) alt (src, title)) = do+ pageWidth <- asks envPrintWidth+ imgs <- gets stImages+ let+ stImage = M.lookup (T.unpack src) imgs+ generateImgElt (ident, _fp, mt, img) = do+ docprid <- getUniqueId+ nvpicprid <- getUniqueId+ (blipAttrs, blipContents) <-+ case T.takeWhile (/=';') <$> mt of+ Just "image/svg+xml" -> do+ -- get fallback png+ mediabag <- getMediaBag+ mbFallback <-+ case lookupMedia (T.unpack (src <> ".png")) mediabag of+ Just item -> do+ id' <- T.unpack . ("rId" <>) <$> getUniqueId+ let fp' = "media/" <> id' <> ".png"+ let imgdata = (id',+ fp',+ Just (mediaMimeType item),+ BL.toStrict $ mediaContents item)+ modify $ \st -> st { stImages =+ M.insert fp' imgdata $ stImages st }+ return $ Just id'+ Nothing -> return Nothing+ let extLst = mknode "a:extLst" []+ [ mknode "a:ext"+ [("uri","{28A0092B-C50C-407E-A947-70E740481C1C}")]+ [ mknode "a14:useLocalDpi"+ [("xmlns:a14","http://schemas.microsoft.com/office/drawing/2010/main"),+ ("val","0")] () ]+ , mknode "a:ext"+ [("uri","{96DAC541-7B7A-43D3-8B79-37D633B846F1}")]+ [ mknode "asvg:svgBlip"+ [("xmlns:asvg", "http://schemas.microsoft.com/office/drawing/2016/SVG/main"),+ ("r:embed",T.pack ident)] () ]+ ]+ return (maybe [] (\id'' -> [("r:embed", T.pack id'')]) mbFallback,+ [extLst])+ _ -> return ([("r:embed", T.pack ident)], [])+ let+ (xpt,ypt) = desiredSizeInPoints opts attr+ (either (const def) id (imageSize opts img))+ -- 12700 emu = 1 pt+ pageWidthPt = case dimension Width attr of+ Just (Percent a) -> pageWidth * floor (a * 127)+ _ -> pageWidth * 12700+ (xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700) pageWidthPt+ cNvPicPr = mknode "pic:cNvPicPr" [] $+ mknode "a:picLocks" [("noChangeArrowheads","1")+ ,("noChangeAspect","1")] ()+ nvPicPr = mknode "pic:nvPicPr" []+ [ mknode "pic:cNvPr"+ [("descr",src)+ ,("id", nvpicprid)+ ,("name","Picture")] ()+ , cNvPicPr ]+ blipFill = mknode "pic:blipFill" []+ [ mknode "a:blip" blipAttrs blipContents+ , mknode "a:stretch" [] $+ mknode "a:fillRect" [] ()+ ]+ xfrm = mknode "a:xfrm" []+ [ mknode "a:off" [("x","0"),("y","0")] ()+ , mknode "a:ext" [("cx",tshow xemu)+ ,("cy",tshow yemu)] () ]+ prstGeom = mknode "a:prstGeom" [("prst","rect")] $+ mknode "a:avLst" [] ()+ ln = mknode "a:ln" [("w","9525")]+ [ mknode "a:noFill" [] ()+ , mknode "a:headEnd" [] ()+ , mknode "a:tailEnd" [] () ]+ spPr = mknode "pic:spPr" [("bwMode","auto")]+ [xfrm, prstGeom, mknode "a:noFill" [] (), ln]+ graphic = mknode "a:graphic" [] $+ mknode "a:graphicData"+ [("uri","http://schemas.openxmlformats.org/drawingml/2006/picture")]+ [ mknode "pic:pic" []+ [ nvPicPr+ , blipFill+ , spPr+ ]+ ]+ imgElt = mknode "w:r" [] $+ mknode "w:drawing" [] $+ mknode "wp:inline" []+ [ mknode "wp:extent" [("cx",tshow xemu),("cy",tshow yemu)] ()+ , mknode "wp:effectExtent"+ [("b","0"),("l","0"),("r","0"),("t","0")] ()+ , mknode "wp:docPr"+ [ ("descr", stringify alt)+ , ("title", title)+ , ("id", docprid)+ , ("name","Picture")+ ] ()+ , graphic+ ]+ return [Elem imgElt]++ wrapBookmark imgident =<< case stImage of+ Just imgData -> generateImgElt imgData+ Nothing -> ( do --try+ (img, mt) <- P.fetchItem src+ ident <- ("rId" <>) <$> getUniqueId++ let+ imgext = case mt >>= extensionFromMimeType of+ Just x -> "." <> x+ Nothing -> case imageType img of+ Just Png -> ".png"+ Just Jpeg -> ".jpeg"+ Just Gif -> ".gif"+ Just Pdf -> ".pdf"+ Just Eps -> ".eps"+ Just Svg -> ".svg"+ Just Emf -> ".emf"+ Just Tiff -> ".tiff"+ Just Webp -> ".webp"+ Just Avif -> ".avif"+ Nothing -> ""+ imgpath = "media/" <> ident <> imgext+ mbMimeType = mt <|> getMimeType (T.unpack imgpath)++ imgData = (T.unpack ident, T.unpack imgpath, mbMimeType, img)++ if T.null imgext+ then -- without an extension there is no rule for content type+ inlinesToOpenXML opts alt -- return alt to avoid corrupted docx+ else do+ -- insert mime type to use in constructing [Content_Types].xml+ modify $ \st -> st { stImages = M.insert (T.unpack src) imgData $ stImages st }+ generateImgElt imgData+ )+ `catchError` ( \e -> do+ report $ CouldNotFetchResource src $ T.pack (show e)+ -- emit alt text+ inlinesToOpenXML opts alt+ )++br :: Element+br = mknode "w:r" [] [mknode "w:br" [] ()]+++withDirection :: PandocMonad m => WS m a -> WS m a+withDirection x = do+ isRTL <- asks envRTL+ paraProps <- asks envParaProperties+ textProps <- asks envTextProperties+ -- We want to clean all bidirection (bidi) and right-to-left (rtl)+ -- properties from the props first. This is because we don't want+ -- them to stack up.+ let paraProps' = filter (\e -> (qName . elName) e /= "bidi") (otherElements paraProps)+ textProps' = filter (\e -> (qName . elName) e /= "rtl") (otherElements textProps)+ paraStyle = styleElement paraProps+ textStyle = styleElement textProps+ if isRTL+ -- if we are going right-to-left, we (re?)add the properties.+ then flip local x $+ \env -> env { envParaProperties = EnvProps paraStyle $ mknode "w:bidi" [] () : paraProps'+ , envTextProperties = EnvProps textStyle $ mknode "w:rtl" [] () : textProps'+ }+ else flip local x $ \env -> env { envParaProperties = EnvProps paraStyle paraProps'+ , envTextProperties = EnvProps textStyle textProps'+ }++wrapBookmark :: (PandocMonad m) => Text -> [Content] -> WS m [Content]+wrapBookmark "" contents = return contents+wrapBookmark ident contents = do+ id' <- getUniqueId+ let bookmarkStart = mknode "w:bookmarkStart"+ [("w:id", id')+ ,("w:name", toBookmarkName ident)] ()+ bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()+ return $ Elem bookmarkStart : contents ++ [Elem bookmarkEnd]++-- Word imposes a 40 character limit on bookmark names and requires+-- that they begin with a letter. So we just use a hash of the+-- identifier when otherwise we'd have an illegal bookmark name.+toBookmarkName :: Text -> Text+toBookmarkName s+ | Just (c, _) <- T.uncons s+ , isLetter c+ , T.length s <= 40 = s+ | otherwise = T.pack $ 'X' : drop 1 (show (hashWith SHA1 (fromText s)))++maxListLevel :: Int+maxListLevel = 8++convertSpace :: [Inline] -> [Inline]+convertSpace (Str x : Space : Str y : xs) = convertSpace (Str (x <> " " <> y) : xs)+convertSpace (Str x : Str y : xs) = convertSpace (Str (x <> y) : xs)+convertSpace (x:xs) = x : convertSpace xs+convertSpace [] = []
@@ -2,7 +2,7 @@ {- | Module : Text.Pandoc.Writers.Docx.StyleMap Copyright : © 2014-2020 Jesse Rosenthal <jrosenthal@jhu.edu>,- 2014-2022 John MacFarlane <jgm@berkeley.edu>,+ 2014-2024 John MacFarlane <jgm@berkeley.edu>, 2015-2019 Nikolay Yakimov <root@livid.pp.ru> License : GNU GPL, version 2 or above
@@ -3,7 +3,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Text.Pandoc.Writers.Docx.Table-Copyright : Copyright (C) 2012-2022 John MacFarlane+Copyright : Copyright (C) 2012-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> @@ -11,11 +11,18 @@ -} module Text.Pandoc.Writers.Docx.Table ( tableToOpenXML+ , rowToOpenXML+ , OOXMLRow (..)+ , OOXMLCell (..)+ , RowType (..) ) where -import Control.Monad.State.Strict ( modify, gets, unless )+import Control.Monad.State.Strict ( modify, gets )+import Control.Monad ( unless , zipWithM )+import Control.Monad.Except ( throwError ) import Data.Array ( elems, (!), assocs, indices ) import Data.Text (Text)+import Data.Maybe (catMaybes, fromMaybe) import Text.Pandoc.Definition ( ColSpec, Caption(Caption),@@ -26,18 +33,22 @@ Alignment(..), RowSpan(..), ColSpan(..),- ColWidth(ColWidth) )-import Text.Pandoc.Class.PandocMonad (PandocMonad, translateTerm)+ ColWidth(..) )+import Text.Pandoc.Class.PandocMonad (PandocMonad)+import Text.Pandoc.Translations (translateTerm) import Text.Pandoc.Writers.Docx.Types ( WS, WriterState(stNextTableNum, stInTable),+ WriterEnv(..), setFirstPara, pStyleM, withParaProp, withParaPropM )+import Control.Monad.Reader (asks) import Text.Pandoc.Shared ( tshow, stringify )-import Text.Pandoc.Options (WriterOptions, isEnabled)+import Text.Pandoc.Options (WriterOptions(..), isEnabled, CaptionPosition(..)) import Text.Pandoc.Extensions (Extension(Ext_native_numbering))+import Text.Pandoc.Error (PandocError(PandocSomeError)) import Text.Printf (printf) import Text.Pandoc.Writers.GridTable ( rowArray,@@ -60,7 +71,7 @@ -> WS m [Content] tableToOpenXML opts blocksToOpenXML gridTable = do setFirstPara- let (Grid.Table (ident,_,_) caption colspecs _rowheads thead tbodies tfoot) =+ let (Grid.Table (ident,_,tableAttr) caption colspecs _rowheads thead tbodies tfoot) = gridTable let (Caption _maybeShortCaption captionBlocks) = caption tablenum <- gets stNextTableNum@@ -97,18 +108,26 @@ -- 0×0400 Do not apply column banding conditional formattin let tblLookVal = if hasHeader then (0x20 :: Int) else 0 let (gridCols, tblWattr) = tableLayout (elems colspecs)+ listLevel <- asks envListLevel+ let tblStyle = fromMaybe "Table" (lookup "custom-style" tableAttr)+ let indent = (listLevel + 1) * 720+ let hasWidths = not $ all ((== ColWidthDefault) . snd) colspecs let tbl = mknode "w:tbl" [] ( mknode "w:tblPr" []- ( mknode "w:tblStyle" [("w:val","Table")] () :- mknode "w:tblW" tblWattr () :- mknode "w:tblLook" [("w:firstRow",if hasHeader then "1" else "0")- ,("w:lastRow",if hasFooter then "1" else "0")- ,("w:firstColumn","0")- ,("w:lastColumn","0")- ,("w:noHBand","0")- ,("w:noVBand","0")- ,("w:val", T.pack $ printf "%04x" tblLookVal)- ] () :+ ( [ mknode "w:tblStyle" [("w:val",tblStyle)] (),+ mknode "w:tblW" tblWattr () ] +++ [ mknode "w:jc" [("w:val","left")] () | indent > 0 ] +++ [ mknode "w:tblInd" [("w:w", tshow indent),("w:type","dxa")] ()+ | indent > 0 ] +++ [ mknode "w:tblLayout" [("w:type", "fixed")] () | hasWidths ] +++ [ mknode "w:tblLook" [("w:firstRow",if hasHeader then "1" else "0")+ ,("w:lastRow",if hasFooter then "1" else "0")+ ,("w:firstColumn","0")+ ,("w:lastColumn","0")+ ,("w:noHBand","0")+ ,("w:noVBand","0")+ ,("w:val", T.pack $ printf "%04x" tblLookVal)+ ] () ] ++ [ mknode "w:tblCaption" [("w:val", captionStr)] () | not (T.null captionStr) ] )@@ -116,7 +135,10 @@ : head' ++ mconcat bodies ++ foot' ) modify $ \s -> s { stInTable = False }- return $ captionXml ++ [Elem tbl]+ return $+ case writerTableCaptionPosition opts of+ CaptionAbove -> captionXml ++ [Elem tbl]+ CaptionBelow -> Elem tbl : captionXml addLabel :: Text -> Text -> Int -> [Block] -> [Block] addLabel tableid tablename tablenum bs =@@ -141,7 +163,7 @@ AlignLeft -> "left" AlignRight -> "right" AlignCenter -> "center"- AlignDefault -> "left"+ AlignDefault -> "" tableLayout :: [ColSpec] -> ([Element], [(Text, Text)]) tableLayout specs =@@ -171,8 +193,8 @@ cellGridToOpenXML blocksToOpenXML rowType aligns part@(Part _ cellArray _) = if null (elems cellArray) then return mempty- else mapM (rowToOpenXML blocksToOpenXML) $- partToRows rowType aligns part+ else partToRows rowType aligns part >>=+ fmap catMaybes . mapM (rowToOpenXML blocksToOpenXML) data OOXMLCell = OOXMLCell Attr Alignment RowSpan ColSpan [Block]@@ -180,45 +202,48 @@ data OOXMLRow = OOXMLRow RowType Attr [OOXMLCell] -partToRows :: RowType -> [Alignment] -> Part -> [OOXMLRow]-partToRows rowType aligns part =- let- toOOXMLCell :: Alignment -> RowIndex -> ColIndex -> GridCell -> [OOXMLCell]- toOOXMLCell columnAlign ridx cidx = \case- ContentCell attr align rowspan colspan blocks ->- -- Respect non-default, cell specific alignment.- let align' = case align of- AlignDefault -> columnAlign- _ -> align- in [OOXMLCell attr align' rowspan colspan blocks]- ContinuationCell idx'@(ridx',cidx') | ridx /= ridx', cidx == cidx' ->- case (partCellArray part)!idx' of- (ContentCell _ _ _ colspan _) -> [OOXMLCellMerge colspan]- x -> error $ "Content cell expected, got, " ++ show x ++- " at index " ++ show idx'- _ -> mempty- mkRow :: (RowIndex, Attr) -> OOXMLRow- mkRow (ridx, attr) = OOXMLRow rowType attr- . mconcat- . zipWith (\align -> uncurry $ toOOXMLCell align ridx)- aligns- . assocs- . rowArray ridx- $ partCellArray part- in map mkRow $ assocs (partRowAttrs part)+partToRows :: PandocMonad m+ => RowType -> [Alignment] -> Part -> WS m [OOXMLRow]+partToRows rowType aligns part = do+ let toOOXMLCell :: PandocMonad m =>+ Alignment -> RowIndex -> ColIndex -> GridCell -> WS m [OOXMLCell]+ toOOXMLCell columnAlign ridx cidx = \case+ UnassignedCell ->+ throwError $ PandocSomeError "Encountered unassigned table cell"+ ContentCell attr align rowspan colspan blocks -> do+ -- Respect non-default, cell specific alignment.+ let align' = case align of+ AlignDefault -> columnAlign+ _ -> align+ return [OOXMLCell attr align' rowspan colspan blocks]+ ContinuationCell idx'@(ridx',cidx') | ridx /= ridx', cidx == cidx' -> do+ case (partCellArray part)!idx' of+ (ContentCell _ _ _ colspan _) -> return [OOXMLCellMerge colspan]+ x -> error $ "Content cell expected, got, " ++ show x +++ " at index " ++ show idx'+ _ -> return mempty+ let mkRow :: PandocMonad m => (RowIndex, Attr) -> WS m OOXMLRow+ mkRow (ridx, attr) = do+ cs <- zipWithM (\align -> uncurry $ toOOXMLCell align ridx)+ aligns+ (assocs . rowArray ridx $ partCellArray part)+ return $ OOXMLRow rowType attr . mconcat $ cs+ mapM mkRow $ assocs (partRowAttrs part) rowToOpenXML :: PandocMonad m => ([Block] -> WS m [Content]) -> OOXMLRow- -> WS m Element-rowToOpenXML blocksToOpenXML (OOXMLRow rowType _attr cells) = do- xmlcells <- mapM (ooxmlCellToOpenXML blocksToOpenXML) cells- let addTrPr = case rowType of- HeadRow -> (mknode "w:trPr" []- [mknode "w:tblHeader" [("w:val", "true")] ()] :)- BodyRow -> id- FootRow -> id- return $ mknode "w:tr" [] (addTrPr xmlcells)+ -> WS m (Maybe Element)+rowToOpenXML blocksToOpenXML (OOXMLRow rowType _attr cells)+ | null cells = return Nothing+ | otherwise = do+ xmlcells <- mapM (ooxmlCellToOpenXML blocksToOpenXML) cells+ let addTrPr = case rowType of+ HeadRow -> (mknode "w:trPr" []+ [mknode "w:tblHeader" [("w:val", "on")] ()] :)+ BodyRow -> id+ FootRow -> id+ return $ Just $ mknode "w:tr" [] (addTrPr xmlcells) ooxmlCellToOpenXML :: PandocMonad m => ([Block] -> WS m [Content])@@ -232,7 +257,7 @@ , mknode "w:p" [] [mknode "w:pPr" [] ()]] OOXMLCell _attr align rowspan (ColSpan colspan) contents -> do compactStyle <- pStyleM "Compact"- es <- withParaProp (alignmentFor align) $ blocksToOpenXML contents+ es <- maybe id withParaProp (alignmentFor align) $ blocksToOpenXML contents -- Table cells require a <w:p> element, even an empty one! -- Not in the spec but in Word 2007, 2010. See #4953. And -- apparently the last element must be a <w:p>, see #6983.@@ -250,5 +275,6 @@ e:_ | qName (elName e) == "p" -> es _ -> es ++ [Elem $ mknode "w:p" [] ()] -alignmentFor :: Alignment -> Element-alignmentFor al = mknode "w:jc" [("w:val",alignmentToString al)] ()+alignmentFor :: Alignment -> Maybe Element+alignmentFor AlignDefault = Nothing+alignmentFor al = Just $ mknode "w:jc" [("w:val",alignmentToString al)] ()
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.Docx-Copyright : Copyright (C) 2012-2022 John MacFarlane+Copyright : Copyright (C) 2012-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> @@ -40,12 +40,15 @@ data ListMarker = NoMarker | BulletMarker+ | CheckboxMarker Bool | NumberMarker ListNumberStyle ListNumberDelim Int deriving (Show, Read, Eq, Ord) listMarkerToId :: ListMarker -> Text listMarkerToId NoMarker = "990" listMarkerToId BulletMarker = "991"+listMarkerToId (CheckboxMarker False) = "992"+listMarkerToId (CheckboxMarker True) = "993" listMarkerToId (NumberMarker sty delim n) = T.pack $ '9' : '9' : styNum : delimNum : show n where styNum = case sty of@@ -81,10 +84,12 @@ , envListLevel :: Int , envListNumId :: Int , envInDel :: Bool+ , envInNote :: Bool , envChangesAuthor :: Text , envChangesDate :: Text , envPrintWidth :: Integer , envLang :: Maybe Text+ , envSectPr :: Maybe Element } defaultWriterEnv :: WriterEnv@@ -95,10 +100,12 @@ , envListLevel = -1 , envListNumId = 1 , envInDel = False+ , envInNote = False , envChangesAuthor = "unknown" , envChangesDate = "1969-12-31T19:00:00Z" , envPrintWidth = 1 , envLang = Nothing+ , envSectPr = Nothing } @@ -114,6 +121,7 @@ , stDelId :: Int , stStyleMaps :: StyleMaps , stFirstPara :: Bool+ , stFirstSectionHeader :: Bool -- ^ True until first section header is processed , stNumIdUsed :: Bool -- ^ True if the current numId (envListNumId) has been used. -- Should only be used once, for the first paragraph. , stInTable :: Bool@@ -139,6 +147,7 @@ , stDelId = 1 , stStyleMaps = StyleMaps M.empty M.empty , stFirstPara = False+ , stFirstSectionHeader = True , stNumIdUsed = False , stInTable = False , stInList = False
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.DokuWiki- Copyright : Copyright (C) 2008-2022 John MacFarlane+ Copyright : Copyright (C) 2008-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : Clare Macrae <clare.macrae@googlemail.com>@@ -14,7 +14,7 @@ -} {-- [ ] Implement nested blockquotes (currently only ever does one level)+ [x] Implement nested blockquotes (currently only ever does one level) [x] Implement alignment of text in tables [ ] Implement comments [ ] Work through the Dokuwiki spec, and check I've not missed anything out@@ -32,11 +32,13 @@ import qualified Data.Text as T import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Definition+import Text.Pandoc.Extensions import Text.Pandoc.ImageSize import Text.Pandoc.Logging-import Text.Pandoc.Options (WrapOption (..), WriterOptions (writerTableOfContents, writerTemplate, writerWrapText))-import Text.Pandoc.Shared (camelCaseToHyphenated, escapeURI, isURI, linesToPara,- removeFormatting, trimr, tshow)+import Text.Pandoc.Options (WrapOption (..), WriterOptions (writerTableOfContents,+ writerTemplate, writerWrapText), isEnabled)+import Text.Pandoc.Shared (figureDiv, linesToPara, removeFormatting, trimr)+import Text.Pandoc.URI (escapeURI, isURI) import Text.Pandoc.Templates (renderTemplate) import Text.DocLayout (render, literal) import Text.Pandoc.Writers.Shared (defField, metaToContext, toLegacyTable)@@ -48,8 +50,8 @@ data WriterEnvironment = WriterEnvironment { stIndent :: Text -- Indent after the marker at the beginning of list items- , stUseTags :: Bool -- True if we should use HTML tags because we're in a complex list , stBackSlashLB :: Bool -- True if we should produce formatted strings with newlines (as in a table cell)+ , stBlockQuoteLevel :: Int -- Block quote level } instance Default WriterState where@@ -57,8 +59,8 @@ instance Default WriterEnvironment where def = WriterEnvironment { stIndent = ""- , stUseTags = False- , stBackSlashLB = False }+ , stBackSlashLB = False+ , stBlockQuoteLevel = 0 } type DokuWiki m = ReaderT WriterEnvironment (StateT WriterState m) @@ -98,42 +100,32 @@ -> Block -- ^ Block element -> DokuWiki m Text -blockToDokuWiki _ Null = return ""- blockToDokuWiki opts (Div _attrs bs) = do contents <- blockListToDokuWiki opts bs- return $ contents <> "\n"+ indent <- asks stIndent+ return $ contents <> if T.null indent then "\n" else "" blockToDokuWiki opts (Plain inlines) = inlineListToDokuWiki opts inlines --- title beginning with fig: indicates that the image is a figure--- dokuwiki doesn't support captions - so combine together alt and caption into alt-blockToDokuWiki opts (SimpleFigure attr txt (src, tit)) = do- capt <- if null txt- then return ""- else (" " <>) `fmap` inlineListToDokuWiki opts txt- let opt = if null txt- then ""- else "|" <> if T.null tit then capt else tit <> capt- return $ "{{" <> src <> imageDims opts attr <> opt <> "}}\n"- blockToDokuWiki opts (Para inlines) = do+ bqLevel <- asks stBlockQuoteLevel+ let bqPrefix = case bqLevel of+ 0 -> ""+ n -> T.replicate n ">" <> " " indent <- asks stIndent- useTags <- asks stUseTags contents <- inlineListToDokuWiki opts inlines- return $ if useTags- then "<HTML><p></HTML>" <> contents <> "<HTML></p></HTML>"- else contents <> if T.null indent then "\n" else ""+ return $ bqPrefix <> contents <> if T.null indent then "\n" else "" blockToDokuWiki opts (LineBlock lns) = blockToDokuWiki opts $ linesToPara lns -blockToDokuWiki _ b@(RawBlock f str)+blockToDokuWiki opts b@(RawBlock f str) | f == Format "dokuwiki" = return str -- See https://www.dokuwiki.org/wiki:syntax -- use uppercase HTML tag for block-level content:- | f == Format "html" = return $ "<HTML>\n" <> str <> "\n</HTML>"+ | f == Format "html"+ , isEnabled Ext_raw_html opts = return $ "<HTML>\n" <> str <> "\n</HTML>" | otherwise = "" <$ report (BlockNotRendered b) @@ -146,19 +138,22 @@ let eqs = T.replicate ( 7 - level ) "=" return $ eqs <> " " <> contents <> " " <> eqs <> "\n" -blockToDokuWiki _ (CodeBlock (_,classes,_) str) =- return $ "<code" <>+blockToDokuWiki _ (CodeBlock (_,classes,_) str) = do+ bqLevel <- asks stBlockQuoteLevel+ let bqPrefix = case bqLevel of+ 0 -> ""+ n -> T.replicate n ">" <> " "+ return $ bqPrefix <>+ "<code" <> (case classes of [] -> "" (x:_) -> " " <> fromMaybe x (M.lookup x languageNames)) <> ">\n" <> str <> (if "\n" `T.isSuffixOf` str then "" else "\n") <> "</code>\n" -blockToDokuWiki opts (BlockQuote blocks) = do- contents <- blockListToDokuWiki opts blocks- if isSimpleBlockQuote blocks- then return $ T.unlines $ map ("> " <>) $ T.lines contents- else return $ "<HTML><blockquote>\n" <> contents <> "</blockquote></HTML>"+blockToDokuWiki opts (BlockQuote blocks) =+ local (\st -> st{ stBlockQuoteLevel = stBlockQuoteLevel st + 1 })+ (blockListToDokuWiki opts blocks) blockToDokuWiki opts (Table _ blkCapt specs thead tbody tfoot) = do let (capt, aligns, _, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot@@ -189,102 +184,77 @@ (if null headers' then "" else renderRow "^" headers' <> "\n") <> T.unlines (map (renderRow "|") rows') -blockToDokuWiki opts x@(BulletList items) = do- oldUseTags <- asks stUseTags+blockToDokuWiki opts (BulletList items) = do indent <- asks stIndent backSlash <- asks stBackSlashLB- let useTags = oldUseTags || not (isSimpleList x)- if useTags- then do- contents <- local (\s -> s { stUseTags = True })- (mapM (listItemToDokuWiki opts) items)- return $ "<HTML><ul></HTML>\n" <> vcat contents <> "<HTML></ul></HTML>\n"- else do- contents <- local (\s -> s { stIndent = stIndent s <> " "- , stBackSlashLB = backSlash})+ contents <- local (\s -> s { stIndent = stIndent s <> " "+ , stBackSlashLB = backSlash}) (mapM (listItemToDokuWiki opts) items)- return $ vcat contents <> if T.null indent then "\n" else ""+ return $ vcat contents <> if T.null indent then "\n" else "" -blockToDokuWiki opts x@(OrderedList attribs items) = do- oldUseTags <- asks stUseTags+blockToDokuWiki opts (OrderedList _attribs items) = do indent <- asks stIndent backSlash <- asks stBackSlashLB- let useTags = oldUseTags || not (isSimpleList x)- if useTags- then do- contents <- local (\s -> s { stUseTags = True })- (mapM (orderedListItemToDokuWiki opts) items)- return $ "<HTML><ol" <> listAttribsToString attribs <> "></HTML>\n" <> vcat contents <> "<HTML></ol></HTML>\n"- else do- contents <- local (\s -> s { stIndent = stIndent s <> " "- , stBackSlashLB = backSlash})- (mapM (orderedListItemToDokuWiki opts) items)- return $ vcat contents <> if T.null indent then "\n" else ""+ contents <- local (\s -> s { stIndent = stIndent s <> " "+ , stBackSlashLB = backSlash})+ (mapM (orderedListItemToDokuWiki opts) items)+ return $ vcat contents <> if T.null indent then "\n" else "" +blockToDokuWiki opts (Figure attr capt body) =+ blockToDokuWiki opts $ figureDiv attr capt body+ -- TODO Need to decide how to make definition lists work on dokuwiki - I don't think there -- is a specific representation of them. -- TODO This creates double '; ; ' if there is a bullet or ordered list inside a definition list-blockToDokuWiki opts x@(DefinitionList items) = do- oldUseTags <- asks stUseTags+blockToDokuWiki opts (DefinitionList items) = do indent <- asks stIndent backSlash <- asks stBackSlashLB- let useTags = oldUseTags || not (isSimpleList x)- if useTags- then do- contents <- local (\s -> s { stUseTags = True })- (mapM (definitionListItemToDokuWiki opts) items)- return $ "<HTML><dl></HTML>\n" <> vcat contents <> "<HTML></dl></HTML>\n"- else do- contents <- local (\s -> s { stIndent = stIndent s <> " "- , stBackSlashLB = backSlash})- (mapM (definitionListItemToDokuWiki opts) items)- return $ vcat contents <> if T.null indent then "\n" else ""+ contents <- local (\s -> s { stIndent = stIndent s <> " "+ , stBackSlashLB = backSlash})+ (mapM (definitionListItemToDokuWiki opts) items)+ return $ vcat contents <> if T.null indent then "\n" else "" -- Auxiliary functions for lists: --- | Convert ordered list attributes to HTML attribute string-listAttribsToString :: ListAttributes -> Text-listAttribsToString (startnum, numstyle, _) =- let numstyle' = camelCaseToHyphenated $ tshow numstyle- in (if startnum /= 1- then " start=\"" <> tshow startnum <> "\""- else "") <>- (if numstyle /= DefaultStyle- then " style=\"list-style-type: " <> numstyle' <> ";\""- else "")- -- | Convert bullet list item (list of blocks) to DokuWiki. listItemToDokuWiki :: PandocMonad m => WriterOptions -> [Block] -> DokuWiki m Text listItemToDokuWiki opts items = do- useTags <- asks stUseTags- if useTags- then do- contents <- blockListToDokuWiki opts items- return $ "<HTML><li></HTML>" <> contents <> "<HTML></li></HTML>"- else do- bs <- mapM (blockToDokuWiki opts) items- let contents = case items of- [_, CodeBlock _ _] -> T.concat bs- _ -> vcat bs- indent <- asks stIndent- backSlash <- asks stBackSlashLB- let indent' = if backSlash then T.drop 2 indent else indent- return $ indent' <> "* " <> contents+ bqLevel <- asks stBlockQuoteLevel+ let bqPrefix = case bqLevel of+ 0 -> ""+ n -> T.replicate n ">" <> " "+ let useWrap = not (isSimpleListItem items)+ bs <- mapM (blockToDokuWiki opts) items+ let contents = case items of+ [_, CodeBlock _ _] -> T.concat bs+ _ -> vcat bs+ indent <- asks stIndent+ backSlash <- asks stBackSlashLB+ let indent' = if backSlash then T.drop 2 indent else indent+ return $ bqPrefix <> indent' <> "* " <>+ if useWrap+ then "<WRAP>\n" <> contents <> "\n</WRAP>"+ else contents -- | Convert ordered list item (list of blocks) to DokuWiki. -- | TODO Emiminate dreadful duplication of text from listItemToDokuWiki orderedListItemToDokuWiki :: PandocMonad m => WriterOptions -> [Block] -> DokuWiki m Text orderedListItemToDokuWiki opts items = do- contents <- blockListToDokuWiki opts items- useTags <- asks stUseTags- if useTags- then return $ "<HTML><li></HTML>" <> contents <> "<HTML></li></HTML>"- else do- indent <- asks stIndent- backSlash <- asks stBackSlashLB- let indent' = if backSlash then T.drop 2 indent else indent- return $ indent' <> "- " <> contents+ bqLevel <- asks stBlockQuoteLevel+ let bqPrefix = case bqLevel of+ 0 -> ""+ n -> T.replicate n ">" <> " "+ let useWrap = not (isSimpleListItem items)+ contents <- local (\st -> st{ stBlockQuoteLevel = 0 })+ (blockListToDokuWiki opts items)+ indent <- asks stIndent+ backSlash <- asks stBackSlashLB+ let indent' = if backSlash then T.drop 2 indent else indent+ return $ bqPrefix <> indent' <> "- " <>+ if useWrap+ then "<WRAP>\n" <> contents <> "\n</WRAP>"+ else contents -- | Convert definition list item (label, list of blocks) to DokuWiki. definitionListItemToDokuWiki :: PandocMonad m@@ -292,19 +262,33 @@ -> ([Inline],[[Block]]) -> DokuWiki m Text definitionListItemToDokuWiki opts (label, items) = do+ let useWrap = not (all isSimpleListItem items)+ bqLevel <- asks stBlockQuoteLevel+ let bqPrefix = case bqLevel of+ 0 -> ""+ n -> T.replicate n ">" <> " " labelText <- inlineListToDokuWiki opts label- contents <- mapM (blockListToDokuWiki opts) items- useTags <- asks stUseTags- if useTags- then return $ "<HTML><dt></HTML>" <> labelText <> "<HTML></dt></HTML>\n" <>- T.intercalate "\n" (map (\d -> "<HTML><dd></HTML>" <> d <> "<HTML></dd></HTML>") contents)- else do- indent <- asks stIndent- backSlash <- asks stBackSlashLB- let indent' = if backSlash then T.drop 2 indent else indent- return $ indent' <> "* **" <> labelText <> "** " <> T.concat contents+ contents <- local (\st -> st{ stBlockQuoteLevel = 0 })+ (mapM (blockListToDokuWiki opts) items)+ indent <- asks stIndent+ backSlash <- asks stBackSlashLB+ let indent' = if backSlash then T.drop 2 indent else indent+ return $ bqPrefix <> indent' <> "* **" <> labelText <> "** " <>+ if useWrap+ then "<WRAP>\n" <> vcat contents <> "\n</WRAP>"+ else T.intercalate "; " contents --- | True if the list can be handled by simple wiki markup, False if HTML tags will be needed.+-- | True if list item can be handled with the simple wiki syntax. False if+-- WRAP tags will be needed.+isSimpleListItem :: [Block] -> Bool+isSimpleListItem [] = True+isSimpleListItem [x, CodeBlock{}] | isPlainOrPara x = True+isSimpleListItem (Div _ bs : ys) = -- see #8920+ isSimpleListItem bs && all isSimpleList ys+isSimpleListItem (x:ys) | isPlainOrPara x = all isSimpleList ys+isSimpleListItem _ = False+--- | True if the list can be handled by simple wiki markup, False if HTML tags will be needed.+ isSimpleList :: Block -> Bool isSimpleList x = case x of@@ -313,22 +297,11 @@ DefinitionList items -> all (all isSimpleListItem . snd) items _ -> False --- | True if list item can be handled with the simple wiki syntax. False if--- HTML tags will be needed.-isSimpleListItem :: [Block] -> Bool-isSimpleListItem [] = True-isSimpleListItem [x, CodeBlock{}] | isPlainOrPara x = True-isSimpleListItem (x:ys) | isPlainOrPara x = all isSimpleList ys-isSimpleListItem _ = False- isPlainOrPara :: Block -> Bool isPlainOrPara (Plain _) = True isPlainOrPara (Para _) = True isPlainOrPara _ = False -isSimpleBlockQuote :: [Block] -> Bool-isSimpleBlockQuote bs = all isPlainOrPara bs- -- | Concatenates strings with line breaks between them. vcat :: [Text] -> Text vcat = T.intercalate "\n"@@ -358,8 +331,9 @@ (if align' == AlignLeft || align' == AlignCenter then " " else "")- contents <- local (\s -> s { stBackSlashLB = True }) $- blockListToDokuWiki opts item+ contents <- local (\s -> s { stBackSlashLB = True+ , stBlockQuoteLevel = 0 }) $+ blockListToDokuWiki opts item return $ mkcell contents -- | Convert list of Pandoc block elements to DokuWiki.@@ -449,9 +423,10 @@ DisplayMath -> "$$" InlineMath -> "$" -inlineToDokuWiki _ il@(RawInline f str)+inlineToDokuWiki opts il@(RawInline f str) | f == Format "dokuwiki" = return str- | f == Format "html" = return $ "<html>" <> str <> "</html>"+ | f == Format "html"+ , isEnabled Ext_raw_html opts = return $ "<html>" <> str <> "</html>" | otherwise = "" <$ report (InlineNotRendered il) inlineToDokuWiki _ LineBreak = do@@ -488,7 +463,8 @@ return $ "{{" <> source <> imageDims opts attr <> txt <> "}}" inlineToDokuWiki opts (Note contents) = do- contents' <- blockListToDokuWiki opts contents+ contents' <- local (\st -> st{ stBlockQuoteLevel = 0 })+ (blockListToDokuWiki opts contents) return $ "((" <> contents' <> "))" -- note - may not work for notes with multiple blocks
@@ -5,7 +5,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Text.Pandoc.Writers.EPUB- Copyright : Copyright (C) 2010-2022 John MacFarlane+ Copyright : Copyright (C) 2010-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -20,14 +20,14 @@ import Control.Applicative ( (<|>) ) import Control.Monad (mplus, unless, when, zipWithM) import Control.Monad.Except (catchError, throwError)-import Control.Monad.State.Strict (StateT, evalState, evalStateT, get,+import Control.Monad.State.Strict (State, StateT, evalState, evalStateT, get, gets, lift, modify) import qualified Data.ByteString.Lazy as B import qualified Data.ByteString.Lazy.Char8 as B8 import Data.Char (isAlphaNum, isAscii, isDigit) import Data.List (isInfixOf, isPrefixOf) import qualified Data.Map as M-import Data.Maybe (fromMaybe, isNothing, mapMaybe, isJust)+import Data.Maybe (fromMaybe, isNothing, mapMaybe, isJust, catMaybes) import qualified Data.Set as Set import qualified Data.Text as T import Data.Text (Text)@@ -36,8 +36,10 @@ import Text.HTML.TagSoup (Tag (TagOpen), fromAttrib, parseTags) import Text.Pandoc.Builder (fromList, setMeta) import Text.Pandoc.Writers.Shared (ensureValidXmlIdentifiers)+import Data.Tree (Tree(..)) import Text.Pandoc.Class (PandocMonad, report) import qualified Text.Pandoc.Class.PandocPure as P+import Text.Pandoc.Data (readDataFile) import qualified Text.Pandoc.Class.PandocMonad as P import Data.Time import Text.Pandoc.Definition@@ -45,21 +47,23 @@ import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.MIME (MimeType, extensionFromMimeType, getMimeType)-import Text.Pandoc.Network.HTTP (urlEncode)+import Text.Pandoc.URI (urlEncode) import Text.Pandoc.Options (EPUBVersion (..), HTMLMathMethod (..), ObfuscationMethod (NoObfuscation), WrapOption (..), WriterOptions (..))-import Text.Pandoc.Shared (makeSections, normalizeDate, renderTags',+import Text.Pandoc.Shared (normalizeDate, renderTags', stringify, uniqueIdent, tshow) import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.UUID (getRandomUUID)-import Text.Pandoc.Walk (query, walk, walkM)+import Text.Pandoc.Walk (walk, walkM) import Text.Pandoc.Writers.HTML (writeHtmlStringForEPUB) import Text.Printf (printf) import Text.Pandoc.XML.Light import Text.Pandoc.XML (escapeStringForXML) import Text.DocTemplates (FromContext(lookupContext), Context(..), ToContext(toVal), Val(..))+import Text.Pandoc.Chunks (splitIntoChunks, Chunk(..), ChunkedDoc(..),+ SecInfo(..)) -- A Chapter includes a list of blocks. newtype Chapter = Chapter [Block]@@ -96,6 +100,11 @@ , epubPageDirection :: Maybe ProgressionDirection , epubIbooksFields :: [(Text, Text)] , epubCalibreFields :: [(Text, Text)]+ , epubAccessModes :: [Text] -- https://kb.daisy.org/publishing/docs/metadata/schema.org/accessMode.html+ , epubAccessModeSufficient :: [Text] -- https://kb.daisy.org/publishing/docs/metadata/schema.org/accessModeSufficient.html+ , epubAccessibilityFeatures :: [Text] -- https://kb.daisy.org/publishing/docs/metadata/schema.org/accessibilityFeature.html+ , epubAccessibilityHazards :: [Text] -- https://kb.daisy.org/publishing/docs/metadata/schema.org/accessibilityHazard.html+ , epubAccessibilitySummary :: Maybe Text -- https://kb.daisy.org/publishing/docs/metadata/schema.org/accessibilitySummary.html } deriving Show data Date = Date{@@ -247,7 +256,6 @@ | name == "description" = md { epubDescription = Just $ strContent e } | name == "type" = md { epubType = Just $ strContent e } | name == "format" = md { epubFormat = Just $ strContent e }- | name == "type" = md { epubType = Just $ strContent e } | name == "publisher" = md { epubPublisher = Just $ strContent e } | name == "source" = md { epubSource = Just $ strContent e } | name == "relation" = md { epubRelation = Just $ strContent e }@@ -258,16 +266,15 @@ | otherwise = md where getAttr n = lookupAttr (opfName n) attrs addMetadataFromXML e@(Element (QName "meta" _ _) attrs _ _) md =- case getAttr "property" of+ case getAttr "property" `mplus` getAttr "name" of Just s | "ibooks:" `T.isPrefixOf` s -> md{ epubIbooksFields = (T.drop 7 s, strContent e) : epubIbooksFields md }- _ -> case getAttr "name" of- Just s | "calibre:" `T.isPrefixOf` s ->+ | "calibre:" `T.isPrefixOf` s -> md{ epubCalibreFields = (T.drop 8 s, fromMaybe "" $ getAttr "content") : epubCalibreFields md }- _ -> md+ _ -> md where getAttr n = lookupAttr (unqual n) attrs addMetadataFromXML _ md = md @@ -356,6 +363,11 @@ , epubPageDirection = pageDirection , epubIbooksFields = ibooksFields , epubCalibreFields = calibreFields+ , epubAccessModes = accessModes+ , epubAccessModeSufficient = accessModeSufficient+ , epubAccessibilityFeatures = accessibilityFeatures+ , epubAccessibilityHazards = accessibilityHazards+ , epubAccessibilitySummary = accessibilitySummary } where identifiers = getIdentifier meta titles = getTitle meta@@ -399,6 +411,22 @@ Just (MetaMap mp) -> M.toList $ M.map metaValueToString mp _ -> []+ accessModes = case lookupMeta "accessModes" meta of+ Just (MetaList xs) -> map metaValueToString xs+ _ -> ["textual"]+ accessModeSufficient = case lookupMeta "accessModeSufficient" meta of+ Just (MetaList xs) -> map metaValueToString xs+ _ -> ["textual"]+ accessibilityFeatures =+ case lookupMeta "accessibilityFeatures" meta of+ Just (MetaList xs) -> map metaValueToString xs+ _ -> ["alternativeText", "readingOrder",+ "structuralNavigation", "tableOfContents"]+ accessibilityHazards =+ case lookupMeta "accessibilityHazards" meta of+ Just (MetaList xs) -> map metaValueToString xs+ _ -> ["none"]+ accessibilitySummary = metaValueToString <$> lookupMeta "accessibilitySummary" meta -- | Produce an EPUB2 file from a Pandoc document. writeEPUB2 :: PandocMonad m@@ -438,8 +466,8 @@ pandocToEPUB version opts doc = do let doc' = ensureValidXmlIdentifiers doc -- handle pictures- Pandoc meta blocks <- walkM (transformInline opts) doc' >>=- walkM transformBlock+ Pandoc meta blocks <- walkM (transformInline version opts) doc' >>=+ walkM (transformBlock version) picEntries <- mapMaybe (snd . snd) <$> gets stMediaPaths epubSubdir <- gets stEpubSubdir@@ -460,7 +488,7 @@ -- stylesheet stylesheets <- case epubStylesheets metadata of [] -> (\x -> [B.fromChunks [x]]) <$>- P.readDataFile "epub.css"+ readDataFile "epub.css" fs -> mapM P.readFileLazy fs stylesheetEntries <- zipWithM (\bs n -> mkEntry ("styles/stylesheet" ++ show n ++ ".css") bs)@@ -494,7 +522,8 @@ , writerWrapText = WrapAuto } -- cover page- (cpgEntry, cpicEntry) <- createCoverPage meta metadata opts' vars cssvars writeHtml plainTitle+ (cpgEntry, cpicEntry, mbCoverImageName) <-+ createCoverPage meta metadata opts' vars cssvars writeHtml plainTitle -- title page tpContent <- lift $ writeHtml opts'{@@ -525,22 +554,27 @@ -- body pages -- add level 1 header to beginning if none there- let secs = makeSections True Nothing- $ addIdentifiers opts- $ case blocks of- (Div _- (Header{}:_) : _) -> blocks- (Header 1 _ _ : _) -> blocks- _ -> Header 1 ("",["unnumbered"],[])- (docTitle' meta) : blocks+ let blocks' = addIdentifiers opts+ $ case blocks of+ (Div _+ (Header{}:_) : _) -> blocks+ (Header 1 _ _ : _) -> blocks+ _ -> Header 1 ("",["unnumbered"],[])+ (docTitle' meta) : blocks - -- create the chapters and their reftable from the original options and the sections- let (chapters, reftable) = createChaptersAndReftable opts secs+ -- create the chapters+ let chunkedDoc = splitIntoChunks "ch%n.xhtml"+ (writerNumberSections opts)+ Nothing+ (writerSplitLevel opts)+ (Pandoc meta blocks') + -- Create the chapter entries from the chapters. -- Also requires access to the extended writer options and context -- as well as the css Context and html writer- chapterEntries <- createChapterEntries opts' vars cssvars writeHtml chapters+ chapterEntries <- createChapterEntries opts' vars cssvars writeHtml+ (chunkedChunks chunkedDoc) @@ -605,11 +639,11 @@ ([("version", case version of EPUB2 -> "2.0" EPUB3 -> "3.0")- ,("xmlns","http://www.idpf.org/2007/opf")- ,("unique-identifier","epub-id-1")- ] +++ ,("xmlns","http://www.idpf.org/2007/opf")] +++ [("xml:lang", epubLanguage metadata) | version == EPUB3] +++ [("unique-identifier","epub-id-1")] ++ [("prefix","ibooks: http://vocabulary.itunes.apple.com/rdf/ibooks/vocabulary-extensions-1.0/") | version == EPUB3]) $- [ metadataElement version metadata currentTime+ [ metadataElement version metadata mbCoverImageName currentTime , unode "manifest" $ [ unode "item" ! [("id","ncx"), ("href","toc.ncx") ,("media-type","application/x-dtbncx+xml")] $ ()@@ -624,7 +658,9 @@ (n :: Int, fp) <- zip [1..] (map (makeRelative epubSubdir . eRelativePath) stylesheetEntries) ] ++- map chapterNode (cpgEntry ++ (tpEntry : chapterEntries)) +++ map chapterNode (cpgEntry +++ [tpEntry | writerEpubTitlePage opts] +++ chapterEntries) ++ (case cpicEntry of [] -> [] (x:_) -> [add_attrs@@ -638,11 +674,12 @@ Nothing -> [] Just _ -> [ unode "itemref" ! [("idref", "cover_xhtml")] $ () ]- ++ ((unode "itemref" ! [("idref", "title_page_xhtml")+ ++ ([unode "itemref" ! [("idref", "title_page_xhtml") ,("linear", case lookupMeta "title" meta of Just _ -> "yes"- Nothing -> "no")] $ ()) :+ Nothing -> "no")] $ ()+ | writerEpubTitlePage opts] ++ [unode "itemref" ! [("idref", "nav")] $ () | writerTableOfContents opts ] ++ map chapterRefNode chapterEntries)@@ -662,40 +699,14 @@ contentsEntry <- mkEntry "content.opf" contentsData -- toc.ncx- let tocLevel = writerTOCDepth opts-- -- Helper function for both the toc and anv Entries- let navPointNode :: PandocMonad m- => (Int -> [Inline] -> T.Text -> [Element] -> Element)- -> Block -> StateT Int m [Element]- navPointNode formatter (Div (ident,_,_)- (Header lvl (_,_,kvs) ils : children)) =- if lvl > tocLevel- then return []- else do- n <- get- modify (+1)- let num = fromMaybe "" $ lookup "number" kvs- let tit = if writerNumberSections opts && not (T.null num)- then Span ("", ["section-header-number"], [])- [Str num] : Space : ils- else ils- src <- case lookup ident reftable of- Just x -> return x- Nothing -> throwError $ PandocSomeError $- ident <> " not found in reftable"- subs <- concat <$> mapM (navPointNode formatter) children- return [formatter n tit src subs]- navPointNode formatter (Div _ bs) =- concat <$> mapM (navPointNode formatter) bs- navPointNode _ _ = return []- -- Create the tocEntry from the metadata together with the sections and title.- tocEntry <- createTocEntry meta metadata plainTitle secs navPointNode+ tocEntry <- createTocEntry opts' meta metadata plainTitle+ (chunkedTOC chunkedDoc) -- Create the navEntry using the metadata, all of the various writer options, -- the CSS and HTML helpers, the document and toc title as well as the epub version and all of the sections- navEntry <- createNavEntry meta metadata opts opts' vars cssvars writeHtml plainTitle tocTitle version secs navPointNode+ navEntry <- createNavEntry opts' meta metadata vars cssvars+ writeHtml tocTitle version (chunkedTOC chunkedDoc) -- mimetype mimetypeEntry <- mkEntry "mimetype" $@@ -723,7 +734,8 @@ -- construct archive let archive = foldr addEntryToArchive emptyArchive $ [mimetypeEntry, containerEntry, appleEntry,- contentsEntry, tocEntry, navEntry, tpEntry] +++ contentsEntry, tocEntry, navEntry] +++ [tpEntry | writerEpubTitlePage opts] ++ stylesheetEntries ++ picEntries ++ cpicEntry ++ cpgEntry ++ chapterEntries ++ fontEntries return $ fromArchive archive@@ -731,6 +743,7 @@ -- | Function used during conversion from pandoc to EPUB to create the cover page. -- The first Entry list is for the cover while the second one is for the cover image. -- If no cover images are specified, empty lists will be returned.+-- The third value of the returned tuple is the cover image name. createCoverPage :: PandocMonad m => Meta -> EPUBMetadata@@ -739,18 +752,14 @@ -> (Bool -> Context Text) -> (WriterOptions -> Pandoc -> m B8.ByteString) -> Text- -> StateT EPUBState m ([Entry], [Entry])-createCoverPage meta metadata opts' vars cssvars writeHtml plainTitle = + -> StateT EPUBState m ([Entry], [Entry], Maybe FilePath)+createCoverPage meta metadata opts' vars cssvars writeHtml plainTitle = case epubCoverImage metadata of- Nothing -> return ([],[])+ Nothing -> return ([],[], Nothing) Just img -> do let fp = takeFileName img -- retrieve cover image file- mediaPaths <- gets (map (fst . snd) . stMediaPaths)- coverImageName <- -- see #4206- if ("media/" <> fp) `elem` mediaPaths- then getMediaNextNewName (takeExtension fp)- else return fp+ coverImageName <- getMediaNextNewName (takeExtension fp) -- see #4206 -- image dimensions imgContent <- lift $ P.readFileLazy img (coverImageWidth, coverImageHeight) <-@@ -778,7 +787,7 @@ coverImageEntry <- mkEntry ("media/" ++ coverImageName) imgContent - return ( [ coverEntry ], [ coverImageEntry ] )+ return ( [ coverEntry ], [ coverImageEntry ], Just coverImageName ) -- | Converts the given chapters to entries using the writeHtml function -- and the various provided options@@ -787,13 +796,13 @@ -> Context Text -> (Bool -> Context Text) -> (WriterOptions -> Pandoc -> StateT EPUBState m B8.ByteString)- -> [Chapter]+ -> [Chunk] -> StateT EPUBState m [Entry] createChapterEntries opts' vars cssvars writeHtml chapters = do -- Create an entry from the chapter with the provided number. -- chapToEntry :: Int -> Chapter -> StateT EPUBState m Entry- let chapToEntry num (Chapter bs) =- mkEntry ("text/" ++ T.unpack (showChapter num)) =<<+ let chapToEntry num chunk =+ mkEntry ("text/" ++ chunkPath chunk) =<< -- Combine all provided options writeHtml opts'{ writerVariables = Context (M.fromList@@ -801,13 +810,16 @@ ("pagetitle", toVal' $ showChapter num)]) <> cssvars True <> vars } pdoc- where (pdoc, bodyType) =+ where bs = chunkContents chunk+ meta' = setMeta "title" (fromList+ (walk removeNote+ (chunkHeading chunk))) nullMeta+ (pdoc, bodyType) = case bs of- (Div (_,"section":_,kvs) (Header _ _ xs : _) : _) ->+ (Div (_,"section":_,kvs) _ : _) -> -- remove notes or we get doubled footnotes- (Pandoc (setMeta "title"- (walk removeNote $ fromList xs) nullMeta) bs,- -- Check if the chapters belongs to the frontmatter, + (Pandoc meta' bs,+ -- Check if the chapters belongs to the frontmatter, -- backmatter of bodymatter defaulting to the body case lookup "epub:type" kvs of Nothing -> "bodymatter"@@ -815,7 +827,7 @@ | x `elem` frontMatterTypes -> "frontmatter" | x `elem` backMatterTypes -> "backmatter" | otherwise -> "bodymatter")- _ -> (Pandoc nullMeta bs, "bodymatter")+ _ -> (Pandoc meta' bs, "bodymatter") frontMatterTypes = ["prologue", "abstract", "acknowledgments", "copyright-page", "dedication", "credits", "keywords", "imprint",@@ -829,118 +841,39 @@ zipWithM chapToEntry [1..] chapters --- | Splits the blocks into chapters and creates a corresponding reftable-createChaptersAndReftable :: WriterOptions -> [Block] -> ([Chapter], [(Text, Text)])-createChaptersAndReftable opts secs = (chapters, reftable)- where - chapterHeaderLevel = writerEpubChapterLevel opts-- isChapterHeader :: Block -> Bool- isChapterHeader (Div _ (Header n _ _:_)) = n <= chapterHeaderLevel- isChapterHeader _ = False-- secsToChapters :: [Block] -> [Chapter]- secsToChapters [] = []- secsToChapters (d@(Div attr (h@(Header lvl _ _) : bs)) : rest)- -- If the header is of the same level as chapters, create a chapter- | chapterHeaderLevel == lvl =- Chapter [d] : secsToChapters rest- -- If the header is a level higher than chapters, - -- create a chapter of everything until the next chapter header.- | chapterHeaderLevel > lvl =- Chapter [Div attr (h:xs)] :- secsToChapters ys ++ secsToChapters rest- where (xs, ys) = break isChapterHeader bs- secsToChapters bs =- -- If this is the last block, keep it as is, - -- otherwise create a chapter for everything until the next chapter header.- (if null xs then id else (Chapter xs :)) $ secsToChapters ys- where (xs, ys) = break isChapterHeader bs- - -- Convert the sections to initial chapters- chapters' = secsToChapters secs-- -- Extract references for the reftable from Inline elements- extractLinkURL' :: Int -> Inline -> [(T.Text, T.Text)]- extractLinkURL' num (Span (ident, _, _) _)- | not (T.null ident) = [(ident, showChapter num <> "#" <> ident)]- extractLinkURL' num (Link (ident, _, _) _ _)- | not (T.null ident) = [(ident, showChapter num <> "#" <> ident)]- extractLinkURL' num (Image (ident, _, _) _ _)- | not (T.null ident) = [(ident, showChapter num <> "#" <> ident)]- extractLinkURL' num (RawInline fmt raw)- | isHtmlFormat fmt- = foldr (\tag ->- case tag of- TagOpen{} ->- case fromAttrib "id" tag of- "" -> id- x -> ((x, showChapter num <> "#" <> x):)- _ -> id)- [] (parseTags raw)- extractLinkURL' _ _ = []- - -- Extract references for the reftable from Block elements- extractLinkURL :: Int -> Block -> [(T.Text, T.Text)]- extractLinkURL num (Div (ident, _, _) _)- | not (T.null ident) = [(ident, showChapter num <> "#" <> ident)]- extractLinkURL num (Header _ (ident, _, _) _)- | not (T.null ident) = [(ident, showChapter num <> "#" <> ident)]- extractLinkURL num (Table (ident,_,_) _ _ _ _ _)- | not (T.null ident) = [(ident, showChapter num <> "#" <> ident)]- extractLinkURL num (RawBlock fmt raw)- | isHtmlFormat fmt- = foldr (\tag ->- case tag of- TagOpen{} ->- case fromAttrib "id" tag of- "" -> id- x -> ((x, showChapter num <> "#" <> x):)- _ -> id)- [] (parseTags raw)- extractLinkURL num b = query (extractLinkURL' num) b-- -- Create a reference table for the chapters with appropriate numbering- reftable = concat $ zipWith (\(Chapter bs) num ->- query (extractLinkURL num) bs)- chapters' [1..]-- fixInternalReferences :: Inline -> Inline- fixInternalReferences (Link attr lab (src, tit))- | Just ('#', xs) <- T.uncons src = case lookup xs reftable of- Just ys -> Link attr lab (ys, tit)- Nothing -> Link attr lab (src, tit)- fixInternalReferences x = x-- -- internal reference IDs change when we chunk the file,- -- so that '#my-header-1' might turn into 'chap004.xhtml#my-header'.- -- this fixes that:- chapters = map (\(Chapter bs) ->- Chapter $ walk fixInternalReferences bs)- chapters'- createTocEntry :: PandocMonad m =>- Meta- -> EPUBMetadata- -> Text- -> [Block]- -> ((Int -> [Inline] -> T.Text -> [Element] -> Element) -> Block -> StateT Int m [Element])- -> StateT EPUBState m Entry-createTocEntry meta metadata plainTitle secs navPointNode = do- let navMapFormatter :: Int -> [Inline] -> T.Text -> [Element] -> Element- navMapFormatter n tit src subs = unode "navPoint" !- [("id", "navPoint-" <> tshow n)] $- [ unode "navLabel" $ unode "text" $ stringify tit- , unode "content" ! [("src", "text/" <> src)] $ ()- ] ++ subs+ WriterOptions+ -> Meta+ -> EPUBMetadata+ -> Text+ -> Tree SecInfo+ -> StateT EPUBState m Entry+createTocEntry opts meta metadata plainTitle (Node _ secs) = do+ let mkNavPoint :: Tree SecInfo -> State Int (Maybe Element)+ mkNavPoint (Node secinfo subsecs)+ | secLevel secinfo > writerTOCDepth opts = return Nothing+ | otherwise = do+ n <- get+ modify (+ 1)+ subs <- catMaybes <$> mapM mkNavPoint subsecs+ let secnum' = case secNumber secinfo of+ Just t -> t <> " "+ Nothing -> ""+ let title' = secnum' <> stringify (secTitle secinfo)+ return $ Just $ unode "navPoint" !+ [("id", "navPoint-" <> tshow n)] $+ [ unode "navLabel" $ unode "text" title'+ , unode "content" !+ [("src", "text/" <> secPath secinfo)] $ ()+ ] ++ subs let tpNode = unode "navPoint" ! [("id", "navPoint-0")] $- [ unode "navLabel" $ unode "text" (stringify $ docTitle' meta)+ [ unode "navLabel" $ unode "text"+ (stringify $ docTitle' meta) , unode "content" ! [("src", "text/title_page.xhtml")] $ () ] - navMap <- lift $ evalStateT- (concat <$> mapM (navPointNode navMapFormatter) secs) 1+ let navMap = evalState (catMaybes <$> mapM mkNavPoint secs) 1 uuid <- case epubIdentifier metadata of (x:_) -> return $ identifierText x -- use first identifier as UUID@@ -962,70 +895,75 @@ Just img -> [unode "meta" ! [("name","cover"), ("content", toId img)] $ ()] , unode "docTitle" $ unode "text" plainTitle- , unode "navMap" $- tpNode : navMap+ , unode "navMap" $ [tpNode | writerEpubTitlePage opts] ++ navMap ] mkEntry "toc.ncx" tocData -createNavEntry :: PandocMonad m =>- Meta- -> EPUBMetadata- -> WriterOptions- -> WriterOptions- -> Context Text- -> (Bool -> Context Text)- -> (WriterOptions -> Pandoc -> m B8.ByteString)- -> Text- -> Text- -> EPUBVersion- -> [Block]- -> ((Int -> [Inline] -> T.Text -> [Element] -> Element) -> Block -> StateT Int m [Element])- -> StateT EPUBState m Entry-createNavEntry meta metadata opts opts' vars cssvars writeHtml plainTitle tocTitle version secs navPointNode = do- let navXhtmlFormatter :: Int -> [Inline] -> T.Text -> [Element] -> Element- navXhtmlFormatter n tit src subs = unode "li" !- [("id", "toc-li-" <> tshow n)] $- (unode "a" !- [("href", "text/" <> src)]- $ titElements)- : case subs of- [] -> []- (_:_) -> [unode "ol" ! [("class","toc")] $ subs]- where titElements = either (const []) id $- parseXMLContents (TL.fromStrict titRendered)- titRendered = case P.runPure- (writeHtmlStringForEPUB version- opts{ writerTemplate = Nothing- , writerVariables =- Context (M.fromList- [("pagetitle", toVal $- escapeStringForXML plainTitle)])- <> writerVariables opts}- (Pandoc nullMeta- [Plain $ walk clean tit])) of- Left _ -> stringify tit- Right x -> x- -- can't have <a> elements inside generated links...- clean (Link _ ils _) = Span ("", [], []) ils- clean (Note _) = Str ""- clean x = x+createNavEntry :: PandocMonad m+ => WriterOptions+ -> Meta+ -> EPUBMetadata+ -> Context Text+ -> (Bool -> Context Text)+ -> (WriterOptions -> Pandoc -> m B8.ByteString)+ -> Text+ -> EPUBVersion+ -> Tree SecInfo+ -> StateT EPUBState m Entry+createNavEntry opts meta metadata+ vars cssvars writeHtml tocTitle version (Node _ secs) = do+ let mkItem :: Tree SecInfo -> State Int (Maybe Element)+ mkItem (Node secinfo subsecs)+ | secLevel secinfo > writerTOCDepth opts = return Nothing+ | otherwise = do+ n <- get+ modify (+ 1)+ subs <- catMaybes <$> mapM mkItem subsecs+ let secnum' = case secNumber secinfo of+ Just num -> [Span ("", ["section-header-number"], [])+ [Str num] , Str "\160"]+ Nothing -> []+ let title' = secnum' <> secTitle secinfo+ -- can't have <a> elements inside generated links...+ let clean (Link _ ils _) = Span ("", [], []) ils+ clean (Note _) = Str ""+ clean x = x+ let titRendered = case P.runPure+ (writeHtmlStringForEPUB version+ opts{ writerTemplate = Nothing }+ (Pandoc nullMeta+ [Plain $ walk clean title'])) of+ Left _ -> stringify title'+ Right x -> x+ let titElements = either (const []) id $+ parseXMLContents (TL.fromStrict titRendered) + return $ Just $ unode "li" !+ [("id", "toc-li-" <> tshow n)] $+ (unode "a" !+ [("href", "text/" <> secPath secinfo)]+ $ titElements)+ : case subs of+ [] -> []+ (_:_) -> [unode "ol" ! [("class","toc")] $ subs]+ let navtag = if version == EPUB3 then "nav" else "div"- tocBlocks <- lift $ evalStateT- (concat <$> mapM (navPointNode navXhtmlFormatter) secs) 1+ let tocBlocks = evalState (catMaybes <$> mapM mkItem secs) 1 let navBlocks = [RawBlock (Format "html") $ showElement $ -- prettyprinting introduces bad spaces unode navtag ! ([("epub:type","toc") | version == EPUB3] +++ [("role","doc-toc") | version == EPUB3] ++ [("id","toc")]) $ [ unode "h1" ! [("id","toc-title")] $ tocTitle , unode "ol" ! [("class","toc")] $ tocBlocks ]] let landmarkItems = if version == EPUB3- then unode "li"+ then [ unode "li" [ unode "a" ! [("href", "text/title_page.xhtml") ,("epub:type", "titlepage")] $- ("Title Page" :: Text) ] :+ ("Title Page" :: Text) ] |+ writerEpubTitlePage opts ] ++ [ unode "li" [ unode "a" ! [("href", "text/cover.xhtml") ,("epub:type", "cover")] $@@ -1045,7 +983,7 @@ ,("hidden","hidden")] $ [ unode "ol" landmarkItems ] | not (null landmarkItems)]- navData <- lift $ writeHtml opts'{ writerVariables =+ navData <- lift $ writeHtml opts{ writerVariables = Context (M.fromList [("navpage", toVal' "true") ,("body-type", toVal' "frontmatter") ])@@ -1056,8 +994,9 @@ -- Return mkEntry "nav.xhtml" navData -metadataElement :: EPUBVersion -> EPUBMetadata -> UTCTime -> Element-metadataElement version md currentTime =+metadataElement :: EPUBVersion -> EPUBMetadata -> Maybe FilePath -> UTCTime+ -> Element+metadataElement version md mbCoverImage currentTime = unode "metadata" ! [("xmlns:dc","http://purl.org/dc/elements/1.1/") ,("xmlns:opf","http://www.idpf.org/2007/opf")] $ mdNodes where mdNodes = identifierNodes ++ titleNodes ++ dateNodes@@ -1067,6 +1006,14 @@ ++ publisherNodes ++ sourceNodes ++ relationNodes ++ coverageNodes ++ rightsNodes ++ coverImageNodes ++ modifiedNodes ++ belongsToCollectionNodes+ ++ case version of+ EPUB2 -> []+ EPUB3 -> accessModeNodes +++ accessModeSufficientNodes +++ accessibilityFeatureNodes +++ accessibilityHazardNodes +++ accessibilitySummaryNodes+ metaprop = if version == EPUB2 then "name" else "property" withIds base f = concat . zipWith f (map (\x -> base <> T.cons '-' (tshow x)) ([1..] :: [Int]))@@ -1082,9 +1029,9 @@ (x:_) -> [dcNode "date" ! [("id","epub-date")] $ dateText x] ibooksNodes = map ibooksNode (epubIbooksFields md)- ibooksNode (k, v) = unode "meta" ! [("property", "ibooks:" <> k)] $ v+ ibooksNode (k, v) = unode "meta" ! [(metaprop, "ibooks:" <> k)] $ v calibreNodes = map calibreNode (epubCalibreFields md)- calibreNode (k, v) = unode "meta" ! [("name", "calibre:" <> k),+ calibreNode (k, v) = unode "meta" ! [(metaprop, "calibre:" <> k), ("content", v)] $ () languageNodes = [dcTag "language" $ epubLanguage md] creatorNodes = withIds "epub-creator" (toCreatorNode "creator") $@@ -1103,18 +1050,27 @@ coverImageNodes = maybe [] (\img -> [unode "meta" ! [("name","cover"), ("content",toId img)] $ ()])- $ epubCoverImage md- modifiedNodes = [ unode "meta" ! [("property", "dcterms:modified")] $+ mbCoverImage+ modifiedNodes = [ unode "meta" ! [(metaprop, "dcterms:modified")] $ showDateTimeISO8601 currentTime | version == EPUB3 ] belongsToCollectionNodes = maybe []- (\belongsToCollection -> (unode "meta" ! [("property", "belongs-to-collection"), ("id", "epub-collection-1")] $ belongsToCollection )+ (\belongsToCollection -> (unode "meta" ! [(metaprop, "belongs-to-collection"), ("id", "epub-collection-1")] $ belongsToCollection ) :- [unode "meta" ! [("refines", "#epub-collection-1"), ("property", "collection-type")] $ ("series" :: Text) ])+ [unode "meta" ! [("refines", "#epub-collection-1"), (metaprop, "collection-type")] $ ("series" :: Text) ]) (epubBelongsToCollection md)++ maybe []- (\groupPosition -> [unode "meta" ! [("refines", "#epub-collection-1"), ("property", "group-position")] $ groupPosition ])+ (\groupPosition -> [unode "meta" ! [("refines", "#epub-collection-1"), (metaprop, "group-position")] $ groupPosition ]) (epubGroupPosition md)+ schemanode k v = unode "meta" ! [(metaprop, "schema:" <> k)] $ v+ accessModeNodes = map (schemanode "accessMode") (epubAccessModes md)+ accessModeSufficientNodes = map (schemanode "accessModeSufficient") (epubAccessModeSufficient md)+ accessibilityFeatureNodes = map (schemanode "accessibilityFeature")+ (epubAccessibilityFeatures md)+ accessibilityHazardNodes = map (schemanode "accessibilityHazard")+ (epubAccessibilityHazards md)+ accessibilitySummaryNodes = maybe [] (\summary -> [schemanode "accessibilitySummary" summary]) $ epubAccessibilitySummary md+ dcTag n s = unode ("dc:" <> n) s dcTag' n s = [dcTag n s] toIdentifierNode id' (Identifier txt scheme)@@ -1124,7 +1080,7 @@ | otherwise = (dcNode "identifier" ! [("id",id')] $ txt) : maybe [] ((\x -> [unode "meta" ! [ ("refines","#" <> id')- , ("property","identifier-type")+ , (metaprop,"identifier-type") , ("scheme","onix:codelist5") ] $ x@@ -1139,10 +1095,10 @@ (creatorRole creator >>= toRelator)) $ creatorText creator] | otherwise = [dcNode s ! [("id",id')] $ creatorText creator] ++ maybe [] (\x -> [unode "meta" !- [("refines","#" <> id'),("property","file-as")] $ x])+ [("refines","#" <> id'),(metaprop,"file-as")] $ x]) (creatorFileAs creator) ++ maybe [] (\x -> [unode "meta" !- [("refines","#" <> id'),("property","role"),+ [("refines","#" <> id'),(metaprop,"role"), ("scheme","marc:relators")] $ x]) (creatorRole creator >>= toRelator) toTitleNode id' title@@ -1154,10 +1110,10 @@ | otherwise = [dcNode "title" ! [("id",id')] $ titleText title] ++ maybe [] (\x -> [unode "meta" !- [("refines","#" <> id'),("property","file-as")] $ x])+ [("refines","#" <> id'),(metaprop,"file-as")] $ x]) (titleFileAs title) ++ maybe [] (\x -> [unode "meta" !- [("refines","#" <> id'),("property","title-type")] $ x])+ [("refines","#" <> id'),(metaprop,"title-type")] $ x]) (titleType title) toDateNode id' date = [dcNode "date" ! (("id",id') :@@ -1168,9 +1124,9 @@ [("id",id')] $ subjectText subject] | otherwise = (dcNode "subject" ! [("id",id')] $ subjectText subject) : maybe [] (\x -> (unode "meta" !- [("refines", "#" <> id'),("property","authority")] $ x) :+ [("refines", "#" <> id'),(metaprop,"authority")] $ x) : maybe [] (\y -> [unode "meta" !- [("refines", "#" <> id'),("property","term")] $ y])+ [("refines", "#" <> id'),(metaprop,"term")] $ y]) (subjectTerm subject)) (subjectAuthority subject) schemeToOnix :: Text -> Text@@ -1184,11 +1140,18 @@ schemeToOnix "ISBN-13" = "15" schemeToOnix "Legal deposit number" = "17" schemeToOnix "URN" = "22"- schemeToOnix "OCLC" = "23"+ schemeToOnix "OCLC number" = "23"+ schemeToOnix "Co-publisher’s ISBN-13" = "24" schemeToOnix "ISMN-13" = "25" schemeToOnix "ISBN-A" = "26"- schemeToOnix "JP" = "27"- schemeToOnix "OLCC" = "28"+ schemeToOnix "JP e-code" = "27"+ schemeToOnix "OLCC number" = "28"+ schemeToOnix "JP Magazine ID" = "29"+ schemeToOnix "UPC-12+5" = "30"+ schemeToOnix "BNF Control number" = "31"+ schemeToOnix "ISSN-13" = "34"+ schemeToOnix "ARK" = "35"+ schemeToOnix "Digital file internal version number" = "36" schemeToOnix _ = "01" showDateTimeISO8601 :: UTCTime -> Text@@ -1220,8 +1183,10 @@ Just (n,_) -> return $ T.pack n Nothing -> catchError (do (img, mbMime) <- P.fetchItem $ T.pack oldsrc- let ext = maybe (takeExtension (takeWhile (/='?') oldsrc)) T.unpack- (("." <>) <$> (mbMime >>= extensionFromMimeType))+ let ext = maybe+ (takeExtension (takeWhile (/='?') oldsrc))+ (T.unpack . ("." <>))+ (mbMime >>= extensionFromMimeType) newName <- getMediaNextNewName ext let newPath = "media/" ++ newName entry <- mkEntry newPath (B.fromChunks . (:[]) $ img)@@ -1238,42 +1203,47 @@ modify $ \st -> st { stMediaNextId = nextId + 1 } return $ "file" ++ show nextId ++ ext -isHtmlFormat :: Format -> Bool-isHtmlFormat (Format "html") = True-isHtmlFormat (Format "html4") = True-isHtmlFormat (Format "html5") = True-isHtmlFormat _ = False+isHtmlFormat :: EPUBVersion -> Format -> Bool+isHtmlFormat _ (Format "html") = True+isHtmlFormat _ (Format "html4") = True+isHtmlFormat _ (Format "html5") = True+isHtmlFormat _ (Format "epub") = True+isHtmlFormat EPUB2 (Format "epub2") = True+isHtmlFormat EPUB3 (Format "epub3") = True+isHtmlFormat _ _ = False transformBlock :: PandocMonad m- => Block+ => EPUBVersion+ -> Block -> E m Block-transformBlock (RawBlock fmt raw)- | isHtmlFormat fmt = do+transformBlock version (RawBlock fmt raw)+ | isHtmlFormat version fmt = do let tags = parseTags raw tags' <- mapM transformTag tags return $ RawBlock fmt (renderTags' tags')-transformBlock b = return b+transformBlock _ b = return b transformInline :: PandocMonad m- => WriterOptions+ => EPUBVersion+ -> WriterOptions -> Inline -> E m Inline-transformInline _opts (Image attr@(_,_,kvs) lab (src,tit))+transformInline _ _opts (Image attr@(_,_,kvs) lab (src,tit)) | isNothing (lookup "external" kvs) = do newsrc <- modifyMediaRef $ T.unpack src return $ Image attr lab ("../" <> newsrc, tit)-transformInline opts x@(Math t m)+transformInline _ opts x@(Math t m) | WebTeX url <- writerHTMLMathMethod opts = do newsrc <- modifyMediaRef (T.unpack (url <> urlEncode m)) let mathclass = if t == DisplayMath then "display" else "inline" return $ Span ("",["math",mathclass],[]) [Image nullAttr [x] ("../" <> newsrc, "")]-transformInline _opts (RawInline fmt raw)- | isHtmlFormat fmt = do+transformInline version _opts (RawInline fmt raw)+ | isHtmlFormat version fmt = do let tags = parseTags raw tags' <- mapM transformTag tags return $ RawInline fmt (renderTags' tags')-transformInline _ x = return x+transformInline _ _ x = return x (!) :: (t -> Element) -> [(Text, Text)] -> t -> Element (!) f attrs n = add_attrs (map (\(k,v) -> Attr (unqual k) v) attrs) (f n)
@@ -3,7 +3,7 @@ {- | Module : Text.Pandoc.Writers.FB2 Copyright : Copyright (C) 2011-2012 Sergey Astanin- 2012-2022 John MacFarlane+ 2012-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane@@ -18,27 +18,28 @@ -} module Text.Pandoc.Writers.FB2 (writeFB2) where -import Control.Monad (zipWithM)+import Control.Monad (zipWithM, liftM) import Control.Monad.Except (catchError, throwError)-import Control.Monad.State.Strict (StateT, evalStateT, get, gets, lift, liftM, modify)-import Data.ByteString.Base64 (encodeBase64)+import Control.Monad.State.Strict (StateT, evalStateT, get, gets, lift, modify)+import Data.ByteString.Base64 (encode) import Data.Char (isAscii, isControl, isSpace) import Data.Either (lefts, rights) import Data.List (intercalate) import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Lazy as TL-import Text.Pandoc.Network.HTTP (urlEncode)+import qualified Data.Text.Encoding as TE+import Text.Pandoc.URI (urlEncode, isURI) import Text.Pandoc.XML.Light as X- import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import qualified Text.Pandoc.Class.PandocMonad as P import Text.Pandoc.Definition import Text.Pandoc.Error (PandocError(..)) import Text.Pandoc.Logging import Text.Pandoc.Options (HTMLMathMethod (..), WriterOptions (..), def)-import Text.Pandoc.Shared (capitalize, isURI, orderedListMarkers,+import Text.Pandoc.Shared (blocksToInlines, capitalize, orderedListMarkers, makeSections, tshow, stringify)+import Text.Pandoc.Walk (walk) import Text.Pandoc.Writers.Shared (lookupMetaString, toLegacyTable, ensureValidXmlIdentifiers) import Data.Generics (everywhere, mkT)@@ -236,7 +237,7 @@ report $ CouldNotDetermineMimeType link return Nothing Just mime -> return $ Just (mime,- encodeBase64 bs))+ TE.decodeUtf8 $ encode bs)) (\e -> do report $ CouldNotFetchResource link (tshow e) return Nothing)@@ -299,11 +300,11 @@ -- | Convert a block-level Pandoc's element to FictionBook XML representation. blockToXml :: PandocMonad m => Block -> FBM m [Content]+blockToXml (Plain [img@Image {}]) = insertImage NormalImage img blockToXml (Plain ss) = cMapM toXml ss -- FIXME: can lead to malformed FB2+-- Special handling for singular images and display math elements blockToXml (Para [Math DisplayMath formula]) = insertMath NormalImage formula--- title beginning with fig: indicates that the image is a figure-blockToXml (SimpleFigure atr alt (src, tit)) =- insertImage NormalImage (Image atr alt (src,tit))+blockToXml (Para [img@(Image {})]) = insertImage NormalImage img blockToXml (Para ss) = list . el "p" <$> cMapM toXml ss blockToXml (CodeBlock _ s) = return . spaceBeforeAfter . map (el "p" . el "code") . T.lines $ s@@ -360,7 +361,11 @@ align_str AlignCenter = "center" align_str AlignRight = "right" align_str AlignDefault = "left"-blockToXml Null = return []+blockToXml (Figure _attr (Caption _ longcapt) body) =+ let alt = blocksToInlines longcapt+ addAlt (Image imgattr [] tgt) = Image imgattr alt tgt+ addAlt inln = inln+ in cMapM blockToXml (walk addAlt body) -- Replace plain text with paragraphs and add line break after paragraphs. -- It is used to convert plain text from tight list items to paragraphs.
@@ -5,10 +5,10 @@ {- | Module : Text.Pandoc.Writers.GridTable-Copyright : © 2020-2022 Albert Krewinkel+Copyright : © 2020-2024 Albert Krewinkel License : GNU GPL, version 2 or above -Maintainer : Albert Krewinkel <albert@zeitkraut.de>+Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Grid representation of pandoc tables. The structures in this module allow to describe 'Text.Pandoc.Definition.Table' elements without loss@@ -45,6 +45,7 @@ data GridCell = ContentCell Attr Alignment RowSpan ColSpan [Block] | ContinuationCell CellIndex+ | UnassignedCell deriving (Show) -- | Row index in a table part.@@ -81,10 +82,15 @@ -> [B.TableBody] -> B.TableFoot -> Table-toTable attr caption colSpecs thead tbodies tfoot =+toTable attr caption colSpecs thead' tbodies' tfoot' = Table attr caption colSpecs' rowHeads thGrid tbGrids tfGrid where- colSpecs' = listArray (ColIndex 1, ColIndex $ length colSpecs) colSpecs+ -- normalize in case it's invalid shape:+ thead = B.normalizeTableHead numcols thead'+ tbodies = map (B.normalizeTableBody numcols) tbodies'+ tfoot = B.normalizeTableFoot numcols tfoot'+ numcols = length colSpecs+ colSpecs' = listArray (ColIndex 1, ColIndex numcols) colSpecs rowHeads = case listToMaybe tbodies of Nothing -> RowHeadColumns 0 Just (TableBody _attr rowHeadCols _headerRows _rows) -> rowHeadCols@@ -103,7 +109,7 @@ fromBuilderCell :: BuilderCell -> GridCell fromBuilderCell = \case FilledCell c -> c- FreeCell -> error "Found an unassigned cell. Please report this as a bug!"+ FreeCell -> UnassignedCell rowsToPart :: Attr -> [B.Row] -> Part rowsToPart attr = \case
@@ -1,3 +1,5 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE OverloadedStrings #-}@@ -6,7 +8,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Writers.HTML- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -29,25 +31,30 @@ tagWithAttributes ) where import Control.Monad.State.Strict-import Data.Char (ord)-import Data.List (intercalate, intersperse, partition, delete, (\\), foldl')+ ( StateT, MonadState(get), gets, modify, evalStateT )+import Control.Monad ( liftM, when, foldM, unless )+import Control.Monad.Trans ( MonadTrans(lift) )+import Data.Char (ord, isSpace, isAscii)+import Data.List (intercalate, intersperse, partition, delete, (\\))+import qualified Data.List as L import Data.List.NonEmpty (NonEmpty((:|)))+import Data.Containers.ListUtils (nubOrd) import Data.Maybe (fromMaybe, isJust, isNothing) import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Lazy as TL-import Network.URI (URI (..), parseURIReference)+import Network.URI (URI (..), parseURIReference, escapeURIString)+import Text.Pandoc.URI (urlEncode) import Numeric (showHex) import Text.DocLayout (render, literal, Doc) import Text.Blaze.Internal (MarkupM (Empty), customLeaf, customParent)-import Text.DocTemplates (FromContext (lookupContext), Context (..))+import Text.DocTemplates (FromContext (lookupContext), Context (..), Val(..))+import qualified Text.DocTemplates.Internal as DT import Text.Blaze.Html hiding (contents)-import Text.Pandoc.Translations (Term(Abstract))-import Text.Pandoc.CSS (cssAttributes) import Text.Pandoc.Definition-import Text.Pandoc.Highlighting (formatHtmlBlock, formatHtmlInline, highlight,- styleToCss)+import Text.Pandoc.Highlighting (formatHtmlBlock, formatHtml4Block,+ formatHtmlInline, highlight, styleToCss, defaultStyle) import Text.Pandoc.ImageSize import Text.Pandoc.Options import Text.Pandoc.Shared@@ -57,7 +64,6 @@ import Text.Pandoc.Writers.Math import Text.Pandoc.Writers.Shared import qualified Text.Pandoc.Writers.AnnotatedTable as Ann-import Text.Pandoc.Network.HTTP (urlEncode) import Text.Pandoc.XML (escapeStringForXML, fromEntities, toEntities, html5Attributes, html4Attributes, rdfaAttributes) import qualified Text.Blaze.XHtml5 as H5@@ -67,8 +73,8 @@ import Text.Blaze.Html.Renderer.Text (renderHtml) import qualified Text.Blaze.XHtml1.Transitional as H import qualified Text.Blaze.XHtml1.Transitional.Attributes as A-import Text.Pandoc.Class.PandocMonad (PandocMonad, report,- translateTerm)+import Text.Pandoc.Class.PandocMonad (PandocMonad, report)+import Text.Pandoc.Translations (Term(Abstract), translateTerm) import Text.Pandoc.Class.PandocPure (runPure) import Text.Pandoc.Error import Text.Pandoc.Logging@@ -83,6 +89,7 @@ data WriterState = WriterState { stNotes :: [Html] -- ^ List of notes , stEmittedNotes :: Int -- ^ How many notes we've already pushed out to the HTML+ , stEmittedNoteBlocks :: Int -- ^ How many @\<div class=footnote>@ blocks we've already pushed out , stMath :: Bool -- ^ Math is used in document , stQuotes :: Bool -- ^ <q> tag is used , stHighlighting :: Bool -- ^ Syntax highlighting is used@@ -98,7 +105,11 @@ } defaultWriterState :: WriterState-defaultWriterState = WriterState {stNotes= [], stEmittedNotes = 0, stMath = False, stQuotes = False,+defaultWriterState = WriterState {stNotes= [],+ stEmittedNotes = 0,+ stEmittedNoteBlocks = 0,+ stMath = False,+ stQuotes = False, stHighlighting = False, stHtml5 = False, stEPUBVersion = Nothing,@@ -114,21 +125,20 @@ strToHtml :: Text -> Html strToHtml t- | T.any isSpecial t = strToHtml' $ T.unpack t+ | T.any isSpecial t =+ let !x = L.foldl' go mempty $ T.groupBy samegroup t+ in x | otherwise = toHtml t where- strToHtml' ('\'':xs) = preEscapedString "\'" `mappend` strToHtml' xs- strToHtml' ('"' :xs) = preEscapedString "\"" `mappend` strToHtml' xs- strToHtml' (x:xs) | needsVariationSelector x- = preEscapedString [x, '\xFE0E'] `mappend`- case xs of- ('\xFE0E':ys) -> strToHtml' ys- _ -> strToHtml' xs- strToHtml' xs@(_:_) = case break isSpecial xs of- (_ ,[]) -> toHtml xs- (ys,zs) -> toHtml ys `mappend` strToHtml' zs- strToHtml' [] = ""- isSpecial c = c == '\'' || c == '"' || needsVariationSelector c+ samegroup c d = d == '\xFE0E' || not (isSpecial c || isSpecial d)+ isSpecial '\'' = True+ isSpecial '"' = True+ isSpecial c = needsVariationSelector c+ go h "\'" = h <> preEscapedString "\'"+ go h "\"" = h <> preEscapedString "\""+ go h txt | T.length txt == 1 && T.all needsVariationSelector txt+ = h <> preEscapedString (T.unpack txt <> "\xFE0E")+ go h txt = h <> toHtml txt -- See #5469: this prevents iOS from substituting emojis. needsVariationSelector :: Char -> Bool@@ -232,21 +242,23 @@ Just cols -> render (Just cols) $ layoutMarkup body Just tpl -> do -- warn if empty lang- when (isNothing (getField "lang" context :: Maybe Text)) $+ when (isNothing (getField "lang" context :: Maybe Text) &&+ hasVariable "lang" tpl) $ report NoLangSpecified- -- check for empty pagetitle (context' :: Context Text) <-+ -- check for empty pagetitle case getField "pagetitle" context of Just (s :: Text) | not (T.null s) -> return context- _ -> do- let fallback = T.pack $- case lookupContext "sourcefile"- (writerVariables opts) of- Nothing -> "Untitled"- Just [] -> "Untitled"- Just (x:_) -> takeBaseName $ T.unpack x- report $ NoTitleElement fallback- return $ resetField "pagetitle" (literal fallback) context+ _ | hasVariable "pagetitle" tpl -> do+ let fallback = T.pack $+ case lookupContext "sourcefile"+ (writerVariables opts) of+ Nothing -> "Untitled"+ Just [] -> "Untitled"+ Just (x:_) -> takeBaseName $ T.unpack x+ report $ NoTitleElement fallback+ return $ resetField "pagetitle" (literal fallback) context+ | otherwise -> return context return $ render colwidth $ renderTemplate tpl (defField "body" (layoutMarkup body) context') @@ -256,7 +268,7 @@ Just _ -> preEscapedText <$> writeHtmlString' st opts d Nothing | writerPreferAscii opts- -> preEscapedText <$> writeHtmlString' st opts d+ -> preEscapedText <$> writeHtmlString' st opts d | otherwise -> do (body, _) <- evalStateT (pandocToHtml opts d) st return body@@ -267,6 +279,7 @@ -> Pandoc -> StateT WriterState m (Html, Context Text) pandocToHtml opts (Pandoc meta blocks) = do+ lift $ setupTranslations meta let slideLevel = fromMaybe (getSlideLevel blocks) $ writerSlideLevel opts modify $ \st -> st{ stSlideLevel = slideLevel } metadata <- metaToContext opts@@ -280,8 +293,8 @@ lookupMetaString "description" meta slideVariant <- gets stSlideVariant abstractTitle <- translateTerm Abstract- let sects = adjustNumbers opts $- makeSections (writerNumberSections opts) Nothing $+ let sects = makeSectionsWithOffsets+ (writerNumberOffset opts) (writerNumberSections opts) Nothing $ if slideVariant == NoSlides then blocks else prepSlides slideLevel blocks@@ -295,16 +308,18 @@ if null (stNotes st) then return mempty else do- notes <- footnoteSection EndOfDocument (stEmittedNotes st + 1) (reverse (stNotes st))+ notes <- footnoteSection opts EndOfDocument (stEmittedNotes st + 1) (reverse (stNotes st)) modify (\st' -> st'{ stNotes = mempty, stEmittedNotes = stEmittedNotes st' + length (stNotes st') }) return notes st <- get+ let html5 = stHtml5 st let thebody = blocks' >> notes let math = layoutMarkup $ case writerHTMLMathMethod opts of MathJax url | slideVariant /= RevealJsSlides -> -- mathjax is handled via a special plugin in revealjs- H.script ! A.src (toValue url)+ H.script ! A.defer mempty+ ! A.src (toValue $ toURI html5 url) ! A.type_ "text/javascript" $ case slideVariant of SlideousSlides ->@@ -314,7 +329,7 @@ KaTeX url -> do H.script ! A.defer mempty !- A.src (toValue $ url <> "katex.min.js") $ mempty+ A.src (toValue $ toURI html5 $ url <> "katex.min.js") $ mempty nl let katexFlushLeft = case lookupContext "classoption" metadata of@@ -337,30 +352,25 @@ ] nl H.link ! A.rel "stylesheet" !- A.href (toValue $ url <> "katex.min.css")+ A.href (toValue $ toURI html5 url <> "katex.min.css") - _ -> case lookupContext "mathml-script"- (writerVariables opts) of- Just s | not (stHtml5 st) ->- H.script ! A.type_ "text/javascript"- $ preEscapedString- ("/*<![CDATA[*/\n" <> T.unpack s <>- "/*]]>*/\n")- | otherwise -> mempty- Nothing -> mempty+ _ -> mempty 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 . (case stCslEntrySpacing st of Nothing -> id- Just 0 -> id Just n -> defField "csl-entry-spacing" (literal $ tshow n <> "em"))@@ -423,7 +433,21 @@ defField "transitionSpeed" ("default" :: Doc Text) . defField "backgroundTransition" ("fade" :: Doc Text) . defField "viewDistance" ("3" :: Doc Text) .- defField "mobileViewDistance" ("2" :: Doc Text)+ defField "mobileViewDistance" ("2" :: Doc Text) .+ (case (lookupContext "scrollProgress" metadata+ :: Maybe (Val Text)) of+ Just (BoolVal False) -> id+ Just (BoolVal True) -> defField "scrollProgress" True+ _ -> defField "scrollProgressAuto" True) .+ defField "scrollActivationWidth" ("0" :: Doc Text) .+ defField "scrollSnap" ("mandatory" :: Doc Text) .+ defField "scrollLayout" ("full" :: Doc Text) .+ (case writerHighlightMethod opts of+ IdiomaticHighlighting+ | slideVariant == RevealJsSlides ->+ defField "highlight-js" True .+ defField "highlightjs-theme" ("monokai" :: Doc Text)+ _ -> id) else id) . defField "document-css" (isNothing mCss && slideVariant == NoSlides) . defField "quotes" (stQuotes st) .@@ -443,8 +467,10 @@ defField "slidy-url" ("https://www.w3.org/Talks/Tools/Slidy2" :: Doc Text) . defField "slideous-url" ("slideous" :: Doc Text) .- defField "revealjs-url" ("https://unpkg.com/reveal.js@^4/" :: Doc Text) $+ defField "revealjs-url" ("https://unpkg.com/reveal.js@^5" :: Doc Text) $ defField "s5-url" ("s5/default" :: Doc Text) .+ defField "table-caption-below"+ (writerTableCaptionPosition opts == CaptionBelow) . defField "html5" (stHtml5 st) $ metadata return (thebody, context)@@ -482,30 +508,24 @@ => WriterOptions -> [Html] -> StateT WriterState m Html defList opts items = toList H.dl opts (items ++ [nl]) -isTaskListItem :: [Block] -> Bool-isTaskListItem (Plain (Str "☐":Space:_):_) = True-isTaskListItem (Plain (Str "☒":Space:_):_) = True-isTaskListItem (Para (Str "☐":Space:_):_) = True-isTaskListItem (Para (Str "☒":Space:_):_) = True-isTaskListItem _ = False- listItemToHtml :: PandocMonad m => WriterOptions -> [Block] -> StateT WriterState m Html-listItemToHtml opts bls- | Plain (Str "☐":Space:is) : bs <- bls = taskListItem False id is bs- | Plain (Str "☒":Space:is) : bs <- bls = taskListItem True id is bs- | Para (Str "☐":Space:is) : bs <- bls = taskListItem False H.p is bs- | Para (Str "☒":Space:is) : bs <- bls = taskListItem True H.p is bs- | otherwise = blockListToHtml opts bls+listItemToHtml opts bls =+ case toTaskListItem bls of+ Just (checked, (Para is:bs)) -> taskListItem checked H.p is bs+ Just (checked, (Plain is:bs)) -> taskListItem checked id is bs+ _ -> blockListToHtml opts bls where taskListItem checked constr is bs = do let checkbox = if checked then checkbox' ! A.checked "" else checkbox'- checkbox' = H.input ! A.type_ "checkbox" ! A.disabled ""+ checkbox' = H.input ! A.type_ "checkbox" isContents <- inlineListToHtml opts is bsContents <- blockListToHtml opts bs- return $ constr (checkbox >> isContents) >> bsContents+ return $ constr (H.label (checkbox >> isContents)) >>+ (if null bs then mempty else nl) >>+ bsContents -- | Construct table of contents from list of elements. tableOfContents :: PandocMonad m => WriterOptions -> [Block]@@ -526,13 +546,23 @@ -- | Convert list of Note blocks to a footnote <div>. -- Assumes notes are sorted. footnoteSection ::- PandocMonad m => ReferenceLocation -> Int -> [Html] -> StateT WriterState m Html-footnoteSection refLocation startCounter notes = do+ PandocMonad m => WriterOptions -> ReferenceLocation -> Int -> [Html] -> StateT WriterState m Html+footnoteSection opts refLocation startCounter notes = do html5 <- gets stHtml5 slideVariant <- gets stSlideVariant let hrtag = if refLocation /= EndOfBlock then (if html5 then H5.hr else H.hr) <> nl else mempty+ idName <- do+ blockCount <- gets stEmittedNoteBlocks+ modify $ \st -> st{ stEmittedNoteBlocks = blockCount + 1 }+ return $+ -- Keep the first note section's id undecorated to maintain a target for+ -- old links which don't expect numbered sections, or for when the notes+ -- are rendered all together at the end of the document.+ if blockCount <= 0+ then "footnotes"+ else "footnotes-" <> show (blockCount + 1) let additionalClassName = case refLocation of EndOfBlock -> "footnotes-end-of-block" EndOfDocument -> "footnotes-end-of-document"@@ -542,13 +572,20 @@ let container x | html5 , epubVersion == Just EPUB3- = H5.section ! A.id "footnotes"+ = H5.section ! A.id (fromString idName) ! A.class_ className ! customAttribute "epub:type" "footnotes" $ x- | html5 = H5.section ! A.id "footnotes"- ! A.class_ className- ! customAttribute "role" "doc-endnotes"+ | html5+ , refLocation == EndOfDocument+ -- Note: we need a section for a new slide in slide formats.+ = H5.section ! prefixedId opts (fromString idName)+ ! A5.class_ className+ ! A5.role "doc-endnotes" $ x+ | html5 = H5.aside ! prefixedId opts (fromString idName)+ ! A5.class_ className+ ! A5.role "doc-footnote"+ $ x | slideVariant /= NoSlides = H.div ! A.class_ "footnotes slide" $ x | otherwise = H.div ! A.class_ className $ x return $@@ -561,11 +598,12 @@ hrtag -- Keep the previous output exactly the same if we don't -- have multiple notes sections- if startCounter == 1- then H.ol $ mconcat notes >> nl- else H.ol ! A.start (fromString (show startCounter)) $- mconcat notes >> nl- nl+ case epubVersion of+ Just _ -> mconcat notes+ Nothing | startCounter == 1 ->+ (H.ol (nl >> mconcat notes)) >> nl+ Nothing -> (H.ol ! A.start (fromString (show startCounter)) $+ nl >> mconcat notes) >> nl -- | Parse a mailto link; return Just (name, domain) or Nothing. parseMailto :: Text -> Maybe (Text, Text)@@ -581,12 +619,14 @@ obfuscateLink :: PandocMonad m => WriterOptions -> Attr -> Html -> Text -> StateT WriterState m Html-obfuscateLink opts attr txt s | writerEmailObfuscation opts == NoObfuscation =- addAttrs opts attr $ H.a ! A.href (toValue s) $ txt-obfuscateLink opts attr (TL.toStrict . renderHtml -> txt) s =+obfuscateLink opts attr txt s | writerEmailObfuscation opts == NoObfuscation = do+ html5 <- gets stHtml5+ addAttrs opts attr $ H.a ! A.href (toValue $ toURI html5 s) $ txt+obfuscateLink opts attr (TL.toStrict . renderHtml -> txt) s = do+ html5 <- gets stHtml5 let meth = writerEmailObfuscation opts- s' = T.toLower (T.take 7 s) <> T.drop 7 s- in case parseMailto s' of+ let s' = T.toLower (T.take 7 s) <> T.drop 7 s+ case parseMailto s' of (Just (name', domain)) -> let domain' = T.replace "." " dot " domain at' = obfuscateChar '@'@@ -614,7 +654,8 @@ linkText <> "+'<\\/'+'a'+'>');\n// -->\n")) >> H.noscript (preEscapedText $ obfuscateString altText) _ -> throwError $ PandocSomeError $ "Unknown obfuscation method: " <> tshow meth- _ -> addAttrs opts attr $ H.a ! A.href (toValue s) $ toHtml txt -- malformed email+ _ -> addAttrs opts attr $ H.a ! A.href (toValue $ toURI html5 s)+ $ toHtml txt -- malformed email -- | Obfuscate character as entity. obfuscateChar :: Char -> Text@@ -644,7 +685,7 @@ addAttrs :: PandocMonad m => WriterOptions -> Attr -> Html -> StateT WriterState m Html-addAttrs opts attr h = foldl' (!) h <$> attrsToHtml opts attr+addAttrs opts attr h = L.foldl' (!) h <$> attrsToHtml opts attr toAttrs :: PandocMonad m => [(Text, Text)] -> StateT WriterState m [Attribute]@@ -662,7 +703,8 @@ addAttr html5 mbEpubVersion x y | T.null x = id -- see #7546 | html5- = if x `Set.member` (html5Attributes <> rdfaAttributes)+ = if (x `Set.member` (html5Attributes <> rdfaAttributes)+ && x /= "label") -- #10048 || T.any (== ':') x -- e.g. epub: namespace || "data-" `T.isPrefixOf` x || "aria-" `T.isPrefixOf` x@@ -679,9 +721,10 @@ => WriterOptions -> Attr -> StateT WriterState m [Attribute] attrsToHtml opts (id',classes',keyvals) = do attrs <- toAttrs keyvals+ let classes'' = nubOrd $ filter (not . T.null) classes' return $ [prefixedId opts id' | not (T.null id')] ++- [A.class_ (toValue $ T.unwords classes') | not (null classes')] ++ attrs+ [A.class_ (toValue $ T.unwords classes'') | not (null classes'')] ++ attrs imgAttrsToHtml :: PandocMonad m => WriterOptions -> Attr -> StateT WriterState m [Attribute]@@ -709,79 +752,24 @@ (Just x) -> [("style", tshow dir <> ":" <> tshow x)] Nothing -> [] -figure :: PandocMonad m- => WriterOptions -> Attr -> [Inline] -> (Text, Text)- -> StateT WriterState m Html-figure opts attr@(_, _, attrList) txt (s,tit) = do- html5 <- gets stHtml5- -- Screen-readers will normally read the @alt@ text and the figure; we- -- want to avoid them reading the same text twice. With HTML5 we can- -- use aria-hidden for the caption; with HTML4, we use an empty- -- alt-text instead.- -- When the alt text differs from the caption both should be read.- let alt = if html5 then txt else [Str ""]- let tocapt = if html5- then (H5.figcaption !) $- if isJust (lookup "alt" attrList)- then mempty- else H5.customAttribute (textTag "aria-hidden")- (toValue @Text "true")- else H.p ! A.class_ "caption"- img <- inlineToHtml opts (Image attr alt (s,tit))- capt <- if null txt- then return mempty- else (nl <>) . tocapt <$> inlineListToHtml opts txt- let inner = mconcat [nl, img, capt, nl]- return $ if html5- then H5.figure inner- else H.div ! A.class_ "figure" $ inner---adjustNumbers :: WriterOptions -> [Block] -> [Block]-adjustNumbers opts doc =- if all (==0) (writerNumberOffset opts)- then doc- else walk go doc- where- go (Div (ident,"section":classes,kvs) lst) =- Div (ident,"section":classes,map fixnum kvs) lst- go (Header level (ident,classes,kvs) lst) =- Header level (ident,classes,map fixnum kvs) lst- go x = x- fixnum ("number",num) = ("number",- showSecNum $ zipWith (+)- (writerNumberOffset opts ++ repeat 0)- (map (fromMaybe 0 . safeRead) $- T.split (=='.') num))- fixnum x = x- showSecNum = T.intercalate "." . map tshow- blockToHtmlInner :: PandocMonad m => WriterOptions -> Block -> StateT WriterState m Html-blockToHtmlInner _ Null = return mempty blockToHtmlInner opts (Plain lst) = inlineListToHtml opts lst-blockToHtmlInner opts (Para [Image attr@(_,classes,_) txt (src,tit)])- | "r-stretch" `elem` classes = do- slideVariant <- gets stSlideVariant- case slideVariant of- RevealJsSlides ->- -- a "stretched" image in reveal.js must be a direct child- -- of the slide container- inlineToHtml opts (Image attr txt (src, tit))- _ -> figure opts attr txt (src, tit)--- title beginning with fig: indicates that the image is a figure-blockToHtmlInner opts (SimpleFigure attr caption (src, title)) =- figure opts attr caption (src, title) blockToHtmlInner opts (Para lst) = do- contents <- inlineListToHtml opts lst- case contents of- Empty _ | not (isEnabled Ext_empty_paragraphs opts) -> return mempty- _ -> return $ H.p contents-blockToHtmlInner opts (LineBlock lns) =- if writerWrapText opts == WrapNone- then blockToHtml opts $ linesToPara lns- else do- htmlLines <- inlineListToHtml opts $ intercalate [LineBreak] lns- return $ H.div ! A.class_ "line-block" $ htmlLines+ slideVariant <- gets stSlideVariant+ case (slideVariant, lst) of+ (RevealJsSlides, [Image attr@(_,classes,_) txt (src,tit)])+ | "r-stretch" `elem` classes -> do+ -- a "stretched" image in reveal.js must be a direct child+ -- of the slide container+ inlineToHtml opts (Image attr txt (src, tit))+ _ -> do+ contents <- inlineListToHtml opts lst+ case contents of+ Empty _ | not (isEnabled Ext_empty_paragraphs opts) -> return mempty+ _ -> return $ H.p contents+blockToHtmlInner opts (LineBlock lns) = do+ htmlLines <- inlineListToHtml opts $ intercalate [LineBreak] lns+ return $ H.div ! A.class_ "line-block" $ htmlLines blockToHtmlInner opts (Div (ident, "section":dclasses, dkvs) (Header level hattr@(hident,hclasses,hkvs) ils : xs)) = do@@ -808,15 +796,17 @@ let inDiv' zs = RawBlock (Format "html") ("<div class=\"" <> fragmentClass <> "\">") : (zs ++ [RawBlock (Format "html") "</div>"])- let breakOnPauses zs = case splitBy isPause zs of+ let breakOnPauses zs+ | slide = case splitBy isPause zs of [] -> [] y:ys -> y ++ concatMap inDiv' ys+ | otherwise = zs let (titleBlocks, innerSecs) = if titleSlide -- title slides have no content of their own then let (as, bs) = break isSec xs- in (breakOnPauses as, bs)- else ([], breakOnPauses xs)+ in (walk breakOnPauses as, bs)+ else ([], walk breakOnPauses xs) let secttag = if html5 then H5.section else H.div@@ -826,9 +816,19 @@ modify $ \st -> st{ stInSection = True } res <- blockListToHtml opts innerSecs modify $ \st -> st{ stInSection = inSection }- return res- let classes' = ordNub $- ["title-slide" | titleSlide] ++ ["slide" | slide] +++ notes <- gets stNotes+ let emitNotes = writerReferenceLocation opts == EndOfSection &&+ not (null notes)+ if emitNotes+ then do+ st <- get+ renderedNotes <- footnoteSection opts (writerReferenceLocation opts)+ (stEmittedNotes st + 1) (reverse notes)+ modify (\st' -> st'{ stNotes = mempty,+ stEmittedNotes = stEmittedNotes st' + length notes })+ return (res <> renderedNotes)+ else return res+ let classes' = ["title-slide" | titleSlide] ++ ["slide" | slide] ++ ["section" | (slide || writerSectionDivs opts) && not html5 ] ++ ["level" <> tshow level | slide || writerSectionDivs opts ]@@ -865,6 +865,11 @@ if null innerSecs then mempty else nl <> innerContents+blockToHtmlInner opts (Div (ident, classes, kvs) [b])+ | Just "1" <- lookup "wrapper" kvs+ -- unwrap "wrapper" div, putting attr on child+ = blockToHtmlInner opts b >>=+ addAttrs opts (ident, classes, [(k,v) | (k,v) <- kvs, k /= "wrapper"]) blockToHtmlInner opts (Div attr@(ident, classes, kvs') bs) = do html5 <- gets stHtml5 slideVariant <- gets stSlideVariant@@ -878,16 +883,21 @@ , k /= "width" || "column" `notElem` classes] ++ [("style", "width:" <> w <> ";") | "column" `elem` classes , ("width", w) <- kvs'] ++- [("role", "doc-bibliography") | isCslBibBody && html5] ++- [("role", "doc-biblioentry") | isCslBibEntry && html5]+ [("role", "list") | isCslBibBody && html5] +++ [("role", "listitem") | isCslBibEntry && html5] let speakerNotes = "notes" `elem` classes -- we don't want incremental output inside speaker notes, see #1394- let opts' = if | speakerNotes -> opts{ writerIncremental = False }- | "incremental" `elem` classes -> opts{ writerIncremental = True }- | "nonincremental" `elem` classes -> opts{ writerIncremental = False }- | otherwise -> opts+ let (opts', isIncrDiv) =+ if | speakerNotes ->+ (opts{ writerIncremental = False }, False)+ | "incremental" `elem` classes ->+ (opts{ writerIncremental = True }, True)+ | "nonincremental" `elem` classes ->+ (opts{ writerIncremental = False }, True)+ | otherwise ->+ (opts, False) -- we remove "incremental" and "nonincremental" if we're in a- -- slide presentaiton format.+ -- slide presentation format. classes' = case slideVariant of NoSlides -> classes _ -> filter (\k -> k /= "incremental" && k /= "nonincremental") classes@@ -906,18 +916,22 @@ let (divtag, classes'') = if html5 && "section" `elem` classes' then (H5.section, filter (/= "section") classes') else (H.div, classes')- if speakerNotes- then case slideVariant of- RevealJsSlides -> addAttrs opts' attr $- H5.aside contents'- DZSlides -> do- t <- addAttrs opts' attr $- H5.div contents'- return $ t ! H5.customAttribute "role" "note"- NoSlides -> addAttrs opts' attr $- H.div contents'- _ -> return mempty- else addAttrs opts (ident, classes'', kvs) $+ if | isIncrDiv && (ident, classes'', kvs) == nullAttr ->+ -- Unwrap divs that only have (non)increment information+ pure contents+ | speakerNotes ->+ case slideVariant of+ RevealJsSlides -> addAttrs opts' attr $+ H5.aside contents'+ DZSlides -> do+ t <- addAttrs opts' attr $+ H5.div contents'+ return $ t ! A5.role "note"+ NoSlides -> addAttrs opts' attr $+ H.div contents'+ _ -> return mempty+ | otherwise ->+ addAttrs opts (ident, classes'', kvs) $ divtag contents' blockToHtmlInner opts (RawBlock f str) = do ishtml <- isRawHtml f@@ -926,7 +940,9 @@ else if (f == Format "latex" || f == Format "tex") && allowsMathEnvironments (writerHTMLMathMethod opts) && isMathEnvironment str- then blockToHtml opts $ Plain [Math DisplayMath str]+ then do+ modify (\st -> st {stMath = True})+ blockToHtml opts $ Plain [Math DisplayMath str] else do report $ BlockNotRendered (RawBlock f str) return mempty@@ -934,6 +950,8 @@ html5 <- gets stHtml5 return $ if html5 then H5.hr else H.hr blockToHtmlInner opts (CodeBlock (id',classes,keyvals) rawCode) = do+ html5 <- gets stHtml5+ slideVariant <- gets stSlideVariant id'' <- if T.null id' then do modify $ \st -> st{ stCodeBlockNum = stCodeBlockNum st + 1 }@@ -951,20 +969,37 @@ adjCode = if tolhs then T.unlines . map ("> " <>) . T.lines $ rawCode else rawCode- hlCode = if isJust (writerHighlightStyle opts)- then highlight (writerSyntaxMap opts) formatHtmlBlock- (id'',classes',keyvals) adjCode- else Left ""- case hlCode of- Left msg -> do- unless (T.null msg) $- report $ CouldNotHighlight msg- addAttrs opts (id',classes,keyvals)- $ H.pre $ H.code $ toHtml adjCode- Right h -> modify (\st -> st{ stHighlighting = True }) >>- -- we set writerIdentifierPrefix to "" since id'' already- -- includes it:- addAttrs opts{writerIdentifierPrefix = ""} (id'',[],keyvals) h+ isIdiomaticRevealJs = slideVariant == RevealJsSlides &&+ writerHighlightMethod opts == IdiomaticHighlighting+ if isIdiomaticRevealJs+ then do+ -- For idiomatic reveal.js highlighting, put attributes on <code>+ -- with language- prefix, and let highlight.js do the highlighting.+ modify (\st -> st{ stHighlighting = True })+ let (langClasses, otherClasses) = case classes' of+ (lang:rest) -> (["language-" <> lang], rest)+ [] -> ([], [])+ codeAttrs = (id', langClasses ++ otherClasses, keyvals)+ codeTag <- addAttrs opts codeAttrs $ H.code $ toHtml adjCode+ return $ H.pre codeTag+ else do+ let highlighted = highlight (writerSyntaxMap opts)+ (if html5 then formatHtmlBlock else formatHtml4Block)+ (id'',classes',keyvals) adjCode+ hlCode = case writerHighlightMethod opts of+ Skylighting _ -> highlighted+ DefaultHighlighting -> highlighted+ _ -> Left ""+ case hlCode of+ Left msg -> do+ unless (T.null msg) $+ report $ CouldNotHighlight msg+ addAttrs opts (id',classes,keyvals)+ $ H.pre $ H.code $ toHtml adjCode+ Right h -> modify (\st -> st{ stHighlighting = True }) >>+ -- we set writerIdentifierPrefix to "" since id'' already+ -- includes it:+ addAttrs opts{writerIdentifierPrefix = ""} (id'',[],keyvals) h blockToHtmlInner opts (BlockQuote blocks) = do -- in S5, treat list in blockquote specially -- if default is incremental, make it nonincremental;@@ -1001,7 +1036,8 @@ else [ (k, v) | (k, v) <- kvs , k `elem` (["lang", "dir", "title", "style" , "align"] ++ intrinsicEventsHTML4)]- addAttrs opts (ident,classes,kvs')+ let classes' = if level > 6 then "heading":classes else classes+ addAttrs opts (ident,classes',kvs') $ case level of 1 -> H.h1 contents' 2 -> H.h2 contents'@@ -1009,11 +1045,10 @@ 4 -> H.h4 contents' 5 -> H.h5 contents' 6 -> H.h6 contents'- _ -> H.p ! A.class_ "heading" $ contents'+ _ -> H.p contents' blockToHtmlInner opts (BulletList lst) = do contents <- mapM (listItemToHtml opts) lst- let isTaskList = not (null lst) && all isTaskListItem lst- (if isTaskList then (! A.class_ "task-list") else id) <$>+ (if isJust (mapM toTaskListItem lst) then (! A.class_ "task-list") else id) <$> unordList opts contents blockToHtmlInner opts (OrderedList (startnum, numstyle, _) lst) = do contents <- mapM (listItemToHtml opts) lst@@ -1037,7 +1072,7 @@ numstyle'] else []) l <- ordList opts contents- return $ foldl' (!) l attribs+ return $ L.foldl' (!) l attribs blockToHtmlInner opts (DefinitionList lst) = do contents <- mapM (\(term, defs) -> do term' <- liftM H.dt $ inlineListToHtml opts term@@ -1048,14 +1083,42 @@ defList opts contents blockToHtmlInner opts (Table attr caption colspecs thead tbody tfoot) = tableToHtml opts (Ann.toTable attr caption colspecs thead tbody tfoot)+blockToHtmlInner opts (Figure attrs (Caption _ captBody) body) = do+ html5 <- gets stHtml5 + figAttrs <- attrsToHtml opts attrs+ contents <- blockListToHtml opts body+ captCont <- blockListToHtml opts captBody+ let figCaption = mconcat $+ if html5+ then let fcattr = if captionIsAlt captBody body+ then H5.customAttribute+ (textTag "aria-hidden")+ (toValue @Text "true")+ else mempty+ in [ H5.figcaption ! fcattr $ captCont ]+ else [ (H.div ! A.class_ "figcaption") captCont ]+ let innards = mconcat $+ if null captBody+ then [nl, contents, nl]+ else case writerFigureCaptionPosition opts of+ CaptionAbove -> [nl, figCaption, nl, contents, nl]+ CaptionBelow -> [nl, contents, nl, figCaption, nl]+ return $+ if html5+ then foldl (!) H5.figure figAttrs innards+ else foldl (!) H.div (A.class_ "float" : figAttrs) innards+ where+ captionIsAlt capt [Plain [Image (_, _, kv) desc _]] =+ let alt = fromMaybe (stringify desc) $ lookup "alt" kv+ in stringify capt == alt+ captionIsAlt _ _ = False+ -- | Convert Pandoc block element to HTML. All the legwork is done by -- 'blockToHtmlInner', this just takes care of emitting the notes after -- the block if necessary. blockToHtml :: PandocMonad m => WriterOptions -> Block -> StateT WriterState m Html blockToHtml opts block = do- -- Ignore inserted section divs -- they are not blocks as they came from- -- the document itself (at least not when coming from markdown) let isSection = case block of Div (_, classes, _) _ | "section" `elem` classes -> True _ -> False@@ -1065,13 +1128,13 @@ doc <- blockToHtmlInner opts block st <- get let emitNotes =- (writerReferenceLocation opts == EndOfBlock && stBlockLevel st == 1) ||- (writerReferenceLocation opts == EndOfSection && isSection)+ writerReferenceLocation opts == EndOfBlock && stBlockLevel st == 1 res <- if emitNotes then do notes <- if null (stNotes st) then return mempty- else footnoteSection (writerReferenceLocation opts) (stEmittedNotes st + 1) (reverse (stNotes st))+ else footnoteSection opts (writerReferenceLocation opts)+ (stEmittedNotes st + 1) (reverse (stNotes st)) modify (\st' -> st'{ stNotes = mempty, stEmittedNotes = stEmittedNotes st' + length (stNotes st') }) return (doc <> notes) else return doc@@ -1239,19 +1302,13 @@ => WriterOptions -> TableRow -> StateT WriterState m Html-tableRowToHtml opts (TableRow tblpart attr rownum rowhead rowbody) = do- let rowclass = case rownum of- Ann.RowNumber x | x `rem` 2 == 1 -> "odd"- _ | tblpart /= Thead -> "even"- _ -> "header"- let attr' = case attr of- (id', classes, rest) -> (id', rowclass:classes, rest)+tableRowToHtml opts (TableRow tblpart attr _rownum rowhead rowbody) = do let celltype = case tblpart of Thead -> HeaderCell _ -> BodyCell headcells <- mapM (cellToHtml opts HeaderCell) rowhead bodycells <- mapM (cellToHtml opts celltype) rowbody- rowHtml <- addAttrs opts attr' $ H.tr $ do+ rowHtml <- addAttrs opts attr $ H.tr $ do nl mconcat headcells mconcat bodycells@@ -1259,13 +1316,6 @@ rowHtml nl -alignmentToString :: Alignment -> Maybe Text-alignmentToString = \case- AlignLeft -> Just "left"- AlignRight -> Just "right"- AlignCenter -> Just "center"- AlignDefault -> Nothing- colspanAttrib :: ColSpan -> Attribute colspanAttrib = \case ColSpan 1 -> mempty@@ -1301,12 +1351,12 @@ let align' = case align of AlignDefault -> colAlign _ -> align- let kvs' = case alignmentToString align' of+ let kvs' = case htmlAlignmentToString align' of Nothing -> kvs Just alignStr -> if html5- then addStyle ("text-align", alignStr) kvs+ then htmlAddStyle ("text-align", alignStr) kvs else case break ((== "align") . fst) kvs of (_, []) -> ("align", alignStr) : kvs (xs, _:rest) -> xs ++ ("align", alignStr) : rest@@ -1319,23 +1369,6 @@ tag' ! attribs $ contents nl --- | Adds a key-value pair to the @style@ attribute.-addStyle :: (Text, Text) -> [(Text, Text)] -> [(Text, Text)]-addStyle (key, value) kvs =- let cssToStyle = T.intercalate " " . map (\(k, v) -> k <> ": " <> v <> ";")- in case break ((== "style") . fst) kvs of- (_, []) ->- -- no style attribute yet, add new one- ("style", cssToStyle [(key, value)]) : kvs- (xs, (_,cssStyles):rest) ->- -- modify the style attribute- xs ++ ("style", cssToStyle modifiedCssStyles) : rest- where- modifiedCssStyles =- case break ((== key) . fst) $ cssAttributes cssStyles of- (cssAttribs, []) -> (key, value) : cssAttribs- (pre, _:post) -> pre ++ (key, value) : post- toListItems :: [Html] -> [Html] toListItems items = map toListItem items ++ [nl] @@ -1406,7 +1439,7 @@ = Just (t . H.u, cs) | otherwise = Just (t, c:cs)- spanLikeTags = foldl' go Nothing+ spanLikeTags = L.foldl' go Nothing in case spanLikeTags classes of Just (tag, cs) -> do h <- inlineListToHtml opts ils@@ -1446,11 +1479,12 @@ modify $ \st -> st{ stHighlighting = True } addAttrs opts (ids,[],kvs) $ fromMaybe id sampOrVar h- where hlCode = if isJust (writerHighlightStyle opts)- then highlight- (writerSyntaxMap opts)- formatHtmlInline attr str- else Left ""+ where hlCode = case writerHighlightMethod opts of+ Skylighting _ -> highlighted+ DefaultHighlighting -> highlighted+ _ -> Left ""+ highlighted = highlight (writerSyntaxMap opts)+ formatHtmlInline attr str (sampOrVar,cs') | "sample" `elem` cs = (Just H.samp,"sample" `delete` cs)@@ -1494,8 +1528,7 @@ InlineMath -> "\\textstyle " DisplayMath -> "\\displaystyle " return $ imtag ! A.style "vertical-align:middle"- ! A.src (toValue . (url <>) .- urlEncode $ s <> str')+ ! A.src (toValue . (url <>) . urlEncode $ s <> str') ! A.alt (toValue str') ! A.title (toValue str') ! A.class_ mathClass@@ -1536,16 +1569,23 @@ case istex of True | allowsMathEnvironments mm && isMathEnvironment str- -> inlineToHtml opts $ Math DisplayMath str+ -> do+ modify (\st -> st {stMath = True})+ inlineToHtml opts $ Math DisplayMath str | allowsRef mm && isRef str- -> inlineToHtml opts $ Math InlineMath str+ -> do+ modify (\st -> st {stMath = True})+ inlineToHtml opts $ Math InlineMath str _ -> do report $ InlineNotRendered inline return mempty (Link attr txt (s,_)) | "mailto:" `T.isPrefixOf` s -> do- linkText <- inlineListToHtml opts txt+ -- We need to remove links from link text, because an+ -- <a> element is not allowed inside another <a>+ -- element.+ linkText <- inlineListToHtml opts (removeLinks txt) obfuscateLink opts attr linkText s (Link (ident,classes,kvs) txt (s,tit)) -> do- linkText <- inlineListToHtml opts txt+ linkText <- inlineListToHtml opts (removeLinks txt) slideVariant <- gets stSlideVariant let s' = case T.uncons s of Just ('#',xs) -> let prefix = if slideVariant == RevealJsSlides@@ -1553,12 +1593,14 @@ else writerIdentifierPrefix opts in "#" <> prefix <> xs _ -> s- let link = H.a ! A.href (toValue s') $ linkText+ let link = H.a ! A.href (toValue $ toURI html5 s')+ $ linkText link' <- addAttrs opts (ident, classes, kvs) link return $ if T.null tit then link' else link' ! A.title (toValue tit) (Image attr@(_, _, attrList) txt (s, tit)) -> do+ epubVersion <- gets stEPUBVersion let alternate = stringify txt slideVariant <- gets stSlideVariant let isReveal = slideVariant == RevealJsSlides@@ -1567,26 +1609,34 @@ -- reveal.js uses data-src for lazy loading (if isReveal then customAttribute "data-src" $ toValue s- else A.src $ toValue s) :+ else A.src $ toValue $ toURI html5 s) : [A.title $ toValue tit | not (T.null tit)] ++ attrs imageTag = (if html5 then H5.img else H.img- , [A.alt $ toValue alternate | not (null txt) &&- isNothing (lookup "alt" attrList)] )+ , [A.alt $ toValue alternate |+ isNothing (lookup "alt" attrList) &&+ (isJust epubVersion || not (null txt))] ) mediaTag tg fallbackTxt = let linkTxt = if null txt then fallbackTxt else alternate- in (tg $ H.a ! A.href (toValue s) $ toHtml linkTxt+ in (tg $ H.a ! A.href (toValue $ toURI html5 s)+ $ toHtml linkTxt , [A5.controls ""] )- normSrc = maybe (T.unpack s) uriPath (parseURIReference $ T.unpack s)- (tag, specAttrs) = case mediaCategory normSrc of+ s' = fromMaybe s $ T.stripSuffix ".gz" s+ category =+ if "data:" `T.isPrefixOf` s+ then Just . T.takeWhile (/= '/') . T.drop 5 $ s+ else case parseURIReference (T.unpack s') of+ Just u -> mediaCategory $ uriPath u+ Nothing -> mediaCategory (T.unpack s)+ (tag, specAttrs) = case category of Just "image" -> imageTag Just "video" -> mediaTag H5.video "Video" Just "audio" -> mediaTag H5.audio "Audio" Just _ -> (H5.embed, []) _ -> imageTag- return $ foldl' (!) tag $ attributes ++ specAttrs+ return $ L.foldl' (!) tag $ attributes ++ specAttrs -- note: null title included, as in Markdown.pl (Note contents) -> do notes <- gets stNotes@@ -1599,7 +1649,7 @@ modify $ \st -> st {stNotes = htmlContents:notes} slideVariant <- gets stSlideVariant let revealSlash = T.pack ['/' | slideVariant == RevealJsSlides]- let link = H.a ! A.href (toValue $ "#" <>+ let link = H.a ! A.href (toValue $ toURI html5 $ "#" <> revealSlash <> writerIdentifierPrefix opts <> "fn" <> ref) ! A.class_ "footnote-ref"@@ -1609,56 +1659,76 @@ else H.sup) $ toHtml ref return $ case epubVersion of- Just EPUB3 -> link ! customAttribute "epub:type" "noteref"- _ | html5 -> link ! H5.customAttribute- "role" "doc-noteref"+ Just EPUB3 -> link ! customAttribute "epub:type" "noteref" ! customAttribute "role" "doc-noteref"+ _ | html5 -> link ! A5.role "doc-noteref" _ -> link- (Cite cits il)-> do contents <- inlineListToHtml opts (walk addRoleToLink il)+ (Cite cits il)-> do contents <- inlineListToHtml opts+ (if html5+ then walk addBibliorefRole il+ else il) let citationIds = T.unwords $ map citationId cits let result = H.span ! A.class_ "citation" $ contents return $ if html5 then result ! customAttribute "data-cites" (toValue citationIds) else result -addRoleToLink :: Inline -> Inline-addRoleToLink (Link (id',classes,kvs) ils (src,tit)) =+addBibliorefRole :: Inline -> Inline+addBibliorefRole (Link (id',classes,kvs) ils (src,tit))+ | "#ref-" `T.isPrefixOf` src = Link (id',classes,("role","doc-biblioref"):kvs) ils (src,tit)-addRoleToLink x = x+addBibliorefRole x = x blockListToNote :: PandocMonad m => WriterOptions -> Text -> [Block] -> StateT WriterState m Html blockListToNote opts ref blocks = do- html5 <- gets stHtml5- -- If last block is Para or Plain, include the backlink at the end of- -- that block. Otherwise, insert a new Plain block with the backlink.- let kvs = [("role","doc-backlink") | html5]- let backlink = [Link ("",["footnote-back"],kvs)- [Str "↩"] ("#" <> "fnref" <> ref,"")]- let blocks' = if null blocks- then []- else let lastBlock = last blocks- otherBlocks = init blocks- in case lastBlock of- Para [Image (_,cls,_) _ (_,tit)]- | "fig:" `T.isPrefixOf` tit- || "r-stretch" `elem` cls- -> otherBlocks ++ [lastBlock,- Plain backlink]- Para lst -> otherBlocks ++- [Para (lst ++ backlink)]- Plain lst -> otherBlocks ++- [Plain (lst ++ backlink)]- _ -> otherBlocks ++ [lastBlock,- Plain backlink]- contents <- blockListToHtml opts blocks'- let noteItem = H.li ! prefixedId opts ("fn" <> ref) $ contents epubVersion <- gets stEPUBVersion- let noteItem' = case epubVersion of- Just EPUB3 -> noteItem !- customAttribute "epub:type" "footnote"- _ -> noteItem- return $ nl >> noteItem'+ html5 <- gets stHtml5+ case epubVersion of+ Nothing -> do -- web page+ -- If last block is Para or Plain, include the backlink at the end of+ -- that block. Otherwise, insert a new Plain block with the backlink.+ let kvs = [("role","doc-backlink") | html5]+ let backlink = [Link ("",["footnote-back"],kvs)+ [Str "↩"] ("#" <> "fnref" <> ref,"")]+ let blocks' = if null blocks+ then []+ else let lastBlock = last blocks+ otherBlocks = init blocks+ in case lastBlock of+ Para [Image (_,cls,_) _ (_,tit)]+ | "fig:" `T.isPrefixOf` tit+ || "r-stretch" `elem` cls+ -> otherBlocks ++ [lastBlock,+ Plain backlink]+ Para lst -> otherBlocks +++ [Para (lst ++ backlink)]+ Plain lst -> otherBlocks +++ [Plain (lst ++ backlink)]+ _ -> otherBlocks ++ [lastBlock,+ Plain backlink]+ contents <- blockListToHtml opts blocks'+ let noteItem = H.li ! prefixedId opts ("fn" <> ref) $ contents+ return $ noteItem >> nl+ Just epubv -> do+ let kvs = [("role","doc-backlink") | html5]+ let backlink = Link ("",["footnote-back"],kvs)+ [Str ref] ("#" <> "fnref" <> ref,"")+ let addBacklinkInlines bs+ | epubv == EPUB3 = bs+ | otherwise =+ case bs of+ (Para ils : rest) ->+ Para (backlink : Str "." : Space : ils) : rest+ (Plain ils : rest) ->+ Plain (backlink : Str "." : Space : ils) : rest+ _ -> Para [backlink , Str "."] : blocks+ contents <- blockListToHtml opts (addBacklinkInlines blocks)+ let noteItem = (if epubv == EPUB3+ then H5.aside ! customAttribute "epub:type" "footnote" ! customAttribute "role" "doc-footnote"+ else H.div) ! prefixedId opts ("fn" <> ref)+ $ nl >> contents >> nl+ return $ noteItem >> nl inDiv :: PandocMonad m=> Text -> Html -> StateT WriterState m Html inDiv cls x = do@@ -1696,6 +1766,7 @@ , "multline" , "multline*" , "pmatrix"+ , "prooftree" -- bussproofs , "smallmatrix" , "split" , "subarray"@@ -1719,8 +1790,45 @@ [ "onclick", "ondblclick", "onmousedown", "onmouseup", "onmouseover" , "onmouseout", "onmouseout", "onkeypress", "onkeydown", "onkeyup"] ++-- | Check to see if Format is valid HTML isRawHtml :: PandocMonad m => Format -> StateT WriterState m Bool isRawHtml f = do html5 <- gets stHtml5+ epubVersion <- gets stEPUBVersion return $ f == Format "html" ||- ((html5 && f == Format "html5") || f == Format "html4")+ ((html5 && f == Format "html5") || f == Format "html4") ||+ isEpubFormat epubVersion f ||+ isSlideVariant f++-- | Check to see if Format matches with an EPUB variant+isEpubFormat :: Maybe EPUBVersion -> Format -> Bool+isEpubFormat Nothing _ = False+isEpubFormat (Just EPUB2) f =+ f == Format "epub" || f == Format "epub2"+isEpubFormat (Just EPUB3) f =+ f == Format "epub" || f == Format "epub3"++-- | Check to see if Format matches with an HTML slide variant+isSlideVariant :: Format -> Bool+isSlideVariant f = f `elem` [Format "s5", Format "slidy", Format "slideous",+ Format "dzslides", Format "revealjs"]++toURI :: Bool -> Text -> Text+toURI isHtml5 t = if isHtml5 then t else escapeURI t+ where+ escapeURI = T.pack . escapeURIString (not . needsEscaping) . T.unpack+ needsEscaping c = isSpace c || T.any (== c) "<>|\"{}[]^`" || not (isAscii c)++hasVariable :: Text -> DT.Template a -> Bool+hasVariable var = checkVar+ where+ matches v' = T.intercalate "." (DT.varParts v') == var+ checkVar (DT.Interpolate v) = matches v+ checkVar (DT.Conditional v t1 t2) = matches v || checkVar t1 || checkVar t2+ checkVar (DT.Iterate v t1 t2) = matches v || checkVar t1 || checkVar t2+ checkVar (DT.Nested t) = checkVar t+ checkVar (DT.Partial _ t) = checkVar t+ checkVar (DT.Concat t1 t2) = checkVar t1 || checkVar t2+ checkVar (DT.Literal _) = False+ checkVar DT.Empty = False
@@ -14,7 +14,9 @@ Haddock: <http://www.haskell.org/haddock/doc/html/> -} module Text.Pandoc.Writers.Haddock (writeHaddock) where+import Control.Monad (zipWithM) import Control.Monad.State.Strict+ ( StateT, MonadState(get), modify, evalStateT ) import Data.Char (isAlphaNum) import Data.Default import Data.Text (Text)@@ -25,6 +27,7 @@ import Text.Pandoc.Options import Text.DocLayout import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Shared @@ -90,16 +93,12 @@ => WriterOptions -- ^ Options -> Block -- ^ Block element -> StateT WriterState m (Doc Text)-blockToHaddock _ Null = return empty blockToHaddock opts (Div _ ils) = do contents <- blockListToHaddock opts ils return $ contents <> blankline blockToHaddock opts (Plain inlines) = do contents <- inlineListToHaddock opts inlines return $ contents <> cr--- title beginning with fig: indicates figure-blockToHaddock opts (SimpleFigure attr alt (src, tit))- = blockToHaddock opts (Para [Image attr alt (src,tit)]) blockToHaddock opts (Para inlines) = -- TODO: if it contains linebreaks, we need to use a @...@ block (<> blankline) `fmap` blockToHaddock opts (Plain inlines)@@ -126,14 +125,12 @@ blockToHaddock opts (BlockQuote blocks) = blockListToHaddock opts blocks blockToHaddock opts (Table _ blkCapt specs thead tbody tfoot) = do- let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot- caption' <- inlineListToHaddock opts caption+ let Caption _ caption = blkCapt+ caption' <- blockListToHaddock opts caption let caption'' = if null caption then empty else blankline <> caption' <> blankline- tbl <- gridTable opts blockListToHaddock- (all null headers) (map (const AlignDefault) aligns)- widths headers rows+ tbl <- gridTable opts blockListToHaddock specs thead tbody tfoot return $ (tbl $$ blankline $$ caption'') $$ blankline blockToHaddock opts (BulletList items) = do contents <- mapM (bulletListItemToHaddock opts) items@@ -149,6 +146,9 @@ blockToHaddock opts (DefinitionList items) = do contents <- mapM (definitionListItemToHaddock opts) items return $ vcat contents <> blankline+blockToHaddock opts (Figure _ (Caption _ longcapt) body) =+ -- Haddock has no concept of figures, floats, or captions.+ fmap (<> blankline) (blockListToHaddock opts (body ++ longcapt)) -- | Convert bullet list item (list of blocks) to haddock bulletListItemToHaddock :: PandocMonad m
@@ -17,7 +17,9 @@ -} module Text.Pandoc.Writers.ICML (writeICML) where import Control.Monad.Except (catchError)+import Control.Monad (liftM2) import Control.Monad.State.Strict+ ( MonadTrans(lift), StateT(runStateT), MonadState(state, get, put) ) import Data.List (intersperse) import Data.Maybe (fromMaybe, maybeToList) import qualified Data.Set as Set@@ -28,8 +30,9 @@ import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.DocLayout+import Text.DocLayout hiding (link) import Text.Pandoc.Shared+import Text.Pandoc.URI (isURI) import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Math (texMathToInlines) import Text.Pandoc.Writers.Shared@@ -41,6 +44,7 @@ data WriterState = WriterState{ blockStyles :: Set.Set Text , inlineStyles :: Set.Set Text+ , objectStyles :: Set.Set Text , links :: Hyperlink , listDepth :: Int , maxListDepth :: Int@@ -52,6 +56,7 @@ defaultWriterState = WriterState{ blockStyles = Set.empty , inlineStyles = Set.empty+ , objectStyles = Set.empty , links = [] , listDepth = 1 , maxListDepth = 0@@ -144,9 +149,10 @@ meta (main, st) <- runStateT (blocksToICML opts [] blocks) defaultWriterState let context = defField "body" main- $ defField "charStyles" (charStylesToDoc st)- $ defField "parStyles" (parStylesToDoc st)- $ defField "hyperlinks" (hyperlinksToDoc $ links st) metadata+ $ defField "charStyles" (charStylesToDoc st)+ $ defField "parStyles" (parStylesToDoc st)+ $ defField "objectStyles" (objectStylesToDoc st)+ $ defField "hyperlinks" (hyperlinksToDoc $ links st) metadata return $ render colwidth $ (if writerPreferAscii opts then fmap toEntities else id) $ case writerTemplate opts of@@ -154,9 +160,13 @@ Just tpl -> renderTemplate tpl context -- | Auxiliary functions for parStylesToDoc and charStylesToDoc.-contains :: Text -> (Text, (Text, Text)) -> [(Text, Text)]-contains s rule =- [snd rule | fst rule `Text.isInfixOf` s]+contains :: Text -> (Text, (Text, Text)) -> [(Text, Text)] -> [(Text, Text)]+contains s (t, (k,v)) attrs =+ if t `Text.isInfixOf` s+ then case lookup k attrs of -- avoid duplicates, #9158+ Nothing -> (k, v) : attrs+ Just _ -> attrs+ else attrs -- | The monospaced font to use as default. monospacedFont :: Doc Text@@ -180,7 +190,7 @@ where makeStyle s = let countSubStrs sub str = length $ Text.breakOnAll sub str- attrs = concatMap (contains s) [+ attrs = foldr (contains s) [] [ (defListTermName, ("BulletsAndNumberingListType", "BulletList")) , (defListTermName, ("FontStyle", "Bold")) , (tableHeaderName, ("FontStyle", "Bold"))@@ -245,7 +255,7 @@ charStylesToDoc st = vcat $ map makeStyle $ Set.toAscList $ inlineStyles st where makeStyle s =- let attrs = concatMap (contains s) [+ let attrs = foldr (contains s) [] [ (strikeoutName, ("StrikeThru", "true")) , (superscriptName, ("Position", "Superscript")) , (subscriptName, ("Position", "Subscript"))@@ -265,6 +275,16 @@ else empty in inTags True "CharacterStyle" ([("Self", "CharacterStyle/"<>s), ("Name", s)] ++ attrs') props +-- | Convert a WriterState with its object styles to the ICML listing of Object Styles.+objectStylesToDoc :: WriterState -> Doc Text+objectStylesToDoc st = vcat $ map makeStyle $ Set.toAscList $ objectStyles st+ where+ makeStyle s =+ let attrs = []+ props = inTags True "Properties" [] $+ inTags False "BasedOn" [("type", "string")] (text "$ID/None")+ in inTags True "ObjectStyle" ([("Self", "ObjectStyle/"<>s), ("Name", s)] ++ attrs) props+ -- | Escape colon characters as %3a escapeColons :: Text -> Text escapeColons txt = Text.replace ":" "%3a" txt@@ -309,10 +329,6 @@ -- | Convert a Pandoc block element to ICML. blockToICML :: PandocMonad m => WriterOptions -> Style -> Block -> WS m (Doc Text) blockToICML opts style (Plain lst) = parStyle opts style "" lst-blockToICML opts style (SimpleFigure attr txt (src, tit)) = do- figure <- parStyle opts (figureName:style) "" [Image attr txt (src, tit)]- caption <- parStyle opts (imgCaptionName:style) "" txt- return $ intersperseBrs [figure, caption] blockToICML opts style (Para lst) = parStyle opts (paragraphName:style) "" lst blockToICML opts style (LineBlock lns) = blockToICML opts style $ linesToPara lns@@ -342,9 +358,9 @@ then "0" else "1" nrRows = length rows- nrCols = if null rows- then 0- else length $ head rows+ nrCols = case rows of+ [] -> 0+ (r:_) -> length r rowsToICML [] _ = return empty rowsToICML (col:rest) rowNr = liftM2 ($$) (colsToICML col aligns rowNr (0::Int)) $ rowsToICML rest (rowNr+1)@@ -383,8 +399,17 @@ blockToICML opts style (Div (_ident, _, kvs) lst) = let dynamicStyle = maybeToList $ lookup dynamicStyleKey kvs in blocksToICML opts (dynamicStyle <> style) lst-blockToICML _ _ Null = return empty+blockToICML opts style (Figure attr capt@(Caption _ longcapt) body) =+ case body of+ [Plain [img@(Image {})]] -> do+ figure <- parStyle opts (figureName:style) "" [img]+ caption <- parStyle opts (imgCaptionName:style) "" $+ blocksToInlines longcapt+ return $ intersperseBrs [figure, caption]+ _ -> -- fallback to rendering the figure as a Div+ blockToICML opts style $ figureDiv attr capt body + -- | Convert a list of lists of blocks to ICML list items. listItemsToICML :: PandocMonad m => WriterOptions -> Text -> Style -> Maybe ListAttributes -> [[Block]] -> WS m (Doc Text) listItemsToICML _ _ _ _ [] = return empty@@ -418,14 +443,15 @@ then firstListItemName:style else style stl' = makeNumbStart attribs ++ stl- in if length item > 1- then do- let insertTab (Para lst) = blockToICML opts (subListParName:style) $ Para $ Str "\t":lst- insertTab block = blockToICML opts style block- f <- blockToICML opts stl' $ head item- r <- mapM insertTab $ tail item- return $ intersperseBrs (f : r)- else blocksToICML opts stl' item+ in case item of+ (i:rest@(_:_)) -> do+ let insertTab (Para lst) = blockToICML opts (subListParName:style)+ (Para (Str "\t":lst))+ insertTab block = blockToICML opts style block+ f <- blockToICML opts stl' i+ r <- mapM insertTab rest+ return $ intersperseBrs (f : r)+ _ -> blocksToICML opts stl' item definitionListItemToICML :: PandocMonad m => WriterOptions -> Style -> ([Inline],[[Block]]) -> WS m (Doc Text) definitionListItemToICML opts style (term,defs) = do@@ -472,9 +498,9 @@ inlineToICML opts style ident (Link _ lst (url, title)) = do content <- inlinesToICML opts (linkName:style) ident lst state $ \st ->- let link_id = if null $ links st- then 1::Int- else 1 + fst (head $ links st)+ let link_id = case links st of+ [] -> 1 :: Int+ ((n,_):_) -> 1 + n newst = st{ links = (link_id, url):links st } cont = inTags True "HyperlinkTextSource" [("Self","htss-"<>tshow link_id), ("Name",title), ("Hidden","false")] content@@ -486,7 +512,7 @@ in inlinesToICML opts (dynamicStyle <> style) ident lst -- ident will be the id of the span, that we need to use down in the hyperlink setter -- if T.null ident--- then +-- then -- else do -- | Convert a list of block elements to an ICML footnote.@@ -533,11 +559,12 @@ attrs' = if firstListItemName `elem` style then let ats = attrs : [("NumberingContinue", "false")] begins = filter (Text.isPrefixOf beginsWithName) style- in if null begins- then ats- else let i = fromMaybe "" $ Text.stripPrefix beginsWithName- $ head begins- in ("NumberingStartAt", i) : ats+ in case begins of+ [] -> ats+ (b:_) ->+ let i = fromMaybe ""+ (Text.stripPrefix beginsWithName b)+ in ("NumberingStartAt", i) : ats else [attrs] in do content <- inlinesToICML opts [] ident lst@@ -559,7 +586,7 @@ -- | Create the markup for the content (incl. named destinations) -- | NOTE: since we have no easy way to get actual named dests, we just create them for any short content blocks makeContent :: Text -> Doc Text -> Doc Text-makeContent ident cont +makeContent ident cont | isEmpty cont = empty | not (Text.null ident) = makeLinkDest ident cont | otherwise = inTagsSimple "Content" $ flush cont@@ -587,6 +614,10 @@ attrs = [("AppliedCharacterStyle", stl)] in (stlStr, attrs) +-- | Key for specifying user-defined object (image) styles+objectStyleKey :: Text+objectStyleKey = "object-style"+ -- | Assemble an ICML Image. imageICML :: PandocMonad m => WriterOptions -> Style -> Attr -> Target -> WS m (Doc Text) imageICML opts style attr (src, _) = do@@ -620,18 +651,44 @@ , selfClosingTag "PathPointType" [("Anchor", hw<>" -"<>hh), ("LeftDirection", hw<>" -"<>hh), ("RightDirection", hw<>" -"<>hh)] ]- image = inTags True "Image"- [("Self","ue6"), ("ItemTransform", scale<>" -"<>hw<>" -"<>hh)]- $ vcat [- inTags True "Properties" [] $ vcat [- inTags True "Profile" [("type","string")] $ text "$ID/Embedded"- , selfClosingTag "GraphicBounds" [("Left","0"), ("Top","0")- , ("Right", showFl $ ow*ow / imgWidth)- , ("Bottom", showFl $ oh*oh / imgHeight)]- ]- , selfClosingTag "Link" [("Self", "ueb"), ("LinkResourceURI", src')]- ]- doc = inTags True "CharacterStyleRange" attrs- $ inTags True "Rectangle" [("Self","uec"), ("StrokeWeight", "0"),- ("ItemTransform", scale<>" "<>hw<>" -"<>hh)] (props $$ image)- state $ \st -> (doc, st{ inlineStyles = Set.insert stlStr $ inlineStyles st } )++ isdata = "data:" `Text.isPrefixOf` src' && "base64," `Text.isInfixOf` src'+ contents =+ if isdata+ then -- see #8398+ inTags True "Contents" [] $+ literal ("<![CDATA[" <> Text.replace "%20" ""+ (Text.drop 1 (Text.dropWhile (/=',') src')) <> "]]>")+ else mempty+ link = if isdata+ then mempty+ else selfClosingTag "Link" [("Self", "ueb"),+ ("LinkResourceURI", src')]+ (_,_,kvs) = attr+ applyObjectStyle = lookup objectStyleKey kvs+ image = inTags True "Image"+ [("Self","ue6"), ("ItemTransform", scale <> " -" <> hw <> " -" <> hh)]+ $ vcat [+ inTags True "Properties" [] $ vcat [+ inTags True "Profile" [("type","string")] $ text "$ID/Embedded",+ selfClosingTag "GraphicBounds" [("Left","0"), ("Top","0"),+ ("Right", showFl $ ow * ow / imgWidth),+ ("Bottom", showFl $ oh * oh / imgHeight)],+ contents+ ],+ link+ ]+ doc = inTags True "CharacterStyleRange" attrs+ $ inTags True "Rectangle"+ ([("Self","uec"),+ ("StrokeWeight", "0"),+ ("ItemTransform", scale <> " " <> hw <> " -" <> hh)] +++ maybe [] (\aos -> [("AppliedObjectStyle", "ObjectStyle/" <> aos)]) applyObjectStyle+ )+ (props $$ image)+ state $ \st -> (doc, st{+ inlineStyles = Set.insert stlStr $ inlineStyles st,+ objectStyles = case applyObjectStyle of+ Just styleName -> Set.insert styleName $ objectStyles st+ Nothing -> objectStyles st+ })
@@ -2,7 +2,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Text.Pandoc.Writers.Ipynb- Copyright : Copyright (C) 2019-2022 John MacFarlane+ Copyright : Copyright (C) 2019-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -14,7 +14,8 @@ -} module Text.Pandoc.Writers.Ipynb ( writeIpynb ) where-import Control.Monad.State+import Control.Monad (foldM)+import Control.Monad.State ( StateT(runStateT), modify ) import qualified Data.Map as M import Data.Maybe (catMaybes, fromMaybe) import Text.Pandoc.Options@@ -29,7 +30,8 @@ import qualified Data.Text.Lazy as TL import Data.Aeson as Aeson import qualified Text.Pandoc.UTF8 as UTF8-import Text.Pandoc.Shared (safeRead, isURI)+import Text.Pandoc.Shared (safeRead)+import Text.Pandoc.URI (isURI) import Text.Pandoc.Writers.Shared (metaToContext') import Text.Pandoc.Writers.Markdown (writePlain, writeMarkdown) import qualified Data.Text.Encoding as TE
@@ -4,7 +4,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Writers.JATS- Copyright : 2017-2022 John MacFarlane+ Copyright : 2017-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -22,12 +22,12 @@ , writeJatsArticleAuthoring ) where import Control.Applicative ((<|>))+import Control.Monad import Control.Monad.Reader import Control.Monad.State import Data.Generics (everywhere, mkT)-import Data.List (partition) import qualified Data.Map as M-import Data.Maybe (fromMaybe, listToMaybe)+import Data.Maybe (fromMaybe, listToMaybe, isNothing) import Data.Time (toGregorian, Day, parseTimeM, defaultTimeLocale, formatTime) import qualified Data.Text as T import Data.Text (Text)@@ -41,8 +41,9 @@ import Text.Pandoc.Options import Text.DocLayout import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate)-import Text.DocTemplates (Context(..), Val(..))+import Text.DocTemplates (Context(..), Val(..), toVal) import Text.Pandoc.Writers.JATS.References (referencesToJATS) import Text.Pandoc.Writers.JATS.Table (tableToJATS) import Text.Pandoc.Writers.JATS.Types@@ -53,6 +54,54 @@ import qualified Text.Pandoc.Writers.AnnotatedTable as Ann import qualified Text.XML.Light as Xml +-- | Default human-readable names for roles in the Contributor Role+-- Taxonomy (CRediT). This is useful for generating JATS that annotate+-- contributor roles+creditNames :: M.Map Text Text+creditNames = M.fromList [+ ("conceptualization", "Conceptualization"),+ ("data-curation", "Data curation"),+ ("formal-analysis", "Formal analysis"),+ ("funding-acquisition", "Funding acquisition"),+ ("investigation", "Investigation"),+ ("methodology", "Methodology"),+ ("project-administration", "Project administration"),+ ("resources", "Resources"),+ ("software", "Software"),+ ("supervision", "Supervision"),+ ("validation", "Validation"),+ ("visualization", "Visualization"),+ ("writing-original-draft", "Writing – original draft"),+ ("writing-review-editing", "Writing – review & editing")]++-- | Ensure every role with a `credit` key also has a `credit-name`,+-- using a default value if necessary+addCreditNames :: Context Text -> Context Text+addCreditNames context =+ case getField "author" context of+ -- If there is an "authors" key, then we replace the existing value+ -- with one we mutate by running the addCreditNamesToAuthor helper+ -- function on each+ Just (ListVal authors) ->+ resetField "author" (map addCreditNamesToAuthor authors) context+ -- If there is no "authors" key in the context, then we don't have to do+ -- anything, and just return the context as is+ _ -> context+ where+ addCreditNamesToAuthor :: Val Text -> Val Text+ addCreditNamesToAuthor val = fromMaybe val $ do+ MapVal authorCtx <- pure val+ ListVal roles <- getField "roles" authorCtx+ return $ toVal $ resetField "roles" (map addCreditNameToRole roles) authorCtx++ addCreditNameToRole :: Val Text -> Val Text+ addCreditNameToRole val = fromMaybe val $ do+ MapVal roleCtx <- pure val+ guard $ isNothing (getField "credit-name" roleCtx :: Maybe (Val Text))+ creditId <- getField "credit" roleCtx+ creditName <- M.lookup creditId creditNames+ return $ toVal $ resetField "credit-name" creditName roleCtx+ -- | Convert a @'Pandoc'@ document to JATS (Archiving and Interchange -- Tag Set.) writeJatsArchiving :: PandocMonad m => WriterOptions -> Pandoc -> m Text@@ -70,6 +119,7 @@ -- | Alias for @'writeJatsArchiving'@. This function exists for backwards -- compatibility, but will be deprecated in the future. Use -- @'writeJatsArchiving'@ instead.+{-# DEPRECATED writeJATS "Use writeJatsArchiving instead" #-} writeJATS :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeJATS = writeJatsArchiving @@ -89,29 +139,47 @@ runReaderT (evalStateT (docToJATS opts d) initialState) environment +-- see #9017 for motivation+ensureReferenceHeader :: [Block] -> [Block]+ensureReferenceHeader [] = []+ensureReferenceHeader (h@(Header{}):refs@(Div ("refs",_,_) _) : xs) =+ h:refs:xs+ensureReferenceHeader (refs@(Div ("refs",_,_) _) : xs) =+ Header 1 nullAttr mempty : refs : xs+ensureReferenceHeader (x:xs) = x :ensureReferenceHeader xs+ -- | Convert Pandoc document to string in JATS format. docToJATS :: PandocMonad m => WriterOptions -> Pandoc -> JATS m Text-docToJATS opts (Pandoc meta blocks) = do- let isBackBlock (Div ("refs",_,_) _) = True- isBackBlock _ = False- let (backblocks, bodyblocks) = partition isBackBlock blocks+docToJATS opts (Pandoc meta blocks') = do -- The numbering here follows LaTeX's internal numbering let startLvl = case writerTopLevelDivision opts of TopLevelPart -> -1 TopLevelChapter -> 0 TopLevelSection -> 1 TopLevelDefault -> 1- let fromBlocks = blocksToJATS opts . makeSections False (Just startLvl)+ let blocks = makeSections (writerNumberSections opts) (Just startLvl)+ $ ensureReferenceHeader blocks'+ let splitBackBlocks b@(Div ("refs",_,_) _) (fs, bs) = (fs, b:bs)+ splitBackBlocks (Div (ident,("section":_),_)+ ( Header lev (_,hcls,hkvs) hils+ : (Div rattrs@("refs",_,_) rs)+ : rest+ )) (fs, bs)+ = (fs ++ rest,+ Div rattrs+ (Header lev (ident,hcls,hkvs) hils : rs) : bs)+ splitBackBlocks b (fs, bs) = (b:fs, bs)+ let (bodyblocks, backblocks) = foldr splitBackBlocks ([],[]) blocks let colwidth = if writerWrapText opts == WrapAuto then Just $ writerColumns opts else Nothing metadata <- metaToContext opts- fromBlocks+ (blocksToJATS opts . makeSections False (Just startLvl)) (fmap chomp . inlinesToJATS opts) meta- main <- fromBlocks bodyblocks+ main <- blocksToJATS opts bodyblocks notes <- gets (reverse . map snd . jatsNotes)- backs <- fromBlocks backblocks+ backs <- blocksToJATS opts backblocks tagSet <- asks jatsTagSet -- In the "Article Authoring" tag set, occurrence of fn-group elements -- is restricted to table footers. Footnotes have to be placed inline.@@ -135,8 +203,12 @@ formatTime defaultTimeLocale "%F" day) ] Just x -> x+ title' <- inlinesToJATS opts $ map fixLineBreak+ (lookupMetaInlines "title" meta) let context = defField "body" main $ defField "back" back+ $ addCreditNames+ $ resetField "title" title' $ resetField "date" date $ defField "mathml" (case writerHTMLMathMethod opts of MathML -> True@@ -214,17 +286,6 @@ maybe empty (inTagsSimple "label" . text . T.unpack) mbmarker $$ contents -imageMimeType :: Text -> [(Text, Text)] -> (Text, Text)-imageMimeType src kvs =- let mbMT = getMimeType (T.unpack src)- maintype = fromMaybe "image" $- lookup "mimetype" kvs `mplus`- (T.takeWhile (/='/') <$> mbMT)- subtype = fromMaybe "" $- lookup "mime-subtype" kvs `mplus`- (T.drop 1 . T.dropWhile (/='/') <$> mbMT)- in (maintype, subtype)- languageFor :: WriterOptions -> [Text] -> Text languageFor opts classes = case langs of@@ -249,17 +310,29 @@ "platforms", "position", "specific-use"]] lang = languageFor opts classes +-- <break/> is only allowed as a direct child of <td> or <title> or+-- <article-title>+fixLineBreak :: Inline -> Inline+fixLineBreak LineBreak = RawInline (Format "jats") "<break/>"+fixLineBreak x = x+ -- | Convert a Pandoc block element to JATS. blockToJATS :: PandocMonad m => WriterOptions -> Block -> JATS m (Doc Text)-blockToJATS _ Null = return empty-blockToJATS opts (Div (id',"section":_,kvs) (Header _lvl _ ils : xs)) = do+blockToJATS opts (Div (id',"section":_,kvs) (Header _lvl (_,_,hkvs) ils : xs)) = do let idAttr = [ ("id", writerIdentifierPrefix opts <> escapeNCName id') | not (T.null id')] let otherAttrs = ["sec-type", "specific-use"] let attribs = idAttr ++ [(k,v) | (k,v) <- kvs, k `elem` otherAttrs]- title' <- inlinesToJATS opts ils+ title' <- inlinesToJATS opts (map fixLineBreak ils)+ let label = if writerNumberSections opts+ then+ case lookup "number" hkvs of+ Just num -> inTagsSimple "label" (literal num)+ Nothing -> mempty+ else mempty contents <- blocksToJATS opts xs return $ inTags True "sec" attribs $+ label $$ inTagsSimple "title" title' $$ contents -- Bibliography reference: blockToJATS opts (Div (ident,_,_) [Para lst]) | "ref-" `T.isPrefixOf` ident =@@ -270,7 +343,13 @@ refs <- asks jatsReferences contents <- if null refs then blocksToJATS opts xs- else referencesToJATS opts refs+ else do+ titleElement <- case xs of+ (Header _ _ title:_) ->+ inTagsSimple "title" <$> inlinesToJATS opts title+ _ -> return mempty+ elementRefs <- referencesToJATS opts refs+ return $ titleElement $$ elementRefs return $ inTagsIndented "ref-list" contents blockToJATS opts (Div (ident,[cls],kvs) bs) | cls `elem` ["fig", "caption", "table-wrap"] = do contents <- blocksToJATS opts bs@@ -281,43 +360,31 @@ return $ inTags True cls attr contents blockToJATS opts (Div (ident,_,kvs) bs) = do contents <- blocksToJATS opts bs- let attr = [("id", escapeNCName ident) | not (T.null ident)] ++- [("xml:lang",l) | ("lang",l) <- kvs] ++- [(k,v) | (k,v) <- kvs, k `elem` ["specific-use",- "content-type", "orientation", "position"]]- return $ inTags True "boxed-text" attr contents+ -- Attributes that are allowed on both @<p>@ and @<boxed-text>@ elements+ let generic_attr = [("id", escapeNCName ident) | not (T.null ident)] +++ [("xml:lang",l) | ("lang",l) <- kvs] +++ [(k,v) | (k,v) <- kvs, k `elem` ["specific-use",+ "content-type"]]+ let boxed_attr = [(k,v) | (k,v) <- kvs, k `elem` ["orientation", "position"]]+ let attr = generic_attr <> boxed_attr+ return $+ if null attr+ then contents+ else -- The contents must be wrapped in an appropriate element.+ let element = if null boxed_attr+ then "p"+ else "boxed-text"+ in inTags True element (generic_attr <> boxed_attr) contents blockToJATS opts (Header _ _ title) = do- title' <- inlinesToJATS opts title+ title' <- inlinesToJATS opts (map fixLineBreak title) return $ inTagsSimple "title" title'+-- Special cases for bare images, which are rendered as graphics+blockToJATS _opts (Plain [Image attr alt tgt]) =+ return $ graphic attr alt tgt+blockToJATS _opts (Para [Image attr alt tgt]) =+ return $ graphic attr alt tgt -- No Plain, everything needs to be in a block-level tag blockToJATS opts (Plain lst) = blockToJATS opts (Para lst)-blockToJATS opts (SimpleFigure (ident, _, kvs) txt (src, tit)) = do- alt <- inlinesToJATS opts txt- let (maintype, subtype) = imageMimeType src kvs- let capt = if null txt- then empty- else inTagsSimple "caption" $ inTagsSimple "p" alt- let attr = [("id", escapeNCName ident) | not (T.null ident)] ++- [(k,v) | (k,v) <- kvs, k `elem` ["fig-type", "orientation",- "position", "specific-use"]]- let graphicattr = [("mimetype",maintype),- ("mime-subtype",subtype),- ("xlink:href",src), -- do we need to URL escape this?- ("xlink:title",tit)]- return $ inTags True "fig" attr $- capt $$ selfClosingTag "graphic" graphicattr-blockToJATS _ (Para [Image (ident,_,kvs) _ (src, tit)]) = do- let (maintype, subtype) = imageMimeType src kvs- let attr = [("id", escapeNCName ident) | not (T.null ident)] ++- [("mimetype", maintype),- ("mime-subtype", subtype),- ("xlink:href", src)] ++- [("xlink:title", tit) | not (T.null tit)] ++- [(k,v) | (k,v) <- kvs, k `elem` ["baseline-shift",- "content-type", "specific-use", "xlink:actuate",- "xlink:href", "xlink:role", "xlink:show",- "xlink:type"]]- return $ selfClosingTag "graphic" attr blockToJATS opts (Para lst) = inTagsSimple "p" <$> inlinesToJATS opts lst blockToJATS opts (LineBlock lns) =@@ -373,7 +440,46 @@ blockToJATS _ HorizontalRule = return empty -- not semantic blockToJATS opts (Table attr caption colspecs thead tbody tfoot) = tableToJATS opts (Ann.toTable attr caption colspecs thead tbody tfoot)+blockToJATS opts (Figure (ident, _, kvs) (Caption _short longcapt) body) = do+ -- Remove the alt text from images if it's the same as the caption text.+ let unsetAltIfDupl = \case+ Image attr alt tgt+ | stringify alt == stringify longcapt -> Image attr [] tgt+ inline -> inline+ capt <- if null longcapt+ then pure empty+ else inTagsSimple "caption" <$> blocksToJATS opts longcapt + -- We handle the element specially if it's a figure with subfigures, i.e., if+ -- all immediate children are figures themselves.+ let hasSubfigures = all (\case { Figure{} -> True; _ -> False}) body+ needsWrapping = if hasSubfigures+ then (const False)+ else \case+ -- Wrap all figure content elements, except for those+ -- allowed as direct subelements.+ BlockQuote{} -> False+ CodeBlock{} -> False+ Para{} -> False+ Plain [Image{}] -> False+ Plain [Math{}] -> False+ Table{} -> False+ _ -> True++ children <- wrappedBlocksToJATS needsWrapping opts $ walk unsetAltIfDupl body+ let (tag, allowedAttributes) =+ if hasSubfigures+ then ( "fig-group"+ , ["content-type", "orientation", "position", "specific-use"]+ )+ else ("fig"+ , ["fig-type", "orientation", "position", "specific-use"]+ )+ let xmlattr = [("id", escapeNCName ident) | not (T.null ident)] +++ [(k,v) | (k,v) <- kvs+ , k `elem` allowedAttributes]+ return $ inTags True tag xmlattr $ capt $$ children+ -- | Convert a list of inline elements to JATS. inlinesToJATS :: PandocMonad m => WriterOptions -> [Inline] -> JATS m (Doc Text) inlinesToJATS opts lst = hcat <$> mapM (inlineToJATS opts) (fixCitations lst)@@ -414,9 +520,8 @@ contents <- inlinesToJATS opts lst return $ char '“' <> contents <> char '”' inlineToJATS opts (Code a str) =- return $ inTags False tag attr $ literal (escapeStringForXML str)- where (lang, attr) = codeAttr opts a- tag = if T.null lang then "monospace" else "code"+ return $ inTags False "monospace" attr $ literal (escapeStringForXML str)+ where (_lang, attr) = codeAttr opts a inlineToJATS _ il@(RawInline f x) | f == "jats" = return $ literal x | otherwise = do@@ -531,27 +636,53 @@ "xlink:type"]] contents <- inlinesToJATS opts txt return $ inTags False "ext-link" attr contents-inlineToJATS _ (Image (ident,_,kvs) _ (src, tit)) = do+inlineToJATS _ (Image attr alt tgt) = do+ let elattr = graphicAttr attr alt tgt+ return $ case altToJATS alt of+ Nothing -> selfClosingTag "inline-graphic" elattr+ Just altTag -> inTags True "inline-graphic" elattr altTag++graphic :: Attr -> [Inline] -> Target -> (Doc Text)+graphic attr alt tgt =+ let elattr = graphicAttr attr alt tgt+ in case altToJATS alt of+ Nothing -> selfClosingTag "graphic" elattr+ Just altTag -> inTags True "graphic" elattr altTag++graphicAttr :: Attr -> [Inline] -> Target -> [(Text, Text)]+graphicAttr (ident, _, kvs) _alt (src, tit) =+ let (maintype, subtype) = imageMimeType src kvs+ in [("id", escapeNCName ident) | not (T.null ident)] +++ [ ("mimetype", maintype)+ , ("mime-subtype", subtype)+ , ("xlink:href", src)+ ] +++ [("xlink:title", tit) | not (T.null tit)] +++ [(k,v) | (k,v) <- kvs+ , k `elem` [ "baseline-shift", "content-type", "specific-use"+ , "xlink:actuate", "xlink:href", "xlink:role"+ , "xlink:show", "xlink:type"]+ ]++altToJATS :: [Inline] -> Maybe (Doc Text)+altToJATS alt =+ if null alt+ then Nothing+ else Just . inTagsSimple "alt-text" .+ hsep . map literal . T.words $ stringify alt++imageMimeType :: Text -> [(Text, Text)] -> (Text, Text)+imageMimeType src kvs = let mbMT = getMimeType (T.unpack src)- let maintype = fromMaybe "image" $+ maintype = fromMaybe "image" $ lookup "mimetype" kvs `mplus` (T.takeWhile (/='/') <$> mbMT)- let subtype = fromMaybe "" $+ subtype = fromMaybe "" $ lookup "mime-subtype" kvs `mplus` (T.drop 1 . T.dropWhile (/='/') <$> mbMT)- let attr = [("id", escapeNCName ident) | not (T.null ident)] ++- [("mimetype", maintype),- ("mime-subtype", subtype),- ("xlink:href", src)] ++- [("xlink:title", tit) | not (T.null tit)] ++- [(k,v) | (k,v) <- kvs, k `elem` ["baseline-shift",- "content-type", "specific-use", "xlink:actuate",- "xlink:href", "xlink:role", "xlink:show",- "xlink:type"]]- return $ selfClosingTag "inline-graphic" attr+ in (maintype, subtype) isParaOrList :: Block -> Bool-isParaOrList SimpleFigure{} = False -- implicit figures are not paragraphs isParaOrList Para{} = True isParaOrList Plain{} = True isParaOrList BulletList{} = True
@@ -2,10 +2,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.JATS.References- Copyright : © 2021-2022 Albert Krewinkel+ Copyright : © 2021-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -147,13 +147,11 @@ fourDigits n = T.takeEnd 4 $ "000" <> tshow n toNameElements :: Name -> Doc Text-toNameElements name =- if not (isEmpty nameTags)- then inTags' "name" [] nameTags- else if nameLiteral name == Just "others" -- indicates an "et al."- then "<etal/>"- else nameLiteral name `inNameTag` "string-name"- where+toNameElements name+ | not (isEmpty nameTags) = inTags' "name" [] nameTags+ | nameLiteral name == Just "others" = "<etal/>"+ | otherwise = nameLiteral name `inNameTag` "string-name"+ where inNameTag mVal tag = case mVal of Nothing -> empty Just val -> inTags' tag [] . literal $ escapeStringForXML val
@@ -3,10 +3,10 @@ {-# LANGUAGE TupleSections #-} {- | Module : Text.Pandoc.Writers.JATS.Table- Copyright : © 2020-2022 Albert Krewinkel+ Copyright : © 2020-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -234,8 +234,13 @@ tableCellToJats opts ctype colAlign (Cell attr align rowspan colspan item) = do blockToJats <- asks jatsBlockWriter inlinesToJats <- asks jatsInlinesWriter+ let fixBreak LineBreak = RawInline (Format "jats") "<break/>"+ fixBreak x = x let cellContents = \case- [Plain inlines] -> inlinesToJats opts inlines+ [Plain inlines] -> inlinesToJats opts+ (map fixBreak inlines)+ -- Note: <break/> is allowed only as a direct+ -- child of <td>, so we don't use walk. blocks -> blockToJats needsWrapInCell opts blocks let tag' = case ctype of BodyCell -> "td"
@@ -1,6 +1,6 @@ {- | Module : Text.Pandoc.Writers.JATS.Types- Copyright : Copyright (C) 2017-2022 John MacFarlane+ Copyright : Copyright (C) 2017-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -3,10 +3,10 @@ {-# LANGUAGE PatternGuards #-} {- | Module : Text.Pandoc.Writers.Jira- Copyright : © 2010-2022 Albert Krewinkel, John MacFarlane+ Copyright : © 2010-2024 Albert Krewinkel, John MacFarlane License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -18,7 +18,6 @@ module Text.Pandoc.Writers.Jira ( writeJira ) where import Control.Monad.Reader (ReaderT, ask, asks, runReaderT) import Control.Monad.State.Strict (StateT, evalStateT, gets, modify)-import Data.Foldable (find) import Data.Text (Text) import Text.Jira.Parser (plainText) import Text.Jira.Printer (prettyBlocks, prettyInlines)@@ -103,7 +102,6 @@ Para xs -> singleton . Jira.Para <$> toJiraInlines xs Plain xs -> singleton . Jira.Para <$> toJiraInlines xs RawBlock fmt cs -> rawBlockToJira fmt cs- Null -> return mempty Table _ blkCapt specs thead tbody tfoot -> singleton <$> do let (_, _, _, hd, body) = toLegacyTable blkCapt specs thead tbody tfoot headerRow <- if all null hd@@ -114,6 +112,7 @@ Just header -> header : bodyRows Nothing -> bodyRows return $ Jira.Table rows+ Figure attr _ body -> toJiraPanel attr body jiraBlocks <- mapM convert blocks return $ mconcat jiraBlocks @@ -133,9 +132,9 @@ -> JiraConverter m [Jira.Block] toJiraCode (ident, classes, _attribs) code = do return . addAnchor ident . singleton $- case find (\c -> T.toLower c `elem` knownLanguages) classes of- Nothing -> Jira.NoFormat mempty code- Just l -> Jira.Code (Jira.Language l) mempty code+ case classes of+ [] -> Jira.NoFormat mempty code+ l:_ -> Jira.Code (Jira.Language l) mempty code -- | Prepends an anchor with the given identifier. addAnchor :: Text -> [Jira.Block] -> [Jira.Block]@@ -328,12 +327,3 @@ modify $ \s -> s { stNotes = thisnote : curNotes } return . singleton . Jira.Str $ "[" <> T.pack (show newnum) <> "]"---- | Language codes recognized by jira-knownLanguages :: [Text]-knownLanguages =- [ "actionscript", "ada", "applescript", "bash", "c", "c#", "c++"- , "css", "erlang", "go", "groovy", "haskell", "html", "java", "javascript"- , "json", "lua", "nyan", "objc", "perl", "php", "python", "r", "ruby"- , "scala", "sql", "swift", "visualbasic", "xml", "yaml"- ]
@@ -3,10 +3,11 @@ {-# LANGUAGE TupleSections #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Writers.LaTeX- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2025 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -20,43 +21,95 @@ , writeBeamer ) where import Control.Monad.State.Strict-import Data.Char (isDigit)-import Data.List (intersperse, (\\))-import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe, isNothing)+ ( MonadState(get, put),+ gets,+ modify,+ evalStateT )+import Control.Monad+ ( MonadPlus(mplus),+ liftM,+ when,+ unless )+import Crypto.Hash (hashWith, MD5(MD5))+import Data.Containers.ListUtils (nubOrd)+import Data.Char (isDigit, isAscii, isLetter)+import Data.List (intersperse, partition, (\\))+import qualified Data.Set as Set+import Data.Maybe (catMaybes, fromMaybe, isJust, listToMaybe, mapMaybe, isNothing)+import Data.Monoid (Any (..)) import Data.Text (Text) import qualified Data.Text as T import Network.URI (unEscapeString)-import Text.DocTemplates (FromContext(lookupContext), renderTemplate)+import Text.DocTemplates (Context(..), FromContext(lookupContext), Val(..), renderTemplate)+import qualified Data.Map as M import Text.Collate.Lang (renderLang)-import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang)+import Text.Pandoc.Class.PandocMonad (PandocMonad, getPOSIXTime, lookupEnv,+ report, toLang) import Text.Pandoc.Definition import Text.Pandoc.Highlighting (formatLaTeXBlock, formatLaTeXInline, highlight,- styleToLaTeX)+ defaultStyle, styleToLaTeX) import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options import Text.DocLayout import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Slides import Text.Pandoc.Walk (query, walk, walkM) import Text.Pandoc.Writers.LaTeX.Caption (getCaption) import Text.Pandoc.Writers.LaTeX.Table (tableToLaTeX) import Text.Pandoc.Writers.LaTeX.Citation (citationsToNatbib, citationsToBiblatex)-import Text.Pandoc.Writers.LaTeX.Types (LW, WriterState (..), startingState)+import Text.Pandoc.Writers.LaTeX.Types (LW, WriterState (..), startingState,+ PdfStandard (..)) import Text.Pandoc.Writers.LaTeX.Lang (toBabel) import Text.Pandoc.Writers.LaTeX.Util (stringToLaTeX, StringContext(..), toLabel, inCmd, wrapDiv, hypertarget, labelFor, getListingsLanguage, mbBraced) import Text.Pandoc.Writers.Shared+import qualified Data.Attoparsec.Text as A+import qualified Text.Pandoc.UTF8 as UTF8 import qualified Text.Pandoc.Writers.AnnotatedTable as Ann+import Control.Applicative ((<|>)) +-- Work around problems with notes inside emphasis (see #8982)+isolateBigNotes :: ([Inline] -> Inline) -> [Inline] -> [Inline]+isolateBigNotes constructor xs =+ let (before, after) = break isBigNote xs+ in case after of+ (noteInline:rest) -> constructor before :+ noteInline :+ isolateBigNotes constructor rest+ [] -> [constructor xs]++isBigNote :: Inline -> Bool+isBigNote (Note [Plain _]) = False -- A small note+isBigNote (Note [Para _]) = False -- A small note+isBigNote (Note _) = True -- A big note+isBigNote _ = False -- Not a note++raiseBigNotes :: [Inline] -> [Inline]+raiseBigNotes (Emph inner : xs)+ = isolateBigNotes Emph (raiseBigNotes inner) ++ raiseBigNotes xs+raiseBigNotes (Strong inner : xs)+ = isolateBigNotes Strong (raiseBigNotes inner) ++ raiseBigNotes xs+raiseBigNotes (Underline inner : xs)+ = isolateBigNotes Underline (raiseBigNotes inner) ++ raiseBigNotes xs+raiseBigNotes (Strikeout inner : xs)+ = isolateBigNotes Strikeout (raiseBigNotes inner) ++ raiseBigNotes xs+raiseBigNotes (x : xs) = x : raiseBigNotes xs+raiseBigNotes [] = []+ -- | Convert Pandoc to LaTeX. writeLaTeX :: PandocMonad m => WriterOptions -> Pandoc -> m Text-writeLaTeX options document =- evalStateT (pandocToLaTeX options document) $- startingState options+writeLaTeX options document = do+ let Any hasBigNotes =+ query (\il -> if isBigNote il then Any True else Any False) document+ let document' = if hasBigNotes+ then walk raiseBigNotes document+ else document+ evalStateT (pandocToLaTeX options document') $ startingState options -- | Convert Pandoc to LaTeX Beamer. writeBeamer :: PandocMonad m => WriterOptions -> Pandoc -> m Text@@ -67,12 +120,12 @@ pandocToLaTeX :: PandocMonad m => WriterOptions -> Pandoc -> LW m Text pandocToLaTeX options (Pandoc meta blocks) = do- -- Strip off final 'references' header if --natbib or --biblatex+ -- Strip off 'references' header if --natbib or --biblatex let method = writerCiteMethod options+ let isRefsDiv (Div ("refs",_,_) _) = True+ isRefsDiv _ = False let blocks' = if method == Biblatex || method == Natbib- then case reverse blocks of- Div ("refs",_,_) _:xs -> reverse xs- _ -> blocks+ then filter (not . isRefsDiv) blocks else blocks -- see if there are internal links let isInternalLink (Link _ _ (s,_))@@ -82,6 +135,13 @@ let colwidth = if writerWrapText options == WrapAuto then Just $ writerColumns options else Nothing+ docLangs <- catMaybes <$>+ mapM (toLang . Just) (nubOrd (query (extract "lang") blocks))+ mblang <- toLang $ case getLang options meta of+ Just l -> Just l+ Nothing | null docLangs -> Nothing+ | otherwise -> Just "en"+ modify $ \s -> s{ stLang = mblang } metadata <- metaToContext options blockListToLaTeX (fmap chomp . inlineListToLaTeX)@@ -104,11 +164,15 @@ _ -> "article" when (documentClass `elem` chaptersClasses) $ modify $ \s -> s{ stHasChapters = True }- case lookupContext "csquotes" (writerVariables options) `mplus`- (stringify <$> lookupMeta "csquotes" meta) of- Nothing -> return ()- Just "false" -> return ()- Just _ -> modify $ \s -> s{stCsquotes = True}+ let csquotes =+ case lookupContext "csquotes" (writerVariables options) of+ Just (BoolVal v) -> v+ Just (SimpleVal (Text _ t)) -> t /= ("false" :: Text)+ _ -> case stringify <$> lookupMeta "csquotes" meta of+ Nothing -> False+ Just "false" -> False+ Just _ -> True+ when csquotes $ modify $ \s -> s{stCsquotes = True} let (blocks'', lastHeader) = if writerCiteMethod options == Citeproc then (blocks', []) else case reverse blocks' of@@ -120,10 +184,24 @@ main <- blockListToLaTeX blocks''' biblioTitle <- inlineListToLaTeX lastHeader st <- get- titleMeta <- stringToLaTeX TextString $ stringify $ docTitle meta+ titleMeta <- escapeCommas <$> -- see #10501+ stringToLaTeX TextString (stringify $ docTitle meta)+ subtitleMeta <- stringToLaTeX TextString (stringify $ lookupMetaInlines "subtitle" meta) authorsMeta <- mapM (stringToLaTeX TextString . stringify) $ docAuthors meta- docLangs <- catMaybes <$>- mapM (toLang . Just) (ordNub (query (extract "lang") blocks))+ -- 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) $ mapMaybe (\(x,y) ->@@ -133,11 +211,6 @@ ,("tmargin","margin-top") ,("bmargin","margin-bottom") ]- mblang <- toLang $ case getLang options meta of- Just l -> Just l- Nothing | null docLangs -> Nothing- | otherwise -> Just "en"- -- we need a default here since lang is used in template conditionals let dirs = query (extract "dir") blocks @@ -146,7 +219,20 @@ _ -> []) $ lookupMetaInlines "nocite" meta - let context = defField "toc" (writerTableOfContents options) $+ -- see #7414, avoid escaped underscores+ let unescapeUnderscore = T.replace "\\_" "_"+ let bibliography' = map unescapeUnderscore <$>+ getField "bibliography" metadata++ -- Process PDF standard metadata for DocumentMetadata+ pdfStd <- processPdfStandard metadata++ let context = (case bibliography' of+ Nothing -> id+ Just xs -> resetField "bibliography" xs) $+ defField "toc" (writerTableOfContents options) $+ defField "lof" (writerListOfFigures options) $+ defField "lot" (writerListOfTables options) $ defField "toc-depth" (tshow (writerTOCDepth options - if stHasChapters st@@ -154,28 +240,37 @@ else 0)) $ defField "body" main $ defField "title-meta" titleMeta $+ defField "subtitle-meta" subtitleMeta $ defField "author-meta" (T.intercalate "; " authorsMeta) $ defField "documentclass" documentClass $ defField "verbatim-in-note" (stVerbInNote st) $ defField "tables" (stTable st) $ defField "multirow" (stMultiRow st) $+ defField "cancel" (stCancel st) $ defField "strikeout" (stStrikeout st) $ defField "url" (stUrl st) $ defField "numbersections" (writerNumberSections options) $ defField "lhs" (stLHS st) $ defField "graphics" (stGraphics st) $+ defField "subfigure" (stSubfigure st) $+ 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 .@@ -200,17 +295,36 @@ Just (Just ('A', ds)) | not (T.null ds) && T.all isDigit ds -> resetField "papersize" ("a" <> ds)- _ -> id)+ _ -> id) .+ (if reproduciblePDF+ then defField "pdf-trailer-id" trailerID+ else id) $+ (if not (null (pdfStandards pdfStd)) || isJust (pdfVersion pdfStd)+ then resetField "pdfstandard" $ MapVal $ Context $ M.fromList+ [ ("standards", ListVal $ map (SimpleVal . literal) (pdfStandards pdfStd))+ , ("version", maybe NullVal (SimpleVal . literal) (pdfVersion pdfStd))+ , ("tagging", BoolVal (pdfTagging pdfStd))+ ]+ else id) $ metadata+ let babelLang = mblang >>= toBabel let context' = -- note: lang is used in some conditionals in the template, -- so we need to set it if we have any babel/polyglossia: maybe id (\l -> defField "lang" (literal $ renderLang l)) mblang $ maybe id (\l -> defField "babel-lang"- (literal $ toBabel l)) mblang+ (literal l)) babelLang+ $ (case babelLang of -- see #8283+ Just l | l `notElem` ldfLanguages+ -> defField "babeloptions" ("provide=*" :: Text)+ _ -> id) $ defField "babel-otherlangs"- (map (literal . toBabel) docLangs)+ (map literal+ (filter (`elem` ldfLanguages) .+ nubOrd . catMaybes .+ filter (/= babelLang)+ $ map toBabel docLangs)) $ defField "latex-dir-rtl" ((render Nothing <$> getField "dir" context) == Just ("rtl" :: Text)) context@@ -219,6 +333,10 @@ Nothing -> main Just tpl -> renderTemplate tpl context' +-- Commas in title-meta need to be put in braces; see #10501+escapeCommas :: Text -> Text+escapeCommas = T.replace "," "{,}"+ toSlides :: PandocMonad m => [Block] -> LW m [Block] toSlides bs = do opts <- gets stOptions@@ -259,18 +377,15 @@ blockToLaTeX :: PandocMonad m => Block -- ^ Block to convert -> LW m (Doc Text)-blockToLaTeX Null = return empty blockToLaTeX (Div attr@(identifier,"block":dclasses,_) (Header _ _ ils : bs)) = do let blockname | "example" `elem` dclasses = "exampleblock" | "alert" `elem` dclasses = "alertblock" | otherwise = "block"- ref <- toLabel identifier- let anchor = if T.null identifier- then empty- else cr <> "\\protect\\hypertarget" <>- braces (literal ref) <> braces empty+ anchor <- if T.null identifier+ then pure empty+ else (cr <>) <$> hypertarget identifier title' <- inlineListToLaTeX ils contents <- blockListToLaTeX bs wrapDiv attr $ ("\\begin" <> braces blockname <> braces title' <> anchor) $$@@ -282,8 +397,8 @@ hasCodeBlock _ = [] let hasCode (Code _ _) = [True] hasCode _ = []- let classes = ordNub $ dclasses ++ hclasses- let kvs = ordNub $ dkvs ++ hkvs+ let classes = nubOrd $ dclasses ++ hclasses+ let kvs = nubOrd $ dkvs ++ hkvs let fragile = "fragile" `elem` classes || not (null $ query hasCodeBlock bs ++ query hasCode bs) let frameoptions = ["allowdisplaybreaks", "allowframebreaks", "fragile",@@ -303,11 +418,9 @@ slideTitle <- if ils == [Str "\0"] -- marker for hrule then return empty else braces <$> inlineListToLaTeX ils- ref <- toLabel identifier- let slideAnchor = if T.null identifier- then empty- else cr <> "\\protect\\hypertarget" <>- braces (literal ref) <> braces empty+ slideAnchor <- if T.null identifier+ then pure empty+ else (cr <>) <$> hypertarget identifier contents <- blockListToLaTeX bs >>= wrapDiv (identifier,classes,kvs) return $ ("\\begin{frame}" <> options <> slideTitle <> slideAnchor) $$ contents $$ "\\end{frame}"@@ -323,52 +436,37 @@ then modify $ \st -> st{ stIncremental = True } else when (beamer && "nonincremental" `elem` classes) $ modify $ \st -> st { stIncremental = False }- result <- if identifier == "refs" || -- <- for backwards compatibility- "csl-bib-body" `elem` classes+ result <- if (identifier == "refs" || -- <- for backwards compatibility+ "csl-bib-body" `elem` classes) &&+ (not (null bs)) then do modify $ \st -> st{ stHasCslRefs = True } inner <- blockListToLaTeX bs- return $ "\\begin{CSLReferences}" <>- (if "hanging-indent" `elem` classes- then braces "1"- else braces "0") <>- (case lookup "entry-spacing" kvs of- Nothing -> braces "0"- Just s -> braces (literal s))+ return $ ("\\begin{CSLReferences}"+ <> braces+ (if "hanging-indent" `elem` classes+ then "1"+ else "0")+ <> braces+ (maybe "1" literal (lookup "entry-spacing" kvs))) $$ inner $+$ "\\end{CSLReferences}" else blockListToLaTeX bs modify $ \st -> st{ stIncremental = oldIncremental }- linkAnchor' <- hypertarget True identifier empty- -- see #2704 for the motivation for adding \leavevmode- -- and #7078 for \vadjust pre- let linkAnchor =- case bs of- Para _ : _- | not (isEmpty linkAnchor')- -> "\\leavevmode\\vadjust pre{" <> linkAnchor' <> "}%"- _ -> linkAnchor'- wrapNotes txt = if beamer && "notes" `elem` classes- then "\\note" <> braces txt -- speaker notes- else linkAnchor $$ txt- wrapNotes <$> wrapDiv (identifier,classes,kvs) result+ let wrap txt+ | beamer && "notes" `elem` classes+ = pure ("\\note" <> braces txt) -- speaker notes+ | "ref-" `T.isPrefixOf` identifier+ = do+ lab <- toLabel identifier+ pure $ ("\\bibitem" <> brackets "\\citeproctext"+ <> braces (literal lab)) $$ txt+ | otherwise = do+ linkAnchor <- hypertarget identifier+ pure $ linkAnchor $$ txt+ wrapDiv (identifier,classes,kvs) result >>= wrap blockToLaTeX (Plain lst) = inlineListToLaTeX lst-blockToLaTeX (SimpleFigure attr@(ident, _, _) txt (src, tit)) = do- (capt, captForLof, footnotes) <- getCaption inlineListToLaTeX True txt- lab <- labelFor ident- let caption = "\\caption" <> captForLof <> braces capt <> lab- img <- inlineToLaTeX (Image attr txt (src,tit))- innards <- hypertarget True ident $- "\\centering" $$ img $$ caption <> cr- let figure = cr <> "\\begin{figure}" $$ innards $$ "\\end{figure}"- st <- get- return $ (if stInMinipage st- -- can't have figures in notes or minipage (here, table cell)- -- http://www.tex.ac.uk/FAQ-ouparmd.html- then cr <> "\\begin{center}" $$ img $+$ capt $$- "\\end{center}"- else figure) $$ footnotes -- . . . indicates pause in beamer slides blockToLaTeX (Para [Str ".",Space,Str ".",Space,Str "."]) = do beamer <- gets stBeamer@@ -376,11 +474,18 @@ then blockToLaTeX (RawBlock "latex" "\\pause") else inlineListToLaTeX [Str ".",Space,Str ".",Space,Str "."] blockToLaTeX (Para lst) =- inlineListToLaTeX lst+ if null lst+ then do+ opts <- gets stOptions+ if isEnabled Ext_empty_paragraphs opts+ then pure "\\hfill\\par"+ else pure mempty+ else inlineListToLaTeX lst blockToLaTeX (LineBlock lns) = blockToLaTeX $ linesToPara lns blockToLaTeX (BlockQuote lst) = do beamer <- gets stBeamer+ csquotes <- liftM stCsquotes get case lst of [b] | beamer && isListBlock b -> do oldIncremental <- gets stIncremental@@ -393,15 +498,16 @@ modify (\s -> s{stInQuote = True}) contents <- blockListToLaTeX lst modify (\s -> s{stInQuote = oldInQuote})- return $ "\\begin{quote}" $$ contents $$ "\\end{quote}"+ let envname = if csquotes then "displayquote" else "quote"+ return $ ("\\begin" <> braces envname) $$+ contents $$+ ("\\end" <> braces envname) blockToLaTeX (CodeBlock (identifier,classes,keyvalAttr) str) = do opts <- gets stOptions- lab <- labelFor identifier inNote <- stInNote <$> get- linkAnchor' <- hypertarget True identifier lab- let linkAnchor = if isEmpty linkAnchor'- then empty- else linkAnchor' <> "%"+ linkAnchor <- if T.null identifier+ then pure empty+ else ((<> cr) . (<> "%")) <$> hypertarget identifier let lhsCodeBlock = do modify $ \s -> s{ stLHS = True } return $ flush (linkAnchor $$ "\\begin{code}" $$ literal str $$@@ -418,7 +524,8 @@ ref <- toLabel identifier kvs <- mapM (\(k,v) -> (k,) <$> stringToLaTeX TextString v) keyvalAttr- let params = if writerListings (stOptions st)+ let params = if writerHighlightMethod (stOptions st)+ == IdiomaticHighlighting then (case getListingsLanguage classes of Just l -> [ "language=" <> mbBraced l ] Nothing -> []) ++@@ -451,13 +558,16 @@ Right h -> do when inNote $ modify (\s -> s{ stVerbInNote = True }) modify (\s -> s{ stHighlighting = True })- return (flush $ linkAnchor $$ text (T.unpack h))+ return (flush $ linkAnchor $$ literal h) case () of _ | isEnabled Ext_literate_haskell opts && "haskell" `elem` classes && "literate" `elem` classes -> lhsCodeBlock- | writerListings opts -> listingsCodeBlock- | not (null classes) && isJust (writerHighlightStyle opts)+ | writerHighlightMethod opts == IdiomaticHighlighting+ -> listingsCodeBlock+ | not (null classes), Skylighting _ <- writerHighlightMethod opts -> highlightedCodeBlock+ | not (null classes), DefaultHighlighting <- writerHighlightMethod opts+ -> highlightedCodeBlock -- we don't want to use \begin{verbatim} if our code -- contains \end{verbatim}: | inNote@@ -479,14 +589,15 @@ isFirstInDefinition <- gets stIsFirstInDefinition beamer <- gets stBeamer let inc = if beamer && incremental then "[<+->]" else ""- items <- mapM listItemToLaTeX lst+ items <- mapM (listItemToLaTeX False) lst let spacing = if isTightList lst then text "\\tightlist" else empty- return $ text ("\\begin{itemize}" <> inc) $$+ return $ -- force list to start on new line if in a defn list+ (if isFirstInDefinition then "\\hfill" else mempty) $$+ text ("\\begin{itemize}" <> inc) $$ spacing $$ -- force list at beginning of definition to start on new line- (if isFirstInDefinition then "\\item[]" else mempty) $$ vcat items $$ "\\end{itemize}" blockToLaTeX (OrderedList _ []) = return empty -- otherwise latex error@@ -496,7 +607,7 @@ let oldlevel = stOLLevel st isFirstInDefinition <- gets stIsFirstInDefinition put $ st {stOLLevel = oldlevel + 1}- items <- mapM listItemToLaTeX lst+ items <- mapM (listItemToLaTeX True) lst modify (\s -> s {stOLLevel = oldlevel}) let beamer = stBeamer st let tostyle x = case numstyle of@@ -534,12 +645,12 @@ let spacing = if isTightList lst then text "\\tightlist" else empty- return $ text ("\\begin{enumerate}" <> inc)+ return $ -- force list at beginning of definition to start on new line+ (if isFirstInDefinition then "\\hfill" else mempty)+ $$ text ("\\begin{enumerate}" <> inc) $$ stylecommand $$ resetcounter $$ spacing- -- force list at beginning of definition to start on new line- $$ (if isFirstInDefinition then "\\item[]" else mempty) $$ vcat items $$ "\\end{enumerate}" blockToLaTeX (DefinitionList []) = return empty@@ -564,32 +675,89 @@ blockToLaTeX (Table attr blkCapt specs thead tbodies tfoot) = tableToLaTeX inlineListToLaTeX blockListToLaTeX (Ann.toTable attr blkCapt specs thead tbodies tfoot)+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 }+ contents <- case body of+ [b] -> blockToLaTeX b+ bs -> mconcat . intersperse (cr <> "\\hfill") <$>+ mapM (toSubfigure (length bs)) bs+ let innards = "\\centering" $$+ (case writerFigureCaptionPosition opts of+ CaptionBelow -> contents $$ caption+ CaptionAbove -> caption $$ contents) <> cr+ modify $ \st ->+ st{ stInFigure = isSubfigure+ , stSubfigure = stSubfigure st || isSubfigure+ }++ let containsTable = getAny . query (\case+ Table {} -> Any True+ _ -> Any False)+ st <- get+ return $ (case () of+ _ | containsTable body ->+ -- placing a longtable in a figure or center environment does+ -- not make sense.+ cr <> contents+ _ | stInMinipage st ->+ -- can't have figures in notes or minipage (here, table cell)+ -- http://www.tex.ac.uk/FAQ-ouparmd.html+ cr <> "\\begin{center}" $$ contents $+$ capt $$ "\\end{center}"+ _ | isSubfigure ->+ innards+ _ -> cr <> "\\begin{figure}" <> placement $$ innards $$ "\\end{figure}")+ $$ footnotes++toSubfigure :: PandocMonad m => Int -> Block -> LW m (Doc Text)+toSubfigure nsubfigs blk = do+ contents <- blockToLaTeX blk+ let linewidth = tshow @Double (0.9 / fromIntegral nsubfigs) <> "\\linewidth"+ return $ cr <> case blk of+ Figure {} -> vcat+ [ "\\begin{subfigure}[t]" <> braces (literal linewidth)+ , contents+ , "\\end{subfigure}"+ ]+ _ -> vcat+ [ "\\begin{minipage}[t]" <> braces (literal linewidth)+ , contents+ , "\\end{minipage}"+ ]+ blockListToLaTeX :: PandocMonad m => [Block] -> LW m (Doc Text) blockListToLaTeX lst = vsep `fmap` mapM (\b -> setEmptyLine True >> blockToLaTeX b) lst -listItemToLaTeX :: PandocMonad m => [Block] -> LW m (Doc Text)-listItemToLaTeX lst+listItemToLaTeX :: PandocMonad m => Bool -> [Block] -> LW m (Doc Text)+listItemToLaTeX isOrdered lst -- we need to put some text before a header if it's the first -- element in an item. This will look ugly in LaTeX regardless, but -- this will keep the typesetter from throwing an error. | (Header{} :_) <- lst = (text "\\item ~" $$) . nest 2 <$> blockListToLaTeX lst- | Plain (Str "☐":Space:is) : bs <- lst = taskListItem False is bs- | Plain (Str "☒":Space:is) : bs <- lst = taskListItem True is bs- | Para (Str "☐":Space:is) : bs <- lst = taskListItem False is bs- | Para (Str "☒":Space:is) : bs <- lst = taskListItem True is bs+ | not isOrdered+ , Just (checked, bs) <- toTaskListItem lst+ = taskListItem checked bs | otherwise = (text "\\item" $$) . nest 2 <$> blockListToLaTeX lst where- taskListItem checked is bs = do+ taskListItem checked bs = do let checkbox = if checked then "$\\boxtimes$" else "$\\square$"- isContents <- inlineListToLaTeX is- bsContents <- blockListToLaTeX bs- return $ "\\item" <> brackets checkbox- $$ nest 2 (isContents $+$ bsContents)+ let bs' = case bs of+ Plain ils : xs -> Para ils : xs+ _ -> bs+ bsContents <- blockListToLaTeX bs'+ return $ "\\item" <> brackets checkbox $$ nest 2 bsContents defListItemToLaTeX :: PandocMonad m => ([Inline], [[Block]]) -> LW m (Doc Text) defListItemToLaTeX (term, defs) = do@@ -639,6 +807,7 @@ removeInvalidInline x = [x] let lstNoNotes = foldr (mappend . (\x -> walkM removeInvalidInline x)) mempty lst txtNoNotes <- inlineListToLaTeX lstNoNotes+ txtNoLinksNoNotes <- inlineListToLaTeX (removeLinks lstNoNotes) -- footnotes in sections don't work (except for starred variants) -- unless you specify an optional argument: -- \section[mysec]{mysec\footnote{blah}}@@ -676,23 +845,22 @@ 5 -> "subparagraph" _ -> "" inQuote <- gets stInQuote- let prefix = if inQuote && level' >= 4+ let prefix = if inQuote then text "\\mbox{}%" -- needed for \paragraph, \subparagraph in quote environment -- see http://tex.stackexchange.com/questions/169830/ else empty lab <- labelFor ident let star = if unnumbered then text "*" else empty- let stuffing = star <> optional <> contents- stuffing' <- hypertarget True ident $- text ('\\':sectionType) <> stuffing <> lab+ let title = star <> optional <> contents return $ if level' > 5 then txt- else prefix $$ stuffing'+ else prefix+ $$ text ('\\':sectionType) <> title <> lab $$ if unnumbered && not unlisted then "\\addcontentsline{toc}" <> braces (text sectionType) <>- braces txtNoNotes+ braces txtNoLinksNoNotes else empty -- | Convert list of inline elements to LaTeX.@@ -700,31 +868,47 @@ => [Inline] -- ^ Inlines to convert -> LW m (Doc Text) inlineListToLaTeX lst = hcat <$>- mapM inlineToLaTeX (fixLineInitialSpaces . fixInitialLineBreaks $ lst)+ mapM inlineToLaTeX+ (addKerns . fixLineInitialSpaces . fixInitialLineBreaks $ lst) -- nonbreaking spaces (~) in LaTeX don't work after line breaks,- -- so we turn nbsps after hard breaks to \hspace commands.- -- this is mostly used in verse.+ -- so we insert a strut: this is mostly used in verse. where fixLineInitialSpaces [] = [] fixLineInitialSpaces (LineBreak : Str s : xs) | Just ('\160', _) <- T.uncons s- = LineBreak : fixNbsps s <> fixLineInitialSpaces xs+ = LineBreak : RawInline "latex" "\\strut " : Str s+ : fixLineInitialSpaces xs fixLineInitialSpaces (x:xs) = x : fixLineInitialSpaces xs- fixNbsps s = let (ys,zs) = T.span (=='\160') s- in replicate (T.length ys) hspace <> [Str zs]- hspace = RawInline "latex" "\\hspace*{0.333em}" -- We need \hfill\break for a line break at the start -- of a paragraph. See #5591. fixInitialLineBreaks (LineBreak:xs) = RawInline (Format "latex") "\\hfill\\break\n" : fixInitialLineBreaks xs fixInitialLineBreaks xs = xs+ addKerns [] = []+ addKerns (Str s : q@Quoted{} : rest)+ | isQuote (T.takeEnd 1 s) =+ Str s : RawInline (Format "latex") "\\," : addKerns (q:rest)+ addKerns (q@Quoted{} : Str s : rest)+ | isQuote (T.take 1 s) =+ q : RawInline (Format "latex") "\\," : addKerns (Str s : rest)+ addKerns (x:xs) = x : addKerns xs+ isQuote "\"" = True+ isQuote "'" = True+ isQuote "\x2018" = True+ isQuote "\x2019" = True+ isQuote "\x201C" = True+ isQuote "\x201D" = True+ isQuote _ = False -- | Convert inline element to LaTeX inlineToLaTeX :: PandocMonad m => Inline -- ^ Inline to convert -> LW m (Doc Text)+inlineToLaTeX (Span ("",["mark"],[]) lst) = do+ modify $ \st -> st{ stStrikeout = True } -- this gives us the soul package+ inCmd "hl" <$> inSoulCommand (inlineListToLaTeX lst) inlineToLaTeX (Span (id',classes,kvs) ils) = do- linkAnchor <- hypertarget False id' empty+ linkAnchor <- hypertarget id' lang <- toLang $ lookup "lang" kvs let classToCmd "csl-no-emph" = Just "textup" classToCmd "csl-no-strong" = Just "textnormal"@@ -738,10 +922,9 @@ kvToCmd ("dir","ltr") = Just "LR" kvToCmd _ = Nothing langCmds =- case lang of- Just lng -> let l = toBabel lng- in ["foreignlanguage{" <> l <> "}"]- Nothing -> []+ case lang >>= toBabel of+ Just l -> ["foreignlanguage{" <> l <> "}"]+ Nothing -> [] let cmds = mapMaybe classToCmd classes ++ mapMaybe kvToCmd kvs ++ langCmds contents <- inlineListToLaTeX ils return $@@ -754,23 +937,18 @@ else id) $ (if T.null id' then empty- else "\\protect" <> linkAnchor) <>+ else linkAnchor) <> (if null cmds then braces contents else foldr inCmd contents cmds) inlineToLaTeX (Emph lst) = inCmd "emph" <$> inlineListToLaTeX lst inlineToLaTeX (Underline lst) = do- modify $ \st -> st{ stStrikeout = True } -- this gives us the ulem package- inCmd "uline" <$> inlineListToLaTeX lst+ modify $ \st -> st{ stStrikeout = True } -- this gives us the soul package+ inCmd "ul" <$> inSoulCommand (inlineListToLaTeX lst) inlineToLaTeX (Strong lst) = inCmd "textbf" <$> inlineListToLaTeX lst inlineToLaTeX (Strikeout lst) = do- -- we need to protect VERB in an mbox or we get an error- -- see #1294- -- with regular texttt we don't get an error, but we get- -- incorrect results if there is a space, see #5529- contents <- inlineListToLaTeX $ walk (concatMap protectCode) lst modify $ \s -> s{ stStrikeout = True }- return $ inCmd "sout" contents+ inCmd "st" <$> inSoulCommand (inlineListToLaTeX lst) inlineToLaTeX (Superscript lst) = inCmd "textsuperscript" <$> inlineListToLaTeX lst inlineToLaTeX (Subscript lst) =@@ -778,17 +956,21 @@ inlineToLaTeX (SmallCaps lst) = inCmd "textsc"<$> inlineListToLaTeX lst inlineToLaTeX (Cite cits lst) = do- st <- get- let opts = stOptions st- case writerCiteMethod opts of- Natbib -> citationsToNatbib inlineListToLaTeX cits- Biblatex -> citationsToBiblatex inlineListToLaTeX cits- _ -> inlineListToLaTeX lst+ opts <- gets stOptions+ modify $ \st -> st{ stInCite = True }+ res <- case writerCiteMethod opts of+ Natbib -> citationsToNatbib inlineListToLaTeX cits+ Biblatex -> citationsToBiblatex inlineListToLaTeX cits+ _ -> inlineListToLaTeX lst+ modify $ \st -> st{ stInCite = False }+ pure res inlineToLaTeX (Code (_,classes,kvs) str) = do opts <- gets stOptions inHeading <- gets stInHeading inItem <- gets stInItem+ inSoul <- gets stInSoulCommand+ inCaption <- gets stInCaption let listingsCode = do let listingsopts = (case getListingsLanguage classes of Just l -> (("language", mbBraced l):)@@ -837,12 +1019,26 @@ rawCode Right h -> modify (\st -> st{ stHighlighting = True }) >> return (text (T.unpack h))- case () of+ -- for soul commands we need to protect VERB in an mbox or we get an error+ -- (see #1294). with regular texttt we don't get an error, but we get+ -- incorrect results if there is a space (see #5529).+ let inMbox x = "\\mbox" <> braces x++ -- for captions we need to protect VERB with \protect (see #6821)+ let protect x = "\\protect" <> x++ let optionalProtect = case () of _ | inSoul -> inMbox+ | inCaption -> protect+ | otherwise -> id+ optionalProtect <$>+ case writerHighlightMethod opts of _ | inHeading || inItem -> rawCode -- see #5574- | writerListings opts -> listingsCode- | isJust (writerHighlightStyle opts) && not (null classes)+ IdiomaticHighlighting -> listingsCode+ Skylighting _ | not (null classes) -> highlightCode- | otherwise -> rawCode+ DefaultHighlighting | not (null classes)+ -> highlightCode+ _noHighlighting -> rawCode inlineToLaTeX (Quoted qt lst) = do contents <- inlineListToLaTeX lst csquotes <- liftM stCsquotes get@@ -852,13 +1048,21 @@ DoubleQuote -> "\\enquote" <> braces contents SingleQuote -> "\\enquote*" <> braces contents else do- let s1 = if not (null lst) && isQuoted (head lst)- then "\\,"- else empty- let s2 = if not (null lst) && isQuoted (last lst)- then "\\,"- else empty- let inner = s1 <> contents <> s2+ let endsWithQuote xs =+ case reverse xs of+ Quoted{}:_ -> True+ Span _ ys : _ -> endsWithQuote ys+ Str s:_ -> T.takeEnd 1 s == "'"+ _ -> False+ let beginsWithQuote xs =+ case xs of+ Quoted{}:_ -> True+ Span _ ys : _ -> beginsWithQuote ys+ Str s:_ -> T.take 1 s == "`"+ _ -> False+ let inner = (if beginsWithQuote lst then "\\," else mempty)+ <> contents+ <> (if endsWithQuote lst then "\\," else mempty) return $ case qt of DoubleQuote -> if isEnabled Ext_smart opts@@ -868,19 +1072,32 @@ if isEnabled Ext_smart opts then char '`' <> inner <> char '\'' else char '\x2018' <> inner <> char '\x2019'- where- isQuoted (Span _ (x:_)) = isQuoted x- isQuoted (Quoted _ _) = True- isQuoted _ = False 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- return $ "\\(" <> literal (handleMathComment str) <> "\\)"+ inSoul <- gets stInSoulCommand+ let contents = literal (handleMathComment str)+ when (needsCancel str) $ modify $ \st -> st{ stCancel = True }+ return $+ if inSoul -- #9597+ then "$" <> contents <> "$"+ else "\\(" <> contents <> "\\)" inlineToLaTeX (Math DisplayMath str) = do setEmptyLine False- return $ "\\[" <> literal (handleMathComment str) <> "\\]"+ inSoul <- gets stInSoulCommand+ let contents = literal (handleMathComment str)+ when (needsCancel str) $ modify $ \st -> st{ stCancel = True }+ return $+ if inSoul -- # 9597+ then "$$" <> contents <> "$$"+ else "\\[" <> contents <> "\\]" inlineToLaTeX il@(RawInline f str) = do beamer <- gets stBeamer if f == Format "latex" || f == Format "tex" ||@@ -907,36 +1124,57 @@ Just ('#', ident) -> do contents <- inlineListToLaTeX txt lab <- toLabel ident- return $ text "\\protect\\hyperlink" <> braces (literal lab) <> braces contents+ inCite <- gets stInCite+ beamer <- gets stBeamer+ return $+ if inCite && "#ref-" `T.isPrefixOf` src+ then "\\citeproc" <> braces (literal lab) <> braces contents+ else if beamer+ then "\\hyperlink" <> braces (literal lab) <> braces contents+ else "\\hyperref" <> brackets (literal lab) <> braces contents _ -> case txt of- [Str x] | unEscapeString (T.unpack x) == unEscapeString (T.unpack src) -> -- autolink+ -- For soul sommands we need to protect \url and \href in an mbox or+ -- we get an error (see #9366)+ [Str x] | T.all isAscii x -- see #8802+ , unEscapeString (T.unpack x) ==+ unEscapeString (T.unpack src) -> -- autolink do modify $ \s -> s{ stUrl = True } src' <- stringToLaTeX URLString (escapeURI src)- return $ literal $ "\\url{" <> src' <> "}"+ protectInMboxIfInSoul $ literal $ "\\url{" <> src' <> "}" [Str x] | Just rest <- T.stripPrefix "mailto:" src, unEscapeString (T.unpack x) == unEscapeString (T.unpack rest) -> -- email autolink do modify $ \s -> s{ stUrl = True } src' <- stringToLaTeX URLString (escapeURI src) contents <- inlineListToLaTeX txt- return $ "\\href" <> braces (literal src') <>+ protectInMboxIfInSoul $ "\\href" <> braces (literal src') <> braces ("\\nolinkurl" <> braces contents) _ -> do contents <- inlineListToLaTeX txt src' <- stringToLaTeX URLString (escapeURI src)- return $ literal ("\\href{" <> src' <> "}{") <>- contents <> char '}')+ protectInMboxIfInSoul $ literal ("\\href{" <> src' <> "}{") <>+ contents <> char '}') >>= (if T.null id' then return else \x -> do- linkAnchor <- hypertarget False id' x- return ("\\protect" <> linkAnchor))+ linkAnchor <- hypertarget id'+ return (linkAnchor <> x)) inlineToLaTeX il@(Image _ _ (src, _)) | Just _ <- T.stripPrefix "data:" src = do report $ InlineNotRendered il return empty-inlineToLaTeX (Image attr@(_,_,kvs) _ (source, _)) = do+inlineToLaTeX (Image attr@(_,_,kvs) description (source, _)) = do setEmptyLine False- modify $ \s -> s{ stGraphics = True }+ let isSVG = ".svg" `T.isSuffixOf` source || ".SVG" `T.isSuffixOf` source+ modify $ \s -> s{ stGraphics = True+ , stSVG = stSVG s || isSVG } opts <- gets stOptions+ mbalt <- if isSVG+ then pure Nothing+ else case lookup "alt" kvs of+ Just x -> Just <$> stringToLaTeX TextString x+ Nothing+ | null description -> pure Nothing+ | otherwise -> Just <$> stringToLaTeX TextString+ (stringify description) let showDim dir = let d = text (show dir) <> "=" in case dimension dir attr of Just (Pixel a) ->@@ -944,7 +1182,7 @@ Just (Percent a) -> [d <> literal (showFl (a / 100)) <> case dir of- Width -> "\\textwidth"+ Width -> "\\linewidth" Height -> "\\textheight" ] Just dim ->@@ -952,14 +1190,18 @@ Nothing -> case dir of Width | isJust (dimension Height attr) ->- [d <> "\\textwidth"]+ [d <> "\\linewidth"] Height | isJust (dimension Width attr) -> [d <> "\\textheight"] _ -> [] optList = showDim Width <> showDim Height <>+ (case (dimension Height attr, dimension Width attr) of+ (Just _, Just _) -> []+ _ -> ["keepaspectratio"]) <> maybe [] (\x -> ["page=" <> literal x]) (lookup "page" kvs) <> maybe [] (\x -> ["trim=" <> literal x]) (lookup "trim" kvs) <>- maybe [] (\_ -> ["clip"]) (lookup "clip" kvs)+ maybe [] (\x -> ["alt=" <> braces (literal x)]) mbalt <>+ maybe [] (const ["clip"]) (lookup "clip" kvs) options = if null optList then empty else brackets $ mconcat (intersperse "," optList)@@ -969,8 +1211,12 @@ source'' <- stringToLaTeX URLString source' inHeading <- gets stInHeading return $- (if inHeading then "\\protect\\includegraphics" else "\\includegraphics") <>- options <> braces (literal source'')+ (if inHeading then "\\protect" else "") <>+ (case dimension Width attr `mplus` dimension Height attr of+ Just _ -> id+ Nothing -> ("\\pandocbounded" <>) . braces)+ ((if isSVG then "\\includesvg" else "\\includegraphics") <>+ options <> braces (literal source'')) inlineToLaTeX (Note contents) = do setEmptyLine False externalNotes <- gets stExternalNotes@@ -983,8 +1229,12 @@ let noteContents = nest 2 contents' <> optnl beamer <- gets stBeamer -- in beamer slides, display footnote from current overlay forward+ -- and ensure that the note is on the frame, not e.g. the column (#5769, #5954)+ incremental <- gets stIncremental let beamerMark = if beamer- then text "<.->"+ then if incremental+ then text "<.->[frame]"+ else text "<\\value{beamerpauses}->[frame]" else empty if externalNotes then do@@ -1004,11 +1254,6 @@ _ -> s <> "\n" _ -> s -protectCode :: Inline -> [Inline]-protectCode x@(Code _ _) = [ltx "\\mbox{" , x , ltx "}"]- where ltx = RawInline (Format "latex")-protectCode x = [x]- setEmptyLine :: PandocMonad m => Bool -> LW m () setEmptyLine b = modify $ \st -> st{ stEmptyLine = b } @@ -1028,3 +1273,239 @@ -- Look up a key in an attribute and give a list of its values lookKey :: Text -> Attr -> [Text] lookKey key (_,_,kvs) = maybe [] T.words $ lookup key kvs++-- soul doesn't like \(..\) delimiters, so we change these to $ (#9597)+-- when processing their contents.+inSoulCommand :: PandocMonad m => LW m a -> LW m a+inSoulCommand pa = do+ oldInSoulCommand <- gets stInSoulCommand+ modify $ \st -> st{ stInSoulCommand = True }+ result <- pa+ modify $ \st -> st{ stInSoulCommand = oldInSoulCommand }+ pure result++-- Inside soul commands some commands need to be protected in an mbox+-- or we get an error (e.g. see #1294)+protectInMboxIfInSoul :: (PandocMonad m, HasChars a) => Doc a -> LW m (Doc a)+protectInMboxIfInSoul command = do+ inSoul <- gets stInSoulCommand+ return $ if inSoul+ then "\\mbox" <> braces command+ else command++-- Babel languages with a .ldf that works well with all engines (see #8283).+-- We follow the guidance from the Babel documentation:+-- "In general, you should do this for European languages written in Latin+-- and Cyrillic scripts, as well as for Vietnamese."+ldfLanguages :: [Text]+ldfLanguages =+ [ "magyar"+ , "croatian"+ , "ngerman"+ , "germanb"+ , "german"+ , "austrian"+ , "ngermanb"+ , "naustrian"+ , "nswissgerman"+ , "swissgerman"+ , "italian"+ , "greek"+ , "azerbaijani"+ , "american"+ , "newzealand"+ , "UKenglish"+ , "USenglish"+ , "australian"+ , "british"+ , "canadian"+ , "english"+ , "bahasa"+ , "slovak"+ , "finnish"+ , "occitan"+ , "swedish"+ , "brazil"+ , "portuguese"+ , "portuges"+ , "brazilian"+ , "spanish"+ , "norwegian"+ , "norsk"+ , "nynorsk"+ , "bulgarian"+ , "breton"+ , "belarusian"+ , "piedmontese"+ , "esperanto"+ , "lithuanian"+ , "ukraineb"+ , "scottishgaelic"+ , "scottish"+ , "dutch"+ , "afrikaans"+ , "czech"+ , "serbian"+ , "latvian"+ , "catalan"+ , "basque"+ , "albanian"+ , "irish"+ , "serbianc"+ , "interlingua"+ , "bosnian"+ , "friulan"+ , "romanian"+ , "icelandic"+ , "classiclatin"+ , "ecclesiasticlatin"+ , "medievallatin"+ , "latin"+ , "georgian"+ , "macedonian"+ , "welsh"+ , "vietnamese"+ , "romansh"+ , "danish"+ , "lsorbian"+ , "usorbian"+ , "polish-compat"+ , "polish"+ , "estonian"+ , "french"+ , "frenchb"+ , "canadien"+ , "acadian"+ , "francais"+ , "turkish"+ , "hindi"+ , "northernsami"+ , "samin"+ , "russianb"+ , "galician"+ , "slovene"+ ]++isMathEnv :: Text -> Bool+isMathEnv t =+ case T.stripPrefix "\\begin{" (T.dropWhile isSpaceChar t) of+ Nothing -> False+ Just t' -> T.takeWhile (/= '}') t' `elem`+ [ "align", "align*"+ , "flalign", "flalign*"+ , "alignat", "alignat*"+ , "dmath", "dmath*"+ , "dgroup", "dgroup*"+ , "darray", "darray*"+ , "gather", "gather*"+ , "multline", "multline*"+ , "subequations"+ , "equation", "equation*"+ , "eqnarray"+ , "displaymath"+ ]+ where+ isSpaceChar '\n' = True+ isSpaceChar '\r' = True+ isSpaceChar '\t' = True+ isSpaceChar ' ' = True+ isSpaceChar _ = False++-- True if the math needs the cancel package+needsCancel :: Text -> Bool+needsCancel t =+ case A.parseOnly pCancel t of+ Right True -> True+ _ -> False+ where+ pCancel = (False <$ A.endOfInput) <|> do+ c <- A.anyChar+ case c of+ '\\' -> do+ x <- A.takeWhile isLetter+ if x == "cancel" || x == "xcancel" || x == "bcancel"+ then return True+ else pCancel+ _ -> pCancel++-- PDF standard support for DocumentMetadata++-- | PDF standards supported by LaTeX's DocumentMetadata+-- See: https://github.com/latex3/latex2e documentmetadata-support.dtx+latexSupportedStandards :: Set.Set Text+latexSupportedStandards = Set.fromList+ [ -- PDF/A standards (note: a-1a is NOT supported by LaTeX, only a-1b)+ "a-1b", "a-2a", "a-2b", "a-2u", "a-3a", "a-3b", "a-3u"+ , "a-4", "a-4e", "a-4f"+ -- PDF/X standards+ , "x-4", "x-4p", "x-5g", "x-5n", "x-5pg", "x-6", "x-6n", "x-6p"+ -- PDF/UA standards+ , "ua-1", "ua-2"+ ]++-- | Standards that require PDF tagging (document structure)+-- PDF/A level "a" variants and PDF/UA require tagged structure+taggingRequiredStandards :: Set.Set Text+taggingRequiredStandards = Set.fromList+ ["a-2a", "a-3a", "ua-1", "ua-2"]++-- | Valid PDF versions for DocumentMetadata+validPdfVersions :: Set.Set Text+validPdfVersions = Set.fromList+ ["1.4", "1.5", "1.6", "1.7", "2.0"]++-- | PDF version required by each standard+-- LaTeX defaults to PDF 2.0 with \DocumentMetadata, but some standards+-- have maximum version requirements that are incompatible with 2.0+standardRequiredVersion :: M.Map Text Text+standardRequiredVersion = M.fromList+ [ ("a-1b", "1.4") -- PDF/A-1 requires exactly PDF 1.4+ -- PDF/A-2 and PDF/A-3 require 1.7; must set explicitly since LaTeX defaults to 2.0+ , ("a-2a", "1.7"), ("a-2b", "1.7"), ("a-2u", "1.7")+ , ("a-3a", "1.7"), ("a-3b", "1.7"), ("a-3u", "1.7")+ -- PDF/A-4, PDF/UA-1, PDF/UA-2 work with PDF 2.0 (the default)+ ]++-- | Normalize a PDF standard string: lowercase, strip "pdf" prefix+normalizePdfStandard :: Text -> Text+normalizePdfStandard t =+ let lower = T.toLower t+ in case T.stripPrefix "pdf" lower of+ Just rest -> T.dropWhile (`elem` ['-', '/']) rest+ Nothing -> lower++-- | Normalize a PDF version string+-- Handles YAML parsing quirk where 2.0 becomes integer 2, then string "2"+normalizeVersion :: Text -> Text+normalizeVersion t+ | t == "2" = "2.0"+ | otherwise = t++-- | Check if text is a valid PDF version (after normalization)+isPdfVersion :: Text -> Bool+isPdfVersion t = Set.member (normalizeVersion t) validPdfVersions++-- | Process pdfstandard metadata, returning PDF standard settings+processPdfStandard :: PandocMonad m+ => Context Text+ -> m PdfStandard+processPdfStandard ctx = do+ let standards = fromMaybe [] $ getField "pdfstandard" ctx+ normalized = map normalizePdfStandard standards+ (versions, pdfStds) = partition isPdfVersion normalized+ validStandards = filter (`Set.member` latexSupportedStandards) pdfStds+ invalidStandards = filter (\s -> not (Set.member s latexSupportedStandards)+ && not (isPdfVersion s)) pdfStds+ needsTagging = any (`Set.member` taggingRequiredStandards) validStandards+ -- Use explicit version if provided, otherwise infer from standards+ -- Apply normalizeVersion to handle YAML parsing "2" -> "2.0"+ explicitVersion = normalizeVersion <$> listToMaybe versions+ inferredVersion = listToMaybe $ mapMaybe (`M.lookup` standardRequiredVersion) validStandards+ version = explicitVersion <|> inferredVersion+ -- Warn about unsupported standards+ mapM_ (report . UnsupportedPdfStandard) invalidStandards+ return PdfStandard+ { pdfStandards = validStandards+ , pdfVersion = version+ , pdfTagging = needsTagging+ }
@@ -1,6 +1,6 @@ {- | Module : Text.Pandoc.Writers.LaTeX.Caption- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -23,16 +23,23 @@ import Text.Pandoc.Walk import Text.Pandoc.Writers.LaTeX.Notes (notesToLaTeX) import Text.Pandoc.Writers.LaTeX.Types- ( LW, WriterState (stExternalNotes, stNotes) )+ ( LW, WriterState (stExternalNotes, stNotes, stInCaption) ) ++-- | Produces the components of a LaTeX 'caption' command. Returns a triple+-- containing the caption text, the short caption for the list of+-- figures/tables, and the footnote definitions. getCaption :: PandocMonad m- => ([Inline] -> LW m (Doc Text))- -> Bool -> [Inline]+ => ([Inline] -> LW m (Doc Text)) -- ^ inlines converter+ -> Bool -- ^ whether to extract notes+ -> Caption -> LW m (Doc Text, Doc Text, Doc Text)-getCaption inlineListToLaTeX externalNotes txt = do+getCaption inlineListToLaTeX externalNotes (Caption maybeShort long) = do+ modify $ \st -> st{ stInCaption = True }+ let long' = blocksToInlines long oldExternalNotes <- gets stExternalNotes modify $ \st -> st{ stExternalNotes = externalNotes, stNotes = [] }- capt <- inlineListToLaTeX txt+ capt <- inlineListToLaTeX long' footnotes <- if externalNotes then notesToLaTeX <$> gets stNotes else return empty@@ -41,7 +48,11 @@ let getNote (Note _) = Any True getNote _ = Any False let hasNotes = getAny . query getNote- captForLof <- if hasNotes txt- then brackets <$> inlineListToLaTeX (walk deNote txt)- else return empty+ let toShortCapt = fmap brackets . inlineListToLaTeX . walk deNote+ captForLof <- case maybeShort of+ Nothing -> if hasNotes long'+ then toShortCapt long'+ else return empty+ Just short -> toShortCapt short+ modify $ \st -> st{ stInCaption = False } return (capt, captForLof, footnotes)
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.LaTeX.Citation- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -15,14 +15,22 @@ import Data.Text (Text) import Data.Char (isPunctuation)+import Control.Monad.State (gets)+import Data.Maybe (fromMaybe) import qualified Data.Text as T+import Text.Pandoc.Options import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Definition-import Data.List (foldl')+import qualified Data.List as L import Text.DocLayout (Doc, brackets, empty, (<+>), text, isEmpty, literal, braces) import Text.Pandoc.Walk-import Text.Pandoc.Writers.LaTeX.Types ( LW )+import Text.Pandoc.Writers.LaTeX.Types ( LW, WriterState(stLang, stOptions) )+import Text.Pandoc.Citeproc.Locator (parseLocator, LocatorInfo(..),+ toLocatorMap)+import Citeproc.Types (Lang(..))+import Citeproc.Locale (getLocale)+import Safe (headMay, lastMay) citationsToNatbib :: PandocMonad m => ([Inline] -> LW m (Doc Text))@@ -43,16 +51,17 @@ NormalCitation -> "citep" citationsToNatbib inlineListToLaTeX cits- | noPrefix (tail cits) && noSuffix (init cits) && ismode NormalCitation cits+ | noInnerPrefix cits && noInnerSuffix cits && ismode NormalCitation cits = citeCommand inlineListToLaTeX "citep" p s ks where- noPrefix = all (null . citationPrefix)- noSuffix = all (null . citationSuffix)+ noInnerPrefix [] = True+ noInnerPrefix (_:xs) = all (null . citationPrefix) xs+ noInnerSuffix [] = True+ noInnerSuffix [_] = True+ noInnerSuffix (x:xs) = null (citationSuffix x) && noInnerSuffix xs ismode m = all ((==) m . citationMode)- p = citationPrefix $- head cits- s = citationSuffix $- last cits+ p = maybe mempty citationPrefix $ headMay cits+ s = maybe mempty citationSuffix $ lastMay cits ks = T.intercalate ", " $ map citationId cits citationsToNatbib inlineListToLaTeX (c:cs)@@ -64,7 +73,7 @@ citationsToNatbib inlineListToLaTeX cits = do cits' <- mapM convertOne cits- return $ text "\\citetext{" <> foldl' combineTwo empty cits' <> text "}"+ return $ text "\\citetext{" <> L.foldl' combineTwo empty cits' <> text "}" where citeCommand' = citeCommand inlineListToLaTeX combineTwo a b | isEmpty a = b@@ -101,11 +110,14 @@ -> LW m (Doc Text) citeArgumentsList _inlineListToLaTeX (CiteGroup _ _ []) = return empty citeArgumentsList inlineListToLaTeX (CiteGroup pfxs sfxs ids) = do- pdoc <- inlineListToLaTeX pfxs- sdoc <- inlineListToLaTeX sfxs'- return $ optargs pdoc sdoc <>- braces (literal (T.intercalate "," (reverse ids)))- where sfxs' = stripLocatorBraces $ case sfxs of+ opts <- gets stOptions+ mblang <- gets stLang+ let sfxs' = (case writerCiteMethod opts of+ -- In biblatex, the label p. or pp. can be omitted;+ -- ranges are treated as page ranges by default. See #9275.+ Biblatex -> removePageLabel mblang+ _ -> id) $+ stripLocatorBraces $ case sfxs of (Str t : r) -> case T.uncons t of Just (x, xs) | T.null xs@@ -113,10 +125,14 @@ | isPunctuation x -> Str xs : r _ -> sfxs _ -> sfxs- optargs pdoc sdoc = case (isEmpty pdoc, isEmpty sdoc) of+ optargs pdoc sdoc = case (isEmpty pdoc, isEmpty sdoc) of (True, True ) -> empty (True, False) -> brackets sdoc (_ , _ ) -> brackets pdoc <> brackets sdoc+ pdoc <- inlineListToLaTeX pfxs+ sdoc <- inlineListToLaTeX sfxs'+ return $ optargs pdoc sdoc <>+ braces (literal (T.intercalate "," (reverse ids))) citeArguments :: PandocMonad m => ([Inline] -> LW m (Doc Text))@@ -166,7 +182,7 @@ NormalCitation -> "\\autocites" groups <- mapM (citeArgumentsList inlineListToLaTeX)- (reverse (foldl' grouper [] (c:cs)))+ (reverse (L.foldl' grouper [] (c:cs))) return $ text cmd <> mconcat groups @@ -180,3 +196,14 @@ cid = citationId cit citationsToBiblatex _ _ = return empty++removePageLabel :: Maybe Lang -> [Inline] -> [Inline]+removePageLabel mblang ils =+ case mbLocinfo of+ Just locinfo | locatorLabel locinfo == "page"+ -> Str (locatorLoc locinfo) : ils'+ _ -> ils+ where+ (mbLocinfo, ils') = parseLocator (toLocatorMap locale) ils+ lang = fromMaybe (Lang "en" Nothing (Just "US") [] [] []) mblang+ locale = either mempty id $ getLocale lang
@@ -2,7 +2,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Text.Pandoc.Writers.LaTeX.Lang- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -21,125 +21,132 @@ -- http://mirrors.ctan.org/macros/latex/required/babel/base/babel.pdf -- List of supported languages (slightly outdated): -- http://tug.ctan.org/language/hyph-utf8/doc/generic/hyph-utf8/hyphenation.pdf-toBabel :: Lang -> Text+toBabel :: Lang -> Maybe Text toBabel (Lang "de" _ (Just "AT") vars _ _)- | "1901" `elem` vars = "austrian"- | otherwise = "naustrian"+ | "1901" `elem` vars = Just "austrian"+ | otherwise = Just "naustrian" toBabel (Lang "de" _ (Just "CH") vars _ _)- | "1901" `elem` vars = "swissgerman"- | otherwise = "nswissgerman"+ | "1901" `elem` vars = Just "swissgerman"+ | otherwise = Just "nswissgerman" toBabel (Lang "de" _ _ vars _ _)- | "1901" `elem` vars = "german"- | otherwise = "ngerman"-toBabel (Lang "dsb" _ _ _ _ _) = "lowersorbian"+ | "1901" `elem` vars = Just "german"+ | otherwise = Just "ngerman"+toBabel (Lang "dsb" _ _ _ _ _) = Just "lowersorbian" toBabel (Lang "el" _ _ vars _ _)- | "polyton" `elem` vars = "polutonikogreek"-toBabel (Lang "en" _ (Just "AU") _ _ _) = "australian"-toBabel (Lang "en" _ (Just "CA") _ _ _) = "canadian"-toBabel (Lang "en" _ (Just "GB") _ _ _) = "british"-toBabel (Lang "en" _ (Just "NZ") _ _ _) = "newzealand"-toBabel (Lang "en" _ (Just "UK") _ _ _) = "british"-toBabel (Lang "en" _ (Just "US") _ _ _) = "american"-toBabel (Lang "fr" _ (Just "CA") _ _ _) = "canadien"+ | "polyton" `elem` vars = Just "polytonicgreek"+toBabel (Lang "en" _ (Just "AU") _ _ _) = Just "australian"+toBabel (Lang "en" _ (Just "CA") _ _ _) = Just "canadian"+toBabel (Lang "en" _ (Just "GB") _ _ _) = Just "british"+toBabel (Lang "en" _ (Just "NZ") _ _ _) = Just "newzealand"+toBabel (Lang "en" _ (Just "UK") _ _ _) = Just "british"+toBabel (Lang "en" _ (Just "US") _ _ _) = Just "american"+toBabel (Lang "fr" _ (Just "CA") _ _ _) = Just "french" toBabel (Lang "fra" _ _ vars _ _)- | "aca" `elem` vars = "acadian"-toBabel (Lang "grc" _ _ _ _ _) = "ancientgreek"-toBabel (Lang "hsb" _ _ _ _ _) = "uppersorbian"+ | "aca" `elem` vars = Just "acadian"+toBabel (Lang "grc" _ _ _ _ _) = Just "ancientgreek"+toBabel (Lang "hsb" _ _ _ _ _) = Just "uppersorbian" toBabel (Lang "la" _ _ vars _ _)- | "x-classic" `elem` vars = "classiclatin"-toBabel (Lang "pt" _ (Just "BR") _ _ _) = "brazilian"-toBabel (Lang "sl" _ _ _ _ _) = "slovene"-toBabel x = commonFromBcp47 x+ | "x-classic" `elem` vars = Just "classiclatin"+toBabel (Lang "pt" _ (Just "BR") _ _ _) = Just "brazilian"+toBabel (Lang "sl" _ _ _ _ _) = Just "slovene"+toBabel (Lang "zh" (Just "Hant") (Just "HK") _ _ _) = Just "chinese-hant-hk"+toBabel (Lang "zh" (Just "Hant") (Just "MO") _ _ _) = Just "chinese-hant-mo"+toBabel (Lang "zh" (Just "Hans") (Just "HK") _ _ _) = Just "chinese-hans-hk"+toBabel (Lang "zh" (Just "Hans") (Just "MO") _ _ _) = Just "chinese-hans-mo"+toBabel (Lang "zh" (Just "Hans") _ _ _ _) = Just "chinese-hans"+toBabel (Lang "zh" (Just "Hant") _ _ _ _) = Just "chinese-hant"+toBabel (Lang "zh" _ _ _ _ _) = Just "chinese"+toBabel x = commonFromBcp47 x -- Takes a list of the constituents of a BCP47 language code -- and converts it to a string shared by Babel and Polyglossia. -- https://tools.ietf.org/html/bcp47#section-2.1-commonFromBcp47 :: Lang -> Text-commonFromBcp47 (Lang "sr" (Just "Cyrl") _ _ _ _) = "serbianc"+commonFromBcp47 :: Lang -> Maybe Text+commonFromBcp47 (Lang "sr" (Just "Cyrl") _ _ _ _) = Just "serbianc" commonFromBcp47 (Lang "zh" (Just "Latn") _ vars _ _)- | "pinyin" `elem` vars = "pinyin"+ | "pinyin" `elem` vars = Just "pinyin" commonFromBcp47 (Lang l _ _ _ _ _) = fromIso l where- fromIso "af" = "afrikaans"- fromIso "am" = "amharic"- fromIso "ar" = "arabic"- fromIso "as" = "assamese"- fromIso "ast" = "asturian"- fromIso "bg" = "bulgarian"- fromIso "bn" = "bengali"- fromIso "bo" = "tibetan"- fromIso "br" = "breton"- fromIso "ca" = "catalan"- fromIso "cy" = "welsh"- fromIso "cs" = "czech"- fromIso "cop" = "coptic"- fromIso "da" = "danish"- fromIso "dv" = "divehi"- fromIso "el" = "greek"- fromIso "en" = "english"- fromIso "eo" = "esperanto"- fromIso "es" = "spanish"- fromIso "et" = "estonian"- fromIso "eu" = "basque"- fromIso "fa" = "farsi"- fromIso "fi" = "finnish"- fromIso "fr" = "french"- fromIso "fur" = "friulan"- fromIso "ga" = "irish"- fromIso "gd" = "scottish"- fromIso "gez" = "ethiopic"- fromIso "gl" = "galician"- fromIso "gu" = "gujarati"- fromIso "he" = "hebrew"- fromIso "hi" = "hindi"- fromIso "hr" = "croatian"- fromIso "hu" = "magyar"- fromIso "hy" = "armenian"- fromIso "ia" = "interlingua"- fromIso "id" = "indonesian"- fromIso "ie" = "interlingua"- fromIso "is" = "icelandic"- fromIso "it" = "italian"- fromIso "ja" = "japanese"- fromIso "km" = "khmer"- fromIso "kmr" = "kurmanji"- fromIso "kn" = "kannada"- fromIso "ko" = "korean"- fromIso "la" = "latin"- fromIso "lo" = "lao"- fromIso "lt" = "lithuanian"- fromIso "lv" = "latvian"- fromIso "ml" = "malayalam"- fromIso "mn" = "mongolian"- fromIso "mr" = "marathi"- fromIso "nb" = "norsk"- fromIso "nl" = "dutch"- fromIso "nn" = "nynorsk"- fromIso "no" = "norsk"- fromIso "nqo" = "nko"- fromIso "oc" = "occitan"- fromIso "or" = "oriya"- fromIso "pa" = "punjabi"- fromIso "pl" = "polish"- fromIso "pms" = "piedmontese"- fromIso "pt" = "portuguese"- fromIso "rm" = "romansh"- fromIso "ro" = "romanian"- fromIso "ru" = "russian"- fromIso "sa" = "sanskrit"- fromIso "se" = "samin"- fromIso "sk" = "slovak"- fromIso "sq" = "albanian"- fromIso "sr" = "serbian"- fromIso "sv" = "swedish"- fromIso "syr" = "syriac"- fromIso "ta" = "tamil"- fromIso "te" = "telugu"- fromIso "th" = "thai"- fromIso "ti" = "ethiopic"- fromIso "tk" = "turkmen"- fromIso "tr" = "turkish"- fromIso "uk" = "ukrainian"- fromIso "ur" = "urdu"- fromIso "vi" = "vietnamese"- fromIso _ = ""+ fromIso "af" = Just "afrikaans"+ fromIso "am" = Just "amharic"+ fromIso "ar" = Just "arabic"+ fromIso "as" = Just "assamese"+ fromIso "ast" = Just "asturian"+ fromIso "bg" = Just "bulgarian"+ fromIso "bn" = Just "bengali"+ fromIso "bo" = Just "tibetan"+ fromIso "br" = Just "breton"+ fromIso "ca" = Just "catalan"+ fromIso "cy" = Just "welsh"+ fromIso "cs" = Just "czech"+ fromIso "cop" = Just "coptic"+ fromIso "da" = Just "danish"+ fromIso "dv" = Just "divehi"+ fromIso "el" = Just "greek"+ fromIso "en" = Just "english"+ fromIso "eo" = Just "esperanto"+ fromIso "es" = Just "spanish"+ fromIso "et" = Just "estonian"+ fromIso "eu" = Just "basque"+ fromIso "fa" = Just "persian"+ fromIso "fi" = Just "finnish"+ fromIso "fr" = Just "french"+ fromIso "fur" = Just "friulan"+ fromIso "ga" = Just "irish"+ fromIso "gd" = Just "scottish"+ fromIso "gez" = Just "ethiopic"+ fromIso "gl" = Just "galician"+ fromIso "gu" = Just "gujarati"+ fromIso "he" = Just "hebrew"+ fromIso "hi" = Just "hindi"+ fromIso "hr" = Just "croatian"+ fromIso "hu" = Just "magyar"+ fromIso "hy" = Just "armenian"+ fromIso "ia" = Just "interlingua"+ fromIso "id" = Just "indonesian"+ fromIso "ie" = Just "interlingua"+ fromIso "is" = Just "icelandic"+ fromIso "it" = Just "italian"+ fromIso "ja" = Just "japanese"+ fromIso "km" = Just "khmer"+ fromIso "kmr" = Just "kurmanji"+ fromIso "kn" = Just "kannada"+ fromIso "ko" = Just "korean"+ fromIso "la" = Just "latin"+ fromIso "lo" = Just "lao"+ fromIso "lt" = Just "lithuanian"+ fromIso "lv" = Just "latvian"+ fromIso "ml" = Just "malayalam"+ fromIso "mn" = Just "mongolian"+ fromIso "mr" = Just "marathi"+ fromIso "nb" = Just "norsk"+ fromIso "nl" = Just "dutch"+ fromIso "nn" = Just "nynorsk"+ fromIso "no" = Just "norsk"+ fromIso "nqo" = Just "nko"+ fromIso "oc" = Just "occitan"+ fromIso "or" = Just "oriya"+ fromIso "pa" = Just "punjabi"+ fromIso "pl" = Just "polish"+ fromIso "pms" = Just "piedmontese"+ fromIso "pt" = Just "portuguese"+ fromIso "rm" = Just "romansh"+ fromIso "ro" = Just "romanian"+ fromIso "ru" = Just "russian"+ fromIso "sa" = Just "sanskrit"+ fromIso "se" = Just "samin"+ fromIso "sk" = Just "slovak"+ fromIso "sq" = Just "albanian"+ fromIso "sr" = Just "serbian"+ fromIso "sv" = Just "swedish"+ fromIso "syr" = Just "syriac"+ fromIso "ta" = Just "tamil"+ fromIso "te" = Just "telugu"+ fromIso "th" = Just "thai"+ fromIso "ti" = Just "ethiopic"+ fromIso "tk" = Just "turkmen"+ fromIso "tr" = Just "turkish"+ fromIso "uk" = Just "ukrainian"+ fromIso "ur" = Just "urdu"+ fromIso "vi" = Just "vietnamese"+ fromIso _ = Nothing
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.LaTeX.Notes- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.LaTeX.Table- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -14,7 +14,8 @@ module Text.Pandoc.Writers.LaTeX.Table ( tableToLaTeX ) where-import Control.Monad.State.Strict+import Control.Monad.State.Strict ( gets, modify )+import Control.Monad (when) import Data.List (intersperse) import qualified Data.List.NonEmpty as NonEmpty import Data.List.NonEmpty (NonEmpty ((:|)))@@ -25,18 +26,19 @@ import Text.DocLayout ( Doc, braces, cr, empty, hcat, hsep, isEmpty, literal, nest , text, vcat, ($$) )-import Text.Pandoc.Shared (blocksToInlines, splitBy, tshow)+import Text.Pandoc.Shared (splitBy, tshow) import Text.Pandoc.Walk (walk, query) import Data.Monoid (Any(..)) import Text.Pandoc.Writers.LaTeX.Caption (getCaption) import Text.Pandoc.Writers.LaTeX.Notes (notesToLaTeX) import Text.Pandoc.Writers.LaTeX.Types ( LW, WriterState (stBeamer, stExternalNotes, stInMinipage, stMultiRow- , stNotes, stTable) )+ , stNotes, stTable, stOptions) ) import Text.Pandoc.Writers.LaTeX.Util (labelFor) import Text.Printf (printf) import qualified Text.Pandoc.Builder as B import qualified Text.Pandoc.Writers.AnnotatedTable as Ann+import Text.Pandoc.Options (CaptionPosition(..), WriterOptions(..)) tableToLaTeX :: PandocMonad m => ([Inline] -> LW m (Doc Text))@@ -44,81 +46,127 @@ -> Ann.Table -> LW m (Doc Text) tableToLaTeX inlnsToLaTeX blksToLaTeX tbl = do+ opts <- gets stOptions let (Ann.Table (ident, _, _) caption specs thead tbodies tfoot) = tbl CaptionDocs capt captNotes <- captionToLaTeX inlnsToLaTeX caption ident+ let hasTopCaption = not (isEmpty capt) &&+ writerTableCaptionPosition opts == CaptionAbove+ let hasBottomCaption = not (isEmpty capt) &&+ writerTableCaptionPosition opts == CaptionBelow+ let isSimpleTable =+ all ((== ColWidthDefault) . snd) specs &&+ all (all isSimpleCell)+ (mconcat [ headRows thead+ , concatMap bodyRows tbodies+ , footRows tfoot+ ]) let removeNote (Note _) = Span ("", [], []) [] removeNote x = x let colCount = ColumnCount $ length specs- firsthead <- if isEmpty capt || isEmptyHead thead- then return empty- else ($$ text "\\endfirsthead") <$>- headToLaTeX blksToLaTeX colCount thead- head' <- if isEmptyHead thead- then return "\\toprule()"- -- avoid duplicate notes in head and firsthead:- else headToLaTeX blksToLaTeX colCount- (if isEmpty firsthead- then thead- else walk removeNote thead)- rows' <- mapM (rowToLaTeX blksToLaTeX colCount BodyCell) $- mconcat (map bodyRows tbodies) <> footRows tfoot+ -- The first head is not repeated on the following pages. If we were to just+ -- use a single head, without a separate first head, then the caption would be+ -- repeated on all pages that contain a part of the table. We avoid this by+ -- making the caption part of the first head. The downside is that we must+ -- duplicate the header rows for this.+ head' <- do+ let mkHead = headToLaTeX blksToLaTeX isSimpleTable colCount+ case (hasTopCaption, isEmptyHead thead) of+ (False, True) -> return "\\toprule\\noalign{}"+ (False, False) -> mkHead thead+ (True, True) -> return (capt <> "\\tabularnewline"+ $$ "\\toprule\\noalign{}"+ $$ "\\endfirsthead")+ (True, False) -> do+ -- avoid duplicate notes in head and firsthead:+ firsthead <- mkHead thead+ repeated <- mkHead (walk removeNote thead)+ return $ capt <> "\\tabularnewline"+ $$ firsthead+ $$ "\\endfirsthead"+ $$ repeated+ rows' <- mapM (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $+ mconcat (map bodyRows tbodies)+ lastfoot <- mapM (rowToLaTeX blksToLaTeX isSimpleTable colCount BodyCell) $+ footRows tfoot+ let foot' = (if isEmptyFoot tfoot+ then mempty+ else "\\midrule\\noalign{}" $$ vcat lastfoot)+ $$ "\\bottomrule\\noalign{}"+ $$ (if hasBottomCaption+ then "\\tabularnewline" $$ capt+ else mempty) modify $ \s -> s{ stTable = True } notes <- notesToLaTeX <$> gets stNotes+ beamer <- gets stBeamer+ let makeUnnumbered x = "{\\def\\LTcaptype{none} % do not increment counter" $$ x $$ "}" return- $ "\\begin{longtable}[]" <>- braces ("@{}" <> colDescriptors tbl <> "@{}")+ $ (if null capt then makeUnnumbered else id)+ $ "\\begin{longtable}[]" <>+ braces ("@{}" <> colDescriptors isSimpleTable tbl <> "@{}") -- the @{} removes extra space at beginning and end- $$ capt- $$ firsthead $$ head' $$ "\\endhead"- $$ vcat rows'- $$ "\\bottomrule()"+ $$ vcat+ -- Longtable is not able to detect pagebreaks in Beamer; this+ -- causes problems with the placement of the footer, so make+ -- footer and bottom rule part of the body when targeting Beamer.+ -- See issue #8638.+ (if beamer+ then [ vcat rows'+ , foot'+ ]+ else [ foot'+ , "\\endlastfoot"+ , vcat rows'+ ]) $$ "\\end{longtable}" $$ captNotes $$ notes +isSimpleCell :: Ann.Cell -> Bool+isSimpleCell (Ann.Cell _ _ (Cell _attr _align _rowspan _colspan blocks)) =+ case blocks of+ [Para _] -> not (hasLineBreak blocks)+ [Plain _] -> not (hasLineBreak blocks)+ [] -> True+ _ -> False+ where+ hasLineBreak = getAny . query isLineBreak+ isLineBreak LineBreak = Any True+ isLineBreak _ = Any False+ -- | Total number of columns in a table. newtype ColumnCount = ColumnCount Int -- | Creates column descriptors for the table.-colDescriptors :: Ann.Table -> Doc Text-colDescriptors (Ann.Table _attr _caption specs thead tbodies tfoot) =+colDescriptors :: Bool -> Ann.Table -> Doc Text+colDescriptors isSimpleTable+ (Ann.Table _attr _caption specs _thead _tbodies _tfoot) = let (aligns, widths) = unzip specs defaultWidthsOnly = all (== ColWidthDefault) widths- isSimpleTable = all (all isSimpleCell) $ mconcat- [ headRows thead- , concatMap bodyRows tbodies- , footRows tfoot- ] relativeWidths = if defaultWidthsOnly then replicate (length specs) (1 / fromIntegral (length specs)) else map toRelWidth widths- in if defaultWidthsOnly && isSimpleTable- then hcat $ map (literal . colAlign) aligns- else (cr <>) . nest 2 . vcat . map literal $- zipWith (toColDescriptor (length specs))- aligns- relativeWidths+ in if null aligns+ then "l" -- #9350, table needs at least one column spec+ else if defaultWidthsOnly && isSimpleTable+ then hcat $ map (literal . colAlign) aligns+ else (cr <>) . nest 2 . vcat . map literal $+ zipWith (toColDescriptor (length specs))+ aligns+ relativeWidths where toColDescriptor :: Int -> Alignment -> Double -> Text toColDescriptor numcols align width = T.pack $ printf- ">{%s\\arraybackslash}p{(\\columnwidth - %d\\tabcolsep) * \\real{%0.4f}}"+ ">{%s\\arraybackslash}p{(\\linewidth - %d\\tabcolsep) * \\real{%0.4f}}" (T.unpack (alignCommand align)) ((numcols - 1) * 2) width - isSimpleCell (Ann.Cell _ _ (Cell _attr _align _rowspan _colspan blocks)) =- case blocks of- [Para _] -> True- [Plain _] -> True- [] -> True- _ -> False- toRelWidth ColWidthDefault = 0 toRelWidth (ColWidth w) = w @@ -147,8 +195,7 @@ -> Caption -> Text -- ^ table identifier (label) -> LW m CaptionDocs-captionToLaTeX inlnsToLaTeX (Caption _maybeShort longCaption) ident = do- let caption = blocksToInlines longCaption+captionToLaTeX inlnsToLaTeX caption ident = do (captionText, captForLot, captNotes) <- getCaption inlnsToLaTeX False caption label <- labelFor ident return $ CaptionDocs@@ -158,31 +205,35 @@ else "\\caption" <> captForLot <> braces captionText <> label- <> "\\tabularnewline" } type BlocksWriter m = [Block] -> LW m (Doc Text) headToLaTeX :: PandocMonad m => BlocksWriter m+ -> Bool -> ColumnCount -> Ann.TableHead -> LW m (Doc Text)-headToLaTeX blocksWriter colCount (Ann.TableHead _attr headerRows) = do+headToLaTeX blocksWriter isSimpleTable+ colCount (Ann.TableHead _attr headerRows) = do rowsContents <-- mapM (rowToLaTeX blocksWriter colCount HeaderCell . headerRowCells)+ mapM (rowToLaTeX blocksWriter isSimpleTable+ colCount HeaderCell . headerRowCells) headerRows- return ("\\toprule()" $$ vcat rowsContents $$ "\\midrule()")+ return ("\\toprule\\noalign{}" $$ vcat rowsContents $$ "\\midrule\\noalign{}") -- | Converts a row of table cells into a LaTeX row. rowToLaTeX :: PandocMonad m => BlocksWriter m+ -> Bool -> ColumnCount -> CellType -> [Ann.Cell] -> LW m (Doc Text)-rowToLaTeX blocksWriter colCount celltype row = do- cellsDocs <- mapM (cellToLaTeX blocksWriter colCount celltype) (fillRow row)+rowToLaTeX blocksWriter isSimpleTable colCount celltype row = do+ cellsDocs <- mapM (cellToLaTeX blocksWriter isSimpleTable+ colCount celltype) (fillRow row) return $ hsep (intersperse "&" cellsDocs) <> " \\\\" -- | Pads row with empty cells to adjust for rowspans above this row.@@ -205,6 +256,10 @@ isEmptyHead (Ann.TableHead _attr []) = True isEmptyHead (Ann.TableHead _attr rows) = all (null . headerRowCells) rows +isEmptyFoot :: Ann.TableFoot -> Bool+isEmptyFoot (Ann.TableFoot _attr []) = True+isEmptyFoot (Ann.TableFoot _attr rows) = all (null . headerRowCells) rows+ -- | Gets all cells in a header row. headerRowCells :: Ann.HeaderRow -> [Ann.Cell] headerRowCells (Ann.HeaderRow _attr _rownum cells) = cells@@ -253,11 +308,12 @@ cellToLaTeX :: PandocMonad m => BlocksWriter m+ -> Bool -> ColumnCount -> CellType -> Ann.Cell -> LW m (Doc Text)-cellToLaTeX blockListToLaTeX colCount celltype annotatedCell = do+cellToLaTeX blockListToLaTeX isSimpleTable colCount celltype annotatedCell = do let (Ann.Cell specs colnum cell) = annotatedCell let colWidths = NonEmpty.map snd specs let hasWidths = NonEmpty.head colWidths /= ColWidthDefault@@ -302,7 +358,8 @@ let inMultiColumn x = case colspan of (ColSpan 1) -> x (ColSpan n) ->- let colDescr = multicolumnDescriptor align+ let colDescr = multicolumnDescriptor isSimpleTable+ align colWidths colCount colnum@@ -311,25 +368,36 @@ <> braces (literal colDescr) <> braces ("%\n" <> x) -- linebreak for readability+ let hasColWidths = not (all (== ColWidthDefault) colWidths)+ let aligncmd = case specAlign of+ AlignCenter -> "\\centering\\arraybackslash "+ AlignRight -> "\\raggedright\\arraybackslash "+ _ -> mempty let inMultiRow x = case rowspan of (RowSpan 1) -> x (RowSpan n) -> let nrows = literal (tshow n) in "\\multirow" <> braces nrows- <> braces "*" <> braces x+ <> braces -- width of column+ (if hasColWidths+ then "=" -- max width+ else "*") -- natural width+ <> braces (aligncmd <> x) return . inMultiColumn . inMultiRow $ result -- | Returns the width of a cell spanning @n@ columns.-multicolumnDescriptor :: Alignment+multicolumnDescriptor :: Bool+ -> Alignment -> NonEmpty ColWidth -> ColumnCount -> Ann.ColNumber -> Text-multicolumnDescriptor align+multicolumnDescriptor isSimpleTable+ align colWidths (ColumnCount numcols) (Ann.ColNumber colnum) = let toWidth = \case- ColWidthDefault -> 0+ ColWidthDefault -> (1 / fromIntegral numcols) ColWidth x -> x colspan = length colWidths width = sum $ NonEmpty.map toWidth colWidths@@ -337,13 +405,19 @@ -- no column separators at beginning of first and end of last column. skipColSep = "@{}" :: String in T.pack $- printf "%s>{%s\\arraybackslash}p{(\\columnwidth - %d\\tabcolsep) * \\real{%0.4f} + %d\\tabcolsep}%s"- (if colnum == 0 then skipColSep else "")- (T.unpack (alignCommand align))- (2 * (numcols - 1))- width- (2 * (colspan - 1))- (if colnum + colspan >= numcols then skipColSep else "")+ if isSimpleTable+ then printf "%s%s%s"+ (if colnum == 0 then skipColSep else "")+ (T.unpack (colAlign align))+ (if colnum + colspan >= numcols then skipColSep else "")++ else printf "%s>{%s\\arraybackslash}p{(\\linewidth - %d\\tabcolsep) * \\real{%0.4f} + %d\\tabcolsep}%s"+ (if colnum == 0 then skipColSep else "")+ (T.unpack (alignCommand align))+ (2 * (numcols - 1))+ width+ (2 * (colspan - 1))+ (if colnum + colspan >= numcols then skipColSep else "") -- | Perform a conversion, assuming that the context is a minipage. inMinipage :: Monad m => LW m a -> LW m a
@@ -2,6 +2,7 @@ ( LW , WriterState (..) , startingState+ , PdfStandard (..) ) where import Control.Monad.State.Strict (StateT)@@ -11,6 +12,7 @@ ( WriterOptions (writerIncremental, writerTopLevelDivision) , TopLevelDivision (..) )+import Citeproc.Types (Lang) -- | LaTeX writer type. The type constructor @m@ will typically be an -- instance of PandocMonad.@@ -25,16 +27,20 @@ , stInMinipage :: Bool -- ^ true if in minipage , stInHeading :: Bool -- ^ true if in a section heading , stInItem :: Bool -- ^ true if in \item[..]+ , stInFigure :: Bool -- ^ true if in figure environment+ , stInCite :: Bool -- ^ true if in a Cite , stNotes :: [Doc Text] -- ^ notes in a minipage , stOLLevel :: Int -- ^ level of ordered list nesting , stOptions :: WriterOptions -- ^ writer options, so they don't have to -- be parameter , stVerbInNote :: Bool -- ^ true if document has verbatim text in note , stTable :: Bool -- ^ true if document has a table+ , stSubfigure :: Bool -- ^ true if document has subfigures , stMultiRow :: Bool -- ^ true if document has multirow cells , stStrikeout :: Bool -- ^ true if document has strikeout , stUrl :: Bool -- ^ true if document has visible URL link , stGraphics :: Bool -- ^ true if document contains images+ , stSVG :: Bool -- ^ true if document contains SVGs , stLHS :: Bool -- ^ true if document has literate haskell code , stHasChapters :: Bool -- ^ true if document has chapters , stCsquotes :: Bool -- ^ true if document uses csquotes@@ -46,8 +52,19 @@ , stEmptyLine :: Bool -- ^ true if no content on line , stHasCslRefs :: Bool -- ^ has a Div with class refs , stIsFirstInDefinition :: Bool -- ^ first block in a defn list+ , stLang :: Maybe Lang -- ^ lang specified in metadata+ , stInSoulCommand :: Bool -- ^ in a soul command like ul+ , stCancel :: Bool -- ^ true if document uses \cancel+ , stInCaption :: Bool -- ^ true if in a caption } +-- | PDF standard settings for DocumentMetadata+data PdfStandard = PdfStandard+ { pdfStandards :: [Text] -- ^ list of standards (e.g., ["a-2b", "ua-1"])+ , pdfVersion :: Maybe Text -- ^ PDF version (e.g., "1.7", "2.0")+ , pdfTagging :: Bool -- ^ whether tagging is required+ }+ startingState :: WriterOptions -> WriterState startingState options = WriterState@@ -57,15 +74,19 @@ , stInHeading = False , stInMinipage = False , stInItem = False+ , stInFigure = False+ , stInCite = False , stNotes = [] , stOLLevel = 1 , stOptions = options , stVerbInNote = False , stTable = False+ , stSubfigure = False , stMultiRow = False , stStrikeout = False , stUrl = False , stGraphics = False+ , stSVG = False , stLHS = False , stHasChapters = case writerTopLevelDivision options of TopLevelPart -> True@@ -80,4 +101,8 @@ , stEmptyLine = True , stHasCslRefs = False , stIsFirstInDefinition = False+ , stLang = Nothing+ , stInSoulCommand = False+ , stCancel = False+ , stInCaption = False }
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.LaTeX.Util- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -37,7 +37,7 @@ import Text.Pandoc.Extensions (Extension(Ext_smart)) import Data.Char (isLetter, isSpace, isDigit, isAscii, ord, isAlphaNum) import Text.Printf (printf)-import Text.Pandoc.Shared (safeRead, elemText)+import Text.Pandoc.Shared (safeRead) import qualified Data.Text.Normalize as Normalize import Data.List (uncons) @@ -50,7 +50,7 @@ stringToLaTeX :: PandocMonad m => StringContext -> Text -> LW m Text stringToLaTeX context zs = do opts <- gets stOptions- when ('\x200c' `elemText` zs) $+ when (T.any (== '\x200c') zs) $ modify (\s -> s { stZwnj = True }) return $ T.pack $ foldr (go opts context) mempty $ T.unpack $@@ -91,37 +91,50 @@ '\'':_ -> cs <> "\\," <> xs -- add thin space _ -> cs <> xs in case x of+ _ | isUrl ->+ case x of+ '\\' -> emitc '/' -- NB / works as path sep even on Windows+ '#' -> emits "\\#" -- #9014+ '%' -> emits "\\%" -- #9014+ '{' -> emits "\\%7B"+ '}' -> emits "\\%7D"+ '|' -> emits "\\%7C"+ '^' -> emits "\\%5E"+ '[' -> emits "\\%5B"+ ']' -> emits "\\%5D"+ '`' -> emits "\\%60"+ _ -> emitc x+ '{' -> emits "\\{"+ '}' -> emits "\\}" '?' | ligatures -> -- avoid ?` ligature case xs of- '`':_ -> emits "?{}"+ '`':_ -> emits "?{\\kern0pt}" -- se #10610 _ -> emitc x '!' | ligatures -> -- avoid !` ligature case xs of- '`':_ -> emits "!{}"+ '`':_ -> emits "!{\\kern0pt}" _ -> emitc x- '{' -> emits "\\{"- '}' -> emits "\\}" '`' | ctx == CodeString -> emitcseq "\\textasciigrave"- '$' | not isUrl -> emits "\\$"+ '$' -> emits "\\$" '%' -> emits "\\%" '&' -> emits "\\&"- '_' | not isUrl -> emits "\\_"+ '_' -> emits "\\_" '#' -> emits "\\#"- '-' | not isUrl -> case xs of+ '-' -> case xs of -- prevent adjacent hyphens from forming ligatures ('-':_) -> emits "-\\/" _ -> emitc '-'- '~' | not isUrl -> emitcseq "\\textasciitilde"+ '~' -> emitcseq "\\textasciitilde" '^' -> emits "\\^{}"- '\\'| isUrl -> emitc '/' -- NB. / works as path sep even on Windows- | otherwise -> emitcseq "\\textbackslash"- '|' | not isUrl -> emitcseq "\\textbar"- '<' -> emitcseq "\\textless"- '>' -> emitcseq "\\textgreater"- '[' -> emits "{[}" -- to avoid interpretation as- ']' -> emits "{]}" -- optional arguments+ '\\' -> emitcseq "\\textbackslash"+ '|' -> emitcseq "\\textbar"+ '<' -> emitcseq "\\textless"+ '>' -> emitcseq "\\textgreater"+ '[' -> emits "{[}" -- to avoid interpretation as+ ']' -> emits "{]}" -- optional arguments '\'' -> emitcseq "\\textquotesingle" '\160' -> emits "~"+ '\x00AD' -> emits "\\-" -- shy hyphen '\x200B' -> emits "\\hspace{0pt}" -- zero-width space '\x202F' -> emits "\\," '\x2026' | ligatures -> emitcseq "\\ldots"@@ -182,7 +195,7 @@ where go = T.concatMap $ \x -> case x of _ | (isLetter x || isDigit x) && isAscii x -> T.singleton x- | x `elemText` "_-+=:;." -> T.singleton x+ | T.any (== x) "_-+=:;." -> T.singleton x | otherwise -> T.pack $ "ux" <> printf "%x" (ord x) -- | Puts contents into LaTeX command.@@ -223,7 +236,7 @@ w = maybe "0.48" fromPct (lookup "width" kvs) in inCmd "begin" "column" <> valign <>- braces (literal w <> "\\textwidth")+ braces (literal w <> "\\linewidth") $$ contents $$ inCmd "end" "column" else id@@ -237,24 +250,25 @@ Just "rtl" -> align "RTL" Just "ltr" -> align "LTR" _ -> id- wrapLang txt = case lang of- Just lng -> let l = toBabel lng- in inCmd "begin" "otherlanguage"+ wrapLang txt = case lang >>= toBabel of+ Just l -> inCmd "begin" "otherlanguage" <> (braces (literal l)) $$ blankline <> txt <> blankline $$ inCmd "end" "otherlanguage" Nothing -> txt return $ wrapColumns . wrapColumn . wrapDir . wrapLang $ t -hypertarget :: PandocMonad m => Bool -> Text -> Doc Text -> LW m (Doc Text)-hypertarget _ "" x = return x-hypertarget addnewline ident x = do- ref <- literal `fmap` toLabel ident- return $ text "\\hypertarget"- <> braces ref- <> braces ((if addnewline && not (isEmpty x)- then "%" <> cr- else empty) <> x)+hypertarget :: PandocMonad m => Text -> LW m (Doc Text)+hypertarget "" = return mempty+hypertarget ident = do+ inHeading <- gets stInHeading+ if inHeading+ then do -- see #9209 (these cases should be rare)+ ref <- literal <$> toLabel ident+ return $ text "\\protect\\hypertarget" <> braces ref <> "{}"+ else do+ label <- labelFor ident+ return $ text "\\protect\\phantomsection" <> label labelFor :: PandocMonad m => Text -> LW m (Doc Text) labelFor "" = return empty
@@ -3,7 +3,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Writers.Man- Copyright : Copyright (C) 2007-2022 John MacFarlane+ Copyright : Copyright (C) 2007-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -14,10 +14,13 @@ -} module Text.Pandoc.Writers.Man ( writeMan ) where-import Control.Monad.State.Strict+import Control.Monad ( liftM, zipWithM, unless )+import Control.Monad.State.Strict ( StateT, gets, modify, evalStateT )+import Control.Monad.Trans (MonadTrans(lift)) import Data.List (intersperse) import Data.List.NonEmpty (nonEmpty) import Data.Maybe (fromMaybe)+import qualified Data.Map as M import Data.Text (Text) import qualified Data.Text as T import Text.Pandoc.Builder (deleteMeta)@@ -27,11 +30,15 @@ import Text.Pandoc.Options import Text.DocLayout import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Math import Text.Pandoc.Writers.Shared import Text.Pandoc.Writers.Roff+import Text.Pandoc.Highlighting import Text.Printf (printf)+import Skylighting (TokenType(..), SourceLine, FormatOptions, defaultFormatOpts,+ defStyle, TokenStyle(..), Style(..)) -- | Convert Pandoc to Man. writeMan :: PandocMonad m => WriterOptions -> Pandoc -> m Text@@ -72,15 +79,16 @@ let context = defField "body" main $ setFieldsFromTitle $ defField "has-tables" hasTables- $ defField "hyphenate" True- $ defField "pandoc-version" pandocVersion metadata+ metadata return $ render colwidth $ case writerTemplate opts of Nothing -> main Just tpl -> renderTemplate tpl context escString :: WriterOptions -> Text -> Text-escString _ = escapeString AsciiOnly -- for better portability+escString opts = escapeString True (if writerPreferAscii opts+ then AsciiOnly+ else AllowUTF8) -- | Return man representation of notes. notesToMan :: PandocMonad m => WriterOptions -> [[Block]] -> StateT WriterState m (Doc Text)@@ -105,7 +113,6 @@ => WriterOptions -- ^ Options -> Block -- ^ Block element -> StateT WriterState m (Doc Text)-blockToMan _ Null = return empty blockToMan opts (Div _ bs) = blockListToMan opts bs blockToMan opts (Plain inlines) = splitSentences <$> inlineListToMan opts inlines@@ -126,16 +133,18 @@ 1 -> ".SH " _ -> ".SS " return $ nowrap $ literal heading <> contents-blockToMan opts (CodeBlock _ str) = return $- literal ".IP" $$- literal ".nf" $$- literal "\\f[C]" $$- ((case T.uncons str of- Just ('.',_) -> literal "\\&"- _ -> mempty) <>- literal (escString opts str)) $$- literal "\\f[R]" $$- literal ".fi"+blockToMan opts (CodeBlock attr str) = do+ hlCode <- case highlight (writerSyntaxMap opts) (formatSource opts)+ attr str of+ Right d -> pure d+ Left msg -> do+ unless (T.null msg) $ report $ CouldNotHighlight msg+ pure $ formatSource opts defaultFormatOpts+ (map (\t -> [(NormalTok,t)]) $ T.lines str)+ pure $ literal ".IP" $$+ literal ".EX" $$+ hlCode $$+ literal ".EE" blockToMan opts (BlockQuote blocks) = do contents <- blockListToMan opts blocks return $ literal ".RS" $$ contents $$ literal ".RE"@@ -168,7 +177,6 @@ return $ literal ".PP" $$ caption' $$ literal ".TS" $$ literal "tab(@);" $$ coldescriptions $$ colheadings' $$ vcat body $$ literal ".TE"- blockToMan opts (BulletList items) = do contents <- mapM (bulletListItemToMan opts) items return (vcat contents)@@ -181,6 +189,8 @@ blockToMan opts (DefinitionList items) = do contents <- mapM (definitionListItemToMan opts) items return (vcat contents)+blockToMan opts (Figure attr capt body) = do+ blockToMan opts (figureDiv attr capt body) -- | Convert bullet list item (list of blocks) to man. bulletListItemToMan :: PandocMonad m => WriterOptions -> [Block] -> StateT WriterState m (Doc Text)@@ -190,7 +200,7 @@ bulletListItemToMan opts (Plain first:rest) = do first' <- blockToMan opts (Plain first) rest' <- blockListToMan opts rest- let first'' = literal ".IP \\[bu] 2" $$ first'+ let first'' = literal ".IP \\(bu 2" $$ first' let rest'' = if null rest then empty else literal ".RS 2" $$ rest' $$ literal ".RE"@@ -198,7 +208,7 @@ bulletListItemToMan opts (first:rest) = do first' <- blockToMan opts first rest' <- blockListToMan opts rest- return $ literal "\\[bu] .RS 2" $$ first' $$ rest' $$ literal ".RE"+ return $ literal "\\(bu .RS 2" $$ first' $$ rest' $$ literal ".RE" -- | Convert ordered list item (a list of blocks) to man. orderedListItemToMan :: PandocMonad m@@ -231,7 +241,7 @@ labelText <- inlineListToMan opts label contents <- if null defs then return empty- else liftM vcat $ forM defs $ \case+ else case mconcat defs of (x:xs) -> do first' <- blockToMan opts $ case x of@@ -252,7 +262,13 @@ -> [Block] -- ^ List of block elements -> StateT WriterState m (Doc Text) blockListToMan opts blocks =- vcat <$> mapM (blockToMan opts) blocks+ vcat <$> mapM (blockToMan opts) (go blocks)+ where+ -- Avoid .PP right after .SH; this is a no-op in groff man and mandoc+ -- but may cause unwanted extra space in some renderers (see #9020)+ go [] = []+ go (h@Header{} : Para ils : rest) = h : Plain ils : go rest+ go (x : xs) = x : go xs -- | Convert list of Pandoc inline elements to man. inlineListToMan :: PandocMonad m => WriterOptions -> [Inline] -> StateT WriterState m (Doc Text)@@ -283,12 +299,11 @@ return $ char '`' <> contents <> char '\'' inlineToMan opts (Quoted DoubleQuote lst) = do contents <- inlineListToMan opts lst- return $ literal "\\[lq]" <> contents <> literal "\\[rq]"+ return $ literal "\\(lq" <> contents <> literal "\\(rq" inlineToMan opts (Cite _ lst) = inlineListToMan opts lst inlineToMan opts (Code _ str) =- -- note that the V font is specially defined in the default man template- withFontFeature 'V' (return (literal $ escString opts str))+ withFontFeature 'C' (return (literal $ escString opts str)) inlineToMan opts (Str str@(T.uncons -> Just ('.',_))) = return $ afterBreak "\\&" <> literal (escString opts str) inlineToMan opts (Str str) = return $ literal $ escString opts str@@ -304,18 +319,22 @@ return empty inlineToMan _ LineBreak = return $ cr <> literal ".PD 0" $$ literal ".P" $$ literal ".PD" <> cr-inlineToMan _ SoftBreak = return space-inlineToMan _ Space = return space+inlineToMan _ SoftBreak = return $ afterBreak "\\" <> space+inlineToMan _ Space = return $ afterBreak "\\" <> space inlineToMan opts (Link _ txt (src, _)) | not (isURI src) = inlineListToMan opts txt -- skip relative links | otherwise = do- linktext <- inlineListToMan opts txt let srcSuffix = fromMaybe src (T.stripPrefix "mailto:" src)- return $ case txt of- [Str s]- | escapeURI s == srcSuffix ->- char '<' <> literal srcSuffix <> char '>'- _ -> linktext <> literal " (" <> literal src <> char ')'+ linktext <- case txt of+ [Str s] | escapeURI s == srcSuffix -> pure mempty+ _ -> inlineListToMan opts txt+ let (start, end) = if "mailto:" `T.isPrefixOf` src+ then (".MT", ".ME")+ else (".UR", ".UE")+ return $ "\\c" <> cr -- \c avoids extra space+ $$ nowrap (start <+> literal srcSuffix)+ $$ linktext+ $$ (end <+> "\\c" <> cr) -- \c avoids space after inlineToMan opts (Image attr alternate (source, tit)) = do let txt = if null alternate || (alternate == [Str ""]) || (alternate == [Str source]) -- to prevent autolinks@@ -329,3 +348,32 @@ notes <- gets stNotes let ref = tshow (length notes) return $ char '[' <> literal ref <> char ']'++formatSource :: WriterOptions -> FormatOptions -> [SourceLine] -> Doc Text+formatSource wopts fopts = vcat . map (formatSourceLine wopts fopts)++formatSourceLine :: WriterOptions -> FormatOptions -> SourceLine -> Doc Text+formatSourceLine _wopts _fopts [] = blankline+formatSourceLine wopts fopts ts@((_,firstTxt):_) =+ (case T.uncons firstTxt of+ Just ('.',_) -> literal "\\&"+ _ -> mempty) <> mconcat (map (formatTok wopts fopts) ts) <> literal "\n"++formatTok :: WriterOptions -> FormatOptions -> (TokenType, Text) -> Doc Text+formatTok wopts _fopts (toktype, t) =+ let txt = literal (escString wopts t)+ 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+ else+ let fonts = ['B' | tokenBold tokStyle] +++ ['I' | tokenItalic tokStyle || tokenUnderline tokStyle]+ in if null fonts+ then txt+ else literal ("\\f[" <> T.pack fonts <> "]") <>+ txt <>+ literal "\\f[R]"
@@ -2,9 +2,10 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-}+{-# LANGUAGE BangPatterns #-} {- | Module : Text.Pandoc.Writers.Markdown- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -20,15 +21,17 @@ writeCommonMark, writeMarkua, writePlain) where-import Control.Monad.Reader-import Control.Monad.State.Strict+import Control.Monad (foldM, zipWithM, MonadPlus(..), when, liftM)+import Control.Monad.Reader ( asks, MonadReader(local) )+import Control.Monad.State.Strict ( gets, modify ) import Data.Default-import Data.List (intersperse, sortOn)+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) import qualified Data.Set as Set import Data.Text (Text)+import Data.Char (isSpace) import qualified Data.Text as T import Text.HTML.TagSoup (Tag (..), isTagText, parseTags) import Text.Pandoc.Class.PandocMonad (PandocMonad, report)@@ -230,8 +233,14 @@ mmdTitleBlock metadata | otherwise -> empty Nothing -> empty+ let modifyTOC =+ if isEnabled Ext_link_attributes opts || isEnabled Ext_attributes opts+ then id+ else walk $ \inln -> case inln of+ Link _attr contents tgt -> Link nullAttr contents tgt+ _ -> inln toc <- if writerTableOfContents opts- then blockToMarkdown opts ( toTableOfContents opts blocks )+ then blockToMarkdown opts . modifyTOC $ toTableOfContents opts blocks else return mempty -- Strip off final 'references' header if markdown citations enabled let blocks' = if isEnabled Ext_citations opts@@ -304,12 +313,12 @@ -- | (Code) blocks with a single class and no attributes can just use it -- standalone, no need to bother with curly braces.-classOrAttrsToMarkdown :: Attr -> Doc Text-classOrAttrsToMarkdown ("",[cls],[]) = literal cls-classOrAttrsToMarkdown attrs = attrsToMarkdown attrs+classOrAttrsToMarkdown :: WriterOptions -> Attr -> Doc Text+classOrAttrsToMarkdown _ ("",[cls],[]) = literal cls+classOrAttrsToMarkdown opts attrs = attrsToMarkdown opts attrs -- | Ordered list start parser for use in Para below.-olMarker :: Parser Text ParserState ()+olMarker :: Parsec Text ParserState () olMarker = do (start, style', delim) <- anyOrderedListMarker if delim == Period && (style' == UpperAlpha || (style' == UpperRoman &&@@ -359,44 +368,60 @@ => WriterOptions -- ^ Options -> Block -- ^ Block element -> MD m (Doc Text)-blockToMarkdown' _ Null = return empty-blockToMarkdown' opts (Div attrs ils) = do- contents <- blockListToMarkdown opts ils- variant <- asks envVariant- return $- case () of- _ | variant == Markua ->- case () of- () | "blurb" `elem` classes' -> prefixed "B> " contents <> blankline- | "aside" `elem` classes' -> prefixed "A> " contents <> blankline- -- necessary to enable option to create a bibliography- | (take 3 (T.unpack id')) == "ref" -> contents <> blankline- | otherwise -> contents <> blankline- | isEnabled Ext_fenced_divs opts &&- attrs /= nullAttr ->- let attrsToMd = if variant == Commonmark- then attrsToMarkdown- else classOrAttrsToMarkdown- in nowrap (literal ":::" <+> attrsToMd attrs) $$- chomp contents $$- literal ":::" <> blankline- | isEnabled Ext_native_divs opts ||- (isEnabled Ext_raw_html opts &&- (variant == Commonmark ||- isEnabled Ext_markdown_in_html_blocks opts)) ->- tagWithAttrs "div" attrs <> blankline <>- contents <> blankline <> "</div>" <> blankline- | isEnabled Ext_raw_html opts &&- isEnabled Ext_markdown_attribute opts ->- tagWithAttrs "div" attrs' <> blankline <>- contents <> blankline <> "</div>" <> blankline- | otherwise -> contents <> blankline- where (id',classes',kvs') = attrs- attrs' = (id',classes',("markdown","1"):kvs')+blockToMarkdown' opts (Div attrs@(_,classes,_) bs)+ | ("sourceCode":_) <- classes+ , [CodeBlock (_,"sourceCode":_,_) _] <- bs+ -- skip pandoc-generated Div wrappers around code blocks+ = blockListToMarkdown opts bs+ | isEnabled Ext_alerts opts+ , (cls:_) <- classes+ , cls `elem` ["note", "tip", "warning", "caution", "important"]+ , (Div ("", ["title"], []) _ : bs') <- bs = do+ contents <- blockListToMarkdown opts bs'+ let alertLabel = literal $ "[!" <> T.toUpper cls <> "]"+ pure $ text "> " <> alertLabel $$ prefixed "> " contents $$ blankline+ | otherwise = do+ contents <- blockListToMarkdown opts bs+ variant <- asks envVariant+ return $+ case () of+ _ | variant == Markua ->+ case () of+ () | "blurb" `elem` classes'+ -> prefixed "B> " contents <> blankline+ | "aside" `elem` classes'+ -> prefixed "A> " contents <> blankline+ -- necessary to enable option to create a bibliography+ | (take 3 (T.unpack id')) == "ref"+ -> contents <> blankline+ | otherwise -> contents <> blankline+ | isEnabled Ext_fenced_divs opts ->+ let attrsToMd = if variant == Commonmark+ then attrsToMarkdown opts+ else classOrAttrsToMarkdown opts+ divNesting = computeDivNestingLevel bs+ numcolons = 3 + divNesting+ colons = literal $ T.replicate numcolons ":"+ in nowrap (colons <+> attrsToMd attrs) $$+ chomp contents $$+ colons <> blankline+ | isEnabled Ext_native_divs opts ||+ (isEnabled Ext_raw_html opts &&+ (variant == Commonmark ||+ isEnabled Ext_markdown_in_html_blocks opts)) ->+ tagWithAttrs "div" attrs <> blankline <>+ contents <> blankline <> "</div>" <> blankline+ | isEnabled Ext_raw_html opts &&+ isEnabled Ext_markdown_attribute opts ->+ tagWithAttrs "div" attrs' <> blankline <>+ contents <> blankline <> "</div>" <> blankline+ | otherwise -> contents <> blankline+ where (id',classes',kvs') = attrs+ attrs' = (id',classes',("markdown","1"):kvs') blockToMarkdown' opts (Plain inlines) = do -- escape if para starts with ordered list marker variant <- asks envVariant- let escapeMarker = T.concatMap $ \x -> if x `elemText` ".()"+ let escapeMarker = T.concatMap $ \x -> if T.any (== x) ".()" then T.pack ['\\', x] else T.singleton x let startsWithSpace (Space:_) = True@@ -418,22 +443,21 @@ _ -> inlines contents <- inlineListToMarkdown opts inlines' return $ contents <> cr-blockToMarkdown' opts (SimpleFigure attr alt (src, tit))- | isEnabled Ext_raw_html opts &&- not (isEnabled Ext_link_attributes opts || isEnabled Ext_attributes opts) &&- attr /= nullAttr = -- use raw HTML- (<> blankline) . literal . T.strip <$>- writeHtml5String opts{ writerTemplate = Nothing }- (Pandoc nullMeta [SimpleFigure attr alt (src, tit)])- | otherwise = blockToMarkdown opts (Para [Image attr alt (src,tit)]) blockToMarkdown' opts (Para inlines) = (<> blankline) `fmap` blockToMarkdown opts (Plain inlines)-blockToMarkdown' opts (LineBlock lns) =- if isEnabled Ext_line_blocks opts- then do- mdLines <- mapM (inlineListToMarkdown opts) lns- return $ vcat (map (hang 2 (literal "| ")) mdLines) <> blankline- else blockToMarkdown opts $ linesToPara lns+blockToMarkdown' opts (LineBlock lns) = do+ variant <- asks envVariant+ case variant of+ PlainText -> do+ let emptyToBlank l = if isEmpty l then blankline else l+ mdLines <- mapM (liftM emptyToBlank . inlineListToMarkdown opts) lns+ return $ vcat mdLines <> blankline+ _ ->+ if isEnabled Ext_line_blocks opts+ then do+ mdLines <- mapM (inlineListToMarkdown opts) lns+ return $ vcat (map (hang 2 (literal "| ")) mdLines) <> blankline+ else blockToMarkdown opts $ linesToPara lns blockToMarkdown' opts b@(RawBlock f str) = do variant <- asks envVariant let Format fmt = f@@ -444,17 +468,20 @@ let renderEmpty = mempty <$ report (BlockNotRendered b) case variant of PlainText- | f == "plain" -> return $ literal str <> literal "\n"+ | f == "plain" -> return $ nest 0 (literal str) <> literal "\n" Commonmark | f `elem` ["gfm", "commonmark", "commonmark_x", "markdown"]- -> return $ literal str <> literal "\n"+ -> return $ nest 0 (literal str) $$ blankline+ | f `elem` ["html", "html5", "html4"]+ -> return $ literal (removeBlankLinesInHTML str) $$ blankline Markdown | f `elem` ["markdown", "markdown_github", "markdown_phpextra", "markdown_mmd", "markdown_strict"]- -> return $ literal str <> literal "\n"+ -- the 'nest 0' ensures that leading and trailing newlines+ -- don't get collapsed. See #10477 for context;+ -> return $ nest 0 (literal str) <> literal "\n" Markua -> renderEmpty- _ | isEnabled Ext_raw_attribute opts -> rawAttribBlock- | f `elem` ["html", "html5", "html4"]+ _ | f `elem` ["html", "html5", "html4"] , isEnabled Ext_markdown_attribute opts -> return $ literal (addMarkdownAttribute str) <> literal "\n" | f `elem` ["html", "html5", "html4"]@@ -463,6 +490,7 @@ | f `elem` ["latex", "tex"] , isEnabled Ext_raw_tex opts -> return $ literal str <> literal "\n"+ | isEnabled Ext_raw_attribute opts -> rawAttribBlock _ -> renderEmpty blockToMarkdown' opts HorizontalRule = do variant <- asks envVariant@@ -491,20 +519,24 @@ && id' == autoId -> empty (id',_,_) | isEnabled Ext_mmd_header_identifiers opts -> space <> brackets (literal id')- _ | variant == Markua -> attrsToMarkua attr+ _ | variant == Markua -> attrsToMarkua opts attr | isEnabled Ext_header_attributes opts || isEnabled Ext_attributes opts ->- space <> attrsToMarkdown attr+ space <> attrsToMarkdown opts attr | otherwise -> empty+ let setext = level <= 2 && writerSetextHeaders opts ||+ (variant == Commonmark &&+ hasLineBreaks inlines) -- #11341 contents <- inlineListToMarkdown opts $- -- ensure no newlines; see #3736- walk lineBreakToSpace $+ (if variant == Commonmark && setext+ then id+ else -- ensure no newlines; see #3736+ walk lineBreakToSpace) $ if level == 1 && variant == PlainText && isEnabled Ext_gutenberg opts then capitalize inlines else inlines - let setext = writerSetextHeaders opts when (not setext && isEnabled Ext_literate_haskell opts) $ report $ ATXHeadingInLHS level (render Nothing contents) @@ -544,9 +576,12 @@ backticks <> attrs <> cr <> literal str <> cr <> backticks <> blankline | isEnabled Ext_fenced_code_blocks opts -> tildes <> attrs <> cr <> literal str <> cr <> tildes <> blankline- _ | variant == Markua -> blankline <> attrsToMarkua attribs <> cr <> backticks <> cr <>+ _ | variant == Markua -> blankline <> attrsToMarkua opts attribs <> cr <> backticks <> cr <> literal str <> cr <> backticks <> cr <> blankline- | otherwise -> nest (writerTabStop opts) (literal str) <> blankline+ | otherwise -> -- don't use nest: see #11542+ let addIndent "" = "\n"+ addIndent x = (T.replicate (writerTabStop opts) " ") <> x <> "\n"+ in literal (mconcat $ map addIndent (T.lines str)) $$ blankline where endlineLen c = maybe 3 ((+1) . maximum) $ nonEmpty [T.length ln@@ -558,10 +593,12 @@ tildes = endline '~' attrs = if isEnabled Ext_fenced_code_attributes opts || isEnabled Ext_attributes opts- then nowrap $ " " <> classOrAttrsToMarkdown attribs- else case attribs of- (_,cls:_,_) -> " " <> literal cls- _ -> empty+ then nowrap $ " " <> classOrAttrsToMarkdown opts attribs+ 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@@ -571,22 +608,38 @@ | variant == PlainText = " " | otherwise = "> " contents <- blockListToMarkdown opts blocks- return $ prefixed leader contents <> blankline-blockToMarkdown' opts t@(Table _ blkCapt specs thead tbody tfoot) = do+ return $ text leader <> prefixed leader contents <> blankline+blockToMarkdown' opts t@(Table attr blkCapt specs thead tbody tfoot) = do let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot+ let isColRowSpans (Cell _ _ rs cs _) = rs > 1 || cs > 1+ let rowHasColRowSpans (Row _ cs) = any isColRowSpans cs+ let hasFooter = case tfoot of+ TableFoot _ [] -> False+ _ -> True+ let tbodyHasColRowSpans (TableBody _ _ rhs rs) =+ any rowHasColRowSpans rhs || any rowHasColRowSpans rs+ let theadHasColRowSpans (TableHead _ rs) = any rowHasColRowSpans rs+ let tfootHasColRowSpans (TableFoot _ rs) = any rowHasColRowSpans rs+ let hasColRowSpans = theadHasColRowSpans thead ||+ any tbodyHasColRowSpans tbody ||+ tfootHasColRowSpans tfoot let numcols = maximum (length aligns :| length widths : map length (headers:rows)) caption' <- inlineListToMarkdown opts caption- let caption''+ let caption'' = if attr == nullAttr+ then caption'+ else caption' <+> attrsToMarkdown opts attr+ let caption''' | null caption = blankline | isEnabled Ext_table_captions opts- = blankline $$ (": " <> caption') $$ blankline- | otherwise = blankline $$ caption' $$ blankline+ = blankline $$ (": " <> caption'') $$ blankline+ | otherwise = blankline $$ caption'' $$ blankline let hasSimpleCells = onlySimpleTableCells $ headers : rows- let isSimple = hasSimpleCells && all (==0) widths+ let isSimple = hasSimpleCells && not hasFooter &&+ all (==0) widths && not hasColRowSpans let isPlainBlock (Plain _) = True isPlainBlock _ = False- let hasBlocks = not (all isPlainBlock $ concat . concat $ headers:rows)+ let hasBlocks = not (all (all (all isPlainBlock)) $ headers:rows) let padRow r = case numcols - length r of x | x > 0 -> r ++ replicate x empty | otherwise -> r@@ -596,45 +649,51 @@ let widths' = case numcols - length widths of x | x > 0 -> widths ++ replicate x 0.0 | otherwise -> widths- (nst,tbl) <-- case True of- _ | isSimple &&- isEnabled Ext_simple_tables opts -> do- rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers- rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))- rows- (nest 2,) <$> pandocTable opts False (all null headers)- aligns' widths' rawHeaders rawRows- | isSimple &&- isEnabled Ext_pipe_tables opts -> do- rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers- rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))- rows- (id,) <$> pipeTable opts (all null headers) aligns' widths'- rawHeaders rawRows- | not hasBlocks &&- isEnabled Ext_multiline_tables opts -> do- rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers- rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))- rows- (nest 2,) <$> pandocTable opts True (all null headers)- aligns' widths' rawHeaders rawRows- | isEnabled Ext_grid_tables opts &&- writerColumns opts >= 8 * numcols -> (id,) <$>- gridTable opts blockListToMarkdown- (all null headers) aligns' widths' headers rows- | hasSimpleCells &&- isEnabled Ext_pipe_tables opts -> do- rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers- rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts))- rows- (id,) <$> pipeTable opts (all null headers) aligns' widths'- rawHeaders rawRows- | isEnabled Ext_raw_html opts -> fmap (id,) $- literal <$>- writeHtml5String opts{ writerTemplate = Nothing } (Pandoc nullMeta [t])- | otherwise -> return (id, literal "[TABLE]")- return $ nst (tbl $$ caption'') $$ blankline+ let mkTable f = do+ rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers+ rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts)) rows+ f (all null headers) aligns' widths' rawHeaders rawRows+ case True of+ _ | isSimple &&+ isEnabled Ext_simple_tables opts -> do+ tbl <- mkTable (pandocTable opts False)+ return $ nest 2 (tbl $$ caption''') $$ blankline+ | isSimple &&+ isEnabled Ext_pipe_tables opts -> do+ tbl <- mkTable (pipeTable opts)+ return $ (tbl $$ caption''') $$ blankline+ | not (hasBlocks || hasColRowSpans || hasFooter) &&+ isEnabled Ext_multiline_tables opts -> do+ tbl <- mkTable (pandocTable opts True)+ return $ nest 2 (tbl $$ caption''') $$ blankline+ | isEnabled Ext_grid_tables opts &&+ (hasColRowSpans || writerColumns opts >= 8 * numcols+ || hasFooter) -> do+ tbl <- gridTable opts blockListToMarkdown+ specs thead tbody tfoot+ return $ (tbl $$ caption''') $$ blankline+ | hasSimpleCells,+ not hasColRowSpans,+ isEnabled Ext_pipe_tables opts -> do+ tbl <- mkTable (pipeTable opts)+ return $ (tbl $$ caption''') $$ blankline+ | isEnabled Ext_raw_html opts -> do -- HTML fallback+ tbl <- literal . removeBlankLinesInHTML <$>+ writeHtml5String opts{ writerTemplate = Nothing }+ (Pandoc nullMeta [t])+ return $ tbl $$ blankline -- caption is in the HTML table+ | hasSimpleCells,+ hasColRowSpans,+ isEnabled Ext_pipe_tables opts -> do+ -- In this case an approximate pipe table will be rendered,+ -- without col/row spans. This is better than nothing, since+ -- we have no other way to render the table correctly (#11128).+ tbl <- mkTable (pipeTable opts)+ return $ (tbl $$ caption''') $$ blankline+ | otherwise+ -> do+ report (BlockNotRendered t)+ return $ (literal "[TABLE]" $$ caption''') $$ blankline blockToMarkdown' opts (BulletList items) = do contents <- inList $ mapM (bulletListItemToMarkdown opts) items return $ (if isTightList items then vcat else vsep)@@ -666,6 +725,43 @@ blockToMarkdown' opts (DefinitionList items) = do contents <- inList $ mapM (definitionListItemToMarkdown opts) items return $ mconcat contents <> blankline+blockToMarkdown' opts (Figure figattr capt body) = do+ let combinedAttr imgattr = case imgattr of+ ("", cls, kvs)+ | (figid, [], []) <- figattr+ -> Just (figid, cls, [(k,v) | (k,v) <- kvs+ , k /= "alt" ||+ v /= "" && v /= trim (stringify capt)])+ _ -> Nothing+ case body of+ [Plain [Image imgAttr alt (src, ttl)]]+ | isEnabled Ext_implicit_figures opts+ , Just imgAttr' <- combinedAttr imgAttr+ , isEnabled Ext_link_attributes opts || imgAttr' == nullAttr+ -> do+ -- use implicit figures if possible+ let tgt' = (src, fromMaybe ttl $ T.stripPrefix "fig:" ttl)+ let descr = case capt of+ Caption _ bs -> blocksToInlines bs+ -- add alt attribute if image description different from caption,+ -- so this won't be lost:+ let imgAttr'' = case imgAttr' of+ (i,c,kv)+ | not (null alt)+ , Nothing <- lookup "alt" kv+ , stringify descr /= stringify alt ->+ (i, c, ("alt", stringify alt) : kv)+ _ -> imgAttr'+ contents <- inlineListToMarkdown opts [Image imgAttr'' descr tgt']+ return $ contents <> blankline+ _ ->+ -- fallback to raw html if possible or div otherwise+ if isEnabled Ext_raw_html opts+ then figureToMarkdown opts figattr capt body+ else if (isEnabled Ext_fenced_divs opts || isEnabled Ext_native_divs opts) ||+ not (isEnabled Ext_implicit_figures opts)+ then blockToMarkdown' opts $ figureDiv figattr capt body+ else blockListToMarkdown opts body inList :: Monad m => MD m a -> MD m a inList p = local (\env -> env {envInList = True}) p@@ -679,6 +775,25 @@ x /= "markdown"] _ -> s +-- | Converts a figure to Markdown by wrapping it in a div named `figure`.+figureToMarkdown :: PandocMonad m+ => WriterOptions+ -> Attr+ -> Caption+ -> [Block]+ -> MD m (Doc Text)+figureToMarkdown opts attr@(ident, classes, kvs) capt body+ | isEnabled Ext_raw_html opts =+ (<> blankline) . literal . T.strip <$>+ writeHtml5String+ opts{ writerTemplate = Nothing }+ (Pandoc nullMeta [Figure attr capt body])+ | otherwise = do+ let attr' = (ident, ["figure"] `union` classes, kvs)+ let Caption _mbshort caption = capt+ let captionBs = [Div ("",["caption"],[]) caption | not (null caption)]+ blockToMarkdown' opts (Div attr' (body <> captionBs))+ itemEndsWithTightList :: [Block] -> Bool itemEndsWithTightList bs = case bs of@@ -695,7 +810,13 @@ let start = case variant of Markua -> "* " Commonmark -> "- "- _ -> "- " <> T.replicate (writerTabStop opts - 2) " "+ Markdown+ | isEnabled Ext_four_space_rule opts+ -> "- " <> T.replicate (writerTabStop opts - 2) " "+ PlainText+ | isEnabled Ext_four_space_rule opts+ -> "- " <> T.replicate (writerTabStop opts - 2) " "+ _ -> "- " -- remove trailing blank line if item ends with a tight list let contents' = if itemEndsWithTightList bs then chomp contents <> cr@@ -740,26 +861,23 @@ let tabStop = writerTabStop opts variant <- asks envVariant let leader = case variant of- PlainText -> " "- Markua -> ":"- _ -> ": "- let sps = case writerTabStop opts - 3 of- n | n > 0 -> literal $ T.replicate n " "- _ -> literal " "+ PlainText -> " "+ _ -> ":"+ let leadingChars = case tabStop of+ -- Always use two leading characters for Markua+ n | variant == Markua -> 2+ | isEnabled Ext_four_space_rule opts+ , n >= 2 -> n+ | otherwise -> 2+ let sps = literal $ T.replicate (leadingChars - 1) " " let isTight = case defs of ((Plain _ : _): _) -> True _ -> False- if isEnabled Ext_compact_definition_lists opts- then do- let contents = vcat $ map (\d -> hang tabStop (leader <> sps)- $ vcat d <> cr) defs'- return $ nowrap labelText <> cr <> contents <> cr- else do- let contents = (if isTight then vcat else vsep) $ map- (\d -> hang tabStop (leader <> sps) $ vcat d)- defs'- return $ blankline <> nowrap labelText $$- (if isTight then empty else blankline) <> contents <> blankline+ let contents = (if isTight then vcat else vsep) $ map+ (\d -> hang leadingChars (leader <> sps) $ vcat d)+ defs'+ return $ blankline <> nowrap labelText $$+ (if isTight then empty else blankline) <> contents <> blankline else return $ nowrap (chomp labelText <> literal " " <> cr) <> vsep (map vsep defs') <> blankline@@ -812,8 +930,8 @@ isListBlock (DefinitionList _) = True isListBlock _ = False commentSep- | variant == PlainText = Null- | variant == Markua = Null+ | variant == PlainText = Plain []+ | variant == Markua = Plain [] | isEnabled Ext_raw_html opts = RawBlock "html" "<!-- -->\n" | otherwise = RawBlock "markdown" " \n" mconcat <$> mapM (blockToMarkdown opts) (fixBlocks blocks)@@ -822,3 +940,29 @@ lineBreakToSpace LineBreak = Space lineBreakToSpace SoftBreak = Space lineBreakToSpace x = x++removeBlankLinesInHTML :: Text -> Text+removeBlankLinesInHTML = T.pack . go False . T.unpack+ where go _ [] = []+ go True ('\n':cs) = " " <> go False cs+ go False ('\n':cs) = '\n' : go True cs+ go !afternewline (!c:cs)+ | isSpace c = c : go afternewline cs+ | otherwise = c : go False cs++computeDivNestingLevel :: [Block] -> Int+computeDivNestingLevel = foldr go 0+ 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
@@ -3,7 +3,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Writers.Markdown.Inline- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -16,8 +16,11 @@ attrsToMarkdown, attrsToMarkua ) where+import Control.Monad (when, liftM2) import Control.Monad.Reader+ ( asks, MonadReader(local) ) import Control.Monad.State.Strict+ ( MonadState(get), gets, modify ) import Data.Char (isAlphaNum, isDigit) import Data.List (find, intersperse) import Data.List.NonEmpty (nonEmpty)@@ -32,7 +35,7 @@ import Text.Pandoc.Parsing hiding (blankline, blanklines, char, space) import Text.DocLayout import Text.Pandoc.Shared-import Text.Pandoc.Network.HTTP (urlEncode)+import Text.Pandoc.URI (urlEncode, escapeURI, isURI) import Text.Pandoc.Writers.Shared import Text.Pandoc.Walk import Text.Pandoc.Writers.HTML (writeHtml5String)@@ -66,6 +69,32 @@ _ -> '@':go cs go' cs = go cs go [] = []+ go ['\\'] = ['\\','\\']+ go ('-':'-':cs)+ | isEnabled Ext_smart opts = '\\':'-':go('-':cs)+ go ('.':'.':'.':cs)+ | isEnabled Ext_smart opts = '\\':'.':'.':'.':go cs+ go (':':':':':':cs)+ | isEnabled Ext_fenced_divs opts -- see #11571+ = '\\':':':':':':': (takeWhile (==':') cs ++ go cs)+ go (c:'_':d:cs)+ | isAlphaNum c+ , isAlphaNum d =+ if isEnabled Ext_intraword_underscores opts+ then c:'_':go (d:cs)+ else c:'\\':'_':go (d:cs)+ go ('\\':c:cs)+ | isEnabled Ext_raw_tex opts = '\\':'\\':go (c:cs)+ | isAlphaNum c = '\\' : go (c:cs)+ | otherwise = '\\':'\\': go cs+ go ('!':'[':cs) = '\\':'!':'[': go cs+ go ('=':'=':cs)+ | isEnabled Ext_mark opts = '\\':'=':go ('=':cs)+ go ('~':'~':cs)+ | isEnabled Ext_strikeout opts = '\\':'~':go ('~':cs)+ go ('&':cs)+ | Right _ <- parse characterReference "" ('&':cs)+ = '\\':'&': go cs go (c:cs) = case c of '[' -> '\\':c:go cs@@ -73,52 +102,33 @@ '`' -> '\\':c:go cs '*' -> '\\':c:go cs '_' -> '\\':c:go cs- '\\' | isEnabled Ext_raw_tex opts -> '\\':c:go cs- | otherwise ->- case cs of -- don't escape \ if we don't have to:- d:_ | isAlphaNum d -> c:go cs- _ -> '\\':c:go cs '>' | isEnabled Ext_all_symbols_escapable opts -> '\\':'>':go cs | otherwise -> ">" ++ go cs '<' | isEnabled Ext_all_symbols_escapable opts -> '\\':'<':go cs | otherwise -> "<" ++ go cs '|' | isEnabled Ext_pipe_tables opts -> '\\':'|':go cs '^' | isEnabled Ext_superscript opts -> '\\':'^':go cs- '~' | isEnabled Ext_subscript opts ||- isEnabled Ext_strikeout opts -> '\\':'~':go cs+ '~' | isEnabled Ext_subscript opts -> '\\':'~':go cs '$' | isEnabled Ext_tex_math_dollars opts -> '\\':'$':go cs '\'' | isEnabled Ext_smart opts -> '\\':'\'':go cs '"' | isEnabled Ext_smart opts -> '\\':'"':go cs- '-' | isEnabled Ext_smart opts ->- case cs of- '-':_ -> '\\':'-':go cs- _ -> '-':go cs- '.' | isEnabled Ext_smart opts ->- case cs of- '.':'.':rest -> '\\':'.':'.':'.':go rest- _ -> '.':go cs- _ -> case cs of- '_':x:xs- | isEnabled Ext_intraword_underscores opts- , isAlphaNum c- , isAlphaNum x -> c : '_' : x : go xs- _ -> c : go cs+ _ -> c : go cs -- Escape the escape character, as well as formatting pairs escapeMarkuaString :: Text -> Text escapeMarkuaString s = foldr (uncurry T.replace) s [("--","~-~-"), ("**","~*~*"),("//","~/~/"),("^^","~^~^"),(",,","~,~,")] -attrsToMarkdown :: Attr -> Doc Text-attrsToMarkdown attribs = braces $ hsep [attribId, attribClasses, attribKeys]+attrsToMarkdown :: WriterOptions -> Attr -> Doc Text+attrsToMarkdown opts attribs = braces $ hsep [attribId, attribClasses, attribKeys] where attribId = case attribs of ("",_,_) -> empty- (i,_,_) -> "#" <> escAttr i+ (i,_,_) -> "#" <> escAttr (writerIdentifierPrefix opts <> i) attribClasses = case attribs of (_,[],_) -> empty (_,cs,_) -> hsep $- map (escAttr . ("."<>))- cs+ map (escAttr . ("."<>)) $+ filter (not . T.null) cs attribKeys = case attribs of (_,_,[]) -> empty (_,_,ks) -> hsep $@@ -130,13 +140,13 @@ escAttrChar '\\' = literal "\\\\" escAttrChar c = literal $ T.singleton c -attrsToMarkua:: Attr -> Doc Text-attrsToMarkua attributes+attrsToMarkua:: WriterOptions -> Attr -> Doc Text+attrsToMarkua opts attributes | null list = empty | otherwise = braces $ intercalateDocText list where attrId = case attributes of ("",_,_) -> []- (i,_,_) -> [literal $ "id: " <> i]+ (i,_,_) -> [literal $ "id: " <> writerIdentifierPrefix opts <> i] -- all non explicit (key,value) attributes besides id are getting -- a default class key to be Markua conform attrClasses = case attributes of@@ -180,7 +190,7 @@ linkAttributes opts attr = if (isEnabled Ext_link_attributes opts || isEnabled Ext_attributes opts) && attr /= nullAttr- then attrsToMarkdown attr+ then attrsToMarkdown opts attr else empty getKey :: Doc Text -> Key@@ -264,6 +274,11 @@ | T.all isDigit (T.take 1 t) -- starts with digit -- see #7058 = liftM2 (<>) (inlineToMarkdown opts x) (go (RawInline (Format "html") "<!-- -->" : y : zs))+ go (Str t : i : is)+ | isLinkOrSpan i+ , T.takeEnd 1 t == "!"+ = do x <- inlineToMarkdown opts (Str (T.dropEnd 1 t))+ ((x <> "\\!") <>) <$> go (i:is) go (i:is) = case i of Link {} -> case is of -- If a link is followed by another link, or '[', '(' or ':'@@ -291,13 +306,17 @@ (RawInline _ (T.stripPrefix " [" -> Just _ )):_ -> unshortcutable _ -> shortcutable _ -> shortcutable- where shortcutable = liftM2 (<>) (inlineToMarkdown opts i) (go is)- unshortcutable = do- iMark <- local- (\env -> env { envRefShortcutable = False })- (inlineToMarkdown opts i)- fmap (iMark <>) (go is)- thead = fmap fst . T.uncons+ where+ shortcutable = liftM2 (<>) (inlineToMarkdown opts i) (go is)+ unshortcutable = do+ iMark <- local+ (\env -> env { envRefShortcutable = False })+ (inlineToMarkdown opts i)+ fmap (iMark <>) (go is)+ thead = fmap fst . T.uncons+ isLinkOrSpan Link{} = True+ isLinkOrSpan Span{} = True+ isLinkOrSpan _ = False -- Remove breaking spaces that might cause bad wraps. avoidBadWraps :: Bool -> Doc Text -> Doc Text@@ -319,14 +338,6 @@ toList (Concat a b) = a : toList b toList x = [x] -isOrderedListMarker :: Text -> Bool-isOrderedListMarker xs = not (T.null xs) && (T.last xs `elem` ['.',')']) &&- isRight (runParser (anyOrderedListMarker >> eof)- defaultParserState "" xs)- where- isRight (Right _) = True- isRight (Left _) = False- -- | Convert Pandoc inline element to markdown. inlineToMarkdown :: PandocMonad m => WriterOptions -> Inline -> MD m (Doc Text) inlineToMarkdown opts (Span ("",["emoji"],kvs) [Str s]) =@@ -334,6 +345,10 @@ Just emojiname | isEnabled Ext_emoji opts -> return $ ":" <> literal emojiname <> ":" _ -> inlineToMarkdown opts (Str s)+inlineToMarkdown opts (Span ("",["mark"],[]) ils)+ | isEnabled Ext_mark opts+ = do contents <- inlineListToMarkdown opts ils+ return $ "==" <> contents <> "==" inlineToMarkdown opts (Span attrs ils) = do variant <- asks envVariant contents <- inlineListToMarkdown opts ils@@ -344,11 +359,11 @@ _ -> id $ case variant of PlainText -> contents- Markua -> "`" <> contents <> "`" <> attrsToMarkua attrs+ Markua -> "`" <> contents <> "`" <> attrsToMarkua opts attrs _ | attrs == nullAttr -> contents | isEnabled Ext_bracketed_spans opts -> let attrs' = if attrs /= nullAttr- then attrsToMarkdown attrs+ then attrsToMarkdown opts attrs else empty in "[" <> contents <> "]" <> attrs' | isEnabled Ext_raw_html opts ||@@ -356,14 +371,16 @@ tagWithAttrs "span" attrs <> contents <> literal "</span>" | otherwise -> contents inlineToMarkdown _ (Emph []) = return empty+inlineToMarkdown opts (Emph [Emph ils]) = -- #10642+ inlineListToMarkdown opts ils inlineToMarkdown opts (Emph lst) = do variant <- asks envVariant contents <- inlineListToMarkdown opts lst return $ case variant of PlainText- | isEnabled Ext_gutenberg opts -> "_" <> contents <> "_"+ | isEnabled Ext_gutenberg opts -> delimited "_" "_" contents | otherwise -> contents- _ -> "*" <> contents <> "*"+ _ -> delimited "*" "*" contents inlineToMarkdown _ (Underline []) = return empty inlineToMarkdown opts (Underline lst) = do variant <- asks envVariant@@ -371,7 +388,7 @@ case variant of PlainText -> return contents _ | isEnabled Ext_bracketed_spans opts ->- return $ "[" <> contents <> "]" <> "{.underline}"+ return $ delimited "[" "]{.underline}" contents | isEnabled Ext_native_spans opts -> return $ tagWithAttrs "span" ("", ["underline"], []) <> contents@@ -390,12 +407,12 @@ else lst _ -> do contents <- inlineListToMarkdown opts lst- return $ "**" <> contents <> "**"+ return $ delimited "**" "**" contents inlineToMarkdown _ (Strikeout []) = return empty inlineToMarkdown opts (Strikeout lst) = do contents <- inlineListToMarkdown opts lst return $ if isEnabled Ext_strikeout opts- then "~~" <> contents <> "~~"+ then delimited "~~" "~~" contents else if isEnabled Ext_raw_html opts then "<s>" <> contents <> "</s>" else contents@@ -404,7 +421,7 @@ local (\env -> env {envEscapeSpaces = envVariant env == Markdown}) $ do contents <- inlineListToMarkdown opts lst if isEnabled Ext_superscript opts- then return $ "^" <> contents <> "^"+ then return $ delimited "^" "^" contents else if isEnabled Ext_raw_html opts then return $ "<sup>" <> contents <> "</sup>" else@@ -422,7 +439,7 @@ local (\env -> env {envEscapeSpaces = envVariant env == Markdown}) $ do contents <- inlineListToMarkdown opts lst if isEnabled Ext_subscript opts- then return $ "~" <> contents <> "~"+ then return $ delimited "~" "~" contents else if isEnabled Ext_raw_html opts then return $ "<sub>" <> contents <> "</sub>" else@@ -466,9 +483,9 @@ let attrsEnabled = isEnabled Ext_inline_code_attributes opts || isEnabled Ext_attributes opts let attrs = case variant of- Markua -> attrsToMarkua attr+ Markua -> attrsToMarkua opts attr _ -> if attrsEnabled && attr /= nullAttr- then attrsToMarkdown attr+ then attrsToMarkdown opts attr else empty case variant of PlainText -> return $ literal str@@ -489,22 +506,24 @@ else escapeText opts) $ str return $ literal str' inlineToMarkdown opts (Math InlineMath str) = do+ let str' = T.strip str variant <- asks envVariant case () of _ | variant == Markua -> return $ "`" <> literal str <> "`" <> "$" | otherwise -> case writerHTMLMathMethod opts of WebTeX url ->- let str' = T.strip str- in inlineToMarkdown opts+ inlineToMarkdown opts (Image nullAttr [Str str'] (url <> urlEncode str', str'))- _ | isEnabled Ext_tex_math_dollars opts ->- return $ "$" <> literal str <> "$"+ _ | isEnabled Ext_tex_math_gfm opts ->+ return $ "$`" <> literal str' <> "`$"+ | isEnabled Ext_tex_math_dollars opts ->+ return $ "$" <> literal str' <> "$" | isEnabled Ext_tex_math_single_backslash opts ->- return $ "\\(" <> literal str <> "\\)"+ return $ "\\(" <> literal str' <> "\\)" | isEnabled Ext_tex_math_double_backslash opts ->- return $ "\\\\(" <> literal str <> "\\\\)"+ return $ "\\\\(" <> literal str' <> "\\\\)" | otherwise ->- texMathToInlines InlineMath str >>=+ texMathToInlines InlineMath str' >>= inlineListToMarkdown opts . (if variant == PlainText then makeMathPlainer else id) @@ -512,7 +531,7 @@ variant <- asks envVariant case () of _ | variant == Markua -> do- let attributes = attrsToMarkua (addKeyValueToAttr ("",[],[])+ let attributes = attrsToMarkua opts (addKeyValueToAttr ("",[],[]) ("format", "latex")) return $ blankline <> attributes <> cr <> literal "```" <> cr <> literal str <> cr <> literal "```" <> blankline@@ -522,7 +541,11 @@ in (\x -> blankline <> x <> blankline) `fmap` inlineToMarkdown opts (Image nullAttr [Str str'] (url <> urlEncode str', str'))- _ | isEnabled Ext_tex_math_dollars opts ->+ _ | isEnabled Ext_tex_math_gfm opts ->+ return $ cr <> (literal "``` math"+ $$ literal (T.dropAround (=='\n') str)+ $$ literal "```") <> cr+ | isEnabled Ext_tex_math_dollars opts -> return $ "$$" <> literal str <> "$$" | isEnabled Ext_tex_math_single_backslash opts -> return $ "\\[" <> literal str <> "\\]"@@ -566,7 +589,7 @@ if variant == PlainText || isEnabled Ext_hard_line_breaks opts then return cr else return $- if isEnabled Ext_escaped_line_breaks opts+ if variant == Commonmark || isEnabled Ext_escaped_line_breaks opts then "\\" <> cr else " " <> cr inlineToMarkdown _ Space = do@@ -634,10 +657,14 @@ case txt of [Str s] | escapeURI s == srcSuffix -> True _ -> False+ let useWikilink = "wikilink" `elem` classes &&+ (isEnabled Ext_wikilinks_title_after_pipe opts ||+ isEnabled Ext_wikilinks_title_before_pipe opts) let useRefLinks = writerReferenceLinks opts && not useAuto shortcutable <- asks envRefShortcutable let useShortcutRefLinks = shortcutable &&- isEnabled Ext_shortcut_reference_links opts+ (variant == Commonmark ||+ isEnabled Ext_shortcut_reference_links opts) reftext <- if useRefLinks then literal <$> getReference attr linktext (src, tit) else return mempty@@ -646,11 +673,18 @@ | useAuto -> return $ literal srcSuffix | otherwise -> return linktext Markua- | T.null tit -> return $ result <> attrsToMarkua attr- | otherwise -> return $ result <> attrsToMarkua attributes+ | T.null tit -> return $ result <> attrsToMarkua opts attr+ | otherwise -> return $ result <> attrsToMarkua opts attributes where result = "[" <> linktext <> "](" <> (literal src) <> ")" attributes = addKeyValueToAttr attr ("title", tit)- _ | useAuto -> return $ "<" <> literal srcSuffix <> ">"+ -- Use wikilinks where possible+ _ | src == stringify txt && useWikilink ->+ return $ "[[" <> literal (stringify txt) <> "]]"+ | useAuto -> return $ "<" <> literal srcSuffix <> ">"+ | useWikilink && isEnabled Ext_wikilinks_title_after_pipe opts -> return $+ "[[" <> literal src <> "|" <> literal (stringify txt) <> "]]"+ | useWikilink && isEnabled Ext_wikilinks_title_before_pipe opts -> return $+ "[[" <> literal (stringify txt) <> "|" <> literal src <> "]]" | useRefLinks -> let first = "[" <> linktext <> "]" second = if getKey linktext == getKey reftext@@ -682,7 +716,7 @@ else alternate linkPart <- inlineToMarkdown opts (Link attr txt (source, tit)) alt <- inlineListToMarkdown opts alternate- let attributes | variant == Markua = attrsToMarkua $+ let attributes | variant == Markua = attrsToMarkua opts $ addKeyValueToAttr (addKeyValueToAttr attr ("title", tit)) ("alt", render (Just (writerColumns opts)) alt) | otherwise = empty@@ -704,19 +738,3 @@ where go (Emph xs) = Span nullAttr xs go x = x--toSubscriptInline :: Inline -> Maybe Inline-toSubscriptInline Space = Just Space-toSubscriptInline (Span attr ils) = Span attr <$> traverse toSubscriptInline ils-toSubscriptInline (Str s) = Str . T.pack <$> traverse toSubscript (T.unpack s)-toSubscriptInline LineBreak = Just LineBreak-toSubscriptInline SoftBreak = Just SoftBreak-toSubscriptInline _ = Nothing--toSuperscriptInline :: Inline -> Maybe Inline-toSuperscriptInline Space = Just Space-toSuperscriptInline (Span attr ils) = Span attr <$> traverse toSuperscriptInline ils-toSuperscriptInline (Str s) = Str . T.pack <$> traverse toSuperscript (T.unpack s)-toSuperscriptInline LineBreak = Just LineBreak-toSuperscriptInline SoftBreak = Just SoftBreak-toSuperscriptInline _ = Nothing
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.Markdown- Copyright : © 2006-2022 John MacFarlane+ Copyright : © 2006-2024 John MacFarlane License : GPL-2.0-or-later Maintainer : John MacFarlane <jgm@berkeley.edu> @@ -36,23 +36,30 @@ -> MD m (Doc Text) pipeTable opts headless aligns widths rawHeaders rawRows = do let sp = literal " "- let blockFor AlignLeft x y = lblock (x + 2) (sp <> y) <> lblock 0 empty- blockFor AlignCenter x y = cblock (x + 2) (sp <> y <> sp) <> lblock 0 empty- blockFor AlignRight x y = rblock (x + 2) (y <> sp) <> lblock 0 empty- blockFor _ x y = lblock (x + 2) (sp <> y) <> lblock 0 empty let contentWidths = map (max 3 . maybe 3 maximum . nonEmpty . map offset) $ transpose (rawHeaders : rawRows) let colwidth = writerColumns opts let numcols = length contentWidths let maxwidth = sum contentWidths+ -- if cell contents are > COLUMNS, adding padding looks bad+ let pad = maxwidth <= writerColumns opts+ let blockFor _ _ y | not pad = sp <> y <> sp <> lblock 0 empty+ blockFor AlignLeft x y = lblock (x + 2) (sp <> y) <> lblock 0 empty+ blockFor AlignCenter x y = cblock (x + 2) (sp <> y <> sp) <> lblock 0 empty+ blockFor AlignRight x y = rblock (x + 2) (y <> sp) <> lblock 0 empty+ blockFor AlignDefault x y = lblock (x + 2) (sp <> y) <> lblock 0 empty variant <- asks envVariant let pipeWidths = if variant == Markdown && not (all (== 0) widths) && maxwidth + (numcols + 1) > colwidth then map- (floor . (* fromIntegral (colwidth - (numcols +1))))+ (max 0 .+ floor .+ (* fromIntegral (colwidth - (numcols +1)))) widths- else contentWidths+ else if pad+ then contentWidths+ else map (const 2) widths let torow cs = nowrap $ literal "|" <> hcat (intersperse (literal "|") $ zipWith3 blockFor aligns contentWidths (map chomp cs))
@@ -1,7 +1,6 @@-{-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.Markdown.Types- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -78,5 +77,3 @@ , stIds = Set.empty , stNoteNum = 1 }--
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.MediaWiki- Copyright : Copyright (C) 2008-2022 John MacFarlane+ Copyright : Copyright (C) 2008-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -16,23 +16,28 @@ import Control.Monad.Reader import Control.Monad.State.Strict import Data.Maybe (fromMaybe)+import qualified Data.List as DL import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T+import Data.List.NonEmpty (NonEmpty((:|))) import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Definition import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.DocLayout (render, literal)+import Text.DocLayout import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate)+import qualified Text.Pandoc.Writers.AnnotatedTable as Ann import Text.Pandoc.Writers.Shared import Text.Pandoc.XML (escapeStringForXML) data WriterState = WriterState { stNotes :: Bool -- True if there are notes , stOptions :: WriterOptions -- writer options+ , stInDefLabel :: Bool -- True if in definition list label } data WriterReader = WriterReader {@@ -46,7 +51,8 @@ -- | Convert Pandoc to MediaWiki. writeMediaWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeMediaWiki opts document =- let initialState = WriterState { stNotes = False, stOptions = opts }+ let initialState = WriterState {+ stNotes = False, stOptions = opts, stInDefLabel = False } env = WriterReader { options = opts, listLevel = [], useTags = False } in evalStateT (runReaderT (pandocToMediaWiki document) env) initialState @@ -55,21 +61,21 @@ pandocToMediaWiki (Pandoc meta blocks) = do opts <- asks options metadata <- metaToContext opts- (fmap (literal . trimr) . blockListToMediaWiki)- (fmap (literal . trimr) . inlineListToMediaWiki)+ (fmap chomp . blockListToMediaWiki)+ (fmap chomp . inlineListToMediaWiki) meta body <- blockListToMediaWiki blocks notesExist <- gets stNotes let notes = if notesExist- then "\n<references />"- else ""+ then cr <> literal "<references />"+ else mempty let main = body <> notes let context = defField "body" main $ defField "toc" (writerTableOfContents opts) metadata- return $+ return $ render Nothing $ case writerTemplate opts of Nothing -> main- Just tpl -> render Nothing $ renderTemplate tpl context+ Just tpl -> renderTemplate tpl context -- | Escape special characters for MediaWiki. escapeText :: Text -> Text@@ -78,14 +84,14 @@ -- | Convert Pandoc block element to MediaWiki. blockToMediaWiki :: PandocMonad m => Block -- ^ Block element- -> MediaWikiWriter m Text--blockToMediaWiki Null = return ""+ -> MediaWikiWriter m (Doc Text) blockToMediaWiki (Div attrs bs) = do contents <- blockListToMediaWiki bs- return $ render Nothing (tagWithAttrs "div" attrs) <> "\n\n" <>- contents <> "\n\n" <> "</div>"+ return $ tagWithAttrs "div" attrs $$+ contents $$+ literal "</div>" $$+ blankline blockToMediaWiki (Plain inlines) = inlineListToMediaWiki inlines@@ -93,57 +99,69 @@ blockToMediaWiki (SimpleFigure attr txt (src, tit)) = do capt <- inlineListToMediaWiki txt img <- imageToMediaWiki attr+ let capt' = render Nothing capt let opt = if T.null tit then- if T.null capt+ if T.null capt' then ""- else "alt=" <> capt+ else "alt=" <> capt' else "alt=" <> tit- return $ "[[" <>- T.intercalate "|"- (filter (not . T.null) ["File:" <> src- , "thumb"- , "none"- , img- , opt- , capt- ]) <>- "]]\n"+ let separator = "<nowiki></nowiki>"+ -- External images (URIs) cannot use [[File:...]] syntax;+ -- they must be rendered as bare URLs. MediaWiki will auto-embed+ -- them when $wgAllowExternalImages is enabled.+ return $ if isURI src+ then literal (separator <> src <> separator) <> cr+ else literal ("[[" <>+ T.intercalate "|"+ (filter (not . T.null) ["File:" <> src+ , "thumb"+ , "none"+ , img+ , opt+ , capt'+ ]) <>+ "]]") <> cr blockToMediaWiki (Para inlines) = do tags <- asks useTags lev <- asks listLevel contents <- inlineListToMediaWiki inlines+ let contents' = render Nothing contents+ let initEsc = if startsWithListMarker contents'+ then literal "<nowiki></nowiki>"+ else mempty return $ if tags- then "<p>" <> contents <> "</p>"- else contents <> if null lev then "\n" else ""+ then literal "<p>" <> contents <> literal "</p>"+ else initEsc <> contents $$+ if null lev then blankline else mempty blockToMediaWiki (LineBlock lns) = blockToMediaWiki $ linesToPara lns blockToMediaWiki b@(RawBlock f str)- | f == Format "mediawiki" = return str- | f == Format "html" = return str- | otherwise = "" <$ report (BlockNotRendered b)+ | f == Format "mediawiki" = return $ literal str+ | f == Format "html" = return $ literal str+ | otherwise = mempty <$ report (BlockNotRendered b) -blockToMediaWiki HorizontalRule = return "\n-----\n"+blockToMediaWiki HorizontalRule = return $ blankline <> literal "-----" <> blankline blockToMediaWiki (Header level (ident,_,_) inlines) = do let autoId = T.replace " " "_" $ stringify inlines contents <- inlineListToMediaWiki inlines- let eqs = T.replicate level "="+ let eqs = literal $ T.replicate level "=" return $ (if T.null ident || autoId == ident- then ""- else "<span id=\"" <> ident <> "\"></span>\n")- <> eqs <> " " <> contents <> " " <> eqs <> "\n"+ then mempty+ else literal ("<span id=\"" <> ident <> "\"></span>") <> cr)+ <> eqs <> space <> contents <> space <> eqs <> blankline blockToMediaWiki (CodeBlock (_,classes,keyvals) str) = do let at = Set.fromList classes `Set.intersection` highlightingLangs let numberLines = any (`elem` ["number","numberLines", "number-lines"]) classes let start = lookup "startFrom" keyvals- return $+ return $ literal $ case Set.toList at of [] -> "<pre" <> (if null classes then ">"@@ -158,21 +176,10 @@ blockToMediaWiki (BlockQuote blocks) = do contents <- blockListToMediaWiki blocks- return $ "<blockquote>" <> contents <> "</blockquote>"+ return $ literal "<blockquote>" <> chomp contents <> cr <> literal "</blockquote>" -blockToMediaWiki (Table _ blkCapt specs thead tbody tfoot) = do- let (capt, aligns, widths, headers, rows') = toLegacyTable blkCapt specs thead tbody tfoot- caption <- if null capt- then return ""- else do- c <- inlineListToMediaWiki capt- return $ "|+ " <> trimr c <> "\n"- let headless = all null headers- let allrows = if headless then rows' else headers:rows'- tableBody <- T.intercalate "|-\n" `fmap`- mapM (tableRowToMediaWiki headless aligns widths)- (zip [1..] allrows)- return $ "{|\n" <> caption <> tableBody <> "|}\n"+blockToMediaWiki (Table attr capt colSpecs thead tbody tfoot) = do+ tableToMediaWiki (Ann.toTable attr capt colSpecs thead tbody tfoot) blockToMediaWiki x@(BulletList items) = do tags <-@@ -180,11 +187,11 @@ if tags then do contents <- local (\ s -> s { useTags = True }) $ mapM listItemToMediaWiki items- return $ "<ul>\n" <> vcat contents <> "</ul>\n"+ return $ literal "<ul>" <> cr <> vcat contents <> literal "</ul>" <> blankline else do lev <- asks listLevel contents <- local (\s -> s { listLevel = listLevel s <> "*" }) $ mapM listItemToMediaWiki items- return $ vcat contents <> if null lev then "\n" else ""+ return $ vcat contents <> if null lev then blankline else mempty blockToMediaWiki x@(OrderedList attribs items) = do tags <-@@ -192,11 +199,11 @@ if tags then do contents <- local (\s -> s { useTags = True }) $ mapM listItemToMediaWiki items- return $ "<ol" <> listAttribsToText attribs <> ">\n" <> vcat contents <> "</ol>\n"+ return $ literal ("<ol" <> listAttribsToText attribs <> ">") <> cr <> vcat contents <> literal "</ol>" <> blankline else do lev <- asks listLevel contents <- local (\s -> s { listLevel = listLevel s <> "#" }) $ mapM listItemToMediaWiki items- return $ vcat contents <> if null lev then "\n" else ""+ return $ vcat contents <> if null lev then blankline else mempty blockToMediaWiki x@(DefinitionList items) = do tags <-@@ -204,12 +211,15 @@ if tags then do contents <- local (\s -> s { useTags = True }) $ mapM definitionListItemToMediaWiki items- return $ "<dl>\n" <> vcat contents <> "</dl>\n"+ return $ literal "<dl>" <> cr <> vcat contents <> literal "</dl>" <> blankline else do lev <- asks listLevel contents <- local (\s -> s { listLevel = listLevel s <> ";" }) $ mapM definitionListItemToMediaWiki items- return $ vcat contents <> if null lev then "\n" else ""+ return $ vcat contents <> if null lev then blankline else mempty +blockToMediaWiki (Figure (ident, classes, kvs) _ body) =+ blockToMediaWiki (Div (ident, ["figure"] `DL.union` classes, kvs) body)+ -- Auxiliary functions for lists: -- | Convert ordered list attributes to HTML attribute string@@ -224,31 +234,33 @@ else "") -- | Convert bullet or ordered list item (list of blocks) to MediaWiki.-listItemToMediaWiki :: PandocMonad m => [Block] -> MediaWikiWriter m Text+listItemToMediaWiki :: PandocMonad m => [Block] -> MediaWikiWriter m (Doc Text) listItemToMediaWiki items = do contents <- blockListToMediaWiki items tags <- asks useTags if tags- then return $ "<li>" <> contents <> "</li>"+ then return $ literal "<li>" <> chomp contents <> literal "</li>" else do marker <- asks listLevel- return $ T.pack marker <> " " <> contents+ return $ literal (T.pack marker) <> space <> chomp contents -- | Convert definition list item (label, list of blocks) to MediaWiki. definitionListItemToMediaWiki :: PandocMonad m => ([Inline],[[Block]])- -> MediaWikiWriter m Text+ -> MediaWikiWriter m (Doc Text) definitionListItemToMediaWiki (label, items) = do+ modify $ \st -> st{ stInDefLabel = True } labelText <- inlineListToMediaWiki label+ modify $ \st -> st{ stInDefLabel = False } contents <- mapM blockListToMediaWiki items tags <- asks useTags if tags- then return $ "<dt>" <> labelText <> "</dt>\n" <>- T.intercalate "\n" (map (\d -> "<dd>" <> d <> "</dd>") contents)+ then return $ literal "<dt>" <> chomp labelText <> literal "</dt>" <> cr <>+ vcat (map (\d -> literal "<dd>" <> chomp d <> literal "</dd>") contents) else do marker <- asks listLevel- return $ T.pack marker <> " " <> labelText <> "\n" <>- T.intercalate "\n" (map (\d -> T.pack (init marker) <> ": " <> d) contents)+ return $ literal (T.pack marker) <> space <> chomp labelText <> cr <>+ vcat (map (\d -> literal (T.pack (init marker)) <> literal ": " <> chomp d) contents) -- | True if the list can be handled by simple wiki markup, False if HTML tags will be needed. isSimpleList :: Block -> Bool@@ -285,53 +297,76 @@ isPlainOrPara (Para _) = True isPlainOrPara _ = False --- | Concatenates strings with line breaks between them.-vcat :: [Text] -> Text-vcat = T.intercalate "\n"- -- Auxiliary functions for tables: -tableRowToMediaWiki :: PandocMonad m- => Bool- -> [Alignment]- -> [Double]- -> (Int, [[Block]])- -> MediaWikiWriter m Text-tableRowToMediaWiki headless alignments widths (rownum, cells) = do- cells' <- mapM (tableCellToMediaWiki headless rownum)- $ zip3 alignments widths cells- return $ T.unlines cells'+tableToMediaWiki :: PandocMonad m => Ann.Table -> MediaWikiWriter m (Doc Text)+tableToMediaWiki (Ann.Table attr capt _ thead tbodies tfoot) = do+ let (ident,classes,kvs) = attr+ caption <- case capt of+ Caption _ [] -> return mempty+ Caption _ longCapt -> do+ c <- blockListToMediaWiki longCapt+ return $ literal "|+ " <> chomp c <> cr+ head' <- tableHeadToMW thead+ bodies' <- mconcat <$> mapM tableBodyToMW tbodies+ foot' <- tableFootToMW tfoot+ return $ literal "{|" <> htmlAttrs (ident, "wikitable":classes, kvs) <> cr+ <> caption <> head' <> bodies' <> foot'+ <> literal "|}" <> blankline -tableCellToMediaWiki :: PandocMonad m- => Bool- -> Int- -> (Alignment, Double, [Block])- -> MediaWikiWriter m Text-tableCellToMediaWiki headless rownum (alignment, width, bs) = do- contents <- blockListToMediaWiki bs- let marker = if rownum == 1 && not headless then "!" else "|"- let percent w = tshow (truncate (100*w) :: Integer) <> "%"- let attrs = ["align=" <> tshow (alignmentToText alignment) |- alignment /= AlignDefault && alignment /= AlignLeft] <>- ["width=\"" <> percent width <> "\"" |- width /= 0.0 && rownum == 1]- let attr = if null attrs- then ""- else T.unwords attrs <> "|"- let sep = case bs of- [Plain _] -> " "- [Para _] -> " "- [] -> ""- _ -> "\n"- return $ marker <> attr <> sep <> trimr contents+tableHeadToMW :: PandocMonad m => Ann.TableHead -> MediaWikiWriter m (Doc Text)+tableHeadToMW (Ann.TableHead _ rows) = headerRowsToMW rows -alignmentToText :: Alignment -> Text-alignmentToText alignment = case alignment of- AlignLeft -> "left"- AlignRight -> "right"- AlignCenter -> "center"- AlignDefault -> "left"+tableFootToMW :: PandocMonad m => Ann.TableFoot -> MediaWikiWriter m (Doc Text)+tableFootToMW (Ann.TableFoot _ rows) = headerRowsToMW rows +tableBodyToMW :: PandocMonad m => Ann.TableBody -> MediaWikiWriter m (Doc Text)+tableBodyToMW (Ann.TableBody _ _ headerRows bodyRows) = do+ headerRows' <- headerRowsToMW headerRows+ bodyRows' <- bodyRowsToMW bodyRows+ return $ headerRows' <> bodyRows'++headerRowsToMW :: PandocMonad m => [Ann.HeaderRow] -> MediaWikiWriter m (Doc Text)+headerRowsToMW rows = mconcat <$> mapM headerRowToMW rows++headerRowToMW :: PandocMonad m => Ann.HeaderRow -> MediaWikiWriter m (Doc Text)+headerRowToMW (Ann.HeaderRow attr _ cells) = do+ cells' <- mconcat <$> mapM (cellToMW "!") cells+ return $ literal "|-" <> htmlAttrs attr <> cr <> cells'++bodyRowsToMW :: PandocMonad m => [Ann.BodyRow] -> MediaWikiWriter m (Doc Text)+bodyRowsToMW rows = mconcat <$> mapM bodyRowToMW rows++bodyRowToMW :: PandocMonad m => Ann.BodyRow -> MediaWikiWriter m (Doc Text)+bodyRowToMW (Ann.BodyRow attr _ headCells bodyCells) = do+ headCells' <- mconcat <$> mapM (cellToMW "!") headCells+ bodyCells' <- mconcat <$> mapM (cellToMW "|") bodyCells+ return $ literal "|-" <> htmlAttrs attr <> cr <> headCells' <> bodyCells'++cellToMW :: PandocMonad m => Text -> Ann.Cell -> MediaWikiWriter m (Doc Text)+cellToMW marker (Ann.Cell (colSpec :| _) _ (Cell attr align rowspan colspan content)) = do+ content' <- blockListToMediaWiki content+ let (ident,classes,keyVals) = attr++ let align' = case align of+ AlignDefault -> fst colSpec+ _ -> align+ let keyVals' = case (htmlAlignmentToString align') of+ Nothing -> keyVals+ Just alignStr -> htmlAddStyle ("text-align", alignStr) keyVals+ let rowspan' = case rowspan of+ RowSpan 1 -> mempty+ RowSpan n -> [("rowspan", T.pack(show n))]+ let colspan' = case colspan of+ ColSpan 1 -> mempty+ ColSpan n -> [("colspan", T.pack(show n))]+ let attrs' = htmlAttrs (ident, classes, rowspan' <> colspan' <> keyVals')+ let attrsRendered = render Nothing attrs'+ let pipeAttr = if T.null attrsRendered then mempty else attrs' <> literal "|"+ let contentRendered = render Nothing content'+ let spaceContent = if T.null contentRendered then mempty else space <> chomp content'+ return $ literal marker <> pipeAttr <> spaceContent <> cr+ imageToMediaWiki :: PandocMonad m => Attr -> MediaWikiWriter m Text imageToMediaWiki attr = do opts <- gets stOptions@@ -352,14 +387,14 @@ -- | Convert list of Pandoc block elements to MediaWiki. blockListToMediaWiki :: PandocMonad m => [Block] -- ^ List of block elements- -> MediaWikiWriter m Text+ -> MediaWikiWriter m (Doc Text) blockListToMediaWiki blocks = vcat <$> mapM blockToMediaWiki blocks -- | Convert list of Pandoc inline elements to MediaWiki.-inlineListToMediaWiki :: PandocMonad m => [Inline] -> MediaWikiWriter m Text+inlineListToMediaWiki :: PandocMonad m => [Inline] -> MediaWikiWriter m (Doc Text) inlineListToMediaWiki lst =- fmap T.concat $ mapM inlineToMediaWiki $ fixup lst+ hcat <$> mapM inlineToMediaWiki (fixup lst) where fixup [] = [] fixup (Str t : x : xs)@@ -372,111 +407,129 @@ isLinkOrImage _ = False -- | Convert Pandoc inline element to MediaWiki.-inlineToMediaWiki :: PandocMonad m => Inline -> MediaWikiWriter m Text+inlineToMediaWiki :: PandocMonad m => Inline -> MediaWikiWriter m (Doc Text) inlineToMediaWiki (Span attrs ils) = do contents <- inlineListToMediaWiki ils- return $ render Nothing (tagWithAttrs "span" attrs) <> contents <> "</span>"+ return $ tagWithAttrs "span" attrs <> contents <> literal "</span>" inlineToMediaWiki (Emph lst) = do contents <- inlineListToMediaWiki lst- return $ "''" <> contents <> "''"+ return $ literal "''" <> contents <> literal "''" inlineToMediaWiki (Underline lst) = do contents <- inlineListToMediaWiki lst- return $ "<u>" <> contents <> "</u>"+ return $ literal "<u>" <> contents <> literal "</u>" inlineToMediaWiki (Strong lst) = do contents <- inlineListToMediaWiki lst- return $ "'''" <> contents <> "'''"+ return $ literal "'''" <> contents <> literal "'''" inlineToMediaWiki (Strikeout lst) = do contents <- inlineListToMediaWiki lst- return $ "<s>" <> contents <> "</s>"+ return $ literal "<s>" <> contents <> literal "</s>" inlineToMediaWiki (Superscript lst) = do contents <- inlineListToMediaWiki lst- return $ "<sup>" <> contents <> "</sup>"+ return $ literal "<sup>" <> contents <> literal "</sup>" inlineToMediaWiki (Subscript lst) = do contents <- inlineListToMediaWiki lst- return $ "<sub>" <> contents <> "</sub>"+ return $ literal "<sub>" <> contents <> literal "</sub>" inlineToMediaWiki (SmallCaps lst) = inlineListToMediaWiki lst inlineToMediaWiki (Quoted SingleQuote lst) = do contents <- inlineListToMediaWiki lst- return $ "\8216" <> contents <> "\8217"+ return $ literal "\8216" <> contents <> literal "\8217" inlineToMediaWiki (Quoted DoubleQuote lst) = do contents <- inlineListToMediaWiki lst- return $ "\8220" <> contents <> "\8221"+ return $ literal "\8220" <> contents <> literal "\8221" inlineToMediaWiki (Cite _ lst) = inlineListToMediaWiki lst inlineToMediaWiki (Code _ str) =- return $ "<code>" <> escapeText str <> "</code>"+ return $ literal $ "<code>" <> escapeText str <> "</code>" -inlineToMediaWiki (Str str) = return $ escapeText str+inlineToMediaWiki (Str str) = do+ inDefLabel <- gets stInDefLabel+ return $ literal $+ if inDefLabel+ then T.intercalate "<nowiki>:</nowiki>" $+ map escapeText $ T.splitOn ":" str+ else escapeText str -inlineToMediaWiki (Math mt str) = return $+inlineToMediaWiki (Math mt str) = return $ literal $ "<math display=\"" <> (if mt == DisplayMath then "block" else "inline") <> "\">" <> str <> "</math>" -- note: str should NOT be escaped inlineToMediaWiki il@(RawInline f str)- | f == Format "mediawiki" = return str- | f == Format "html" = return str- | otherwise = "" <$ report (InlineNotRendered il)+ | f == Format "mediawiki" = return $ literal str+ | f == Format "html" = return $ literal str+ | otherwise = mempty <$ report (InlineNotRendered il) -inlineToMediaWiki LineBreak = return "<br />\n"+inlineToMediaWiki LineBreak = return $ literal "<br />" <> cr inlineToMediaWiki SoftBreak = do wrapText <- gets (writerWrapText . stOptions) listlevel <- asks listLevel case wrapText of- WrapAuto -> return " "- WrapNone -> return " "+ WrapAuto -> return space+ WrapNone -> return space WrapPreserve -> if null listlevel- then return "\n"- else return " "+ then return cr+ else return space -inlineToMediaWiki Space = return " "+inlineToMediaWiki Space = return space inlineToMediaWiki (Link _ txt (src, _)) = do- label <- inlineListToMediaWiki txt+ -- We need to remove links from link text, because an <a> element is+ -- not allowed inside another <a> element.+ label <- inlineListToMediaWiki (removeLinks txt)+ let label' = render Nothing label case txt of- [Str s] | isURI src && escapeURI s == src -> return src- _ -> return $ if isURI src- then "[" <> src <> " " <> label <> "]"+ [Str s] | isURI src && escapeURI s == src -> return $ literal src+ _ -> return $ literal $ if isURI (T.takeWhile (/= '#') src) -- see #11562+ then "[" <> src <> " " <> label' <> "]" else- if src == label+ if src == label' then "[[" <> src' <> "]]"- else "[[" <> src' <> "|" <> label <> "]]"+ else "[[" <> src' <> "|" <> label' <> "]]" -- with leading / it's a link to a help page where src' = fromMaybe src $ T.stripPrefix "/" src inlineToMediaWiki (Image attr alt (source, tit)) = do- img <- imageToMediaWiki attr- alt' <- inlineListToMediaWiki alt- let txt = if T.null alt'- then if T.null tit- then ""- else tit- else alt'- return $ "[[" <>- T.intercalate "|"- (filter (not . T.null)- [ "File:" <> source- , img- , txt- ]) <> "]]"+ let separator = "<nowiki></nowiki>"+ -- External images (URIs) cannot use [[File:...]] syntax;+ -- they must be rendered as bare URLs. MediaWiki will auto-embed+ -- them when $wgAllowExternalImages is enabled.+ if isURI source+ then return $ literal $ separator <> source <> separator+ else do+ img <- imageToMediaWiki attr+ alt' <- inlineListToMediaWiki alt+ let altText = render Nothing alt'+ let txt = if T.null altText+ then if T.null tit+ then ""+ else tit+ else altText+ return $ literal $ "[[" <>+ T.intercalate "|"+ (filter (not . T.null)+ [ "File:" <> source+ , img+ , txt+ ]) <> "]]" inlineToMediaWiki (Note contents) = do contents' <- blockListToMediaWiki contents modify (\s -> s { stNotes = True })- return $ "<ref>" <> stripTrailingNewlines contents' <> "</ref>"+ let rendered = render Nothing contents'+ return $ literal $ "<ref>" <> stripTrailingNewlines rendered <> "</ref>" -- note - does not work for notes with multiple blocks highlightingLangs :: Set.Set Text@@ -663,6 +716,7 @@ "ex", "exs", "ezhil",+ "f#", "factor", "fan", "fancy",@@ -1109,3 +1163,9 @@ "yaml", "yaml+jinja", "zephir" ]++startsWithListMarker :: Text -> Bool+startsWithListMarker t =+ case T.uncons t of+ Nothing -> False+ Just (c,_) -> c == '#' || c == ':' || c == ';' || c == '*'
@@ -2,7 +2,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Writers.Ms- Copyright : Copyright (C) 2007-2022 John MacFarlane+ Copyright : Copyright (C) 2007-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -21,11 +21,14 @@ module Text.Pandoc.Writers.Ms ( writeMs ) where import Control.Monad.State.Strict+ ( gets, modify, evalStateT )+import Control.Monad ( MonadPlus(mplus), liftM, unless, forM )+import Data.Containers.ListUtils (nubOrd) import Data.Char (isAscii, isLower, isUpper, ord) import Data.List (intercalate, intersperse) import Data.List.NonEmpty (nonEmpty) import qualified Data.Map as Map-import Data.Maybe (catMaybes)+import Data.Maybe (catMaybes, isNothing) import Data.Text (Text) import qualified Data.Text as T import Network.URI (escapeURIString, isAllowedInURI)@@ -38,12 +41,14 @@ import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.DocLayout+import Text.DocLayout hiding (Color)+import Text.DocTemplates (lookupContext) import Text.Pandoc.Shared import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Math import Text.Pandoc.Writers.Shared import Text.Pandoc.Writers.Roff+import Text.Pandoc.Writers.Markdown (writePlain) import Text.Printf (printf) import Text.TeXMath (writeEqn) import qualified Data.Text.Encoding as TE@@ -60,6 +65,7 @@ let colwidth = if writerWrapText opts == WrapAuto then Just $ writerColumns opts else Nothing+ title <- chomp <$> inlineListToMs' opts (lookupMetaInlines "title" meta) metadata <- metaToContext opts (blockListToMs opts) (fmap chomp . inlineListToMs' opts)@@ -70,17 +76,19 @@ 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 $ defField "has-inline-math" hasInlineMath $ defField "hyphenate" True- $ defField "pandoc-version" pandocVersion $ defField "toc" (writerTableOfContents opts) $ defField "title-meta" titleMeta $ defField "author-meta" (T.intercalate "; " authorsMeta)- $ defField "highlighting-macros" highlightingMacros metadata+ $ defField "highlighting-macros" highlightingMacros+ $ resetField "title" title metadata return $ render colwidth $ case writerTemplate opts of Nothing -> main@@ -88,14 +96,13 @@ escapeStr :: WriterOptions -> Text -> Text escapeStr opts =- escapeString (if writerPreferAscii opts then AsciiOnly else AllowUTF8)+ escapeString False (if writerPreferAscii opts then AsciiOnly else AllowUTF8) -- In PDFs we need to escape parentheses and backslash. -- In PDF we need to encode as UTF-16 BE. escapePDFString :: Text -> Text escapePDFString t- | T.all isAscii t =- T.replace "(" "\\(" . T.replace ")" "\\)" . T.replace "\\" "\\\\" $ t+ | T.all (\c -> isAscii c && c /= '(' && c /= ')' && c /= '\\' && c /= '"') t = t | otherwise = ("\\376\\377" <>) . -- add bom mconcat . map encodeChar . T.unpack $ t where@@ -123,13 +130,15 @@ -- line. roff treats the line-ending period differently. -- See http://code.google.com/p/pandoc/issues/detail?id=148. +getPdfEngine :: WriterOptions -> Maybe Text+getPdfEngine opts = lookupContext "pdf-engine" (writerVariables opts)+ blockToMs :: PandocMonad m => WriterOptions -- ^ Options -> Block -- ^ Block element -> MS m (Doc Text)-blockToMs _ Null = return empty blockToMs opts (Div (ident,cls,kvs) bs) = do- let anchor = if T.null ident+ let anchor = if isNothing (getPdfEngine opts) || T.null ident then empty else nowrap $ literal ".pdfhref M "@@ -161,25 +170,6 @@ return $ anchor $$ res blockToMs opts (Plain inlines) = splitSentences <$> inlineListToMs' opts inlines-blockToMs opts (Para [Image attr alt (src,_tit)])- | let ext = takeExtension (T.unpack src) in (ext == ".ps" || ext == ".eps") = do- let (mbW,mbH) = (inPoints opts <$> dimension Width attr,- inPoints opts <$> dimension Height attr)- let sizeAttrs = case (mbW, mbH) of- (Just wp, Nothing) -> space <> doubleQuotes- (literal (tshow (floor wp :: Int) <> "p"))- (Just wp, Just hp) -> space <> doubleQuotes- (literal (tshow (floor wp :: Int) <> "p")) <>- space <>- doubleQuotes (literal (tshow (floor hp :: Int)))- _ -> empty- capt <- splitSentences <$> inlineListToMs' opts alt- return $ nowrap (literal ".PSPIC -C " <>- doubleQuotes (literal (escapeStr opts src)) <>- sizeAttrs) $$- literal ".ce 1000" $$- capt $$- literal ".ce 0" blockToMs opts (Para inlines) = do firstPara <- gets stFirstPara resetFirstPara@@ -197,23 +187,30 @@ blockToMs opts (Header level (ident,classes,_) inlines) = do setFirstPara modify $ \st -> st{ stInHeader = True }- contents <- inlineListToMs' opts $ map breakToSpace inlines+ let inlines' = map breakToSpace inlines+ contents <- inlineListToMs' opts inlines'+ plainContents <- inlinesToPlain inlines' modify $ \st -> st{ stInHeader = False } let (heading, secnum) = if writerNumberSections opts && "unnumbered" `notElem` classes then (".NH", "\\*[SN]") else (".SH", "")+ let mbPdfEngine = getPdfEngine opts let anchor = if T.null ident then empty else nowrap $ literal ".pdfhref M " <> doubleQuotes (literal (toAscii ident)) let bookmark = literal ".pdfhref O " <> literal (tshow level <> " ") <>- doubleQuotes (literal $ secnum <>+ nowrap (doubleQuotes+ (literal $ secnum <> (if T.null secnum then "" else " ") <>- escapePDFString (stringify inlines))+ (case mbPdfEngine of+ Just "groff" -> id+ _ -> escapePDFString)+ plainContents)) let backlink = nowrap (literal ".pdfhref L -D " <> doubleQuotes (literal (toAscii ident)) <> space <> literal "\\") <> cr <> literal " -- "@@ -231,9 +228,9 @@ modify $ \st -> st{ stFirstPara = True } return $ (literal heading <> space <> literal (tshow level)) $$ contents $$- bookmark $$- anchor $$- tocEntry+ case mbPdfEngine of+ Nothing -> mempty+ Just _ -> bookmark $$ anchor $$ tocEntry blockToMs opts (CodeBlock attr str) = do hlCode <- highlightCode opts attr str setFirstPara@@ -301,7 +298,6 @@ then "" else ".nr LL \\n[LLold]") $$ literal ".ad"- blockToMs opts (BulletList items) = do contents <- mapM (bulletListItemToMs opts) items setFirstPara@@ -317,6 +313,25 @@ contents <- mapM (definitionListItemToMs opts) items setFirstPara return (vcat contents)+blockToMs opts (Figure figattr (Caption _ caption) body) =+ case body of+ [Plain [ Image attr _alt (src, _tit) ]] -> do+ let ext = takeExtension (T.unpack src)+ let sizeAttrs = getSizeAttrs opts attr+ capt <- blockToMs opts (Div figattr caption)+ let captlines = height capt+ let cmd = case ext of+ ".ps" -> ".PSPIC"+ ".eps" -> ".PSPIC"+ ".pdf" -> ".PDFPIC"+ _ -> "\\\" .IMAGE"+ return $ nowrap (literal cmd <+>+ doubleQuotes (literal src) <>+ sizeAttrs) $$+ literal (".ce " <> tshow captlines) $$+ capt $$+ literal ".sp 1"+ _ -> blockToMs opts $ Div figattr body -- | Convert bullet list item (list of blocks) to ms. bulletListItemToMs :: PandocMonad m => WriterOptions -> [Block] -> MS m (Doc Text)@@ -326,7 +341,7 @@ bulletListItemToMs opts (Plain first:rest) = do first' <- blockToMs opts (Plain first) rest' <- blockListToMs opts rest- let first'' = literal ".IP \\[bu] 3" $$ first'+ let first'' = literal ".IP \\(bu 3" $$ first' let rest'' = if null rest then empty else literal ".RS 3" $$ rest' $$ literal ".RE"@@ -334,7 +349,7 @@ bulletListItemToMs opts (first:rest) = do first' <- blockToMs opts first rest' <- blockListToMs opts rest- return $ literal "\\[bu] .RS 3" $$ first' $$ rest' $$ literal ".RE"+ return $ literal "\\(bu .RS 3" $$ first' $$ rest' $$ literal ".RE" -- | Convert ordered list item (a list of blocks) to ms. orderedListItemToMs :: PandocMonad m@@ -433,7 +448,7 @@ return $ char '`' <> contents <> char '\'' inlineToMs opts (Quoted DoubleQuote lst) = do contents <- inlineListToMs opts lst- return $ literal "\\[lq]" <> contents <> literal "\\[rq]"+ return $ literal "\\(lq" <> contents <> literal "\\(rq" inlineToMs opts (Cite _ lst) = inlineListToMs opts lst inlineToMs opts (Code attr str) = do@@ -454,7 +469,7 @@ Left il -> inlineToMs opts il Right r -> return $ literal "@" <> literal r <> literal "@" inlineToMs opts (Math DisplayMath str) = do- res <- convertMath writeEqn InlineMath str+ res <- convertMath writeEqn DisplayMath str case res of Left il -> do contents <- inlineToMs opts il@@ -477,21 +492,39 @@ inlineToMs opts (Link _ txt (T.uncons -> Just ('#',ident), _)) = do -- internal link contents <- inlineListToMs' opts $ map breakToSpace txt- return $ literal "\\c" <> cr <> nowrap (literal ".pdfhref L -D " <>- doubleQuotes (literal (toAscii ident)) <> literal " -A " <>- doubleQuotes (literal "\\c") <> space <> literal "\\") <> cr <>- literal " -- " <> doubleQuotes (nowrap contents) <> cr <> literal "\\&"+ return $+ case getPdfEngine opts of+ Just _ -> literal "\\c" <> cr <> nowrap (literal ".pdfhref L -D " <>+ doubleQuotes (literal (toAscii ident)) <> literal " -A " <>+ doubleQuotes (literal "\\c") <> space <> literal "\\") <> cr <>+ literal " -- " <> doubleQuotes (nowrap contents) <> cr <>+ literal "\\&"+ Nothing -> contents inlineToMs opts (Link _ txt (src, _)) = do -- external link contents <- inlineListToMs' opts $ map breakToSpace txt- return $ literal "\\c" <> cr <> nowrap (literal ".pdfhref W -D " <>- doubleQuotes (literal (escapeUri src)) <> literal " -A " <>- doubleQuotes (literal "\\c") <> space <> literal "\\") <> cr <>- literal " -- " <> doubleQuotes (nowrap contents) <> cr <> literal "\\&"-inlineToMs opts (Image _ alternate (_, _)) =- return $ char '[' <> literal "IMAGE: " <>- literal (escapeStr opts (stringify alternate))- <> char ']'+ return $+ case getPdfEngine opts of+ Just _ -> literal "\\c" <> cr <> nowrap (literal ".pdfhref W -D " <>+ doubleQuotes (literal (escapeUri src)) <> literal " -A " <>+ doubleQuotes (literal "\\c") <> space <> literal "\\") <> cr <>+ literal " -- " <> doubleQuotes (nowrap contents) <> cr <>+ literal "\\&"+ Nothing -> contents+inlineToMs opts (Image attr alternate (src, _)) = do+ let desc = literal "[IMAGE: " <>+ literal (escapeStr opts (stringify alternate)) <> char ']'+ let sizeAttrs = getSizeAttrs opts attr+ let ext = takeExtension (T.unpack src)+ let cmd = case ext of+ ".ps" -> ".PSPIC"+ ".eps" -> ".PSPIC"+ ".pdf" -> ".PDFPIC"+ _ -> ""+ return $ cr <> nowrap+ (if T.null cmd+ then desc <> " \\\" " <> doubleQuotes (literal src) <> sizeAttrs+ else literal cmd <+> doubleQuotes (literal src) <> sizeAttrs) <> cr inlineToMs _ (Note contents) = do modify $ \st -> st{ stNotes = contents : stNotes st } return $ literal "\\**"@@ -567,7 +600,7 @@ colordefs = map toColorDef allcolors toColorDef c = literal (".defcolor " <> hexColor c <> " rgb #" <> hexColor c)- allcolors = catMaybes $ ordNub $+ allcolors = catMaybes $ nubOrd $ [defaultColor sty, backgroundColor sty, lineNumberColor sty, lineNumberBackgroundColor sty] <> concatMap (colorsForToken. snd) (Map.toList (tokenStyles sty))@@ -629,3 +662,22 @@ Nothing -> "_u" <> tshow (ord c) <> "_" Just '/' -> "_u" <> tshow (ord c) <> "_" -- see #4515 Just c' -> T.singleton c')++getSizeAttrs :: WriterOptions -> Attr -> Doc Text+getSizeAttrs opts attr =+ case (mbW, mbH) of+ (Just wp, Nothing) -> space <> doubleQuotes+ (literal (tshow (floor wp :: Int) <> "p"))+ (Just wp, Just hp) -> space <> doubleQuotes+ (literal (tshow (floor wp :: Int) <> "p"))+ <> space <>+ doubleQuotes+ (literal (tshow (floor hp :: Int) <> "p"))+ _ -> empty+ where+ mbW = inPoints opts <$> dimension Width attr+ mbH = inPoints opts <$> dimension Height attr++inlinesToPlain :: PandocMonad m => [Inline] -> m Text+inlinesToPlain ils = T.strip <$> writePlain def{ writerWrapText = WrapNone }+ (Pandoc nullMeta [Plain ils])
@@ -25,9 +25,12 @@ even though it is supported only in Emacs Muse. -} module Text.Pandoc.Writers.Muse (writeMuse) where+import Control.Monad (zipWithM) import Control.Monad.Except (throwError) import Control.Monad.Reader+ ( asks, MonadReader(local), ReaderT(runReaderT) ) import Control.Monad.State.Strict+ ( StateT, gets, modify, evalStateT ) import Data.Char (isAlphaNum, isAsciiLower, isAsciiUpper, isDigit, isSpace) import Data.Default import Data.List (intersperse, transpose)@@ -43,6 +46,7 @@ import Text.Pandoc.Options import Text.DocLayout import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Math import Text.Pandoc.Writers.Shared@@ -261,12 +265,15 @@ return $ blankline <> attr' $$ nowrap (header' <> contents) <> blankline -- https://www.gnu.org/software/emacs-muse/manual/muse.html#Horizontal-Rules-and-Anchors blockToMuse HorizontalRule = return $ blankline $$ "----" $$ blankline-blockToMuse (Table _ blkCapt specs thead tbody tfoot) =+blockToMuse (Table _ blkCapt specs thead@(TableHead hattr hrows) tbody tfoot) = if isSimple && numcols > 1 then simpleTable caption headers rows else do opts <- asks envOptions- gridTable opts blocksToDoc True (map (const AlignDefault) aligns) widths headers rows+ let tbody' = case hrows of+ [] -> tbody+ _ -> TableBody nullAttr 0 [] hrows : tbody+ gridTable opts blocksToDoc specs (TableHead hattr []) tbody' tfoot where (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot blocksToDoc opts blocks =@@ -275,7 +282,8 @@ (length aligns :| length widths : map length (headers:rows)) isSimple = onlySimpleTableCells (headers : rows) && all (== 0) widths blockToMuse (Div _ bs) = flatBlockListToMuse bs-blockToMuse Null = return empty+blockToMuse (Figure attr capt body) = do+ blockToMuse (figureDiv attr capt body) -- | Return Muse representation of notes collected so far. currentNotesToMuse :: PandocMonad m@@ -714,7 +722,11 @@ then mempty else literal ("#" <> anchor) <> space modify $ \st -> st { stUseTags = False }- return $ anchorDoc <> (if null inlines && not (T.null anchor)- then mempty- else (if null names then (if hasDir then contents' else "<class>" <> contents' <> "</class>")- else "<class name=\"" <> literal (head names) <> "\">" <> contents' <> "</class>"))+ return $ anchorDoc <>+ if null inlines && not (T.null anchor)+ then mempty+ else case names of+ [] | hasDir -> contents'+ | otherwise -> "<class>" <> contents' <> "</class>"+ (n:_) -> "<class name=\"" <> literal n <> "\">" <>+ contents' <> "</class>"
@@ -1,7 +1,6 @@-{-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.Native- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.ODT- Copyright : Copyright (C) 2008-2022 John MacFarlane+ Copyright : Copyright (C) 2008-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -14,7 +14,8 @@ module Text.Pandoc.Writers.ODT ( writeODT ) where import Codec.Archive.Zip import Control.Monad.Except (catchError, throwError)-import Control.Monad.State.Strict+import Control.Monad.State.Strict (StateT, evalStateT, gets, modify, lift)+import Control.Monad (MonadPlus(mplus)) import qualified Data.ByteString.Lazy as B import Data.Maybe (fromMaybe) import Data.Generics (everywhere', mkT)@@ -23,18 +24,21 @@ import qualified Data.Text as T import qualified Data.Text.Lazy as TL import Data.Time-import System.FilePath (takeDirectory, takeExtension, (<.>))+import System.FilePath (takeDirectory, takeExtension, (<.>), (</>), isAbsolute) import Text.Collate.Lang (Lang (..), renderLang) import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang) import qualified Text.Pandoc.Class.PandocMonad as P+import Text.Pandoc.Data (readDataFile) import Text.Pandoc.Definition import Text.Pandoc.Error (PandocError(..)) 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, pandocVersion, tshow)+import Text.Pandoc.Shared (stringify, tshow)+import Text.Pandoc.Version (pandocVersionText) import Text.Pandoc.Writers.Shared (lookupMetaString, lookupMetaBlocks, fixDisplayMath, getLang, ensureValidXmlIdentifiers)@@ -45,6 +49,8 @@ import Text.Pandoc.XML.Light import Text.TeXMath import qualified Text.XML.Light as XL+import Network.URI (parseRelativeReference, URI(uriPath), isURI)+import Skylighting newtype ODTState = ODTState { stEntries :: [Entry] }@@ -59,10 +65,25 @@ writeODT opts doc = let initState = ODTState{ stEntries = [] }- doc' = ensureValidXmlIdentifiers doc+ doc' = fixInternalLinks . ensureValidXmlIdentifiers $ doc in evalStateT (pandocToODT opts doc') initState +-- | ODT internal links are evaluated relative to an imaginary folder+-- structure that mirrors the zip structure. The result is that relative+-- links in the document need to start with `..`. See #3524.+fixInternalLinks :: Pandoc -> Pandoc+fixInternalLinks = walk go+ where+ go (Link attr ils (src,tit)) =+ Link attr ils (fixRel src,tit)+ go x = x+ fixRel uri =+ case parseRelativeReference (T.unpack uri) of+ Just u+ | not (null (uriPath u)) -> tshow $ u{ uriPath = "../" <> uriPath u }+ _ -> uri+ -- | Produce an ODT file from a Pandoc document. pandocToODT :: PandocMonad m => WriterOptions -- ^ Writer options@@ -75,9 +96,10 @@ lang <- toLang (getLang opts meta) refArchive <- case writerReferenceDoc opts of- Just f -> liftM toArchive $ lift $ P.readFileLazy f+ Just f -> lift $ toArchive . B.fromStrict . fst <$>+ (P.fetchItem (T.pack f)) Nothing -> lift $ toArchive . B.fromStrict <$>- P.readDataFile "reference.odt"+ readDataFile "reference.odt" -- handle formulas and pictures -- picEntriesRef <- P.newIORef ([] :: [Entry]) doc' <- walkM (transformPicMath opts) $ walk fixDisplayMath doc@@ -94,7 +116,6 @@ Just m -> selfClosingTag "manifest:file-entry" [("manifest:media-type", m) ,("manifest:full-path", T.pack fp)- ,("manifest:version", "1.2") ] let files = [ ent | ent <- filesInArchive archive, not ("META-INF" `isPrefixOf` ent) ]@@ -106,9 +127,10 @@ $$ inTags True "manifest:manifest" [("xmlns:manifest","urn:oasis:names:tc:opendocument:xmlns:manifest:1.0")- ,("manifest:version","1.2")] ( selfClosingTag "manifest:file-entry"+ ,("manifest:version","1.3")] ( selfClosingTag "manifest:file-entry" [("manifest:media-type","application/vnd.oasis.opendocument.text")- ,("manifest:full-path","/")]+ ,("manifest:full-path","/")+ ,("manifest:version", "1.3")] $$ vcat ( map toFileEntry files ) $$ vcat ( map toFileEntry formulas ) )@@ -138,8 +160,8 @@ ,("xmlns:meta","urn:oasis:names:tc:opendocument:xmlns:meta:1.0") ,("xmlns:ooo","http://openoffice.org/2004/office") ,("xmlns:grddl","http://www.w3.org/2003/g/data-view#")- ,("office:version","1.2")] ( inTags True "office:meta" []- ( metaTag "meta:generator" ("Pandoc/" <> pandocVersion)+ ,("office:version","1.3")] ( inTags True "office:meta" []+ ( metaTag "meta:generator" ("Pandoc/" <> pandocVersionText) $$ metaTag "dc:title" (stringify title) $$@@ -168,29 +190,109 @@ -- make sure mimetype is first let mimetypeEntry = toEntry "mimetype" epochtime $ fromStringLazy "application/vnd.oasis.opendocument.text"- archive'' <- updateStyleWithLang lang+ archive'' <- updateStyle opts lang $ addEntryToArchive mimetypeEntry $ addEntryToArchive metaEntry archive' return $ fromArchive archive'' -updateStyleWithLang :: PandocMonad m => Maybe Lang -> Archive -> O m Archive-updateStyleWithLang Nothing arch = return arch-updateStyleWithLang (Just lang) arch = do+updateStyle :: forall m . PandocMonad m+ => WriterOptions -> Maybe Lang -> Archive -> O m Archive+updateStyle opts mbLang arch = do epochtime <- floor `fmap` lift P.getPOSIXTime- entries <- mapM (\e -> if eRelativePath e == "styles.xml"- then case parseXMLElement- (toTextLazy (fromEntry e)) of- Left msg -> throwError $- PandocXMLError "styles.xml" msg- Right d -> return $- toEntry "styles.xml" epochtime- ( fromTextLazy- . TL.fromStrict- . ppTopElement- . addLang lang $ d )- else return e) (zEntries arch)+ let goEntry :: Entry -> O m Entry+ goEntry e+ | eRelativePath e == "styles.xml"+ = case parseXMLElement (toTextLazy (fromEntry e)) of+ Left msg -> throwError $ PandocXMLError "styles.xml" msg+ Right d -> return $+ toEntry "styles.xml" epochtime+ ( fromTextLazy+ . TL.fromStrict+ . showTopElement+ . maybe id addLang mbLang+ . transformElement (\qn -> qName qn == "styles" &&+ qPrefix qn == Just "office" )+ (addListItemStyles .+ (case writerHighlightMethod opts of+ Skylighting style -> addHlStyles style+ _ -> id))+ $ d )+ | otherwise = pure e+ entries <- mapM goEntry (zEntries arch) return arch{ zEntries = entries } +addHlStyles :: Style -> Element -> Element+addHlStyles sty el =+ el{ elContent = filter (not . isHlStyle) (elContent el) +++ styleToOpenDocument sty }+ where+ isHlStyle (Elem e) = "Tok" `T.isSuffixOf` (qName (elName e))+ isHlStyle _ = False++-- | Ensure the office:styles element contains paragraph styles for+-- list items used by the OpenDocument writer. This injects only the+-- styles that are missing, so a user-supplied reference.odt may+-- override any of them.+addListItemStyles :: Element -> Element+addListItemStyles el =+ el{ elContent = elContent el ++ map Elem missingStyles }+ where+ existing = [ T.concat [ attrVal a+ | a <- elAttribs e+ , qName (attrKey a) == "name"+ , qPrefix (attrKey a) == Just "style" ]+ | Elem e <- elContent el+ , qName (elName e) == "style"+ , qPrefix (elName e) == Just "style" ]+ missingStyles =+ [ s | s <- listItemStyleElements+ , styleNameOf s `notElem` existing ]+ styleNameOf e = T.concat [ attrVal a+ | a <- elAttribs e+ , qName (attrKey a) == "name"+ , qPrefix (attrKey a) == Just "style" ]++listItemStyleElements :: [Element]+listItemStyleElements =+ [ mkParaStyle "List_20_Bullet" "List Bullet" Nothing+ , mkParaStyle "List_20_Bullet_20_Tight" "List Bullet Tight" (Just tightProps)+ , mkParaStyle "List_20_Number" "List Number" Nothing+ , mkParaStyle "List_20_Number_20_Tight" "List Number Tight" (Just tightProps)+ ]+ where+ styleQN n p = QName n Nothing (Just p)+ mkAttr p n v = Attr (styleQN n p) v+ tightProps =+ Element (styleQN "paragraph-properties" "style")+ [ mkAttr "fo" "margin-top" "0in"+ , mkAttr "fo" "margin-bottom" "0in"+ , mkAttr "style" "contextual-spacing" "false"+ ] [] Nothing+ mkParaStyle name display mbProps =+ Element (styleQN "style" "style")+ [ mkAttr "style" "name" name+ , mkAttr "style" "display-name" display+ , mkAttr "style" "family" "paragraph"+ , mkAttr "style" "parent-style-name" "List"+ , mkAttr "style" "class" "list"+ ]+ (maybe [] (\p -> [Elem p]) mbProps)+ Nothing++-- top-down search+transformElement :: (QName -> Bool)+ -> (Element -> Element)+ -> Element+ -> Element+transformElement g f el+ | g (elName el)+ = f el+ | otherwise+ = el{ elContent = map go (elContent el) }+ where+ go (Elem e) = Elem (transformElement g f e)+ go x = x+ -- TODO FIXME avoid this generic traversal! addLang :: Lang -> Element -> Element addLang lang = everywhere' (mkT updateLangAttr)@@ -224,15 +326,23 @@ Just dim -> Just $ Inch $ inInch opts dim Nothing -> Nothing let newattr = (id', cls, dims)- entries <- gets stEntries- let extension = maybe (takeExtension $ takeWhile (/='?') $ T.unpack src) T.unpack- (mbMimeType >>= extensionFromMimeType)- let newsrc = "Pictures/" ++ show (length entries) <.> extension- let toLazy = B.fromChunks . (:[])- epochtime <- floor `fmap` lift P.getPOSIXTime- let entry = toEntry newsrc epochtime $ toLazy img- modify $ \st -> st{ stEntries = entry : entries }- return $ Image newattr lab (T.pack newsrc, t))+ src' <- if writerLinkImages opts+ then+ case T.unpack src of+ s | isURI s -> return src+ | isAbsolute s -> return src+ | otherwise -> return $ T.pack $ ".." </> s+ else do+ entries <- gets stEntries+ let extension = maybe (takeExtension $ takeWhile (/='?') $ T.unpack src) T.unpack+ (mbMimeType >>= extensionFromMimeType)+ let newsrc = "Pictures/" ++ show (length entries) <.> extension+ let toLazy = B.fromChunks . (:[])+ epochtime <- floor `fmap` lift P.getPOSIXTime+ let entry = toEntry newsrc epochtime $ toLazy img+ modify $ \st -> st{ stEntries = entry : entries }+ return $ T.pack newsrc+ return $ Image newattr lab (src', t)) (\e -> do report $ CouldNotFetchResource src $ T.pack (show e) return $ Emph lab)@@ -278,10 +388,43 @@ ,("xmlns:xlink","http://www.w3.org/1999/xlink") ,("xmlns:config","urn:oasis:names:tc:opendocument:xmlns:config:1.0") ,("xmlns:ooo","http://openoffice.org/2004/office")- ,("office:version","1.2")] (+ ,("office:version","1.3")] ( inTagsSimple "office:settings" $ inTags False "config:config-item-set" [("config:name", "ooo:configuration-settings")] $ inTags False "config:config-item" [("config:name", "IsTextMode") ,("config:type", "boolean")] $ text $ if isTextMode then "true" else "false")++styleToOpenDocument :: Style -> [Content]+styleToOpenDocument style = map (Elem . toStyle) alltoktypes+ where alltoktypes = enumFromTo KeywordTok NormalTok+ styleName x =+ case T.break (== ':') x of+ (b, a) | T.null a -> QName x Nothing (Just "style")+ | otherwise -> QName (T.drop 1 a) Nothing (Just b)+ styleAttr (x, y) = Attr (styleName x) y+ styleAttrs = map styleAttr+ styleElement x attrs cs =+ Element (styleName x) (styleAttrs attrs) cs Nothing+ toStyle toktype =+ styleElement "style"+ [("name", tshow toktype), ("family", "text")]+ [Elem (styleElement "text-properties"+ (tokColor toktype ++ tokBgColor toktype +++ [("fo:font-style", "italic") |+ tokFeature tokenItalic toktype ] +++ [("fo:font-weight", "bold") |+ tokFeature tokenBold toktype ] +++ [("style:text-underline-style", "solid") |+ tokFeature tokenUnderline toktype ])+ [])]+ tokStyles = tokenStyles style+ tokFeature f toktype = maybe False f $ Map.lookup toktype tokStyles+ tokColor toktype =+ maybe [] (\c -> [("fo:color", T.pack (fromColor c))])+ ((tokenColor =<< Map.lookup toktype tokStyles)+ `mplus` defaultColor style)+ tokBgColor toktype =+ maybe [] (\c -> [("fo:background-color", T.pack (fromColor c))])+ (tokenBackground =<< Map.lookup toktype tokStyles)
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.OOXML- Copyright : Copyright (C) 2012-2022 John MacFarlane+ Copyright : Copyright (C) 2012-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -24,7 +24,7 @@ ) where import Codec.Archive.Zip-import Control.Monad.Reader+import Control.Monad (mplus) import Control.Monad.Except (throwError) import Text.Pandoc.Error import qualified Data.ByteString as B
@@ -2,7 +2,7 @@ {-# LANGUAGE CPP #-} {- | Module : Text.Pandoc.Writers.OPML- Copyright : Copyright (C) 2013-2022 John MacFarlane+ Copyright : Copyright (C) 2013-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -35,9 +35,9 @@ else Nothing meta' = B.setMeta "date" (B.str $ convertDate $ docDate meta) meta metadata <- metaToContext opts- (fmap literal . writeMarkdown def . Pandoc nullMeta)+ (fmap literal . writeMarkdown' opts . Pandoc nullMeta) (\ils -> literal . T.stripEnd <$>- writeMarkdown def (Pandoc nullMeta [Plain ils]))+ writeMarkdown' opts (Pandoc nullMeta [Plain ils])) meta' let blocks' = makeSections False (Just 1) blocks main <- render colwidth . vcat <$>@@ -49,6 +49,11 @@ Nothing -> main Just tpl -> render colwidth $ renderTemplate tpl context +writeMarkdown' :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeMarkdown' opts = writeMarkdown def{ writerWrapText = writerWrapText opts+ , writerColumns = writerColumns opts+ , writerExtensions = pandocExtensions+ } writeHtmlInlines :: PandocMonad m => [Inline] -> m Text writeHtmlInlines ils =@@ -71,7 +76,7 @@ htmlIls <- writeHtmlInlines title md <- if null blocks then return mempty- else writeMarkdown def $ Pandoc nullMeta blocks+ else writeMarkdown' opts $ Pandoc nullMeta blocks let attrs = ("text", htmlIls) : [("_note", T.stripEnd md) | not (null blocks)] rest' <- vcat <$> mapM (blockToOPML opts) rest
@@ -15,24 +15,25 @@ -} module Text.Pandoc.Writers.OpenDocument ( writeOpenDocument ) where import Control.Arrow ((***), (>>>))-import Control.Monad.State.Strict hiding (when)+import Control.Monad (unless, liftM)+import Control.Monad.State.Strict ( StateT(..), modify, gets, lift ) import Data.Char (chr) import Data.Foldable (find)-import Data.List (sortOn, sortBy, foldl')+import Data.List (sortOn, sortBy)+import qualified Data.List as L import qualified Data.Map as Map-import Data.Maybe (fromMaybe, isNothing)-import Data.Ord (comparing)+import Data.Ord (comparing, Down (Down)) import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T import Text.Collate.Lang (Lang (..), parseLang)-import Text.Pandoc.Class.PandocMonad (PandocMonad, report, translateTerm,- setTranslations, toLang)+import Text.Pandoc.Class.PandocMonad (PandocMonad, report)+import Text.Pandoc.Translations (translateTerm) import Text.Pandoc.Definition import qualified Text.Pandoc.Builder as B import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.DocLayout+import Text.DocLayout hiding (link) import Text.Pandoc.Shared (linesToPara, tshow, blocksToInlines) import Text.Pandoc.Templates (renderTemplate) import qualified Text.Pandoc.Translations as Term (Term(Figure, Table))@@ -43,13 +44,36 @@ import Text.Pandoc.XML import Text.Printf (printf) import Text.Pandoc.Highlighting (highlight)-import Skylighting+import Skylighting (FormatOptions(..), SourceLine, Token) -- | Auxiliary function to convert Plain block to Para. plainToPara :: Block -> Block plainToPara (Plain x) = Para x plainToPara x = x +-- Names of predefined styles in the reference.odt; see data/odt/styles.xml.+defaultBulletListStyleName, defaultNumberedListStyleName :: Text+defaultBulletListStyleName = "List_20_1"+defaultNumberedListStyleName = "Numbering_20_1"++bulletItemStyleName, bulletItemTightStyleName,+ numberItemStyleName, numberItemTightStyleName :: Text+bulletItemStyleName = "List_20_Bullet"+bulletItemTightStyleName = "List_20_Bullet_20_Tight"+numberItemStyleName = "List_20_Number"+numberItemTightStyleName = "List_20_Number_20_Tight"++-- | Predefined inline style names for single-style spans.+wellKnownTextStyle :: Set.Set TextStyle -> Maybe Text+wellKnownTextStyle s = case Set.toList s of+ [Italic] -> Just "Emphasis"+ [Bold] -> Just "Strong_20_Emphasis"+ [Strike] -> Just "Strikeout"+ [Sub] -> Just "Subscript"+ [Sup] -> Just "Superscript"+ [Pre] -> Just "Source_20_Text"+ _ -> Nothing+ -- -- OpenDocument writer --@@ -59,13 +83,14 @@ data ReferenceType = HeaderRef | TableRef- | ImageRef+ | FigureRef data WriterState = WriterState { stNotes :: [Doc Text] , stTableStyles :: [Doc Text] , stParaStyles :: [Doc Text]- , stListStyles :: [(Int, [Doc Text])]+ , stListOverrides :: Map.Map (ListNumberStyle,ListNumberDelim)+ (Text, Doc Text) , stTextStyles :: Map.Map (Set.Set TextStyle) (Text, Doc Text) , stTextStyleAttr :: Set.Set TextStyle@@ -84,7 +109,7 @@ WriterState { stNotes = [] , stTableStyles = [] , stParaStyles = []- , stListStyles = []+ , stListOverrides = Map.empty , stTextStyles = Map.empty , stTextStyleAttr = Set.empty , stIndentPara = 0@@ -114,20 +139,12 @@ addTextStyle attrs i = modify $ \s -> s { stTextStyles = Map.insert attrs i (stTextStyles s) } -addTextStyleAttr :: PandocMonad m => TextStyle -> OD m ()-addTextStyleAttr t = modify $ \s ->- s { stTextStyleAttr = Set.insert t (stTextStyleAttr s) }- increaseIndent :: PandocMonad m => OD m () increaseIndent = modify $ \s -> s { stIndentPara = 1 + stIndentPara s } resetIndent :: PandocMonad m => OD m () resetIndent = modify $ \s -> s { stIndentPara = stIndentPara s - 1 } -inTightList :: PandocMonad m => OD m a -> OD m a-inTightList f = modify (\s -> s { stTight = True }) >> f >>= \r ->- modify (\s -> s { stTight = False }) >> return r- setInDefinitionList :: PandocMonad m => Bool -> OD m () setInDefinitionList b = modify $ \s -> s { stInDefinition = b } @@ -149,35 +166,42 @@ inSpanTags :: Text -> Doc Text -> Doc Text inSpanTags s = inTags False "text:span" [("text:style-name",s)] -withTextStyle :: PandocMonad m => TextStyle -> OD m a -> OD m a-withTextStyle s f = do+withAlteredTextStyles :: PandocMonad m+ => (Set.Set TextStyle -> Set.Set TextStyle) -> OD m a -> OD m a+withAlteredTextStyles f action = do oldTextStyleAttr <- gets stTextStyleAttr- addTextStyleAttr s- res <- f+ modify $ \st -> st{ stTextStyleAttr = f oldTextStyleAttr }+ res <- action modify $ \st -> st{ stTextStyleAttr = oldTextStyleAttr } return res +withTextStyle :: PandocMonad m => TextStyle -> OD m a -> OD m a+withTextStyle s = withAlteredTextStyles (Set.insert s)+ inTextStyle :: PandocMonad m => Doc Text -> OD m (Doc Text) inTextStyle d = do at <- gets stTextStyleAttr if Set.null at then return d- else do- styles <- gets stTextStyles- case Map.lookup at styles of- Just (styleName, _) -> return $- inTags False "text:span" [("text:style-name",styleName)] d- Nothing -> do- let styleName = "T" <> tshow (Map.size styles + 1)- addTextStyle at (styleName,- inTags False "style:style"- [("style:name", styleName)- ,("style:family", "text")]- $ selfClosingTag "style:text-properties"- (sortOn fst . Map.toList- $ foldl' textStyleAttr mempty (Set.toList at)))- return $ inTags False- "text:span" [("text:style-name",styleName)] d+ else case wellKnownTextStyle at of+ Just styleName -> return $+ inTags False "text:span" [("text:style-name", styleName)] d+ Nothing -> do+ styles <- gets stTextStyles+ case Map.lookup at styles of+ Just (styleName, _) -> return $+ inTags False "text:span" [("text:style-name",styleName)] d+ Nothing -> do+ let styleName = "T" <> tshow (Map.size styles + 1)+ addTextStyle at (styleName,+ inTags False "style:style"+ [("style:name", styleName)+ ,("style:family", "text")]+ $ selfClosingTag "style:text-properties"+ (sortOn fst . Map.toList+ $ L.foldl' textStyleAttr mempty (Set.toList at)))+ return $ inTags False+ "text:span" [("text:style-name",styleName)] d formulaStyles :: [Doc Text] formulaStyles = [formulaStyle InlineMath, formulaStyle DisplayMath]@@ -236,11 +260,7 @@ -- | Convert Pandoc document to string in OpenDocument format. writeOpenDocument :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeOpenDocument opts (Pandoc meta blocks) = do- let defLang = Lang "en" (Just "US") Nothing [] [] []- lang <- case lookupMetaString "lang" meta of- "" -> pure defLang- s -> fromMaybe defLang <$> toLang (Just s)- setTranslations lang+ setupTranslations meta let colwidth = if writerWrapText opts == WrapAuto then Just $ writerColumns opts else Nothing@@ -252,25 +272,22 @@ meta ((body, metadata),s) <- flip runStateT defaultWriterState $ do- let collectInlineIdent (Image (ident,_,_) _ _) = [(ident,ImageRef)]- collectInlineIdent _ = [] let collectBlockIdent (Header _ (ident,_,_) _) = [(ident,HeaderRef)]+ collectBlockIdent (Figure (ident,_,_) _ _ ) = [(ident,FigureRef)] collectBlockIdent (Table (ident,_,_) _ _ _ _ _) = [(ident,TableRef)] collectBlockIdent _ = []- modify $ \s -> s{ stIdentTypes = query collectBlockIdent blocks ++ query collectInlineIdent blocks }+ modify $ \s -> s{ stIdentTypes = query collectBlockIdent blocks } m <- metaToContext opts- (blocksToOpenDocument opts)+ (inlinesToOpenDocument opts . blocksToInlines) (fmap chomp . inlinesToOpenDocument opts) meta' b <- blocksToOpenDocument opts blocks return (b, m) let styles = stTableStyles s ++ stParaStyles s ++ formulaStyles ++- map snd (sortBy (flip (comparing fst)) (+ map snd (sortBy (comparing (Down . fst)) ( Map.elems (stTextStyles s)))- listStyle (n,l) = inTags True "text:list-style"- [("style:name", "L" <> tshow n)] (vcat l)- let listStyles = map listStyle (stListStyles s)- let automaticStyles = vcat $ reverse $ styles ++ listStyles+ let listStyles = map snd (Map.elems (stListOverrides s))+ let automaticStyles = vcat $ reverse styles ++ listStyles let context = defField "body" body . defField "toc" (writerTableOfContents opts) . defField "toc-depth" (tshow $ writerTOCDepth opts)@@ -289,54 +306,102 @@ where go i = (<>) i <$> withParagraphStyle o s bs withParagraphStyle _ _ [] = return empty -inPreformattedTags :: PandocMonad m => Text -> OD m (Doc Text)-inPreformattedTags s = do- n <- paraStyle [("style:parent-style-name","Preformatted_20_Text")]- return . inParagraphTagsWithStyle ("P" <> tshow n) . handleSpaces $ s+inPreformattedTags :: PandocMonad m => [Doc Text] -> OD m (Doc Text)+inPreformattedTags s =+ return $ inParagraphTagsWithStyle "Preformatted_20_Text" $ hcat s +-- | Get the list-style name to use for an ordered list with the given+-- numbering style and delimiter, registering an override automatic style+-- if needed. Lists with default style/delimiter use the predefined+-- @Numbering_20_1@ style and no override is generated.+orderedListStyleName :: PandocMonad m+ => ListNumberStyle -> ListNumberDelim -> OD m Text+orderedListStyleName ns nd+ | (ns == DefaultStyle || ns == Decimal) &&+ (nd == DefaultDelim || nd == Period) =+ return defaultNumberedListStyleName+ | otherwise = do+ overrides <- gets stListOverrides+ case Map.lookup (ns, nd) overrides of+ Just (name, _) -> return name+ Nothing -> do+ let name = "Pandoc_5f_Numbering_5f_" <>+ tshow (Map.size overrides + 1)+ doc = inTags True "text:list-style"+ [("style:name", name)]+ (vcat (map (orderedListLevel ns nd) [1..10]))+ modify $ \s -> s { stListOverrides =+ Map.insert (ns, nd) (name, doc)+ (stListOverrides s) }+ return name++orderedListLevel :: ListNumberStyle -> ListNumberDelim -> Int -> Doc Text+orderedListLevel ns nd lvl =+ let suffix = case nd of+ OneParen -> [("style:num-suffix", ")")]+ TwoParens -> [("style:num-prefix", "(")+ ,("style:num-suffix", ")")]+ _ -> [("style:num-suffix", ".")]+ format = case ns of+ UpperAlpha -> "A"+ LowerAlpha -> "a"+ UpperRoman -> "I"+ LowerRoman -> "i"+ _ -> "1"+ in inTags True "text:list-level-style-number"+ ([ ("text:level" , tshow lvl)+ , ("text:style-name" , "Numbering_20_Symbols")+ , ("style:num-format", format)+ ] ++ suffix)+ (selfClosingTag "style:list-level-properties"+ [ ("text:space-before",+ T.pack (printf "%.4fin" (0.1972 * fromIntegral (lvl - 1) :: Double)))+ , ("text:min-label-width", "0.1965in")+ , ("text:min-label-distance", "0.1in")+ ])+ orderedListToOpenDocument :: PandocMonad m- => WriterOptions -> Int -> [[Block]] -> OD m (Doc Text)-orderedListToOpenDocument o pn bs =+ => WriterOptions -> Text -> [[Block]]+ -> OD m (Doc Text)+orderedListToOpenDocument o paraName bs = vcat . map (inTagsIndented "text:list-item") <$>- mapM (orderedItemToOpenDocument o pn . map plainToPara) bs+ mapM (orderedItemToOpenDocument o paraName . map plainToPara) bs orderedItemToOpenDocument :: PandocMonad m- => WriterOptions -> Int -> [Block] -> OD m (Doc Text)-orderedItemToOpenDocument o n bs = vcat <$> mapM go bs- where go (OrderedList a l) = newLevel a l- go (Para l) = inParagraphTagsWithStyle ("P" <> tshow n) <$>+ => WriterOptions -> Text -> [Block]+ -> OD m (Doc Text)+orderedItemToOpenDocument o paraName bs = vcat <$> mapM go bs+ where go (OrderedList a l) = orderedList a l+ go (Para l) = inParagraphTagsWithStyle paraName <$> inlinesToOpenDocument o l go b = blockToOpenDocument o b- newLevel a l = do- nn <- length <$> gets stParaStyles- ls <- head <$> gets stListStyles- modify $ \s -> s { stListStyles = orderedListLevelStyle a ls :- drop 1 (stListStyles s) }- inTagsIndented "text:list" <$> orderedListToOpenDocument o nn l+ orderedList a@(_,ns,nd) l = do+ lstName <- orderedListStyleName ns nd+ let pn = if isTightList l then numberItemTightStyleName+ else numberItemStyleName+ let listAttrs = ("text:style-name", lstName) : startValueAttr a+ inTags True "text:list" listAttrs <$>+ orderedListToOpenDocument o pn l +-- | Generate a @text:start-value@ attribute when the start value is not 1.+startValueAttr :: ListAttributes -> [(Text, Text)]+startValueAttr (s,_,_) | s /= 1 = [("text:start-value", tshow s)]+startValueAttr _ = []+ isTightList :: [[Block]] -> Bool isTightList [] = False isTightList (b:_) | Plain {} : _ <- b = True | otherwise = False -newOrderedListStyle :: PandocMonad m- => Bool -> ListAttributes -> OD m (Int,Int)-newOrderedListStyle b a = do- ln <- (+) 1 . length <$> gets stListStyles- let nbs = orderedListLevelStyle a (ln, [])- pn <- if b then inTightList (paraListStyle ln) else paraListStyle ln- modify $ \s -> s { stListStyles = nbs : stListStyles s }- return (ln,pn)- bulletListToOpenDocument :: PandocMonad m => WriterOptions -> [[Block]] -> OD m (Doc Text) bulletListToOpenDocument o b = do- ln <- (+) 1 . length <$> gets stListStyles- (pn,ns) <- if isTightList b then inTightList (bulletListStyle ln) else bulletListStyle ln- modify $ \s -> s { stListStyles = ns : stListStyles s }- is <- listItemsToOpenDocument ("P" <> tshow pn) o b- return $ inTags True "text:list" [("text:style-name", "L" <> tshow ln)] is+ let pn = if isTightList b then bulletItemTightStyleName+ else bulletItemStyleName+ is <- listItemsToOpenDocument pn o b+ return $ inTags True "text:list"+ [("text:style-name", defaultBulletListStyleName)] is listItemsToOpenDocument :: PandocMonad m => Text -> WriterOptions -> [[Block]] -> OD m (Doc Text)@@ -355,16 +420,18 @@ return $ t' $$ d' inBlockQuote :: PandocMonad m- => WriterOptions -> Int -> [Block] -> OD m (Doc Text)-inBlockQuote o i (b:bs)+ => WriterOptions -> Text -> [Block] -> OD m (Doc Text)+inBlockQuote o sty (b:bs) | BlockQuote l <- b = do increaseIndent ni <- paraStyle [("style:parent-style-name","Quotations")]- go =<< inBlockQuote o ni (map plainToPara l)- | Para l <- b = go =<< inParagraphTagsWithStyle ("P" <> tshow i) <$> inlinesToOpenDocument o l+ inner <- inBlockQuote o ni (map plainToPara l)+ resetIndent+ go inner+ | Para l <- b = go =<< inParagraphTagsWithStyle sty <$> inlinesToOpenDocument o l | otherwise = go =<< blockToOpenDocument o b- where go block = ($$) block <$> inBlockQuote o i bs-inBlockQuote _ _ [] = resetIndent >> return empty+ where go block = ($$) block <$> inBlockQuote o sty bs+inBlockQuote _ _ [] = return empty -- | Convert a list of Pandoc blocks to OpenDocument. blocksToOpenDocument :: PandocMonad m => WriterOptions -> [Block] -> OD m (Doc Text)@@ -376,7 +443,6 @@ Plain b -> if null b then return empty else inParagraphTags =<< inlinesToOpenDocument o b- SimpleFigure attr c (s, t) -> figure attr c s t Para b -> if null b && not (isEnabled Ext_empty_paragraphs o) then return empty@@ -390,20 +456,33 @@ DefinitionList b -> setFirstPara >> defList b BulletList b -> setFirstPara >> bulletListToOpenDocument o b OrderedList a b -> setFirstPara >> orderedList a b- CodeBlock _ s -> setFirstPara >> preformatted s- Table a bc s th tb tf -> setFirstPara >> table (Ann.toTable a bc s th tb tf)+ CodeBlock attrs s -> do+ setFirstPara+ 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" [ ("text:style-name", "Horizontal_20_Line") ]) b@(RawBlock f s) -> if f == Format "opendocument" then return $ text $ T.unpack s else empty <$ report (BlockNotRendered b)- Null -> return empty+ Figure a capt b -> figure o a capt b where defList b = do setInDefinitionList True r <- vcat <$> mapM (deflistItemToOpenDocument o) b setInDefinitionList False return r- preformatted s = flush . vcat <$> mapM (inPreformattedTags . escapeStringForXML) (T.lines s)+ unhighlighted s = flush . vcat <$>+ (mapM ((inPreformattedTags . (:[])) . preformatted) (T.lines s)) mkDiv attr s = do let (ident,_,kvs) = attr i = withLangFromAttr attr $@@ -414,15 +493,19 @@ if T.null ident then i else fmap mkBookmarkedDiv i- mkBlockQuote b = do increaseIndent- i <- paraStyle- [("style:parent-style-name","Quotations")]- inBlockQuote o i (map plainToPara b)- orderedList a b = do (ln,pn) <- newOrderedListStyle (isTightList b) a- inTags True "text:list" [ ("text:style-name", "L" <> tshow ln)]- <$> orderedListToOpenDocument o pn b- table :: PandocMonad m => Ann.Table -> OD m (Doc Text)- table (Ann.Table (ident, _, _) (Caption _ c) colspecs thead tbodies _) = do+ mkBlockQuote b = do sty <- paraStyle+ [("style:parent-style-name","Quotations")]+ inBlockQuote o sty (map plainToPara b)+ orderedList a@(_,ns,nd) b = do+ lstName <- orderedListStyleName ns nd+ let pn = if isTightList b then numberItemTightStyleName+ else numberItemStyleName+ let listAttrs = ("text:style-name", lstName) : startValueAttr a+ inTags True "text:list" listAttrs <$>+ orderedListToOpenDocument o pn b+ table :: PandocMonad m => WriterOptions -> Ann.Table -> OD m (Doc Text)+ table opts+ (Ann.Table (ident, _, _) (Caption _ c) colspecs thead tbodies tfoot) = do tn <- length <$> gets stTableStyles pn <- length <$> gets stParaStyles let genIds = map chr [65..]@@ -447,21 +530,31 @@ then numberedTableCaption ident else unNumberedCaption "TableCaption" th <- colHeadsToOpenDocument o (map fst paraHStyles) thead- tr <- mapM (tableBodyToOpenDocument o (map fst paraStyles)) tbodies+ tr <- mapM (tableBodyToOpenDocument o (map fst paraHStyles) (map fst paraStyles)) tbodies+ tf <- tableFootToOpenDocument o (map fst paraStyles) tfoot let tableDoc = inTags True "table:table" [ ("table:name" , name) , ("table:style-name", name)- ] (vcat columns $$ th $$ vcat tr)- return $ captionDoc $$ tableDoc- figure attr@(ident, _, _) caption source title | null caption =- withParagraphStyle o "Figure" [Para [Image attr caption (source,title)]]- | otherwise = do- imageDoc <- withParagraphStyle o "FigureWithCaption" [Para [Image attr caption (source,title)]]- captionDoc <- inlinesToOpenDocument o caption >>=- if isEnabled Ext_native_numbering o- then numberedFigureCaption ident- else unNumberedCaption "FigureCaption"- return $ imageDoc $$ captionDoc+ ] (vcat columns $$ th $$ vcat tr $$ tf)+ return $+ case writerTableCaptionPosition opts of+ CaptionAbove -> captionDoc $$ tableDoc+ CaptionBelow -> tableDoc $$ captionDoc+ figure opts (ident, _, _) (Caption _ longcapt) body =+ case blocksToInlines longcapt of+ [] ->+ withParagraphStyle o "Figure" body+ caption -> do+ imageDoc <- withParagraphStyle o "FigureWithCaption" $+ map (\case {Plain i -> Para i; b -> b}) body+ captionDoc <- inlinesToOpenDocument o caption >>=+ if isEnabled Ext_native_numbering o+ then numberedFigureCaption ident+ else unNumberedCaption "FigureCaption"+ return $+ case writerFigureCaptionPosition opts of+ CaptionAbove -> captionDoc $$ imageDoc+ CaptionBelow -> imageDoc $$ captionDoc numberedTableCaption :: PandocMonad m => Text -> Doc Text -> OD m (Doc Text)@@ -501,26 +594,43 @@ colHeadsToOpenDocument o ns (Ann.TableHead _ hs) = case hs of [] -> return empty- (x:_) ->- let (Ann.HeaderRow _ _ c) = x- in inTagsIndented "table:table-header-rows" .- inTagsIndented "table:table-row" .- vcat <$> mapM (tableItemToOpenDocument o "TableHeaderRowCell") (zip ns c)+ xs -> inTagsIndented "table:table-header-rows" <$>+ tableHeaderRowsToOpenDocument o ns "TableHeaderRowCell" xs +tableHeaderRowsToOpenDocument :: PandocMonad m+ => WriterOptions -> [Text] -> Text -> [Ann.HeaderRow]+ -> OD m (Doc Text)+tableHeaderRowsToOpenDocument o ns s headerRows =+ vcat <$> mapM headerRowToOpenDocument headerRows+ where+ headerRowToOpenDocument (Ann.HeaderRow _ _ c) =+ inTagsIndented "table:table-row" .+ vcat <$> mapM (tableItemToOpenDocument o s) (zip ns c)+ tableBodyToOpenDocument:: PandocMonad m- => WriterOptions -> [Text] -> Ann.TableBody+ => WriterOptions -> [Text] -> [Text] -> Ann.TableBody -> OD m (Doc Text)-tableBodyToOpenDocument o ns tb =- let (Ann.TableBody _ _ _ r) = tb- in vcat <$> mapM (tableRowToOpenDocument o ns) r+tableBodyToOpenDocument o headns bodyns tb = do+ let (Ann.TableBody _ _ hs r) = tb+ tableRowHeaders <- tableHeaderRowsToOpenDocument o headns "TableRowCell" hs+ tableRows <- mapM (tableRowToOpenDocument o headns bodyns) r+ return $ tableRowHeaders $$ vcat tableRows +tableFootToOpenDocument :: PandocMonad m+ => WriterOptions -> [Text] -> Ann.TableFoot+ -> OD m (Doc Text)+tableFootToOpenDocument o ns (Ann.TableFoot _ r) =+ tableHeaderRowsToOpenDocument o ns "TableRowCell" r+ tableRowToOpenDocument :: PandocMonad m- => WriterOptions -> [Text] -> Ann.BodyRow+ => WriterOptions -> [Text] -> [Text] -> Ann.BodyRow -> OD m (Doc Text)-tableRowToOpenDocument o ns r =- let (Ann.BodyRow _ _ _ c ) = r++tableRowToOpenDocument o headns bodyns r =+ let (Ann.BodyRow _ _ rowheaders cs) = r in inTagsIndented "table:table-row" . vcat <$>- mapM (tableItemToOpenDocument o "TableRowCell") (zip ns c)+ mapM (tableItemToOpenDocument o "TableRowCell")+ ((zip headns rowheaders) ++ (zip (drop (length rowheaders) bodyns) cs)) colspanAttrib :: ColSpan -> [(Text, Text)] colspanAttrib cs =@@ -552,14 +662,9 @@ aa = alignAttrib align a = [ ("table:style-name" , s ) , ("office:value-type", "string" ) ] ++ csa ++ rsa- itemParaStyle <- case aa of- [] -> return 0- _ -> paraStyleFromParent n aa- let itemParaStyle' = case itemParaStyle of- 0 -> n- x -> "P" <> tshow x+ itemParaStyle <- paraStyleFromParent n aa inTags True "table:table-cell" a <$>- withParagraphStyle o itemParaStyle' (map plainToPara i)+ withParagraphStyle o itemParaStyle (map plainToPara i) -- | Convert a list of inline elements to OpenDocument. inlinesToOpenDocument :: PandocMonad m => WriterOptions -> [Inline] -> OD m (Doc Text)@@ -594,6 +699,9 @@ | writerWrapText o == WrapPreserve -> return $ preformatted "\n" | otherwise -> return space+ Span ("", ["mark"], []) xs ->+ inTags False "text:span" [("text:style-name","Highlighted")] <$>+ inlinesToOpenDocument o xs Span attr xs -> mkSpan attr xs LineBreak -> return $ selfClosingTag "text:line-break" [] Str s -> return $ handleSpaces $ escapeStringForXML s@@ -605,14 +713,14 @@ Subscript l -> withTextStyle Sub $ inlinesToOpenDocument o l SmallCaps l -> withTextStyle SmallC $ inlinesToOpenDocument o l Quoted t l -> inQuotes t <$> inlinesToOpenDocument o l- Code attrs s -> if isNothing (writerHighlightStyle o)- then unhighlighted s- else case highlight (writerSyntaxMap o)- formatOpenDocument attrs s of- Right h -> return $ mconcat $ mconcat h+ 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@@ -627,14 +735,9 @@ Image attr _ (s,t) -> mkImg attr s t Note l -> mkNote l where- formatOpenDocument :: FormatOptions -> [SourceLine] -> [[Doc Text]]- formatOpenDocument _fmtOpts = map (map toHlTok)- toHlTok :: Token -> Doc Text- toHlTok (toktype,tok) =- inTags False "text:span" [("text:style-name", T.pack $ show toktype)] $ preformatted tok unhighlighted s = inlinedCode $ preformatted s- preformatted s = handleSpaces $ escapeStringForXML s- inlinedCode s = return $ inTags False "text:span" [("text:style-name", "Source_Text")] s+ inlinedCode s = return $ inTags False "text:span"+ [("text:style-name", "Source_20_Text")] s mkImg (_, _, kvs) s _ = do id' <- gets stImageId modify (\st -> st{ stImageId = id' + 1 })@@ -651,8 +754,12 @@ , ("xlink:show" , "embed" ) , ("xlink:actuate", "onLoad")] mkSpan attr xs = do- let (ident,_,_) = attr- i = withLangFromAttr attr (inlinesToOpenDocument o xs)+ let (ident,_,kvs) = attr+ i = maybe id (\sty ->+ fmap (inTags False "text:span"+ [ ("text:style-name", sty) ]))+ (lookup "custom-style" kvs) .+ withLangFromAttr attr $ inlinesToOpenDocument o xs mkBookmarkedSpan b = if isEmpty b then selfClosingBookmark ident@@ -667,10 +774,20 @@ , ("text:note-class", "footnote" )] $ inTagsSimple "text:note-citation" (text . show $ n + 1) <> inTagsSimple "text:note-body" t- nn <- footNote <$> withParagraphStyle o "Footnote" l+ nn <- footNote <$> withAlteredTextStyles (const mempty)+ (withParagraphStyle o "Footnote" l) addNote nn return nn +formatOpenDocument :: FormatOptions -> [SourceLine] -> [[Doc Text]]+formatOpenDocument _fmtOpts = map (map toHlTok)+toHlTok :: Token -> Doc Text+toHlTok (toktype,tok) =+ inTags False "text:span" [("text:style-name", T.pack $ show toktype)] $ preformatted tok++preformatted :: Text -> Doc Text+preformatted s = handleSpaces $ escapeStringForXML s+ mkLink :: WriterOptions -> [(Text,ReferenceType)] -> Text -> Text -> Doc Text -> Doc Text mkLink o identTypes s t d = let maybeIdentAndType = case T.uncons s of@@ -704,61 +821,12 @@ linkOrReference = case maybeIdentAndType of Just (ident, HeaderRef) -> bookmarkRef' ident Just (ident, TableRef) -> sequenceRef' ident- Just (ident, ImageRef) -> sequenceRef' ident+ Just (ident, FigureRef) -> sequenceRef' ident _ -> link in if isEnabled Ext_xrefs_name o || isEnabled Ext_xrefs_number o then linkOrReference else link -bulletListStyle :: PandocMonad m => Int -> OD m (Int,(Int,[Doc Text]))-bulletListStyle l = do- let doStyles i = inTags True "text:list-level-style-bullet"- [ ("text:level" , tshow (i + 1))- , ("text:style-name" , "Bullet_20_Symbols" )- , ("style:num-suffix", "." )- , ("text:bullet-char", T.singleton (bulletList !! i))- ] (listLevelStyle (1 + i))- bulletList = map chr $ cycle [8226,9702,9642]- listElStyle = map doStyles [0..9]- pn <- paraListStyle l- return (pn, (l, listElStyle))--orderedListLevelStyle :: ListAttributes -> (Int, [Doc Text]) -> (Int,[Doc Text])-orderedListLevelStyle (s,n, d) (l,ls) =- let suffix = case d of- OneParen -> [("style:num-suffix", ")")]- TwoParens -> [("style:num-prefix", "(")- ,("style:num-suffix", ")")]- _ -> [("style:num-suffix", ".")]- format = case n of- UpperAlpha -> "A"- LowerAlpha -> "a"- UpperRoman -> "I"- LowerRoman -> "i"- _ -> "1"- listStyle = inTags True "text:list-level-style-number"- ([ ("text:level" , tshow $ 1 + length ls )- , ("text:style-name" , "Numbering_20_Symbols")- , ("style:num-format", format )- , ("text:start-value", tshow s )- ] ++ suffix) (listLevelStyle (1 + length ls))- in (l, ls ++ [listStyle])--listLevelStyle :: Int -> Doc Text-listLevelStyle i =- let indent = tshow (0.25 + (0.25 * fromIntegral i :: Double)) in- inTags True "style:list-level-properties"- [ ("text:list-level-position-and-space-mode",- "label-alignment")- , ("fo:text-align", "right")- ] $- selfClosingTag "style:list-level-label-alignment"- [ ("text:label-followed-by", "listtab")- , ("text:list-tab-stop-position", indent <> "in")- , ("fo:text-indent", "-0.25in")- , ("fo:margin-left", indent <> "in")- ]- tableStyle :: Int -> Double -> [(Char,Double)] -> Doc Text tableStyle num textWidth wcs = let tableId = "Table" <> tshow (num + 1)@@ -796,15 +864,17 @@ columnStyles = map colStyle wcs in cellStyles $$ table $$ vcat columnStyles -paraStyle :: PandocMonad m => [(Text,Text)] -> OD m Int+-- | Generate (or reuse) a paragraph style with the given attributes.+-- When the only attribute is @style:parent-style-name@ and no+-- indent/tight overrides are active, the parent name is returned+-- directly (no @Pn@ automatic style is created), so that the+-- predefined style passes through unchanged.+paraStyle :: PandocMonad m => [(Text,Text)] -> OD m Text paraStyle attrs = do- pn <- (+) 1 . length <$> gets stParaStyles i <- (*) (0.5 :: Double) . fromIntegral <$> gets stIndentPara b <- gets stInDefinition t <- gets stTight- let styleAttr = [ ("style:name" , "P" <> tshow pn)- , ("style:family" , "paragraph" )]- indentVal = flip (<>) "in" . tshow $ if b then max 0.5 i else i+ let indentVal = flip (<>) "in" . tshow $ if b then max 0.5 i else i tight = if t then [ ("fo:margin-top" , "0in" ) , ("fo:margin-bottom" , "0in" )] else []@@ -815,31 +885,32 @@ , ("style:auto-text-indent" , "false" )] else [] attributes = indent <> tight- paraProps = if null attributes- then mempty- else selfClosingTag- "style:paragraph-properties" attributes- addParaStyle $ inTags True "style:style" (styleAttr <> attrs) paraProps- return pn--paraStyleFromParent :: PandocMonad m => Text -> [(Text,Text)] -> OD m Int-paraStyleFromParent parent attrs = do- pn <- (+) 1 . length <$> gets stParaStyles- let styleAttr = [ ("style:name" , "P" <> tshow pn)- , ("style:family" , "paragraph")- , ("style:parent-style-name", parent)]- paraProps = if null attrs- then mempty- else selfClosingTag- "style:paragraph-properties" attrs- addParaStyle $ inTags True "style:style" styleAttr paraProps- return pn-+ case (attributes, attrs) of+ ([], [("style:parent-style-name", parent)]) -> return parent+ _ -> do+ pn <- (+) 1 . length <$> gets stParaStyles+ let name = "P" <> tshow pn+ styleAttr = [ ("style:name" , name)+ , ("style:family", "paragraph") ]+ paraProps = if null attributes+ then mempty+ else selfClosingTag+ "style:paragraph-properties" attributes+ addParaStyle $ inTags True "style:style" (styleAttr <> attrs) paraProps+ return name -paraListStyle :: PandocMonad m => Int -> OD m Int-paraListStyle l = paraStyle- [("style:parent-style-name","Text_20_body")- ,("style:list-style-name", "L" <> tshow l)]+paraStyleFromParent :: PandocMonad m => Text -> [(Text,Text)] -> OD m Text+paraStyleFromParent parent attrs+ | null attrs = return parent+ | otherwise = do+ pn <- (+) 1 . length <$> gets stParaStyles+ let name = "P" <> tshow pn+ styleAttr = [ ("style:name" , name)+ , ("style:family" , "paragraph")+ , ("style:parent-style-name", parent)]+ paraProps = selfClosingTag "style:paragraph-properties" attrs+ addParaStyle $ inTags True "style:style" styleAttr paraProps+ return name paraTableStyles :: Text -> Int -> [Alignment] -> [(Text, Doc Text)] paraTableStyles _ _ [] = []
@@ -3,11 +3,11 @@ {- | Module : Text.Pandoc.Writers.Org Copyright : © 2010-2015 Puneeth Chaganti <punchagan@gmail.com>- 2010-2022 John MacFarlane <jgm@berkeley.edu>- 2016-2022 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+ 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 <tarleb+pandoc@moltkeplatz.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -16,21 +16,26 @@ Org-Mode: <http://orgmode.org> -} module Text.Pandoc.Writers.Org (writeOrg) where+import Control.Monad (zipWithM) import Control.Monad.State.Strict+ ( StateT, gets, modify, evalStateT ) import Data.Char (isAlphaNum, isDigit)-import Data.List (intersect, intersperse, partition, transpose)+import Data.List (intersperse, partition, dropWhileEnd, transpose) import Data.List.NonEmpty (nonEmpty)+import Data.Maybe (isJust) import Data.Text (Text) import qualified Data.Text as T import qualified Data.Map as M+import Text.DocLayout import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Definition import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.DocLayout import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Citeproc.Locator (parseLocator, LocatorMap(..), LocatorInfo(..))+import Text.Pandoc.Walk (query) import Text.Pandoc.Writers.Shared data WriterState =@@ -66,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@@ -84,17 +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 -> Text+escapeString :: Text -> Doc Text escapeString t- | T.all (\c -> c < '\x2013' || c > '\x2026') t = t- | otherwise = T.concatMap escChar 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 = T.singleton 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 =@@ -104,7 +131,6 @@ blockToOrg :: PandocMonad m => Block -- ^ Block element -> Org m (Doc Text)-blockToOrg Null = return empty blockToOrg (Div (_, ["cell", "code"], _) (CodeBlock attr t : bs)) = do -- ipynb code cell let (ident, classes, kvs) = attr@@ -120,12 +146,6 @@ then return mempty else divToOrg attr bs blockToOrg (Plain inlines) = inlineListToOrg inlines-blockToOrg (SimpleFigure attr txt (src, tit)) = do- capt <- if null txt- then return empty- else ("#+caption: " <>) `fmap` inlineListToOrg txt- img <- inlineToOrg (Image attr txt (src,tit))- return $ capt $$ img $$ blankline blockToOrg (Para inlines) = do contents <- inlineListToOrg inlines return $ contents <> blankline@@ -150,12 +170,28 @@ return empty blockToOrg HorizontalRule = return $ blankline $$ "--------------" $$ blankline blockToOrg (Header level attr inlines) = do- contents <- inlineListToOrg inlines- let headerStr = text $ if level > 999 then " " else replicate level '*'+ let tagName inline = case inline of+ Span (_, _, kv) _ -> (:[]) <$> lookup "tag-name" kv+ _ -> Nothing+ let (htext, tagsInlines) = break (isJust . tagName) inlines+ contents <- inlineListToOrg $ dropWhileEnd (== Space) htext+ columns <- writerColumns <$> gets stOptions+ let headerDoc = mconcat+ [ text $ if level > 999 then " " else replicate level '*'+ , literal " "+ , contents+ ]+ let tags = case query tagName tagsInlines of+ Nothing -> ""+ Just ts -> T.cons ':' (T.intercalate ":" ts) `T.snoc` ':'+ let tagsDoc = if T.null tags+ then empty+ else (<> literal tags) . text . (`replicate` ' ') . max 1 $+ columns - offset headerDoc - realLength tags let drawerStr = if attr == nullAttr then empty else cr <> propertiesDrawer attr- return $ headerStr <> " " <> contents <> drawerStr <> cr+ return $ nowrap (headerDoc <> tagsDoc) <> drawerStr <> cr blockToOrg (CodeBlock (ident,classes,kvs) str) = do let name = if T.null ident then empty@@ -166,23 +202,30 @@ then " +n" <> startnum else " -n" <> startnum else ""- let at = map pandocLangToOrg classes `intersect` orgLangIdentifiers- let lang = case at of+ let lang = case filter (`notElem` ["example","code"]) classes of [] -> Nothing l:_ -> if "code" `elem` classes -- check for ipynb code cell- then Just ("jupyter-" <> l)- else Just l+ then Just ("jupyter-" <> pandocLangToOrg l)+ else Just (pandocLangToOrg l) let args = mconcat $ [ " :" <> k <> " " <> v | (k, v) <- kvs, k `notElem` ["startFrom", "org-language"]] let (beg, end) = case lang of Nothing -> ("#+begin_example" <> numberlines, "#+end_example") Just x -> ("#+begin_src " <> x <> numberlines <> args, "#+end_src")- return $ name $$ literal beg $$ literal str $$ literal end $$ blankline+ -- escape special lines+ let escape_line line =+ let (spaces, code) = T.span (\c -> c == ' ' || c == '\t') line+ in spaces <>+ (if T.isPrefixOf "#+" code || T.isPrefixOf "*" code+ then T.cons ',' code+ else code)+ let escaped = T.unlines . map escape_line . T.lines $ str+ return $ name $$ literal beg $$ literal escaped $$ literal end $$ blankline blockToOrg (BlockQuote blocks) = do contents <- blockListToOrg blocks return $ blankline $$ "#+begin_quote" $$- contents $$ "#+end_quote" $$ blankline+ chomp contents $$ "#+end_quote" $$ blankline blockToOrg (Table _ blkCapt specs thead tbody tfoot) = do let (caption', _, _, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot caption'' <- inlineListToOrg caption'@@ -232,6 +275,18 @@ blockToOrg (DefinitionList items) = do contents <- mapM definitionListItemToOrg items return $ vcat contents $$ blankline+blockToOrg (Figure (ident, _, _) caption body) = do+ -- Represent the figure as content that can be internally linked from other+ -- parts of the document.+ capt <- case caption of+ Caption _ [] -> pure empty+ Caption _ cpt -> ("#+caption: " <>) <$>+ inlineListToOrg (blocksToInlines cpt)+ contents <- blockListToOrg body+ let anchor = if T.null ident+ then empty+ else "<<" <> literal ident <> ">>"+ return (capt $$ anchor $$ contents $$ blankline) -- | Convert bullet list item (list of blocks) to Org. bulletListItemToOrg :: PandocMonad m => [Block] -> Org m (Doc Text)@@ -316,6 +371,7 @@ -- key-value pairs. | UnwrappedWithAnchor Text -- ^ Not mapped to other type, only -- identifier is retained (if any).+ deriving (Show) -- | Gives the most suitable method to render a list of blocks -- with attributes.@@ -332,23 +388,39 @@ = UnwrappedWithAnchor ident where isGreaterBlockClass :: Text -> Bool- isGreaterBlockClass = (`elem` ["center", "quote"]) . T.toLower+ isGreaterBlockClass t = case T.toLower t of+ "center" -> True+ "quote" -> True+ x -> isAdmonition x +isAdmonition :: Text -> Bool+isAdmonition "warning" = True+isAdmonition "important" = True+isAdmonition "tip" = True+isAdmonition "note" = True+isAdmonition "caution" = True+isAdmonition _ = False+ -- | Converts a Div to an org-mode element. divToOrg :: PandocMonad m => Attr -> [Block] -> Org m (Doc Text) divToOrg attr bs = do- contents <- blockListToOrg bs case divBlockType attr of- GreaterBlock blockName attr' ->+ GreaterBlock blockName attr' -> do -- Write as greater block. The ID, if present, is added via -- the #+name keyword; other classes and key-value pairs -- are kept as #+attr_html attributes.- return $ blankline $$ attrHtml attr'+ contents <- case bs of+ (Div ("",["title"],[]) _ : bs')+ | isAdmonition blockName -> blockListToOrg bs'+ _ -> blockListToOrg bs+ return $ blankline+ $$ attrHtml attr' $$ "#+begin_" <> literal blockName- $$ contents+ $$ chomp contents $$ "#+end_" <> literal blockName $$ blankline Drawer drawerName (_,_,kvs) -> do+ contents <- blockListToOrg bs -- Write as drawer. Only key-value pairs are retained. let keys = vcat $ map (\(k,v) -> ":" <> literal k <> ":"@@ -358,6 +430,7 @@ $$ contents $$ blankline $$ text ":END:" $$ blankline UnwrappedWithAnchor ident -> do+ contents <- blockListToOrg bs -- Unwrap the div. All attributes are discarded, except for -- the identifier, which is added as an anchor before the -- div contents.@@ -372,9 +445,13 @@ let name = if T.null ident then mempty else "#+name: " <> literal ident <> cr keyword = "#+attr_html"- classKv = ("class", T.unwords classes)- kvStrings = map (\(k,v) -> ":" <> k <> " " <> v) (classKv:kvs)- in name <> keyword <> ": " <> literal (T.unwords kvStrings) <> cr+ addClassKv = if null classes+ then id+ else (("class", T.unwords classes):)+ kvStrings = map (\(k,v) -> ":" <> k <> " " <> v) (addClassKv kvs)+ in name <> if null kvStrings+ then mempty+ else keyword <> ": " <> literal (T.unwords kvStrings) <> cr -- | Convert list of Pandoc block elements to Org. blockListToOrg :: PandocMonad m@@ -430,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@@ -464,7 +549,12 @@ return $ "[cite" <> sty <> ":" <> citeItems <> "]" else inlineListToOrg lst inlineToOrg (Code _ str) = return $ "=" <> literal str <> "="-inlineToOrg (Str str) = return . literal $ 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@@ -489,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) <> "]]"@@ -514,8 +604,8 @@ isUrl :: Text -> Bool isUrl cs = let (scheme, path) = T.break (== ':') cs- in T.all (\c -> isAlphaNum c || c `elemText` ".-") scheme- && not (T.null path)+ in T.all (\c -> isAlphaNum c || T.any (== c) ".-") scheme+ && not (T.null path) -- | Translate from pandoc's programming language identifiers to those used by -- org-mode.@@ -527,53 +617,6 @@ "r" -> "R" "bash" -> "sh" _ -> cs---- | List of language identifiers recognized by org-mode.--- See <https://orgmode.org/manual/Languages.html>.-orgLangIdentifiers :: [Text]-orgLangIdentifiers =- [ "asymptote"- , "lisp"- , "awk"- , "lua"- , "C"- , "matlab"- , "C++"- , "mscgen"- , "clojure"- , "ocaml"- , "css"- , "octave"- , "D"- , "org"- , "ditaa"- , "oz"- , "calc"- , "perl"- , "emacs-lisp"- , "plantuml"- , "eshell"- , "processing"- , "fortran"- , "python"- , "gnuplot"- , "R"- , "screen"- , "ruby"- , "dot"- , "sass"- , "haskell"- , "scheme"- , "java"- , "sed"- , "js"- , "sh"- , "latex"- , "sql"- , "ledger"- , "sqlite"- , "lilypond"- , "vala" ] -- taken from oc-csl.el in the org source tree: locmap :: LocatorMap
@@ -21,9 +21,12 @@ module Text.Pandoc.Writers.Powerpoint.Output ( presentationToArchive ) where +import Control.Monad ( MonadPlus(mplus), foldM, unless ) import Control.Monad.Except (throwError, catchError) import Control.Monad.Reader+ ( asks, MonadReader(local), ReaderT(runReaderT) ) import Control.Monad.State+ ( StateT, gets, modify, evalStateT ) import Codec.Archive.Zip import Data.List (intercalate, stripPrefix, nub, union, isPrefixOf, intersperse) import Data.Bifunctor (bimap)@@ -47,6 +50,7 @@ import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Error (PandocError(..)) import qualified Text.Pandoc.Class.PandocMonad as P+import Text.Pandoc.Data (readDataFile, readDefaultDataFile) import Text.Pandoc.Options import Text.Pandoc.MIME import qualified Data.ByteString.Lazy as BL@@ -572,11 +576,12 @@ => WriterOptions -> Meta -> Presentation -> m Archive presentationToArchive opts meta pres = do distArchive <- toArchive . BL.fromStrict <$>- P.readDefaultDataFile "reference.pptx"+ readDefaultDataFile "reference.pptx" refArchive <- case writerReferenceDoc opts of- Just f -> toArchive <$> P.readFileLazy f+ Just f -> toArchive . BL.fromStrict . fst+ <$> P.fetchItem (T.pack f) Nothing -> toArchive . BL.fromStrict <$>- P.readDataFile "reference.pptx"+ readDataFile "reference.pptx" let (referenceLayouts, defaultReferenceLayouts) = (getLayoutsFromArchive refArchive, getLayoutsFromArchive distArchive)@@ -909,6 +914,8 @@ Just Svg -> Just ".svg" 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)@@ -918,7 +925,12 @@ let mediaInfo = MediaInfo { mInfoFilePath = fp , mInfoLocalId = maxLocalId + 1 , mInfoGlobalId = newGlobalId- , mInfoMimeType = mbMt+ , mInfoMimeType =+ case mbMt of+ -- see #9113+ Just t | ";base64" `T.isSuffixOf` t+ -> T.stripSuffix ";base64" t+ x -> x , mInfoExt = imgExt , mInfoCaption = (not . null) caption }@@ -1044,10 +1056,12 @@ [mknode "a:bodyPr" [] (), mknode "a:lstStyle" [] ()] <> elements return ( 1- , mknode "p:sp" [] [ mknode "p:nvSpPr" []+ , surroundWithMathAlternate $+ mknode "p:sp" [] [ mknode "p:nvSpPr" [] [ mknode "p:cNvPr" [("id","1"), ("name","TextBox 3")] () , mknode "p:cNvSpPr" [("txBox", "1")] ()- , mknode "p:nvPr" [] ()+ , mknode "p:nvPr" []+ [mknode "p:ph" [("idx", "1")] ()] ] , mknode "p:spPr" [] [ mknode "a:xfrm" []@@ -1343,7 +1357,7 @@ graphicFrameToElements layout tbls cptn shapeToElements _ (RawOOXMLShape str) = return [(Nothing, Text (CData CDataRaw str Nothing))]-shapeToElements layout shp = do+shapeToElements layout shp@(TextBox _) = do (shapeId, element) <- shapeToElement layout shp return [(shapeId, Elem element)] @@ -1401,18 +1415,18 @@ return $ findAttr (QName "def" Nothing Nothing) tblStyleLst graphicToElement :: PandocMonad m => Integer -> Graphic -> P m Element-graphicToElement tableWidth (Tbl tblPr hdrCells rows) = do- let colWidths = if null hdrCells- then case rows of- r : _ | not (null r) -> replicate (length r) $+graphicToElement tableWidth (Tbl widths tblPr hdrCells rows) = do+ let totalWidth = sum widths+ let colWidths = if 0.0 `elem` widths+ then if null hdrCells+ then case rows of+ r@(_:_) : _ -> replicate (length r) $ tableWidth `div` toInteger (length r)- -- satisfy the compiler. This is the same as- -- saying that rows is empty, but the compiler- -- won't understand that `[]` exhausts the- -- alternatives.- _ -> []- else replicate (length hdrCells) $- tableWidth `div` toInteger (length hdrCells)+ []: _ -> []+ [] -> []+ else replicate (length hdrCells) $+ tableWidth `div` toInteger (length hdrCells)+ else map (\w -> round $ w / totalWidth * fromIntegral tableWidth) widths let cellToOpenXML paras = do elements <- mapM paragraphToElement paras@@ -1528,7 +1542,9 @@ let txBody = mknode "p:txBody" [] $ [mknode "a:bodyPr" [] (), mknode "a:lstStyle" [] ()] <> [element]- return (Just shapeIdNum, replaceNamedChildren ns "p" "txBody" [txBody] sp)+ return (Just shapeIdNum,+ surroundWithMathAlternate $+ replaceNamedChildren ns "p" "txBody" [txBody] sp) -- XXX: TODO | otherwise = return (Nothing, mknode "p:sp" [] ()) @@ -1738,7 +1754,9 @@ , Just cSld <- findChild (elemName ns "p" "cSld") layout , Just spTree <- findChild (elemName ns "p" "spTree") cSld = do let combinedAuthorElems = intercalate [Break] authorsElems- subtitleAndAuthorElems = intercalate [Break, Break] [subtitleElems, combinedAuthorElems]+ subtitleAndAuthorElems = intercalate [Break, Break] $+ filter (not . null)+ [subtitleElems, combinedAuthorElems] (titleId, titleElement) <- nonBodyTextToElement layout [PHType "ctrTitle"] titleElems (subtitleId, subtitleElement) <- nonBodyTextToElement layout [PHType "subTitle"] subtitleAndAuthorElems (dateId, dateElement) <- nonBodyTextToElement layout [PHType "dt"] dateElems@@ -1998,6 +2016,7 @@ let txBody = mknode "p:txBody" [] $ [mknode "a:bodyPr" [] (), mknode "a:lstStyle" [] ()] <> elements return $+ surroundWithMathAlternate $ mknode "p:sp" [] [ mknode "p:nvSpPr" [] [ mknode "p:cNvPr" [ ("id", "3")@@ -2425,8 +2444,11 @@ P m Element presentationToSldIdLst minimumSlideRId (Presentation _ slides) = do ids <- mapM (slideToSldIdElement minimumSlideRId) slides- return $ mknode "p:sldIdLst" [] ids+ return $ mkNodeSldIdLst ids +mkNodeSldIdLst :: [Element] -> Element+mkNodeSldIdLst = mknode "p:sldIdLst" []+ presentationToPresentationElement :: PandocMonad m => PresentationRIdUpdateData ->@@ -2440,10 +2462,9 @@ sldIdLst <- presentationToSldIdLst minSlideRId pres let modifySldIdLst :: Content -> Content- modifySldIdLst (Elem e) = case elName e of- (QName "sldIdLst" _ _) -> Elem sldIdLst- _ -> Elem e- modifySldIdLst ct = ct+ modifySldIdLst ct = if isSldIdLst ct+ then Elem sldIdLst+ else ct notesMasterRId = maxSlideRId @@ -2469,15 +2490,9 @@ removeUnwantedMaster :: [Content] -> [Content] removeUnwantedMaster = concatMap removeUnwantedMaster' - insertNotesMaster' :: Content -> [Content]- insertNotesMaster' (Elem e) = case elName e of- (QName "sldMasterIdLst" _ _) -> [Elem e, Elem notesMasterElem]- _ -> [Elem e]- insertNotesMaster' ct = [ct]- insertNotesMaster :: [Content] -> [Content] insertNotesMaster = if presHasSpeakerNotes pres- then concatMap insertNotesMaster'+ then insertAfterSldMasterIdLst notesMasterElem else id updateRIds :: Content -> Content@@ -2497,10 +2512,33 @@ let newValue = updatePresentationRId presentationUpdateRIdData oldValue pure attr {attrVal = "rId" <> T.pack (show newValue)} + -- if there is no sldIdLst in the presentation.xml file, add an empty one+ -- after the sldMasterIdLst so modifySldIdLst can replace it.++ insertSldIdListIfMissing :: [Content] -> [Content]+ insertSldIdListIfMissing contentList = if any isSldIdLst contentList+ then contentList+ else insertAfterSldMasterIdLst (mkNodeSldIdLst []) contentList++ insertAfterSldMasterIdLst' :: Content -> Content -> [Content]+ insertAfterSldMasterIdLst' newElement ct = if isElemName "sldMasterIdLst" ct+ then [ct, newElement]+ else [ct]++ insertAfterSldMasterIdLst :: Element -> [Content] -> [Content]+ insertAfterSldMasterIdLst newElement = concatMap $ insertAfterSldMasterIdLst' $ Elem newElement++ isElemName :: T.Text -> Content -> Bool+ isElemName name (Elem e) = qName (elName e) == name+ isElemName _ _ = False++ isSldIdLst :: Content -> Bool+ isSldIdLst = isElemName "sldIdLst"+ newContent = insertNotesMaster $ removeUnwantedMaster $ (modifySldIdLst . updateRIds) <$>- elContent element+ insertSldIdListIfMissing (elContent element) return $ element{elContent = newContent} @@ -2651,12 +2689,16 @@ mediaInfos <- mconcat . M.elems <$> gets stMediaIds filePaths <- patternsToFilePaths $ inheritedPatterns p let mediaFps = filter (match (compile "ppt/media/image*")) filePaths+ fontFps = filter (match (compile "ppt/fonts/*")) filePaths let defaults = [ DefaultContentType "xml" "application/xml" , DefaultContentType "rels" "application/vnd.openxmlformats-package.relationships+xml" ] mediaDefaults = nub $ mapMaybe mediaContentType mediaInfos <> mapMaybe mediaFileContentType mediaFps+ fontDefaults = [ DefaultContentType "fntdata" "application/x-fontdata"+ | any (\fp -> takeExtension fp == ".fntdata") fontFps+ ] inheritedOverrides = mapMaybe pathToOverride filePaths createdOverrides = mapMaybe pathToOverride [ "docProps/core.xml"@@ -2670,7 +2712,7 @@ relativePaths speakerNotesOverrides <- mapMaybe pathToOverride <$> getSpeakerNotesFilePaths return $ ContentTypes- (defaults <> mediaDefaults)+ (defaults <> mediaDefaults <> fontDefaults) (inheritedOverrides <> createdOverrides <> slideOverrides <> speakerNotesOverrides) presML :: T.Text
@@ -43,7 +43,7 @@ , LinkTarget(..) ) where -+import Control.Monad import Control.Monad.Reader import Control.Monad.State import Data.List (intercalate)@@ -176,11 +176,6 @@ runPres env st p = (pres, reverse $ stLog finalSt) where (pres, finalSt) = runState (runReaderT p env) st --- GHC 7.8 will still complain about concat <$> mapM unless we specify--- Functor. We can get rid of this when we stop supporting GHC 7.8.-concatMapM :: (Monad m) => (a -> m [b]) -> [a] -> m [b]-concatMapM f xs = liftM concat (mapM f xs)- type Pixels = Integer data Presentation = Presentation DocProps [Slide]@@ -244,7 +239,7 @@ , tblPrBandRow :: Bool } deriving (Show, Eq) -data Graphic = Tbl TableProps [TableCell] [[TableCell]]+data Graphic = Tbl [Double] TableProps [TableCell] [[TableCell]] deriving (Show, Eq) @@ -348,7 +343,7 @@ -------------------------------------------------- inlinesToParElems :: [Inline] -> Pres [ParaElem]-inlinesToParElems = concatMapM inlineToParElems+inlinesToParElems = fmap mconcat . mapM inlineToParElems inlineToParElems :: Inline -> Pres [ParaElem] inlineToParElems (Str s) = do@@ -460,15 +455,17 @@ , pPropIndent = Just 0 } , envRunProps = (envRunProps r){rPropCode = True}}) $ do- mbSty <- writerHighlightStyle <$> asks envOpts+ highlightOpt <- writerHighlightMethod <$> asks envOpts synMap <- writerSyntaxMap <$> asks envOpts- case mbSty of- Just sty ->- case highlight synMap (formatSourceLines sty) attr str of- Right pElems -> do pPropsNew <- asks envParaProps- return [Paragraph pPropsNew pElems]- Left _ -> blockToParagraphs $ Para [Str str]- Nothing -> blockToParagraphs $ Para [Str str]+ let highlightWithStyle style = do+ case highlight synMap (formatSourceLines style) attr str of+ Right pElems -> do pPropsNew <- asks envParaProps+ return [Paragraph pPropsNew pElems]+ Left _ -> blockToParagraphs $ Para [Str str]+ case highlightOpt of+ Skylighting sty -> highlightWithStyle sty+ DefaultHighlighting -> highlightWithStyle defaultStyle+ _ -> blockToParagraphs $ Para [Str str] -- We can't yet do incremental lists, but we should render a -- (BlockQuote List) as a list to maintain compatibility with other -- formats.@@ -482,7 +479,7 @@ , pPropIndent = Just 0 } , envRunProps = (envRunProps r){rPropForceSize = Just blockQuoteSize}})$- concatMapM blockToParagraphs blks+ mconcat <$> mapM blockToParagraphs blks -- TODO: work out the format blockToParagraphs blk@(RawBlock _ _) = do addLogMessage $ BlockNotRendered blk return []@@ -506,7 +503,7 @@ , pPropIndent = Nothing , pPropIncremental = incremental }}) $- concatMapM multiParList blksLst+ mconcat <$> mapM multiParList blksLst blockToParagraphs (OrderedList listAttr blksLst) = do pProps <- asks envParaProps incremental <- listShouldBeIncremental@@ -516,7 +513,7 @@ , pPropIndent = Nothing , pPropIncremental = incremental }}) $- concatMapM multiParList blksLst+ mconcat <$> mapM multiParList blksLst blockToParagraphs (DefinitionList entries) = do incremental <- listShouldBeIncremental let go :: ([Inline], [[Block]]) -> Pres [Paragraph]@@ -524,11 +521,12 @@ term <-blockToParagraphs $ Para [Strong ils] -- For now, we'll treat each definition term as a -- blockquote. We can extend this further later.- definition <- concatMapM (blockToParagraphs . BlockQuote) blksLst+ definition <-+ mconcat <$> mapM (blockToParagraphs . BlockQuote) blksLst return $ term ++ definition local (\env -> env {envParaProps = (envParaProps env) {pPropIncremental = incremental}})- $ concatMapM go entries+ $ mconcat <$> mapM go entries blockToParagraphs (Div (_, classes, _) blks) = let hasIncremental = "incremental" `elem` classes hasNonIncremental = "nonincremental" `elem` classes@@ -536,8 +534,15 @@ | hasNonIncremental -> Just InNonIncremental | otherwise -> Nothing addIncremental env = env { envInIncrementalDiv = incremental }- in local addIncremental (concatMapM blockToParagraphs blks)-blockToParagraphs blk = do+ in local addIncremental (mconcat <$> mapM blockToParagraphs blks)+blockToParagraphs (Figure attr capt blks) = -- This never seems to be used:+ blockToParagraphs (Shared.figureDiv attr capt blks)+blockToParagraphs hr@HorizontalRule = notRendered hr+blockToParagraphs tbl@Table{} = notRendered tbl++-- | Report that a block cannot be rendered.+notRendered :: Block -> Pres [Paragraph]+notRendered blk = do addLogMessage $ BlockNotRendered blk return [] @@ -554,7 +559,7 @@ , pPropLevel = level + 1 } })- $ concatMapM blockToParagraphs bs+ $ mconcat <$> mapM blockToParagraphs bs return $ p ++ ps cellToParagraphs :: Alignment -> SimpleCell -> Pres [Paragraph]@@ -592,8 +597,9 @@ withAttr attr . Pic def{picPropLink = Just $ ExternalTarget target} (T.unpack url) title <$> inlinesToParElems ils+blockToShape (Figure _figattr _caption [b]) = blockToShape b blockToShape (Table _ blkCapt specs thead tbody tfoot) = do- let (caption, algn, _, hdrCells, rows) = toLegacyTable blkCapt specs thead tbody tfoot+ let (caption, algn, widths, hdrCells, rows) = toLegacyTable blkCapt specs thead tbody tfoot caption' <- inlinesToParElems caption hdrCells' <- rowToParagraphs algn hdrCells rows' <- mapM (rowToParagraphs algn) rows@@ -605,7 +611,7 @@ , tblPrBandRow = True } - return $ GraphicFrame [Tbl tblPr hdrCells' rows'] caption'+ return $ GraphicFrame [Tbl widths tblPr hdrCells' rows'] caption' -- If the format isn't openxml, we fall through to blockToPargraphs blockToShape (RawBlock (Format "openxml") str) = return $ RawOOXMLShape str blockToShape blk = do paras <- blockToParagraphs blk@@ -641,6 +647,7 @@ notText :: Block -> Bool notText block | startsWithImage block = True notText Table{} = True+notText Figure{} = True notText _ = False startsWithImage :: Block -> Bool@@ -716,6 +723,7 @@ , "columns" `elem` classes , Div (_, clsL, _) blksL : Div (_, clsR, _) blksR : remaining <- divBlks , "column" `elem` clsL, "column" `elem` clsR = do+ -- At least 2 column elements mapM_ (addLogMessage . BlockNotRendered) (blks ++ remaining) let mkTwoColumn left right = do blksL' <- join . take 1 <$> splitBlocks left@@ -744,6 +752,16 @@ if (any null [blksL1, blksL2]) && (any null [blksR1, blksR2]) then mkTwoColumn blksL blksR else mkComparison blksL1 blksL2 blksR1 blksR2+ | Div (_, classes, _) divBlks <- blk+ , "columns" `elem` classes+ , Div (_, cls, _) columnBlks : remaining <- divBlks+ , "column" `elem` cls = do+ -- Only 1 column element.+ mapM_ (addLogMessage . BlockNotRendered) (blks ++ remaining)+ clBlks' <- join . take 1 <$> splitBlocks columnBlks+ shapes <- blocksToShapes clBlks'+ sldId <- asks envCurSlideId+ return $ Slide sldId (ContentSlide [] shapes) spkNotes Nothing bodyBlocksToSlide _ (blk : blks) spkNotes = do sldId <- asks envCurSlideId inNoteSlide <- asks envInNoteSlide@@ -802,7 +820,7 @@ blockToSpeakerNotes :: Block -> Pres SpeakerNotes blockToSpeakerNotes (Div (_, ["notes"], _) blks) = local (\env -> env{envInSpeakerNotes=True}) $- SpeakerNotes <$> concatMapM blockToParagraphs blks+ SpeakerNotes . mconcat <$> mapM blockToParagraphs blks blockToSpeakerNotes _ = return mempty handleSpeakerNotes :: Block -> Pres ()@@ -869,6 +887,12 @@ subtitle <- inlinesToParElems $ lookupMetaInlines "subtitle" meta authors <- mapM inlinesToParElems $ docAuthors meta date <- inlinesToParElems $ docDate meta+ -- Get speaker notes from metadata "notes" field+ let notesBlocks = lookupMetaBlocks "notes" meta+ speakerNotes <- if null notesBlocks+ then return mempty+ else local (\env -> env{envInSpeakerNotes=True}) $+ SpeakerNotes . mconcat <$> mapM blockToParagraphs notesBlocks if null title && null subtitle && null authors && null date then return Nothing else return $@@ -876,7 +900,7 @@ Slide metadataSlideId (MetadataSlide title subtitle authors date)- mempty+ speakerNotes Nothing addSpeakerNotesToMetaSlide :: Slide -> [Block] -> Pres (Slide, [Block])@@ -1041,9 +1065,9 @@ DefinitionList ds -> all (uncurry (&&) . bimap (all inlineIsBlank) (all (all blockIsBlank))) ds Header _ _ ils -> all inlineIsBlank ils HorizontalRule -> True+ Figure _ _ bls -> all blockIsBlank bls Table{} -> False Div _ bls -> all blockIsBlank bls- Null -> True textIsBlank :: T.Text -> Bool textIsBlank = T.all isSpace
@@ -2,7 +2,7 @@ {-# LANGUAGE ViewPatterns #-} {- | Module : Text.Pandoc.Writers.RST- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -14,9 +14,14 @@ reStructuredText: <http://docutils.sourceforge.net/rst.html> -} module Text.Pandoc.Writers.RST ( writeRST, flatten ) where-import Control.Monad.State.Strict-import Data.Char (isSpace)-import Data.List (transpose, intersperse, foldl')+import Control.Monad.State.Strict ( StateT, gets, modify, evalStateT )+import Control.Monad (zipWithM, liftM)+import Data.Char (isSpace, generalCategory, isAscii, isAlphaNum,+ GeneralCategory(+ ClosePunctuation, OpenPunctuation, InitialQuote,+ FinalQuote, DashPunctuation, OtherPunctuation))+import Data.List (transpose, intersperse)+import qualified Data.List as L import qualified Data.List.NonEmpty as NE import Data.Maybe (fromMaybe) import qualified Data.Text as T@@ -29,6 +34,7 @@ import Text.Pandoc.Options import Text.DocLayout import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Shared import Text.Pandoc.Walk@@ -160,25 +166,62 @@ -- | Escape special characters for RST. escapeText :: WriterOptions -> Text -> Text-escapeText o = T.pack . escapeString' True o . T.unpack -- This ought to be parser- where- escapeString' _ _ [] = []- escapeString' firstChar opts (c:cs) =- case c of- '\\' -> '\\':c:escapeString' False opts cs- _ | c `elemText` "`*_|" &&- (firstChar || null cs) -> '\\':c:escapeString' False opts cs- '\'' | isEnabled Ext_smart opts -> '\\':'\'':escapeString' False opts cs- '"' | isEnabled Ext_smart opts -> '\\':'"':escapeString' False opts cs- '-' | isEnabled Ext_smart opts ->- case cs of- '-':_ -> '\\':'-':escapeString' False opts cs- _ -> '-':escapeString' False opts cs- '.' | isEnabled Ext_smart opts ->- case cs of- '.':'.':rest -> '\\':'.':'.':'.':escapeString' False opts rest- _ -> '.':escapeString' False opts cs- _ -> c : escapeString' False opts cs+escapeText opts t =+ if T.any isSpecial t+ then T.pack . escapeString' True . T.unpack $ t+ else t -- optimization+ where+ isSmart = isEnabled Ext_smart opts+ isSpecial c = c == '\\' || c == '_' || c == '`' || c == '*' || c == '|'+ || (isSmart && (c == '-' || c == '.' || c == '"' || c == '\''))+ canFollowInlineMarkup c = c == '-' || c == '.' || c == ',' || c == ':'+ || c == ';' || c == '!' || c == '?' || c == '\''+ || c == '"' || c == ')' || c == ']' || c == '}'+ || c == '>' || isSpace c+ || (not (isAscii c) &&+ generalCategory c `elem`+ [OpenPunctuation, InitialQuote, FinalQuote,+ DashPunctuation, OtherPunctuation])+ canPrecedeInlineMarkup c = c == '-' || c == ':' || c == '/' || c == '\''+ || c == '"' || c == '<' || c == '(' || c == '['+ || c == '{' || isSpace c+ || (not (isAscii c) &&+ generalCategory c `elem`+ [ClosePunctuation, InitialQuote, FinalQuote,+ DashPunctuation, OtherPunctuation])+ escapeString' canStart cs =+ case cs of+ [] -> []+ d:ds+ | d == '\\'+ -> '\\' : d : escapeString' False ds+ '\'':ds+ | isSmart+ -> '\\' : '\'' : escapeString' True ds+ '"':ds+ | isSmart+ -> '\\' : '"' : escapeString' True ds+ '-':'-':ds+ | isSmart+ -> '\\' : '-' : escapeString' False ('-':ds)+ '.':'.':'.':ds+ | isSmart+ -> '\\' : '.' : escapeString' False ('.':'.':ds)+ [e]+ | e == '*' || e == '_' || e == '|' || e == '`'+ -> ['\\',e]+ d:ds+ | canPrecedeInlineMarkup d+ -> d : escapeString' True ds+ e:d:ds+ | e == '*' || e == '_' || e == '|' || e == '`'+ , (not canStart && canFollowInlineMarkup d)+ || (canStart && not (isSpace d))+ -> '\\' : e : escapeString' False (d:ds)+ '_':d:ds+ | not (isAlphaNum d)+ -> '\\' : '_' : escapeString' False (d:ds)+ d:ds -> d : escapeString' False ds titleToRST :: PandocMonad m => [Inline] -> [Inline] -> RST m (Doc Text) titleToRST [] _ = return empty@@ -199,7 +242,6 @@ blockToRST :: PandocMonad m => Block -- ^ Block element -> RST m (Doc Text)-blockToRST Null = return empty blockToRST (Div ("",["title"],[]) _) = return empty -- this is generated by the rst reader and can safely be -- omitted when we're generating rst@@ -210,46 +252,22 @@ let admonition = case classes of (cl:_) | cl `elem` admonitions- -> ".. " <> literal cl <> "::"- cls -> ".. container::" <> space <>+ -> blankline <> ".. " <> literal cl <> "::"+ cls -> blankline <> ".. container::" <> space <> literal (T.unwords (filter (/= "container") cls))+ -- if contents start with block quote, we need to insert+ -- an empty comment to fix the indentation point (#10236)+ let contents' = case bs of+ BlockQuote{}:_-> ".." $+$ contents+ _ -> contents return $ blankline $$ admonition $$ (if T.null ident then blankline else " :name: " <> literal ident $$ blankline) $$- nest 3 contents $$+ nest 3 contents' $$ blankline blockToRST (Plain inlines) = inlineListToRST inlines-blockToRST (SimpleFigure attr txt (src, tit)) = do- description <- inlineListToRST txt- dims <- imageDimsToRST attr- let fig = "figure:: " <> literal src- alt = ":alt: " <> if T.null tit then description else literal tit- capt = description- (_,cls,_) = attr- classes = case cls of- [] -> empty- ["align-right"] -> ":align: right"- ["align-left"] -> ":align: left"- ["align-center"] -> ":align: center"- _ -> ":figclass: " <> literal (T.unwords cls)- return $ hang 3 ".. " (fig $$ alt $$ classes $$ dims $+$ capt) $$ blankline-blockToRST (Para [Image attr txt (src, _)]) = do- description <- inlineListToRST txt- dims <- imageDimsToRST attr- let fig = "image:: " <> literal src- alt | null txt = empty- | otherwise = ":alt: " <> description- capt = empty- (_,cls,_) = attr- classes = case cls of- [] -> empty- ["align-right"] -> ":align: right"- ["align-left"] -> ":align: left"- ["align-center"] -> ":align: center"- _ -> ":class: " <> literal (T.unwords cls)- return $ hang 3 ".. " (fig $$ alt $$ classes $$ dims $+$ capt) $$ blankline blockToRST (Para inlines) | LineBreak `elem` inlines = linesToLineBlock $ splitBy (==LineBreak) inlines@@ -306,13 +324,14 @@ c `notElem` ["sourceCode","literate","numberLines", "number-lines","example"]] of [] -> "::"- (lang:_) -> (".. code:: " <> literal lang) $$ numberlines)+ (lang:_) -> (blankline <> ".. code:: " <> literal lang) $$ numberlines) $+$ nest 3 (literal str) $$ blankline blockToRST (BlockQuote blocks) = do contents <- blockListToRST blocks return $ nest 3 contents <> blankline-blockToRST (Table _ blkCapt specs thead tbody tfoot) = do- let (caption, aligns, widths, headers, rows) = toLegacyTable blkCapt specs thead tbody tfoot+blockToRST (Table _attrs blkCapt specs thead@(TableHead _ theadRows) tbody tfoot@(TableFoot _ tfootRows)) = do+ let (caption, aligns, widths, headers, rows) =+ toLegacyTable blkCapt specs thead tbody tfoot caption' <- inlineListToRST caption let blocksToDoc opts bs = do oldOpts <- gets stOptions@@ -321,22 +340,28 @@ modify $ \st -> st{ stOptions = oldOpts } return result opts <- gets stOptions- let isSimple = all (== 0) widths && length widths > 1- tbl <- if isSimple- then do- tbl' <- simpleTable opts blocksToDoc headers rows- if offset tbl' > writerColumns opts- then gridTable opts blocksToDoc (all null headers)- (map (const AlignDefault) aligns) widths- headers rows- else return tbl'- else gridTable opts blocksToDoc (all null headers)- (map (const AlignDefault) aligns) widths- headers rows+ let specs' = map (\(_,width) -> (AlignDefault, width)) specs+ renderGrid = gridTable opts blocksToDoc specs' thead tbody tfoot+ rowHasRowSpan (Row _ cells) = any cellHasRowSpan cells+ cellHasRowSpan (Cell _ _ rowSpan _ _) = rowSpan > 1+ isSimple = all (== 0) widths && length widths > 1 && not (any rowHasRowSpan $ theadRows ++ tableBodiesToRows tbody ++ tfootRows)+ renderSimple = do+ tbl' <- simpleTable opts blocksToDoc thead tbody tfoot+ if offset tbl' > writerColumns opts+ then renderGrid+ else return tbl'+ isList = writerListTables opts+ renderList = tableToRSTList caption (map (const AlignDefault) aligns)+ widths headers rows+ rendered+ | isList = renderList+ | isSimple = renderSimple+ | otherwise = renderGrid+ tbl <- rendered return $ blankline $$- (if null caption+ (if null caption || isList then tbl- else (".. table:: " <> caption') $$ blankline $$ nest 3 tbl) $$+ else (blankline <> ".. table:: " <> caption') $$ blankline $$ nest 3 tbl) $$ blankline blockToRST (BulletList items) = do contents <- mapM bulletListItemToRST items@@ -362,11 +387,54 @@ -- ensure that sublists have preceding blank line return $ blankline $$ vcat contents $$ blankline +blockToRST (Figure (ident, classes, _kvs)+ (Caption _ longCapt) body) = do+ let figure attr txt (src, tit) = do+ description <- inlineListToRST txt+ capt <- blockListToRST longCapt+ dims <- imageDimsToRST attr+ let fig = "figure::" <+> literal src+ alt = if null txt+ then if T.null tit+ then empty+ else ":alt:" <+> literal tit+ else ":alt:" <+> description+ name = if T.null ident+ then empty+ else "name:" <+> literal ident+ (_,cls,_) = attr+ align = case cls of+ [] -> empty+ ["align-right"] -> ":align: right"+ ["align-left"] -> ":align: left"+ ["align-center"] -> ":align: center"+ _ -> ":figclass: " <> literal (T.unwords cls)+ return $ hang 3 ".. " (fig $$ name $$ alt $$ align $$ dims $+$ capt)+ $$ blankline+ case body of+ [Para [Image attr txt tgt]] -> figure attr txt tgt+ [Plain [Image attr txt tgt]] -> figure attr txt tgt+ _ -> do+ content <- blockListToRST body+ return $ blankline $$ (+ ".. container:: float" <> space <>+ literal (T.unwords (filter (/= "container") classes))) $$+ (if T.null ident+ then blankline+ else " :name: " <> literal ident $$ blankline) $$+ nest 3 content $$+ blankline+ -- | Convert bullet list item (list of blocks) to RST. bulletListItemToRST :: PandocMonad m => [Block] -> RST m (Doc Text) bulletListItemToRST items = do contents <- blockListToRST items- return $ hang 3 "- " contents $$+ -- if a list item starts with block quote, we need to insert+ -- an empty comment to fix the indentation point (#10236)+ let contents' = case items of+ BlockQuote{}:_-> ".." $+$ contents+ _ -> contents+ return $ hang 2 "- " contents' $$ if null items || (endsWithPlain items && not (endsWithList items)) then cr else blankline@@ -379,7 +447,12 @@ orderedListItemToRST marker items = do contents <- blockListToRST items let marker' = marker <> " "- return $ hang (T.length marker') (literal marker') contents $$+ -- if a list item starts with block quote, we need to insert+ -- an empty comment to fix the indentation point (#10236)+ let contents' = case items of+ BlockQuote{}:_-> ".." $+$ contents+ _ -> contents+ return $ hang (T.length marker') (literal marker') contents' $$ if null items || (endsWithPlain items && not (endsWithList items)) then cr else blankline@@ -395,7 +468,12 @@ definitionListItemToRST (label, defs) = do label' <- inlineListToRST label contents <- liftM vcat $ mapM blockListToRST defs- return $ nowrap label' $$ nest 3 (nestle contents) $$+ -- if definition list starts with block quote, we need to insert+ -- an empty comment to fix the indentation point (#10236)+ let contents' = case defs of+ (BlockQuote{}:_):_ -> ".." $+$ contents+ _ -> contents+ return $ nowrap label' $$ nest 3 (nestle contents') $$ if isTightList defs then cr else blankline@@ -438,6 +516,63 @@ -> RST m (Doc Text) blockListToRST = blockListToRST' False +{-++http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#directives++According to the terminology used in the spec, a marker includes a+final whitespace and a block includes the directive arguments. Here+the variable names have slightly different meanings because we don't+want to finish the line with a space if there are no arguments, it+would produce rST that differs from what users expect in a way that's+not easy to detect++-}+toRSTDirective :: Doc Text -> Doc Text -> [(Doc Text, Doc Text)] -> Doc Text -> Doc Text+toRSTDirective typ args options content = marker <> spaceArgs <> cr <> block+ where marker = ".. " <> typ <> "::"+ block = nest 3 (fieldList $$+ blankline $$+ content $$+ blankline)+ spaceArgs = if isEmpty args then "" else " " <> args+ -- a field list could end up being an empty doc thus being+ -- omitted by $$+ fieldList = foldl ($$) "" $ map joinField options+ -- a field body can contain multiple lines+ joinField (name, body) = ":" <> name <> ": " <> body++tableToRSTList :: PandocMonad m+ => [Inline]+ -> [Alignment]+ -> [Double]+ -> [[Block]]+ -> [[[Block]]]+ -> RST m (Doc Text)+tableToRSTList caption _ propWidths headers rows = do+ captionRST <- inlineListToRST caption+ opts <- gets stOptions+ content <- listTableContent toWrite+ pure $ toRSTDirective "list-table" captionRST (directiveOptions opts) content+ where directiveOptions opts = widths (writerColumns opts) propWidths <>+ headerRows+ toWrite = if noHeaders then rows else headers:rows+ headerRows = [("header-rows", text $ show (1 :: Int)) | not noHeaders]+ widths tot pro = [("widths", showWidths tot pro) |+ not (null propWidths || all (==0.0) propWidths)]+ noHeaders = all null headers+ -- >>> showWidths 70 [0.5, 0.5]+ -- "35 35"+ showWidths :: Int -> [Double] -> Doc Text+ showWidths tot = text . unwords . map (show . toColumns tot)+ -- toColumns converts a width expressed as a proportion of the+ -- total into a width expressed as a number of columns+ toColumns :: Int -> Double -> Int+ toColumns t p = round (p * fromIntegral t)+ listTableContent :: PandocMonad m => [[[Block]]] -> RST m (Doc Text)+ listTableContent = fmap vcat .+ mapM (fmap (hang 2 (text "* ") . vcat) . mapM bulletListItemToRST)+ transformInlines :: [Inline] -> [Inline] transformInlines = insertBS . filter hasContents .@@ -507,14 +642,14 @@ okAfterComplex SoftBreak = True okAfterComplex LineBreak = True okAfterComplex (Str (T.uncons -> Just (c,_)))- = isSpace c || c `elemText` "-.,:;!?\\/'\")]}>–—"+ = isSpace c || T.any (== c) "-.,:;!?\\/'\")]}>–—" okAfterComplex _ = False okBeforeComplex :: Inline -> Bool okBeforeComplex Space = True okBeforeComplex SoftBreak = True okBeforeComplex LineBreak = True okBeforeComplex (Str (T.unsnoc -> Just (_,c)))- = isSpace c || c `elemText` "-:/'\"<([{–—"+ = isSpace c || T.any (== c) "-:/'\"<([{–—" okBeforeComplex _ = False isComplex :: Inline -> Bool isComplex (Emph _) = True@@ -540,7 +675,7 @@ | null contents = [outer] | otherwise = combineAll contents where contents = dropInlineParent outer- combineAll = foldl' combine []+ combineAll = L.foldl' combine [] combine :: [Inline] -> Inline -> [Inline] combine f i =@@ -624,6 +759,9 @@ -- | Convert Pandoc inline element to RST. inlineToRST :: PandocMonad m => Inline -> RST m (Doc Text)+inlineToRST (Span ("",["mark"],[]) ils) = do+ contents <- writeInlines ils+ return $ ":mark:`" <> contents <> "`" inlineToRST (Span (_,_,kvs) ils) = do contents <- writeInlines ils return $@@ -672,7 +810,7 @@ -- we use :literal: when the code contains backticks, since -- :literal: allows backslash-escapes; see #3974 return $- if '`' `elemText` str+ if T.any (== '`') str then ":literal:`" <> literal (escapeText opts (trim str)) <> "`" else "``" <> literal (trim str) <> "``" inlineToRST (Str str) = do@@ -685,7 +823,7 @@ modify $ \st -> st{ stHasMath = True } return $ if t == InlineMath then ":math:`" <> literal str <> "`"- else if '\n' `elemText` str+ else if T.any (== '\n') str then blankline $$ ".. math::" $$ blankline $$ nest 3 (literal str) $$ blankline else blankline $$ (".. math:: " <> literal str) $$ blankline@@ -783,25 +921,70 @@ simpleTable :: PandocMonad m => WriterOptions -> (WriterOptions -> [Block] -> m (Doc Text))- -> [[Block]]- -> [[[Block]]]+ -> TableHead+ -> [TableBody]+ -> TableFoot -> m (Doc Text)-simpleTable opts blocksToDoc headers rows = do- -- can't have empty cells in first column:- let fixEmpties (d:ds) = if isEmpty d- then literal "\\ " : ds- else d : ds- fixEmpties [] = []- headerDocs <- if all null headers+simpleTable opts blocksToDoc (TableHead _ headers) tbody (TableFoot _ footers) = do+ headerDocs <- if allRowsEmpty headers then return []- else fixEmpties <$> mapM (blocksToDoc opts) headers- rowDocs <- mapM (fmap fixEmpties . mapM (blocksToDoc opts)) rows- let numChars = maybe 0 maximum . NE.nonEmpty . map offset- let colWidths = map numChars $ transpose (headerDocs : rowDocs)- let toRow = mconcat . intersperse (lblock 1 " ") . zipWith lblock colWidths+ else fixEmpties <$> mapM rowToDoc headers+ rowDocs <- fixEmpties <$> mapM rowToDoc ((tableBodiesToRows tbody) ++ footers)+ let numChars = maybe 0 maximum . NE.nonEmpty . map (offset . fst)+ let colWidths = map numChars $ transpose (headerDocs ++ rowDocs) let hline = nowrap $ hsep (map (\n -> literal (T.replicate n "=")) colWidths)- let hdr = if all null headers+ let hdr = if allRowsEmpty headers then mempty- else hline $$ toRow headerDocs- let bdy = vcat $ map toRow rowDocs+ else hline $$ mapToRow colWidths headerDocs+ let bdy = mapToRow colWidths rowDocs return $ hdr $$ hline $$ bdy $$ hline+ where+ -- can't have empty cells in first column:+ fixEmpties (d:ds) = fixEmpties' d : ds+ fixEmpties [] = []++ fixEmpties' ((d, colSpan):ds) = if isEmpty d+ then (literal "\\ ", colSpan) : ds+ else (d, colSpan) : ds+ fixEmpties' [] = []++ rowToDoc (Row _ cells) = concat <$> mapM cellToDocs cells++ cellToDocs (Cell _ _ _ colSpan blocks) = applyColSpan colSpan <$> (blocksToDoc opts) blocks++ applyColSpan col@(ColSpan colSpan) doc+ | colSpan > 1 =+ -- Fill up columns for the col spans by adding empty docs without a ColSpan.+ let emptyDoc = (literal "", Nothing)+ in (doc, Just col) : replicate (colSpan - 1) emptyDoc+ | otherwise = [(doc, Just col)]++ mapToRow colWidths = vcat . concatMap (toRow colWidths)++ toRow colWidths rowDocsWithColSpans =+ let (rowDocs, colSpans) = unzip rowDocsWithColSpans+ row = intersperseDivider $ zipWith lblock colWidths rowDocs+ colSpanRow = intersperseDivider $ writeColSpans colSpans colWidths+ in if any (maybe False (> 1)) colSpans+ then [row, colSpanRow]+ else [row] -- Don't write out col spans if they are all just 1.++ intersperseDivider = mconcat . intersperse (lblock 1 " ")++ -- Write col span dashes to match the length of the col widths.+ writeColSpans [] _ = []+ writeColSpans _ [] = []+ writeColSpans (Nothing : remainingColSpans) colWidths = writeColSpans remainingColSpans colWidths+ writeColSpans (Just (ColSpan colSpan) : remainingColSpans) colWidths =+ let (colWidths', remainingColWidths) = splitAt colSpan colWidths+ in writeColSpanDashes colWidths' : writeColSpans remainingColSpans remainingColWidths++ writeColSpanDashes colWidths =+ let colWidthsLength = length colWidths+ colWidthsSum = sum colWidths+ dashLength = if colWidthsLength > 1+ -- Offset by 1 for the white spaces between columns so that the col+ -- span dashes align with the end of the columns correctly.+ then colWidthsSum + colWidthsLength - 1+ else colWidthsSum+ in literal $ T.replicate dashLength "-"
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.RTF- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -134,7 +134,7 @@ where surrogate x = not ( (0x0000 <= ord x && ord x <= 0xd7ff) || (0xe000 <= ord x && ord x <= 0xffff) )- enc x = "\\u" <> tshow (ord x) <> "?"+ enc x = "\\u" <> tshow (ord x) <> " ?" -- | Escape special characters. escapeSpecial :: Text -> Text@@ -230,7 +230,6 @@ -> Alignment -- ^ alignment -> Block -- ^ block to convert -> m Text-blockToRTF _ _ Null = return "" blockToRTF indent alignment (Div _ bs) = blocksToRTF indent alignment bs blockToRTF indent alignment (Plain lst) =@@ -270,6 +269,8 @@ else tableRowToRTF True indent aligns sizes headers rows' <- T.concat <$> mapM (tableRowToRTF False indent aligns sizes) rows return $ header' <> rows' <> rtfPar indent 0 alignment caption'+blockToRTF indent alignment (Figure attr capt body) =+ blockToRTF indent alignment $ figureDiv attr capt body tableRowToRTF :: PandocMonad m => Bool -> Int -> [Alignment] -> [Double] -> [[Block]] -> m Text@@ -280,8 +281,9 @@ else sizes' columns <- T.concat <$> zipWithM (tableItemToRTF indent) aligns cols- let rightEdges = tail $ scanl (\sofar new -> sofar + floor (new * totalTwips))- (0 :: Integer) sizes+ let rightEdges = drop 1 $+ scanl (\sofar new -> sofar + floor (new * totalTwips))+ (0 :: Integer) sizes let cellDefs = map (\edge -> (if header then "\\clbrdrb\\brdrs" else "") <> "\\cellx" <> tshow edge)
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.Roff- Copyright : Copyright (C) 2007-2022 John MacFarlane+ Copyright : Copyright (C) 2007-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -26,13 +26,12 @@ import Data.Text (Text) import qualified Data.Text as Text import Data.String-import Data.Maybe (fromMaybe, isJust, catMaybes)+import Data.Maybe (fromMaybe) import Text.Pandoc.Class.PandocMonad (PandocMonad) import Text.Pandoc.Definition import Text.DocLayout import Text.Printf (printf)-import Text.Pandoc.RoffChar (standardEscapes,- characterCodes, combiningAccents)+import Text.Pandoc.RoffChar (standardEscapes, characterCodes) data WriterState = WriterState { stHasInlineMath :: Bool , stFirstPara :: Bool@@ -68,36 +67,37 @@ | AsciiOnly -- ^ escape everything deriving Show -combiningAccentsMap :: Map.Map Char Text-combiningAccentsMap = Map.fromList combiningAccents- essentialEscapes :: Map.Map Char Text essentialEscapes = Map.fromList standardEscapes --- | Escape special characters for roff.-escapeString :: EscapeMode -> Text -> Text-escapeString e = Text.concat . escapeString' e . Text.unpack+-- | Escape special characters for roff. If the first parameter is+-- True, escape @-@ as @\-@, as required by current versions of groff man;+-- otherwise leave it unescaped, as neededfor ms.+escapeString :: Bool -> EscapeMode -> Text -> Text+escapeString escapeHyphen e = Text.concat . escapeString' e . Text.unpack where escapeString' _ [] = [] escapeString' escapeMode ('\n':'.':xs) = "\n\\&." : escapeString' escapeMode xs+ -- see #10533; we need to escape hyphens as \- in man but not in ms:+ escapeString' escapeMode ('-':xs) | escapeHyphen =+ "\\-" : escapeString' escapeMode xs escapeString' escapeMode (x:xs) = case Map.lookup x essentialEscapes of Just s -> s : escapeString' escapeMode xs Nothing | isAscii x -> Text.singleton x : escapeString' escapeMode xs | otherwise ->- case escapeMode of- AllowUTF8 -> Text.singleton x : escapeString' escapeMode xs+ (case escapeMode of+ AllowUTF8 -> Text.singleton x AsciiOnly ->- let accents = catMaybes $ takeWhile isJust- (map (`Map.lookup` combiningAccentsMap) xs)- rest = drop (length accents) xs- s = case Map.lookup x characterCodeMap of- Just t -> "\\[" <> Text.unwords (t:accents) <> "]"- Nothing -> "\\[" <> Text.unwords- (Text.pack (printf "u%04X" (ord x)) : accents) <> "]"- in s : escapeString' escapeMode rest+ case Map.lookup x characterCodeMap of+ Just t+ | Text.length t == 2 -> "\\(" <> t -- see #10716+ | otherwise -> "\\C'" <> t <> "'"+ Nothing ->+ "\\C'" <> Text.pack (printf "u%04X" (ord x)) <> "'")+ : escapeString' escapeMode xs characterCodeMap :: Map.Map Char Text characterCodeMap = Map.fromList characterCodes@@ -112,9 +112,11 @@ fromMaybe False (Map.lookup 'B' features)] ++ ['I' | fromMaybe False $ Map.lookup 'I' features] return $- if null filling- then text "\\f[R]"- else text $ "\\f[" ++ filling ++ "]"+ case filling of+ [] -> text "\\f[R]"+ -- see #9020. C is not a font, use CR.+ ['C'] -> text "\\f[CR]"+ _ -> text $ "\\f[" ++ filling ++ "]" withFontFeature :: (HasChars a, IsString a, PandocMonad m) => Char -> MS m (Doc a) -> MS m (Doc a)
@@ -1,9 +1,11 @@ {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-} {- | Module : Text.Pandoc.Writers.Shared- Copyright : Copyright (C) 2013-2022 John MacFarlane+ Copyright : Copyright (C) 2013-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -22,6 +24,9 @@ , defField , getLang , tagWithAttrs+ , htmlAddStyle+ , htmlAlignmentToString+ , htmlAttrs , isDisplayMath , fixDisplayMath , unsmartify@@ -33,36 +38,61 @@ , stripLeadingTrailingSpace , toSubscript , toSuperscript+ , toSubscriptInline+ , toSuperscriptInline , toTableOfContents , endsWithPlain , toLegacyTable , splitSentences , ensureValidXmlIdentifiers+ , removeLinks+ , setupTranslations+ , isOrderedListMarker+ , toTaskListItem+ , delimited+ , allRowsEmpty+ , tableBodiesToRows+ , insertCurrentSpansAtColumn+ , takePreviousSpansAtColumn+ , decrementTrailingRowSpans ) where-import Safe (lastMay)+import Safe (lastMay, maximumMay) import qualified Data.ByteString.Lazy as BL-import Data.Maybe (fromMaybe, isNothing)-import Control.Monad (zipWithM)+import Control.Monad (MonadPlus, mzero)+import Data.Either (isRight) import Data.Aeson (ToJSON (..), encode)-import Data.Char (chr, ord, isSpace, isLetter)-import Data.List (groupBy, intersperse, transpose, foldl')-import Data.List.NonEmpty (NonEmpty(..), nonEmpty)+import Data.Char (chr, ord, isSpace, isLetter, isUpper)+import Data.List (groupBy, intersperse, transpose, zipWith4)+import qualified Data.List as L+import Data.List.NonEmpty (NonEmpty((:|))) import Data.Text.Conversions (FromText(..)) import qualified Data.Map as M import qualified Data.Text as T import Data.Text (Text) import qualified Text.Pandoc.Builder as Builder+import Text.Pandoc.CSS (cssAttributes) import Text.Pandoc.Definition import Text.Pandoc.Options+import Text.Pandoc.Parsing (runParser, eof, defaultParserState,+ anyOrderedListMarker) import Text.DocLayout import Text.Pandoc.Shared (stringify, makeSections, blocksToInlines)-import Text.Pandoc.Walk (walk)+import Text.Pandoc.Walk (Walkable(..)) import qualified Text.Pandoc.UTF8 as UTF8-import Text.Pandoc.XML (escapeStringForXML)+import Text.Pandoc.XML (escapeStringForXML, rdfaAttributes, html5Attributes) import Text.DocTemplates (Context(..), Val(..), TemplateTarget, ToContext(..), FromContext(..))+import Text.Pandoc.Chunks (tocToList, toTOCTree)+import Text.Collate.Lang (Lang (..))+import Text.Pandoc.Class (PandocMonad, toLang)+import Text.Pandoc.Translations (setTranslations)+import Data.Maybe (fromMaybe)+import qualified Text.Pandoc.Writers.AnnotatedTable as Ann+import qualified Data.Set as Set +-- import Debug.Trace+ -- | Create template Context from a 'Meta' and an association list -- of variables, specified at the command line or in the writer. -- Variables overwrite metadata fields with the same names.@@ -165,19 +195,59 @@ _ -> Nothing -- | Produce an HTML tag with the given pandoc attributes.-tagWithAttrs :: HasChars a => Text -> Attr -> Doc a-tagWithAttrs tag (ident,classes,kvs) = hsep- ["<" <> text (T.unpack tag)- ,if T.null ident+tagWithAttrs :: HasChars a => a -> Attr -> Doc a+tagWithAttrs tag attr = "<" <> literal tag <> (htmlAttrs attr) <> ">"++-- | Produce HTML for the given pandoc attributes, to be used in HTML tags+htmlAttrs :: HasChars a => Attr -> Doc a+htmlAttrs (ident, classes, kvs) = addSpaceIfNotEmpty (hsep [+ if T.null ident then empty else "id=" <> doubleQuotes (text $ T.unpack ident) ,if null classes then empty else "class=" <> doubleQuotes (text $ T.unpack (T.unwords classes))- ,hsep (map (\(k,v) -> text (T.unpack k) <> "=" <>+ ,hsep (map (\(k,v) -> formatKey k <> "=" <> doubleQuotes (text $ T.unpack (escapeStringForXML v))) kvs)- ] <> ">"+ ])+ where+ formatKey x = text . T.unpack $+ if (x `Set.member` (html5Attributes <> rdfaAttributes)+ && x /= "label") -- #10048+ || T.any (== ':') x -- e.g. epub: namespace+ || "data-" `T.isPrefixOf` x+ || "aria-" `T.isPrefixOf` x+ then x+ else "data-" <> x +addSpaceIfNotEmpty :: HasChars a => Doc a -> Doc a+addSpaceIfNotEmpty f = if isEmpty f then f else " " <> f++-- | Adds a key-value pair to the @style@ attribute.+htmlAddStyle :: (Text, Text) -> [(Text, Text)] -> [(Text, Text)]+htmlAddStyle (key, value) kvs =+ let cssToStyle = T.intercalate " " . map (\(k, v) -> k <> ": " <> v <> ";")+ in case break ((== "style") . fst) kvs of+ (_, []) ->+ -- no style attribute yet, add new one+ ("style", cssToStyle [(key, value)]) : kvs+ (xs, (_,cssStyles):rest) ->+ -- modify the style attribute+ xs ++ ("style", cssToStyle modifiedCssStyles) : rest+ where+ modifiedCssStyles =+ case break ((== key) . fst) $ cssAttributes cssStyles of+ (cssAttribs, []) -> (key, value) : cssAttribs+ (pre, _:post) -> pre ++ (key, value) : post++-- | Get the html representation of an alignment key+htmlAlignmentToString :: Alignment -> Maybe Text+htmlAlignmentToString = \case+ AlignLeft -> Just "left"+ AlignRight -> Just "right"+ AlignCenter -> Just "center"+ AlignDefault -> Nothing+ -- | Returns 'True' iff the argument is an inline 'Math' element of type -- 'DisplayMath'. isDisplayMath :: Inline -> Bool@@ -232,121 +302,305 @@ _ -> T.singleton c -- | Writes a grid table.-gridTable :: (Monad m, HasChars a)- => WriterOptions- -> (WriterOptions -> [Block] -> m (Doc a)) -- ^ format Doc writer- -> Bool -- ^ headless- -> [Alignment] -- ^ column alignments- -> [Double] -- ^ column widths- -> [[Block]] -- ^ table header row- -> [[[Block]]] -- ^ table body rows- -> m (Doc a)-gridTable opts blocksToDoc headless aligns widths headers rows = do- -- the number of columns will be used in case of even widths- let numcols = maximum (length aligns :| length widths :- map length (headers:rows))- let officialWidthsInChars widths' = map (- (\x -> if x < 1 then 1 else x) .- (\x -> x - 3) . floor .- (fromIntegral (writerColumns opts) *)- ) widths'- -- handleGivenWidths wraps the given blocks in order for them to fit- -- in cells with given widths. the returned content can be- -- concatenated with borders and frames- let handleGivenWidthsInChars widthsInChars' = do- -- replace page width (in columns) in the options with a- -- given width if smaller (adjusting by two)- let useWidth w = opts{writerColumns = min (w - 2) (writerColumns opts)}- -- prepare options to use with header and row cells- let columnOptions = map useWidth widthsInChars'- rawHeaders' <- zipWithM blocksToDoc columnOptions headers- rawRows' <- mapM- (\cs -> zipWithM blocksToDoc columnOptions cs)- rows- return (widthsInChars', rawHeaders', rawRows')- let handleGivenWidths widths' = handleGivenWidthsInChars- (officialWidthsInChars widths')- -- handleFullWidths tries to wrap cells to the page width or even- -- more in cases where `--wrap=none`. thus the content here is left- -- as wide as possible- let handleFullWidths widths' = do- rawHeaders' <- mapM (blocksToDoc opts) headers- rawRows' <- mapM (mapM (blocksToDoc opts)) rows- let numChars = maybe 0 maximum . nonEmpty . map offset- let minWidthsInChars =- map numChars $ transpose (rawHeaders' : rawRows')- let widthsInChars' = zipWith max- minWidthsInChars- (officialWidthsInChars widths')- return (widthsInChars', rawHeaders', rawRows')- -- handleZeroWidths calls handleFullWidths to check whether a wide- -- table would fit in the page. if the produced table is too wide,- -- it calculates even widths and passes the content to- -- handleGivenWidths- let handleZeroWidths widths' = do- (widthsInChars', rawHeaders', rawRows') <- handleFullWidths widths'- if foldl' (+) 0 widthsInChars' > writerColumns opts- then do -- use even widths except for thin columns- let evenCols = max 5- (((writerColumns opts - 1) `div` numcols) - 3)- let (numToExpand, colsToExpand) =- foldr (\w (n, tot) -> if w < evenCols- then (n, tot + (evenCols - w))- else (n + 1, tot))- (0,0) widthsInChars'- let expandAllowance = colsToExpand `div` numToExpand- let newWidthsInChars = map (\w -> if w < evenCols- then w- else min- (evenCols + expandAllowance)- w)- widthsInChars'- handleGivenWidthsInChars newWidthsInChars- else return (widthsInChars', rawHeaders', rawRows')- -- render the contents of header and row cells differently depending- -- on command line options, widths given in this specific table, and- -- cells' contents- let handleWidths- | writerWrapText opts == WrapNone = handleFullWidths widths- | all (== 0) widths = handleZeroWidths widths- | otherwise = handleGivenWidths widths- (widthsInChars, rawHeaders, rawRows) <- handleWidths- let hpipeBlocks blocks = hcat [beg, middle, end]- where sep' = vfill " | "- beg = vfill "| "- end = vfill " |"- middle = chomp $ hcat $ intersperse sep' blocks- let makeRow = hpipeBlocks . zipWith lblock widthsInChars- let head' = makeRow rawHeaders- let rows' = map (makeRow . map chomp) rawRows- let borderpart ch align widthInChars =- (if align == AlignLeft || align == AlignCenter- then char ':'- else char ch) <>- text (replicate widthInChars ch) <>- (if align == AlignRight || align == AlignCenter- then char ':'- else char ch)- let border ch aligns' widthsInChars' =- char '+' <>- hcat (intersperse (char '+') (zipWith (borderpart ch)- aligns' widthsInChars')) <> char '+'- let body = vcat $ intersperse (border '-' (repeat AlignDefault) widthsInChars)- rows'- let head'' = if headless- then empty- else head' $$ border '=' aligns widthsInChars- if headless- then return $- border '-' aligns widthsInChars $$- body $$- border '-' (repeat AlignDefault) widthsInChars- else return $- border '-' (repeat AlignDefault) widthsInChars $$- head'' $$- body $$- border '-' (repeat AlignDefault) widthsInChars+gridTable :: Monad m+ => WriterOptions+ -> (WriterOptions -> [Block] -> m (Doc Text)) -- ^ format Doc writer+ -> [ColSpec]+ -> TableHead+ -> [TableBody]+ -> TableFoot+ -> m (Doc Text)+gridTable opts blocksToDoc colspecs' thead' tbodies' tfoot' = do+ let Ann.Table _ _ colspecs thead tbodies tfoot =+ Ann.toTable mempty (Caption Nothing mempty)+ colspecs' thead' tbodies' tfoot'+ let renderRows = fmap addDummies . mapM (gridRow opts blocksToDoc)+ let getHeadCells (Ann.HeaderRow _ _ cells) = cells+ let getHeadRows (Ann.TableHead _ rs) = map getHeadCells rs+ headCells <- renderRows (getHeadRows thead)+ let getFootRows (Ann.TableFoot _ xs) = map getHeadCells xs+ footCells <- renderRows (getFootRows tfoot)+ -- We don't distinguish between row head and regular cells here:+ let getBodyCells (Ann.BodyRow _ _ rhcells cells) = rhcells ++ cells+ let getBody (Ann.TableBody _ _ hs xs) = map getHeadCells hs <> map getBodyCells xs+ bodyCells <- mapM (renderRows . getBody) tbodies+ let rows = (setTopBorder SingleLine . setBottomBorder DoubleHeaderLine) headCells +++ (setTopBorder (if null headCells+ then SingleHeaderLine+ else SingleLine) . setBottomBorder SingleLine)+ (mconcat bodyCells) +++ (setTopBorder DoubleLine . setBottomBorder DoubleLine) footCells+ pure $ gridRows $ redoWidths opts colspecs rows +data ColWidthInfo =+ ColWidthInfo+ { colWidthSpecified :: Int+ , colWidthFull :: Int+ , colWidthMin :: Int+ , colWidthUsed :: Int }+ deriving (Show, Ord, Eq)++-- Returns (current widths, full widths, min widths)+extractColWidths :: WriterOptions -> [[RenderedCell Text]] -> [ColWidthInfo]+extractColWidths opts rows =+ zipWith4 ColWidthInfo specifiedwidths fullwidths minwidths currentwidths+ where+ getWidths calcOffset =+ map (fromMaybe 0 . maximumMay) (transpose (map (concatMap (getCellWidths calcOffset)) rows))+ getCellWidths calcOffset c = replicate (cellColSpan c)+ (calcOffset c `div` (cellColSpan c) ++ calcOffset c `rem` (cellColSpan c))+ fullwidths = getWidths (max 1 . offset . cellContents)+ minwidths =+ case writerWrapText opts of+ WrapNone -> fullwidths+ _ -> getWidths (minOffset . cellContents)+ specifiedwidths = getWidths cellWidth+ currentwidths = zipWith (\specw minw -> if specw == 0+ then 0+ else max specw minw)+ specifiedwidths minwidths++resetWidths :: [Int] -> [RenderedCell Text] -> [RenderedCell Text]+resetWidths _ [] = []+resetWidths [] cs = cs+resetWidths (w:ws) (c:cs) =+ case cellColSpan c of+ 1 -> c{ cellWidth = w } : resetWidths ws cs+ n | n < 1 -> c : resetWidths ws cs+ | otherwise -> c{ cellWidth = w + sum (take (n - 1) ws) + (3 * (n-1)) }+ : resetWidths (drop (n - 1) ws) cs++redoWidths :: WriterOptions -> [ColSpec] -> [[RenderedCell Text]] -> [[RenderedCell Text]]+redoWidths _ _ [] = []+redoWidths opts colspecs rows = map (resetWidths newwidths) rows+ where+ numcols = length colspecs+ widthInfos = extractColWidths opts rows+ colsAvailable = writerColumns opts - (3 * numcols) - 1+ -- now, we need to change colWidthUsed 0 to an appropriate number;+ -- either the full width if it fits easily, or an appropriate fraction+ -- of the remaining width. This must be done recursively, because+ -- once we decide that the full width can fit, that may leave less+ -- space for the remaining columns with default width to fill.+ recalculateWidths finalRun numRuns infos =+ let numUnassigned = length (filter ((== 0) . colWidthUsed) infos)+ unusedCols = colsAvailable - sum (map colWidthUsed infos)+ defwidth = if numUnassigned == 0+ then 0+ else unusedCols `div` numUnassigned+ infos' = map (\info -> if colWidthUsed info == 0+ then if finalRun+ then info{ colWidthUsed =+ max (colWidthMin info) defwidth }+ else if colWidthFull info <= defwidth+ then info{ colWidthUsed = colWidthFull info }+ else info+ else info) infos+ in if finalRun || numRuns > 4+ then infos'+ else if infos == infos'+ then recalculateWidths True (numRuns + 1) infos+ -- run again, filling in unassigned widths with a fraction of the+ -- remaining width+ else recalculateWidths False (numRuns + 1) infos'+ -- run again, filling in unassigned widths only if the full with+ -- would be less than the fraction of remaining width+ newwidths = map colWidthUsed $ recalculateWidths False (1 :: Int) widthInfos++makeDummy :: RenderedCell Text -> RenderedCell Text+makeDummy c =+ RenderedCell{ cellColNum = cellColNum c,+ cellColSpan = cellColSpan c,+ cellColSpecs = cellColSpecs c,+ cellAlign = AlignDefault,+ cellRowSpan = cellRowSpan c - 1,+ cellWidth = cellWidth c,+ cellContents = mempty,+ cellBottomBorder = NoLine,+ cellTopBorder = NoLine }++addDummies :: [[RenderedCell Text]] -> [[RenderedCell Text]]+addDummies = reverse . L.foldl' go []+ where+ go [] cs = [cs]+ go (prevRow:rs) cs = addDummiesToRow prevRow cs : prevRow : rs+ addDummiesToRow [] cs = cs+ addDummiesToRow ds [] = map makeDummy ds+ addDummiesToRow (d:ds) (c:cs) =+ if cellColNum d < cellColNum c+ then makeDummy d : addDummiesToRow ds (c:cs)+ else c : addDummiesToRow+ (dropWhile (\x ->+ cellColNum x < cellColNum c + cellColSpan c) (d:ds))+ cs+++setTopBorder :: LineStyle -> [[RenderedCell Text]] -> [[RenderedCell Text]]+setTopBorder _ [] = []+setTopBorder sty (cs:rest) = (map (\c -> c{ cellTopBorder = sty }) cs) : rest++setBottomBorder :: LineStyle -> [[RenderedCell Text]] -> [[RenderedCell Text]]+setBottomBorder _ [] = []+setBottomBorder sty [cs] = [map (\c -> c{ cellBottomBorder = sty }) cs]+setBottomBorder sty (c:cs) = c : setBottomBorder sty cs++gridRows :: [[RenderedCell Text]] -> Doc Text+gridRows [] = mempty+gridRows (x:xs) =+ (case x of+ [] -> mempty+ (c:_) | isHeaderStyle (cellTopBorder c)+ -> formatHeaderLine (cellTopBorder c) (x:xs)+ | otherwise+ -> formatBorder cellTopBorder False x)+ $$+ vcat (zipWith (rowAndBottom (x:xs)) (x:xs) (xs ++ [[]]))+ where+ -- generate wrapped contents. include pipe borders, bottom and left++ renderCellContents c =+ -- we don't use cblock or lblock because the content might+ -- be interpreted as an indented code block...even though it+ -- would look better to right-align right-aligned cells...+ -- (TODO: change this on parsing side?)+ lblock (cellWidth c) (cellContents c)++ formatRow cs = vfill "| " <>+ hcat (intersperse (vfill " | ") (map renderCellContents cs)) <> vfill " |"++ rowAndBottom allRows thisRow nextRow =+ let isLastRow = null nextRow+ border1 = case thisRow of+ [] -> mempty+ (c:_) -> if isHeaderStyle (cellBottomBorder c)+ then formatHeaderLine (cellBottomBorder c) allRows+ else formatBorder cellBottomBorder False thisRow+ border2 = case nextRow of+ [] -> mempty+ (c:_) -> if isHeaderStyle (cellTopBorder c)+ then formatHeaderLine (cellTopBorder c) allRows+ else formatBorder cellTopBorder False nextRow+ combinedBorder = if isLastRow+ then border1+ else literal $ combineBorders+ (render Nothing border1) (render Nothing border2)+ in formatRow thisRow $$ combinedBorder++combineBorders :: Text -> Text -> Text+combineBorders t1 t2 =+ if T.null t1+ then t2+ else T.zipWith go t1 t2+ where+ go '+' _ = '+'+ go _ '+' = '+'+ go ':' _ = ':'+ go _ ':' = ':'+ go '|' '-' = '+'+ go '-' '|' = '+'+ go '|' '=' = '+'+ go '=' '|' = '+'+ go '=' _ = '='+ go _ '=' = '='+ go ' ' d = d+ go c _ = c++formatHeaderLine :: Show a => LineStyle -> [[RenderedCell a]] -> Doc Text+formatHeaderLine lineStyle rows =+ literal $ L.foldl'+ (\t row -> combineBorders t (render Nothing $ formatBorder (const lineStyle) True row))+ mempty rows++formatBorder :: Show a => (RenderedCell a -> LineStyle) -> Bool+ -> [RenderedCell a] -> Doc Text+formatBorder borderStyle alignMarkers cs =+ borderParts <> if lastBorderStyle == NoLine+ then char '|'+ else char '+'+ where+ (lastBorderStyle, borderParts) = L.foldl' addBorder (NoLine, mempty) cs+ addBorder (prevBorderStyle, accum) c =+ (borderStyle c, accum <> char junctionChar <> toBorderSection c)+ where junctionChar = case (borderStyle c, prevBorderStyle) of+ (NoLine, NoLine) -> '|'+ _ -> '+'+ toBorderSection c =+ text $ leftalign : replicate (cellWidth c) lineChar ++ [rightalign]+ where+ lineChar = case borderStyle c of+ NoLine -> ' '+ SingleLine -> '-'+ SingleHeaderLine -> '-'+ DoubleLine -> '='+ DoubleHeaderLine -> '='+ (leftalign, rightalign) =+ case cellAlign c of+ _ | not alignMarkers -> (lineChar,lineChar)+ AlignLeft -> (':',lineChar)+ AlignCenter -> (':',':')+ AlignRight -> (lineChar,':')+ AlignDefault -> (lineChar,lineChar)++data LineStyle = NoLine+ | SingleLine+ | DoubleLine+ | SingleHeaderLine+ | DoubleHeaderLine+ deriving (Show, Ord, Eq)++isHeaderStyle :: LineStyle -> Bool+isHeaderStyle SingleHeaderLine = True+isHeaderStyle DoubleHeaderLine = True+isHeaderStyle _ = False++data RenderedCell a =+ RenderedCell{ cellColNum :: Int+ , cellColSpan :: Int+ , cellColSpecs :: NonEmpty ColSpec+ , cellAlign :: Alignment+ , cellRowSpan :: Int+ , cellWidth :: Int+ , cellContents :: Doc a+ , cellBottomBorder :: LineStyle+ , cellTopBorder :: LineStyle+ }+ deriving (Show)++getColWidth :: ColSpec -> Double+getColWidth (_, ColWidth n) = n+getColWidth (_, ColWidthDefault) = 0 -- TODO?++toCharWidth :: WriterOptions -> Double -> Int+toCharWidth opts width =+ max 0 (floor (width * fromIntegral (writerColumns opts)) - 3)++gridRow :: (Monad m, HasChars a)+ => WriterOptions+ -> (WriterOptions -> [Block] -> m (Doc a)) -- ^ format Doc writer+ -> [Ann.Cell]+ -> m [RenderedCell a]+gridRow opts blocksToDoc = mapM renderCell+ where+ renderer = blocksToDoc opts+ renderCell (Ann.Cell cellcolspecs (Ann.ColNumber colnum)+ (Cell _ _ (RowSpan rowspan) _ blocks)) = do+ let ((align,_):|_) = cellcolspecs+ let width = toCharWidth opts $ sum (fmap getColWidth cellcolspecs)+ rendered <- renderer blocks+ pure $ RenderedCell{ cellColNum = colnum,+ cellColSpan = length cellcolspecs,+ cellColSpecs = cellcolspecs,+ cellAlign = align,+ cellRowSpan = rowspan,+ cellWidth = width,+ cellContents = rendered,+ cellBottomBorder = if rowspan < 2+ then SingleLine+ else NoLine,+ cellTopBorder = SingleLine }++ -- | Retrieve the metadata value for a given @key@ -- and convert to Bool. lookupMetaBool :: Text -> Meta -> Bool@@ -360,6 +614,8 @@ -- | Retrieve the metadata value for a given @key@ -- and extract blocks.+--+-- Note that an empty list is returned for maps, lists, and booleans. lookupMetaBlocks :: Text -> Meta -> [Block] lookupMetaBlocks key meta = case lookupMeta key meta of@@ -370,6 +626,8 @@ -- | Retrieve the metadata value for a given @key@ -- and extract inlines.+--+-- Note that an empty list is returned for maps and lists. lookupMetaInlines :: Text -> Meta -> [Inline] lookupMetaInlines key meta = case lookupMeta key meta of@@ -381,6 +639,8 @@ -- | Retrieve the metadata value for a given @key@ -- and convert to String.+--+-- Note that an empty list is returned for maps, lists, and booleans. lookupMetaString :: Text -> Meta -> Text lookupMetaString key meta = case lookupMeta key meta of@@ -422,38 +682,30 @@ | isSpace c = Just c | otherwise = Nothing +toSubscriptInline :: Inline -> Maybe Inline+toSubscriptInline Space = Just Space+toSubscriptInline (Span attr ils) = Span attr <$> traverse toSubscriptInline ils+toSubscriptInline (Str s) = Str . T.pack <$> traverse toSubscript (T.unpack s)+toSubscriptInline LineBreak = Just LineBreak+toSubscriptInline SoftBreak = Just SoftBreak+toSubscriptInline _ = Nothing++toSuperscriptInline :: Inline -> Maybe Inline+toSuperscriptInline Space = Just Space+toSuperscriptInline (Span attr ils) = Span attr <$> traverse toSuperscriptInline ils+toSuperscriptInline (Str s) = Str . T.pack <$> traverse toSuperscript (T.unpack s)+toSuperscriptInline LineBreak = Just LineBreak+toSuperscriptInline SoftBreak = Just SoftBreak+toSuperscriptInline _ = Nothing+ -- | Construct table of contents (as a bullet list) from document body. toTableOfContents :: WriterOptions -> [Block] -> Block-toTableOfContents opts bs =- BulletList $ filter (not . null)- $ map (sectionToListItem opts)- $ makeSections (writerNumberSections opts) Nothing bs---- | Converts a section Div to a list item for a table of contents;--- returns an empty list if the given block is not a section Div.-sectionToListItem :: WriterOptions -> Block -> [Block]-sectionToListItem opts (Div (ident,_,_)- (Header lev (_,classes,kvs) ils : subsecs))- | lev <= writerTOCDepth opts- , not (isNothing (lookup "number" kvs) && "unlisted" `elem` classes)- = Plain headerLink : [BulletList listContents | not (null listContents)]- where- num = fromMaybe "" $ lookup "number" kvs- addNumber = if T.null num- then id- else (Span ("",["toc-section-number"],[])- [Str num] :) . (Space :)- clean (Link _ xs _) = xs- clean (Note _) = []- clean x = [x]- headerText' = addNumber $ walk (concatMap clean) ils- headerLink = if T.null ident- then headerText'- else [Link ("toc-" <> ident, [], []) headerText' ("#" <> ident, "")]- listContents = filter (not . null) $ map (sectionToListItem opts) subsecs-sectionToListItem _ _ = []+toTableOfContents opts =+ tocToList (writerNumberSections opts) (writerTOCDepth opts)+ . toTOCTree+ . makeSections (writerNumberSections opts) Nothing -- | Returns 'True' iff the list of blocks has a @'Plain'@ as its last -- element.@@ -533,10 +785,10 @@ splitSentences = go . toList where go [] = mempty- go (Text len t : BreakingSpace : xs) =- if isSentenceEnding t- then Text len t <> NewLine <> go xs- else Text len t <> BreakingSpace <> go xs+ go (Text len t : AfterBreak _ : BreakingSpace : xs)+ | isSentenceEnding t = Text len t <> NewLine <> go xs+ go (Text len t : BreakingSpace : xs)+ | isSentenceEnding t = Text len t <> NewLine <> go xs go (x:xs) = x <> go xs toList (Concat (Concat a b) c) = toList (Concat a (Concat b c))@@ -546,12 +798,16 @@ isSentenceEnding t = case T.unsnoc t of Just (t',c)- | c == '.' || c == '!' || c == '?' -> True+ | c == '.' || c == '!' || c == '?'+ , not (isInitial t') -> True | c == ')' || c == ']' || c == '"' || c == '\x201D' -> case T.unsnoc t' of- Just (_,d) -> d == '.' || d == '!' || d == '?'+ Just (t'',d) -> d == '.' || d == '!' || d == '?' &&+ not (isInitial t'') _ -> False _ -> False+ where+ isInitial x = T.length x == 1 && T.all isUpper x -- | Ensure that all identifiers start with a letter, -- and modify internal links accordingly. (Yes, XML allows an@@ -594,3 +850,118 @@ Table (f attr) cap colspecs thead tbodies tfoot goBlock (Div attr bs) = Div (f attr) bs goBlock x = x++-- | Convert links to spans; most useful when writing elements that must not+-- contain links, e.g. to avoid nested links.+removeLinks :: [Inline] -> [Inline]+removeLinks = walk go+ where+ go (Link attr ils _) = Span attr ils+ go x = x++-- | Set translations based on the `lang` in metadata.+setupTranslations :: PandocMonad m => Meta -> m ()+setupTranslations meta = do+ let defLang = Lang "en" (Just "US") Nothing [] [] []+ lang <- case lookupMetaString "lang" meta of+ "" -> pure defLang+ s -> fromMaybe defLang <$> toLang (Just s)+ setTranslations lang++-- True if the string would count as a Markdown ordered list marker.+isOrderedListMarker :: Text -> Bool+isOrderedListMarker xs = not (T.null xs) && (T.last xs `elem` ['.',')']) &&+ isRight (runParser (anyOrderedListMarker >> eof)+ defaultParserState "" xs)++toTaskListItem :: MonadPlus m => [Block] -> m (Bool, [Block])+toTaskListItem (Plain (Str "☐":Space:ils):xs) = pure (False, Plain ils:xs)+toTaskListItem (Plain (Str "☒":Space:ils):xs) = pure (True, Plain ils:xs)+toTaskListItem (Para (Str "☐":Space:ils):xs) = pure (False, Para ils:xs)+toTaskListItem (Para (Str "☒":Space:ils):xs) = pure (True, Para ils:xs)+toTaskListItem _ = mzero++-- | Add an opener and closer to a Doc. If the Doc begins or ends+-- with whitespace, export this outside the opener or closer.+-- This is used for formats, like Markdown, which don't allow spaces+-- after opening or before closing delimiters.+delimited :: Doc Text -> Doc Text -> Doc Text -> Doc Text+delimited opener closer content =+ mconcat initialWS <> opener <> mconcat middle <> closer <> mconcat finalWS+ where+ contents = toList content+ (initialWS, rest) = span isWS contents+ (reverseFinalWS, reverseMiddle) = span isWS (reverse rest)+ finalWS = reverse reverseFinalWS+ middle = reverse reverseMiddle+ isWS NewLine = True+ isWS CarriageReturn = True+ isWS BreakingSpace = True+ isWS BlankLines{} = True+ isWS _ = False+ toList (Concat (Concat a b) c) = toList (Concat a (Concat b c))+ toList (Concat a b) = a : toList b+ toList x = [x]++-- | Determine whether all rows and their cells are empty.+allRowsEmpty :: [Row] -> Bool+allRowsEmpty = all isEmptyRow+ where+ isEmptyRow (Row _ cells) = all isEmptyCell cells+ isEmptyCell (Cell _ _ _ _ blocks) = null blocks++-- | Concatenates the header and body Rows of a List of TableBody into a flat+-- List of Rows.+tableBodiesToRows :: [TableBody] -> [Row]+tableBodiesToRows = concatMap tableBodyToRows+ where+ tableBodyToRows (TableBody _ _ headerRows bodyRows) = headerRows ++ bodyRows++-- | Insert the current span information of a table cell to keep track of it in+-- subsequent rows.+--+-- If 'RowSpan' @> 1@, the current span information will be inserted. Otherwise+-- the previous span information will be left unchanged.+--+-- Use 'takePreviousSpansAtColumn' to take previous span information at+-- subsequent rows. Use 'decrementTrailingRowSpans' to handle previous trailing+-- spans at the end of a row.+--+-- For writers that need to manually apply the 'RowSpan' of cells over multiple+-- rows or otherwise have to keep track of it.+insertCurrentSpansAtColumn :: Int -> M.Map Int (RowSpan, ColSpan) -> RowSpan -> ColSpan -> M.Map Int (RowSpan, ColSpan)+insertCurrentSpansAtColumn columnPosition previousSpans (RowSpan rowSpan) colSpan =+ if (rowSpan > 1)+ then M.insert columnPosition (RowSpan rowSpan - 1, colSpan) previousSpans -- Minus its own row.+ else previousSpans++-- | Take previous span information at a column position that was added with+-- 'insertCurrentSpansAtColumn' if available.+--+-- If the previous 'RowSpan' @>= 1@, this will return 'Just' the previous+-- 'ColSpan' and an adjusted span information where that 'RowSpan' is either+-- decremented or deleted if it would fall to 0. Otherwise this will return+-- 'Nothing'.+takePreviousSpansAtColumn :: Int -> M.Map Int (RowSpan, ColSpan) -> Maybe (ColSpan, M.Map Int (RowSpan, ColSpan))+takePreviousSpansAtColumn columnPosition previousSpans+ | Just previous@(RowSpan previousRowSpan, previousColSpan) <- M.lookup columnPosition previousSpans+ , previousRowSpan >= 1 = Just (previousColSpan, decrementPreviousRowSpans previous)+ | otherwise = Nothing+ where+ decrementPreviousRowSpans (RowSpan previousRowSpan, previousColSpan) =+ if previousRowSpan > 1+ then M.insert columnPosition (RowSpan previousRowSpan - 1, previousColSpan) previousSpans+ else M.delete columnPosition previousSpans++-- | Decrement all previously tracked trailing 'RowSpan' elements at or after a+-- column position.+--+-- For handling previous row spans that are next to the end of a row's cells+-- that were previously added with 'insertCurrentSpansAtColumn'.+decrementTrailingRowSpans :: Int -> M.Map Int (RowSpan, ColSpan) -> M.Map Int (RowSpan, ColSpan)+decrementTrailingRowSpans columnPosition = M.mapWithKey decrementTrailing+ where+ decrementTrailing previousColumnPosition previousSpan@(RowSpan rowSpan, colSpan) =+ if previousColumnPosition >= columnPosition && rowSpan >= 1+ then (RowSpan rowSpan - 1, colSpan)+ else previousSpan
@@ -1,15 +1,15 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternGuards #-} {- |- Module : Text.Pandoc.Writers.Docbook- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Module : Text.Pandoc.Writers.TEI+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu> Stability : alpha Portability : portable -Conversion of 'Pandoc' documents to Docbook XML.+Conversion of 'Pandoc' documents to TEI XML -} module Text.Pandoc.Writers.TEI (writeTEI) where import Data.Text (Text)@@ -22,11 +22,12 @@ import Text.Pandoc.Options import Text.DocLayout import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Shared import Text.Pandoc.XML --- | Convert Pandoc document to string in Docbook format.+-- | Convert Pandoc document to string in TEI XML format. writeTEI :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeTEI opts doc = do let Pandoc meta blocks = ensureValidXmlIdentifiers doc@@ -98,7 +99,6 @@ -- | Convert a Pandoc block element to TEI. blockToTEI :: PandocMonad m => WriterOptions -> Block -> m (Doc Text)-blockToTEI _ Null = return empty blockToTEI opts (Div attr@(_,"section":_,_) (Header lvl _ ils : xs)) = do -- TEI doesn't allow sections with no content, so insert some if needed@@ -129,18 +129,6 @@ -- we use treat as Para to ensure that Plain text ends up contained by -- something: blockToTEI opts (Plain lst) = blockToTEI opts $ Para lst--- title beginning with fig: indicates that the image is a figure---blockToTEI opts (Para [Image attr txt (src,'f':'i':'g':':':_)]) =--- let alt = inlinesToTEI opts txt--- capt = if null txt--- then empty--- else inTagsSimple "title" alt--- in inTagsIndented "figure" $--- capt $$--- (inTagsIndented "mediaobject" $--- (inTagsIndented "imageobject"--- (imageToTEI opts attr src)) $$--- inTagsSimple "textobject" (inTagsSimple "phrase" alt)) blockToTEI opts (Para lst) = inTags False "p" [] <$> inlinesToTEI opts lst blockToTEI opts (LineBlock lns) =@@ -150,9 +138,9 @@ blockToTEI opts (CodeBlock (_,classes,_) str) = return $ literal ("<ab type='codeblock " <> lang <> "'>") <> cr <> flush (literal (escapeStringForXML str) <> cr <> text "</ab>")- where lang = if null langs- then ""- else escapeStringForXML (head langs)+ where lang = case langs of+ [] -> ""+ (l:_) -> escapeStringForXML l syntaxMap = writerSyntaxMap opts isLang l = T.toLower l `elem` map T.toLower (languages syntaxMap) langsFrom s = if isLang s@@ -192,6 +180,8 @@ selfClosingTag "milestone" [("unit","undefined") ,("type","separator") ,("rendition","line")]+blockToTEI opts (Figure attr capt bs) =+ blockToTEI opts (figureDiv attr capt bs) -- TEI Tables -- TEI Simple's tables are composed of cells and rows; other
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.Texinfo- Copyright : Copyright (C) 2008-2022 John MacFarlane+ Copyright : Copyright (C) 2008-2024 John MacFarlane 2012 Peter Wang License : GNU GPL, version 2 or above @@ -12,36 +12,56 @@ Conversion of 'Pandoc' format into Texinfo. -} module Text.Pandoc.Writers.Texinfo ( writeTexinfo ) where+import Control.Monad (zipWithM, unless) import Control.Monad.Except (throwError) import Control.Monad.State.Strict+ ( StateT, MonadState(get), gets, modify, evalStateT ) import Data.Char (chr, ord, isAlphaNum)-import Data.List (maximumBy, transpose, foldl')+import Data.List (maximumBy, transpose)+import qualified Data.List as L import Data.List.NonEmpty (nonEmpty) import Data.Ord (comparing)-import qualified Data.Set as Set+import qualified Data.Map as M import Data.Text (Text) import qualified Data.Text as T import Network.URI (unEscapeString) import System.FilePath import Text.Pandoc.Class.PandocMonad (PandocMonad, report) import Text.Pandoc.Definition+import Text.Pandoc.Walk (walkM) import Text.Pandoc.Error import Text.Pandoc.ImageSize import Text.Pandoc.Logging import Text.Pandoc.Options import Text.DocLayout import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Shared import Text.Printf (printf) data WriterState = WriterState { stStrikeout :: Bool -- document contains strikeout- , stEscapeComma :: Bool -- in a context where we need @comma- , stIdentifiers :: Set.Set Text -- header ids used already+ , stContext :: Context+ , stNodes :: M.Map Text Int -- maps node to number of duplicates+ , stHeadings :: M.Map Text Text -- header ids to node texts , stOptions :: WriterOptions -- writer options } +data Context = NormalContext | NodeContext+ deriving (Eq, Show)++withContext :: PandocMonad m => Context -> TI m a -> TI m a+withContext context pa = do+ oldContext <- gets stContext+ modify $ \s -> s{ stContext = context }+ res <- pa+ modify $ \s -> s{ stContext = oldContext }+ pure res++disallowedInNode :: Char -> Bool+disallowedInNode c = c `elem` ['.',':',',','(',')']+ {- TODO: - internal cross references a la HTML - generated .texi files don't work when run through texi2dvi@@ -53,16 +73,36 @@ writeTexinfo :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeTexinfo options document = evalStateT (pandocToTexinfo options $ wrapTop document)- WriterState { stStrikeout = False, stEscapeComma = False,- stIdentifiers = Set.empty, stOptions = options}+ WriterState { stStrikeout = False,+ stContext = NormalContext,+ stNodes = mempty,+ stHeadings = mempty,+ stOptions = options} -- | Add a "Top" node around the document, needed by Texinfo. wrapTop :: Pandoc -> Pandoc wrapTop (Pandoc meta blocks) = Pandoc meta (Header 0 nullAttr (docTitle meta) : blocks) +addNodeText :: PandocMonad m => Block -> TI m Block+addNodeText (Header lev (ident,_,_) ils) | lev >= 1 && lev <= 4 = do+ node <- render Nothing <$> withContext NodeContext (inlineListToTexinfo ils)+ nodes <- gets stNodes+ node' <- case M.lookup node nodes of+ Just i -> do+ modify $ \st -> st{ stNodes = M.adjust (+ 1) node nodes }+ pure $ node <> " " <> tshow (i + 1)+ Nothing -> do+ modify $ \st -> st{ stNodes = M.insert node 1 nodes }+ pure node+ unless (T.null ident) $+ modify $ \st -> st{ stHeadings = M.insert ident node' (stHeadings st) }+ pure $ Header lev (ident,[],[("node", node')]) ils+addNodeText x = pure x+ pandocToTexinfo :: PandocMonad m => WriterOptions -> Pandoc -> TI m Text-pandocToTexinfo options (Pandoc meta blocks) = do+pandocToTexinfo options (Pandoc meta blocks') = do+ blocks <- walkM addNodeText blocks' let titlePage = not $ all null $ docTitle meta : docDate meta : docAuthors meta let colwidth = if writerWrapText options == WrapAuto@@ -84,55 +124,60 @@ Just tpl -> renderTemplate tpl context -- | Escape things as needed for Texinfo.-stringToTexinfo :: Text -> Text+stringToTexinfo :: PandocMonad m => Text -> TI m Text stringToTexinfo t- | T.all isAlphaNum t = t- | otherwise = T.concatMap escChar t- where escChar '{' = "@{"- escChar '}' = "@}"- escChar '@' = "@@"- escChar '\160' = "@ "- escChar '\x2014' = "---"- escChar '\x2013' = "--"- escChar '\x2026' = "@dots{}"- escChar '\x2019' = "'"- escChar c = T.singleton c--escapeCommas :: PandocMonad m => TI m (Doc Text) -> TI m (Doc Text)-escapeCommas parser = do- oldEscapeComma <- gets stEscapeComma- modify $ \st -> st{ stEscapeComma = True }- res <- parser- modify $ \st -> st{ stEscapeComma = oldEscapeComma }- return res+ | T.all isAlphaNum t = pure t+ | otherwise = do+ context <- gets stContext+ let escChar '{' = "@{"+ escChar '}' = "@}"+ escChar '@' = "@@"+ escChar '\160' = "@ "+ escChar '\x2014' = "---"+ escChar '\x2013' = "--"+ escChar '\x2026' = "@dots{}"+ escChar '\x2019' = "'"+ escChar ',' | context == NodeContext = ""+ escChar ':' | context == NodeContext = ""+ escChar '.' | context == NodeContext = ""+ escChar '(' | context == NodeContext = ""+ escChar ')' | context == NodeContext = ""+ escChar c = T.singleton c+ pure $ T.concatMap escChar t -- | Puts contents into Texinfo command. inCmd :: Text -> Doc Text -> Doc Text inCmd cmd contents = char '@' <> literal cmd <> braces contents +isCodeOrBreak :: Inline -> Bool+isCodeOrBreak (Code{}) = True+isCodeOrBreak LineBreak = True+isCodeOrBreak _ = False++isCode :: Inline -> Bool+isCode (Code{}) = True+isCode _ = False++codeToStr :: Inline -> Inline+codeToStr (Code _ s) = Str s+codeToStr x = x+ -- | Convert Pandoc block element to Texinfo. blockToTexinfo :: PandocMonad m => Block -- ^ Block to convert -> TI m (Doc Text) -blockToTexinfo Null = return empty- blockToTexinfo (Div _ bs) = blockListToTexinfo bs blockToTexinfo (Plain lst) = inlineListToTexinfo lst --- title beginning with fig: indicates that the image is a figure-blockToTexinfo (SimpleFigure attr txt (src, tit)) = do- capt <- if null txt- then return empty- else (\c -> text "@caption" <> braces c) `fmap`- inlineListToTexinfo txt- img <- inlineToTexinfo (Image attr txt (src,tit))- return $ text "@float" $$ img $$ capt $$ text "@end float"--blockToTexinfo (Para lst) =- inlineListToTexinfo lst -- this is handled differently from Plain in blockListToTexinfo+-- this is handled differently from Plain in blockListToTexinfo+blockToTexinfo (Para lst)+ | all isCodeOrBreak lst+ = (\xs -> "@example" $$ vcat xs $$ "@end example")+ <$> mapM (inlineToTexinfo . codeToStr) (filter isCode lst)+ | otherwise = inlineListToTexinfo lst blockToTexinfo (LineBlock lns) = blockToTexinfo $ linesToPara lns@@ -205,22 +250,12 @@ return $ text "@node Top" $$ text "@top " <> txt <> blankline -blockToTexinfo (Header level (ident,_,_) lst)- | level < 1 || level > 4 = blockToTexinfo (Para lst)- | otherwise = do- node <- inlineListForNode lst+blockToTexinfo (Header level (_,_,[("node",node)]) lst) = do txt <- inlineListToTexinfo lst- idsUsed <- gets stIdentifiers- opts <- gets stOptions- let id' = if T.null ident- then uniqueIdent (writerExtensions opts) lst idsUsed- else ident- modify $ \st -> st{ stIdentifiers = Set.insert id' idsUsed } sec <- seccmd level return $ if (level > 0) && (level <= 4)- then blankline <> text "@node " <> node $$- literal sec <> txt $$- text "@anchor" <> braces (literal $ "#" <> id')+ then blankline <> text "@node " <> literal node $$+ literal sec <> txt else txt where seccmd :: PandocMonad m => Int -> TI m Text@@ -230,6 +265,9 @@ seccmd 4 = return "@subsubsection " seccmd _ = throwError $ PandocSomeError "illegal seccmd level" +-- non-node header:+blockToTexinfo (Header _ _ lst) = blockToTexinfo (Para lst)+ blockToTexinfo (Table _ blkCapt specs thead tbody tfoot) = do let (caption, aligns, widths, heads, rows) = toLegacyTable blkCapt specs thead tbody tfoot headers <- if all null heads@@ -254,11 +292,44 @@ text "@end multitable" return $ if isEmpty captionText then tableBody <> blankline- else text "@float" $$+ else text "@float Table" $$ tableBody $$ inCmd "caption" captionText $$ text "@end float" +blockToTexinfo (Figure _ caption [SimpleFigure attr figCaption tgt]) = do+ let capt = if null figCaption+ then let (Caption _ cblks) = caption+ in blocksToInlines cblks+ else figCaption+ captionText <- if null capt+ then return empty+ else (text "@caption" <>) . braces <$> inlineListToTexinfo capt+ img <- inlineToTexinfo (Image attr figCaption tgt)+ return $ text "@float Figure" $$ img $$ captionText $$ text "@end float"++blockToTexinfo (Figure _ fCaption [+ Table attr tCaption@(Caption _ cbody) specs thead tbody tfoot]) = do+ let caption = case cbody of+ [] -> fCaption+ _ -> tCaption+ blockToTexinfo (Table attr caption specs thead tbody tfoot)++blockToTexinfo (Figure _ (Caption _ caption) body) = do+ captionText <- inlineListToTexinfo $ blocksToInlines caption+ content <- blockListToTexinfo body+ return $ text ("@float" ++ floatType body) $$ content $$ (+ if isEmpty captionText+ then empty+ else inCmd "caption" captionText+ ) $$ text "@end float"+ where+ -- floatType according to+ -- https://www.gnu.org/software/texinfo/manual/texinfo/html_node/_0040float.html+ floatType [SimpleFigure {}] = " Figure"+ floatType [Table {}] = " Table"+ floatType _ = ""+ tableHeadToTexinfo :: PandocMonad m => [Alignment] -> [[Block]]@@ -277,7 +348,7 @@ -> [[Block]] -> TI m (Doc Text) tableAnyRowToTexinfo itemtype aligns cols =- (literal itemtype $$) . foldl' (\row item -> row $$+ (literal itemtype $$) . L.foldl' (\row item -> row $$ (if isEmpty row then empty else text " @tab ") <> item) empty <$> zipWithM alignedBlock aligns cols alignedBlock :: PandocMonad m@@ -334,19 +405,23 @@ collectNodes _ [] = [] collectNodes level (x:xs) = case x of- (Header hl _ _) | hl < level -> []- | hl == level -> x : collectNodes level xs- | otherwise -> collectNodes level xs+ (Header hl _ _)+ | hl < level -> []+ | hl == level -> x : collectNodes level xs+ | otherwise -> collectNodes level xs _ -> collectNodes level xs makeMenuLine :: PandocMonad m => Block -> TI m (Doc Text)-makeMenuLine (Header _ _ lst) = do- txt <- inlineListForNode lst- return $ text "* " <> txt <> text "::"-makeMenuLine _ = throwError $ PandocSomeError "makeMenuLine called with non-Header block"+makeMenuLine (Header _ (_,_,[("node", node)]) lst) = do+ txt <- withContext NodeContext $ inlineListToTexinfo lst+ pure $ nowrap $ text "* " <>+ if render Nothing txt == node+ then literal node <> "::"+ else txt <> ": " <> literal node <> "."+makeMenuLine _ = throwError $ PandocSomeError "makeMenuLine called with non-node" listItemToTexinfo :: PandocMonad m => [Block]@@ -376,17 +451,6 @@ -> TI m (Doc Text) inlineListToTexinfo lst = hcat <$> mapM inlineToTexinfo lst --- | Convert list of inline elements to Texinfo acceptable for a node name.-inlineListForNode :: PandocMonad m- => [Inline] -- ^ Inlines to convert- -> TI m (Doc Text)-inlineListForNode = return . literal . stringToTexinfo .- T.filter (not . disallowedInNode) . stringify---- periods, commas, colons, and parentheses are disallowed in node names-disallowedInNode :: Char -> Bool-disallowedInNode c = c `elem` (".,:()" :: String)- -- | Convert inline element to Texinfo inlineToTexinfo :: PandocMonad m => Inline -- ^ Inline to convert@@ -421,9 +485,14 @@ inlineToTexinfo (SmallCaps lst) = inCmd "sc" <$> inlineListToTexinfo lst -inlineToTexinfo (Code _ str) =- return $ literal $ "@code{" <> stringToTexinfo str <> "}"+inlineToTexinfo (Code (_, cls , _) str) | T.pack "variable" `elem` cls = do+ code <- stringToTexinfo str+ return $ literal $ "@code{@var{" <> code <> "}}" +inlineToTexinfo (Code _ str) = do+ code <- stringToTexinfo str+ return $ literal $ "@code{" <> code <> "}"+ inlineToTexinfo (Quoted SingleQuote lst) = do contents <- inlineListToTexinfo lst return $ char '`' <> contents <> char '\''@@ -434,7 +503,7 @@ inlineToTexinfo (Cite _ lst) = inlineListToTexinfo lst-inlineToTexinfo (Str str) = return $ literal (stringToTexinfo str)+inlineToTexinfo (Str str) = literal <$> stringToTexinfo str inlineToTexinfo (Math _ str) = return $ inCmd "math" $ literal str inlineToTexinfo il@(RawInline f str) | f == "latex" || f == "tex" =@@ -453,21 +522,28 @@ inlineToTexinfo Space = return space inlineToTexinfo (Link _ txt (src, _))- | Just ('#', _) <- T.uncons src = do- contents <- escapeCommas $ inlineListToTexinfo txt- return $ text "@ref" <>- braces (literal (stringToTexinfo src) <> text "," <> contents)+ | Just ('#', ident) <- T.uncons src = do+ headings <- gets stHeadings+ target <- case M.lookup ident headings of+ Nothing -> literal <$> stringToTexinfo+ (T.filter (not . disallowedInNode) src)+ Just node -> pure $ literal node+ contents <- withContext NodeContext $ inlineListToTexinfo txt+ return $ text "@ref"+ <> braces (target <> if contents == target+ then mempty+ else text ",," <> contents) | otherwise = case txt of [Str x] | escapeURI x == src -> -- autolink return $ literal $ "@url{" <> x <> "}" _ -> do- contents <- escapeCommas $ inlineListToTexinfo txt- let src1 = stringToTexinfo src+ contents <- withContext NodeContext $ inlineListToTexinfo txt+ src1 <- stringToTexinfo src return $ literal ("@uref{" <> src1 <> ",") <> contents <> char '}' inlineToTexinfo (Image attr alternate (source, _)) = do- content <- escapeCommas $ inlineListToTexinfo alternate+ content <- withContext NodeContext $ inlineListToTexinfo alternate opts <- gets stOptions let showDim dim = case dimension dim attr of (Just (Pixel a)) -> showInInch opts (Pixel a) <> "in"
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.Textile- Copyright : Copyright (C) 2010-2022 John MacFarlane+ Copyright : Copyright (C) 2010-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -13,7 +13,8 @@ Textile: <http://thresholdstate.com/articles/4312/the-textile-reference-manual> -} module Text.Pandoc.Writers.Textile ( writeTextile ) where-import Control.Monad.State.Strict+import Control.Monad (zipWithM, liftM)+import Control.Monad.State.Strict ( StateT, gets, modify, evalStateT ) import Data.Char (isSpace) import Data.Text (Text) import qualified Data.Text as T@@ -99,8 +100,6 @@ -> Block -- ^ Block element -> TW m Text -blockToTextile _ Null = return ""- blockToTextile opts (Div attr bs) = do let startTag = render Nothing $ tagWithAttrs "div" attr let endTag = "</div>"@@ -110,11 +109,6 @@ blockToTextile opts (Plain inlines) = inlineListToTextile opts inlines -blockToTextile opts (SimpleFigure attr txt (src, tit)) = do- capt <- blockToTextile opts (Para txt)- im <- inlineToTextile opts (Image attr txt (src,tit))- return $ im <> "\n" <> capt- blockToTextile opts (Para inlines) = do useTags <- gets stUseTags listLevel <- gets stListLevel@@ -242,6 +236,19 @@ contents <- withUseTags $ mapM (definitionListItemToTextile opts) items return $ "<dl>\n" <> vcat contents <> "\n</dl>\n" +blockToTextile opts (Figure attr (Caption _ caption) body) = do+ let startTag = render Nothing $ tagWithAttrs "figure" attr+ let endTag = "</figure>"+ let captionInlines = blocksToInlines caption+ captionMarkup <- if null captionInlines+ then return ""+ else ((<> "\n\n</figcaption>\n\n") . ("<figcaption>\n\n" <>)) <$>+ inlineListToTextile opts (blocksToInlines caption)+ contents <- blockListToTextile opts body+ return $ startTag <> "\n\n" <>+ captionMarkup <>+ contents <> "\n\n" <> endTag <> "\n"+ -- Auxiliary functions for lists: -- | Convert ordered list attributes to HTML attribute string@@ -330,14 +337,10 @@ -> TW m Text tableRowToTextile opts alignStrings rownum cols' = do let celltype = if rownum == 0 then "th" else "td"- let rowclass = case rownum of- 0 -> "header"- x | x `rem` 2 == 1 -> "odd"- _ -> "even" cols'' <- zipWithM (\alignment item -> tableItemToTextile opts celltype alignment item) alignStrings cols'- return $ "<tr class=\"" <> rowclass <> "\">\n" <> T.unlines cols'' <> "</tr>"+ return $ "<tr>\n" <> T.unlines cols'' <> "</tr>" alignmentToText :: Alignment -> Text alignmentToText alignment = case alignment of@@ -380,37 +383,37 @@ inlineToTextile opts (Emph lst) = do contents <- inlineListToTextile opts lst- return $ if '_' `elemText` contents+ return $ if T.any (== '_') contents then "<em>" <> contents <> "</em>" else "_" <> contents <> "_" inlineToTextile opts (Underline lst) = do contents <- inlineListToTextile opts lst- return $ if '+' `elemText` contents+ return $ if T.any (== '+') contents then "<u>" <> contents <> "</u>" else "+" <> contents <> "+" inlineToTextile opts (Strong lst) = do contents <- inlineListToTextile opts lst- return $ if '*' `elemText` contents+ return $ if T.any (== '*') contents then "<strong>" <> contents <> "</strong>" else "*" <> contents <> "*" inlineToTextile opts (Strikeout lst) = do contents <- inlineListToTextile opts lst- return $ if '-' `elemText` contents+ return $ if T.any (== '-') contents then "<del>" <> contents <> "</del>" else "-" <> contents <> "-" inlineToTextile opts (Superscript lst) = do contents <- inlineListToTextile opts lst- return $ if '^' `elemText` contents+ return $ if T.any (== '^') contents then "<sup>" <> contents <> "</sup>" else "[^" <> contents <> "^]" inlineToTextile opts (Subscript lst) = do contents <- inlineListToTextile opts lst- return $ if '~' `elemText` contents+ return $ if T.any (== '~') contents then "<sub>" <> contents <> "</sub>" else "[~" <> contents <> "~]" @@ -427,7 +430,7 @@ inlineToTextile opts (Cite _ lst) = inlineListToTextile opts lst inlineToTextile _ (Code _ str) =- return $ if '@' `elemText` str+ return $ if T.any (== '@') str then "<tt>" <> escapeStringForXML str <> "</tt>" else "@" <> str <> "@"
@@ -0,0 +1,730 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ScopedTypeVariables #-}+{- |+ Module : Text.Pandoc.Writers.Typst+ Copyright : Copyright (C) 2023 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Conversion of 'Pandoc' format into Typst markup+(<https://typst.app>).+-}+module Text.Pandoc.Writers.Typst (+ writeTypst+ ) where+import Text.Pandoc.Definition+import Text.Pandoc.Class ( PandocMonad, report, runPure, fetchItem )+import Text.Pandoc.ImageSize ( dimension, Dimension(Pixel), Direction(..),+ showInInch )+import Text.Pandoc.Options ( WriterOptions(..), WrapOption(..), isEnabled,+ CaptionPosition(..), HighlightMethod(..) )+import Data.Text (Text)+import Data.List (intercalate, intersperse)+import Data.Bifunctor (first, second)+import Network.URI (unEscapeString)+import qualified Data.Text as T+import Control.Monad (unless)+import Control.Monad.State ( StateT, evalStateT, gets, modify )+import Text.Pandoc.Writers.Shared ( lookupMetaInlines, lookupMetaString,+ metaToContext, defField, resetField,+ setupTranslations )+import Text.Pandoc.Shared (isTightList, orderedListMarkers, tshow, stringify)+import Text.Pandoc.Highlighting (highlight, formatTypstBlock, formatTypstInline,+ styleToTypst)+import Text.Pandoc.Translations (Term(Abstract), translateTerm)+import Text.Pandoc.Error (PandocError(PandocSomeError))+import Text.Pandoc.Walk (query)+import Text.Pandoc.Writers.Math (convertMath)+import qualified Text.TeXMath as TM+import Text.DocLayout+import Text.DocTemplates (renderTemplate)+import Text.Pandoc.Extensions (Extension(..))+import Text.Pandoc.Logging (LogMessage(..))+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Collate.Lang (Lang(..), parseLang)+import Text.Printf (printf)+import Data.Char (isDigit)+import Data.Maybe (fromMaybe)+import Unicode.Char (isXIDContinue)+import qualified Data.ByteString as B++-- | Convert Pandoc to Typst.+writeTypst :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeTypst options document =+ evalStateT (pandocToTypst options document)+ WriterState{ stOptions = options,+ stEscapeContext = NormalContext,+ stHighlighting = False }++data EscapeContext = NormalContext | TermContext+ deriving (Show, Eq)++data WriterState =+ WriterState {+ stOptions :: WriterOptions,+ stEscapeContext :: EscapeContext,+ stHighlighting :: Bool+ }++type TW m = StateT WriterState m++pandocToTypst :: PandocMonad m+ => WriterOptions -> Pandoc -> TW m Text+pandocToTypst options (Pandoc meta blocks) = do+ let colwidth = if writerWrapText options == WrapAuto+ then Just $ writerColumns options+ else Nothing+ setupTranslations meta+ metadata <- metaToContext options+ blocksToTypst+ (fmap chomp . inlinesToTypst)+ meta+ main <- blocksToTypst blocks+ abstractTitle <- translateTerm Abstract+ let toPosition :: CaptionPosition -> Text+ toPosition CaptionAbove = "top"+ toPosition CaptionBelow = "bottom"+ let nociteIds = query (\case+ Cite cs _ -> map citationId cs+ _ -> [])+ $ lookupMetaInlines "nocite" meta+ hasHighlighting <- gets stHighlighting++ let context = defField "body" main+ $ defField "toc" (writerTableOfContents options)+ $ (if isEnabled Ext_citations options+ then defField "citations" True+ . defField "nocite-ids" (filter (/= "*") nociteIds)+ . defField "full-bibliography" ("*" `elem` nociteIds)+ else id)+ $ (case lookupMetaString "lang" meta of+ "" -> id+ lang ->+ case parseLang lang of+ Left _ -> id+ Right l ->+ resetField "lang" (langLanguage l) .+ maybe id (resetField "region") (langRegion l))+ $ defField "csl" (lookupMetaString "citation-style" meta) -- #10661+ $ defField "smart" (isEnabled Ext_smart options)+ $ defField "abstract-title" abstractTitle+ $ defField "toc-depth" (tshow $ writerTOCDepth options)+ $ (if hasHighlighting+ then case writerHighlightMethod options of+ Skylighting sty ->+ defField "highlighting-definitions"+ (T.stripEnd $ styleToTypst sty)+ _ -> id+ else id)+ $ defField "figure-caption-position"+ (toPosition $ writerFigureCaptionPosition options)+ $ defField "table-caption-position"+ (toPosition $ writerTableCaptionPosition options)+ $ defField "page-numbering" ("1" :: Text)+ $ (if writerNumberSections options+ then defField "section-numbering" ("1.1.1.1.1" :: Text)+ else id)+ metadata+ return $ render colwidth $+ case writerTemplate options of+ Nothing -> main+ Just tpl -> renderTemplate tpl context++pickTypstAttrs :: [(Text, Text)] -> ([(Text, Text)],[(Text, Text)])+pickTypstAttrs = foldr go ([],[])+ where+ go (k,v) =+ case T.splitOn ":" k of+ ["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)++toTypstPropsListTerm :: [(Text, Text)] -> Doc Text+toTypstPropsListTerm [] = ""+toTypstPropsListTerm typstAttrs = toTypstPropsListSep typstAttrs <> ","++toTypstPropsListParens :: [(Text, Text)] -> Doc Text+toTypstPropsListParens [] = ""+toTypstPropsListParens typstAttrs = parens $ toTypstPropsListSep typstAttrs++toTypstTextElement :: [(Text, Text)] -> Doc Text -> Doc Text+toTypstTextElement [] content = content+toTypstTextElement typstTextAttrs content = "#text" <> toTypstPropsListParens typstTextAttrs <> brackets content++toTypstSetText :: [(Text, Text)] -> Doc Text+toTypstSetText [] = ""+toTypstSetText typstTextAttrs = "set text" <> parens (toTypstPropsListSep typstTextAttrs) <> ";"++toTypstPoundSetText :: [(Text, Text)] -> Doc Text+toTypstPoundSetText [] = mempty+toTypstPoundSetText typstTextAttrs = "#" <> toTypstSetText typstTextAttrs++toTypstBracesSetText :: [(Text, Text)] -> Doc Text -> Doc Text+toTypstBracesSetText [] x = "#" <> x+toTypstBracesSetText typstTextAttrs x = "#" <> braces (toTypstSetText typstTextAttrs <> x)++blocksToTypst :: PandocMonad m => [Block] -> TW m (Doc Text)+blocksToTypst blocks = vcat <$> mapM blockToTypst blocks++blockToTypst :: PandocMonad m => Block -> TW m (Doc Text)+blockToTypst block =+ case block of+ Plain inlines -> inlinesToTypst inlines+ Para inlines -> do+ ($$ blankline) <$> inlinesToTypst inlines+ Header level (ident,cls,_) inlines -> do+ contents <- inlinesToTypst inlines+ let lab = toLabel FreestandingLabel ident+ let headingAttrs =+ ["outlined: false" | "unlisted" `elem` cls] +++ ["numbering: none" | "unnumbered" `elem` cls]+ return $+ if null headingAttrs+ then nowrap+ (literal (T.replicate level "=") <> space <> contents) <>+ cr <> lab+ else literal "#heading" <>+ parens (literal (T.intercalate ", "+ ("level: " <> tshow level : headingAttrs))) <>+ brackets contents <> cr <> lab+ RawBlock fmt str ->+ case fmt of+ Format "typst" -> return $ literal str+ _ -> return mempty+ CodeBlock (ident,cls,kvs) code -> do+ let go :: Char -> (Int, Int) -> (Int, Int)+ go '`' (longest, current) =+ let !new = current + 1 in (max longest new, new)+ go _ (longest, _) = (longest, 0)+ let (longestBacktickSequence, _) = T.foldr go (0,0) code+ let fence = literal $ T.replicate (max 3 (longestBacktickSequence + 1)) "`"+ let lang = case cls of+ (cl:_) -> literal cl+ _ -> mempty+ opts <- gets stOptions+ case writerHighlightMethod opts of+ Skylighting _ ->+ case highlight (writerSyntaxMap opts) formatTypstBlock+ (ident,cls ++ ["default"],kvs) code of+ Left msg -> do+ unless (T.null msg) $ report $ CouldNotHighlight msg+ return $ fence <> lang <> cr <> literal code <> cr <> fence <> blankline+ Right h -> do+ modify (\s -> s{ stHighlighting = True })+ return (literal h)+ NoHighlighting -> return $ fence <> cr <> literal code <> cr <> fence <> blankline+ _ -> return $ fence <> lang <> cr <> literal code <> cr <> fence <> blankline+ LineBlock lns -> do+ contents <- inlinesToTypst (intercalate [LineBreak] lns)+ return $ contents <> blankline+ BlockQuote blocks -> do+ contents <- blocksToTypst blocks+ return $ "#quote(block: true)[" $$ chomp contents $$ "]" $$ blankline+ HorizontalRule ->+ return $ blankline <> "#horizontalrule" <> blankline+ OrderedList attribs items -> do+ let addBlock = case attribs of+ (1, DefaultStyle, DefaultDelim) -> id+ (1, Decimal, Period) -> id+ (start, sty, delim) -> \x ->+ "#block[" $$+ ("#set enum" <>+ parens (+ "numbering: " <>+ doubleQuoted+ (case orderedListMarkers (1, sty, delim) of+ (m:_) -> m+ [] -> "1.") <>+ ", start: " <>+ text (show start) )) $$+ x $$+ "]"+ items' <- mapM (fmap chomp . listItemToTypst 2 ("+")) items+ return $ addBlock+ (if isTightList items+ then vcat items'+ else vsep items')+ $$ blankline+ BulletList items -> do+ items' <- mapM (fmap chomp . listItemToTypst 2 "-") items+ return $ (if isTightList items+ then vcat items'+ else vsep items') $$ blankline+ DefinitionList items ->+ ($$ blankline) . vsep <$> mapM defListItemToTypst items+ Table (ident,tabclasses,tabkvs) (Caption _ caption) colspecs thead tbodies tfoot -> do+ let lab = toLabel FreestandingLabel ident+ capt' <- if null caption+ then return mempty+ else do+ captcontents <- blocksToTypst caption+ return $ ", caption: " <> brackets captcontents+ let typstFigureKind = literal (", kind: " <> fromMaybe "table" (lookup "typst:figure:kind" tabkvs))+ let numcols = length colspecs+ let (aligns, widths) = unzip colspecs+ let commaSep = hcat . intersperse ", "+ let toPercentage (ColWidth w) =+ literal $ (T.dropWhileEnd (== '.') . T.dropWhileEnd (== '0'))+ (T.pack (printf "%0.2f" (w * 100))) <> "%"+ toPercentage ColWidthDefault = literal "auto"+ let columns = if all (== ColWidthDefault) widths+ then literal $ tshow numcols+ else parens (commaSep (map toPercentage widths))+ let formatalign AlignLeft = "left,"+ formatalign AlignRight = "right,"+ formatalign AlignCenter = "center,"+ formatalign AlignDefault = "auto,"+ let alignarray = parens $ mconcat $ map formatalign aligns++ let fromCell (Cell (_,_,kvs) alignment rowspan colspan bs) = do+ let (typstAttrs, typstTextAttrs) = pickTypstAttrs kvs+ let valign =+ (case lookup "align" typstAttrs of+ Just va -> [va]+ _ -> [])+ let typstAttrs2 = filter ((/="align") . fst) typstAttrs+ let halign =+ (case alignment of+ AlignDefault -> []+ AlignLeft -> [ "left" ]+ AlignRight -> [ "right" ]+ AlignCenter -> [ "center" ])+ let cellaligns = valign ++ halign+ let cellattrs =+ (case cellaligns of+ [] -> []+ _ -> [ "align: " <> T.intercalate " + " cellaligns ]) +++ (case rowspan of+ RowSpan 1 -> []+ RowSpan n -> [ "rowspan: " <> tshow n ]) +++ (case colspan of+ ColSpan 1 -> []+ ColSpan n -> [ "colspan: " <> tshow n ]) +++ map formatTypstProp typstAttrs2+ cellContents <- blocksToTypst bs+ let contents2 = brackets (toTypstPoundSetText typstTextAttrs $$ cellContents)+ pure $ if null cellattrs+ then contents2+ else "table.cell" <>+ parens+ (literal (T.intercalate ", " cellattrs)) <>+ contents2+ let fromRow (Row _ cs) =+ (<> ",") . commaSep <$> mapM fromCell cs+ let fromHead (TableHead _attr headRows) =+ if null headRows+ then pure mempty+ else (($$ "table.hline(),") .+ (<> ",") . ("table.header" <>) . parens . nest 2 . vcat)+ <$> mapM fromRow headRows+ let fromFoot (TableFoot _attr footRows) =+ if null footRows+ then pure mempty+ else (("table.hline()," $$) .+ (<> ",") . ("table.footer" <>) . parens . nest 2 . vcat)+ <$> mapM fromRow footRows+ let fromTableBody (TableBody _attr _rowHeadCols headRows bodyRows) = do+ hrows <- mapM fromRow headRows+ brows <- mapM fromRow bodyRows+ pure $ vcat (hrows ++ ["table.hline()," | not (null hrows)] ++ brows)+ let (typstAttrs, typstTextAttrs) = pickTypstAttrs tabkvs+ header <- fromHead thead+ footer <- fromFoot tfoot+ body <- vcat <$> mapM fromTableBody tbodies+ let table = "table("+ $$ nest 2+ ( "columns: " <> columns <> ","+ $$ "align: " <> alignarray <> ","+ $$ toTypstPropsListTerm typstAttrs+ $$ header+ $$ body+ $$ footer+ )+ $$ ")"+ return $ if "typst:no-figure" `elem` tabclasses+ then toTypstBracesSetText typstTextAttrs table+ else "#figure("+ $$+ nest 2+ ("align(center)[" <> toTypstPoundSetText typstTextAttrs <> "#" <> table <> "]"+ $$ capt'+ $$ typstFigureKind+ $$ ")")+ $$ lab+ $$ blankline+ Figure (ident,_,_) (Caption _mbshort capt) blocks -> do+ caption <- blocksToTypst capt+ opts <- gets stOptions+ let toImage (Image attr inlines (src, _)) =+ Just $ mkImage opts False src attr (getAlt attr inlines)+ toImage _ = Nothing+ contents <- case blocks of+ -- don't need #box around block-level image+ [Para [img]] | Just i <- toImage img -> pure i+ [Plain [img]] | Just i <- toImage img -> pure i+ _ -> brackets <$> blocksToTypst blocks+ let lab = toLabel FreestandingLabel ident+ return $ "#figure(" <> nest 2 ((contents <> ",")+ $$+ ("caption: [" $$ nest 2 caption $$ "]")+ )+ $$ ")" $$ lab $$ blankline+ Div (ident,_,_) (Header lev ("",cls,kvs) ils:rest) ->+ blocksToTypst (Header lev (ident,cls,kvs) ils:rest)+ 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 allTypstTextAttrs+ $$ contents+ $$ ("]" <+> lab)++defListItemToTypst :: PandocMonad m => ([Inline], [[Block]]) -> TW m (Doc Text)+defListItemToTypst (term, defns) = do+ modify $ \st -> st{ stEscapeContext = TermContext }+ term' <- inlinesToTypst term+ modify $ \st -> st{ stEscapeContext = NormalContext }+ defns' <- mapM blocksToTypst defns+ return $ nowrap ("/ " <> term' <> ": " <> "#block[") $$+ chomp (vsep defns') $$ "]"++listItemToTypst :: PandocMonad m => Int -> Doc Text -> [Block] -> TW m (Doc Text)+listItemToTypst ind marker blocks = do+ contents <- blocksToTypst blocks+ return $ hang ind (marker <> space) contents++inlinesToTypst :: PandocMonad m => [Inline] -> TW m (Doc Text)+inlinesToTypst (i@(Span (ident,_,_) _):is) | not (T.null ident) =+ -- insert a zero-width space U+200B before the label+ -- because a typst label refers to preceding element (see #11568)+ ("\x200B" <>) . hcat <$> mapM inlineToTypst (escapeParens (i:is))+inlinesToTypst ils = hcat <$> mapM inlineToTypst (escapeParens ils)++-- Add an escape before a parenthesis right after a non-space element.+-- Otherwise we risk `#emph[test](3)` which will error. See #11210.+escapeParens :: [Inline] -> [Inline]+escapeParens [] = []+escapeParens (s : x : xs)+ | isSpacey s+ = s : x : escapeParens xs+escapeParens (Str t : xs)+ | Just ('(',_) <- T.uncons t+ = RawInline (Format "typst") "\\" : Str t : escapeParens xs+escapeParens (x : xs) = x : escapeParens xs++isSpacey :: Inline -> Bool+isSpacey Space = True+isSpacey SoftBreak = True+isSpacey LineBreak = True+isSpacey _ = False++inlineToTypst :: PandocMonad m => Inline -> TW m (Doc Text)+inlineToTypst inline =+ case inline of+ Str txt -> do+ opts <- gets stOptions+ context <- gets stEscapeContext+ return $ escapeTypst (isEnabled Ext_smart opts) context txt+ Space -> return space+ SoftBreak -> do+ wrapText <- gets $ writerWrapText . stOptions+ case wrapText of+ WrapPreserve -> return cr+ WrapAuto -> return space+ WrapNone -> return space+ LineBreak -> return (space <> "\\" <> space)+ Math mathType str -> do+ res <- convertMath TM.writeTypst mathType str+ case res of+ Left il -> inlineToTypst il+ Right r ->+ (case extractLabel str of -- #10805+ Nothing -> id+ Just lab -> (<> (toLabel FreestandingLabel lab))) <$>+ case mathType of+ InlineMath -> return $ "$" <> literal r <> "$"+ DisplayMath -> return $ "$ " <> literal r <> " $"+ Code (ident,cls,kvs) code -> do+ opts <- gets stOptions+ let defaultHighlightedCode =+ case cls of+ (lang:_) | writerHighlightMethod opts /= NoHighlighting+ -> "#raw(lang:" <> doubleQuoted lang <>+ ", " <> doubleQuoted code <> ")"+ _ | T.any (=='`') code -> "#raw(" <> doubleQuoted code <> ")"+ | otherwise -> "`" <> literal code <> "`"+ case writerHighlightMethod opts of+ Skylighting _ ->+ case highlight (writerSyntaxMap opts) formatTypstInline+ (ident,cls ++ ["default"],kvs) code of+ Left msg -> do+ unless (T.null msg) $ report $ CouldNotHighlight msg+ return defaultHighlightedCode+ Right h -> do+ modify (\s -> s{ stHighlighting = True })+ return (literal h)+ _ -> return defaultHighlightedCode+ RawInline fmt str ->+ case fmt of+ Format "typst" -> return $ literal str+ _ -> return mempty+ Strikeout inlines -> textstyle "#strike" inlines+ Emph inlines -> textstyle "#emph" inlines+ Underline inlines -> textstyle "#underline" inlines+ Strong inlines -> textstyle "#strong" inlines+ Superscript inlines -> textstyle "#super" inlines+ Subscript inlines -> textstyle "#sub" inlines+ SmallCaps inlines -> textstyle "#smallcaps" inlines+ Span (ident,cls,kvs) inlines -> do+ let lab = toLabel FreestandingLabel ident+ let (_, typstTextAttrs) = pickTypstAttrs kvs+ contents <- inlinesToTypst inlines+ let addHl x = "#highlight" <> brackets x+ return $ (if "mark" `elem` cls+ then addHl+ else id)+ (toTypstTextElement typstTextAttrs contents) <> lab+ Quoted quoteType inlines -> do+ opts <- gets stOptions+ let smart = isEnabled Ext_smart opts+ contents <- inlinesToTypst inlines+ return $+ case quoteType of+ DoubleQuote+ | smart -> "\"" <> contents <> "\""+ | otherwise -> "“" <> contents <> "”"+ SingleQuote+ | smart -> "'" <> contents <> "'"+ | otherwise -> "‘" <> contents <> "’"+ Cite citations inlines -> do+ opts <- gets stOptions+ if isEnabled Ext_citations opts+ -- Note: this loses prefix+ then mconcat <$> mapM toCite citations+ else inlinesToTypst inlines+ Link (_,_,kvs) inlines (src,_tit) -> do+ case lookup "reference-type" kvs of+ Just "ref"+ | Just ('#', ident) <- T.uncons src+ -> if T.all isIdentChar ident+ then pure $ literal $ "@" <> ident+ else pure $ "#ref" <> parens (toLabel ArgumentLabel ident)+ _ -> do+ contents <- inlinesToTypst inlines+ let dest = case T.uncons src of+ Just ('#', ident) -> toLabel ArgumentLabel ident+ _ -> doubleQuoted src+ pure $ "#link" <> parens dest <>+ (if inlines == [Str src]+ then mempty+ else nowrap $ brackets contents)+ Image attr inlines (src,_tit) -> do+ opts <- gets stOptions+ pure $ mkImage opts True src attr (getAlt attr inlines)+ Note blocks -> do+ contents <- blocksToTypst blocks+ return $ "#footnote" <> brackets (chomp contents)++-- see #9104; need box or image is treated as block-level+mkImage :: WriterOptions -> Bool -> Text -> Attr -> Maybe Text -> Doc Text+mkImage opts useBox src attr mbAlt+ | useBox = "#box" <> parens coreImage+ | otherwise = coreImage+ where+ src' = T.pack $ unEscapeString $ T.unpack src -- #9389+ showDim (Pixel a) = literal (showInInch opts (Pixel a) <> "in")+ showDim dim = text (show dim)+ dimAttrs =+ (case dimension Height attr of+ Nothing -> mempty+ Just dim -> ", height: " <> showDim dim) <>+ (case dimension Width attr of+ Nothing -> mempty+ Just dim -> ", width: " <> showDim dim)+ altAttr = case mbAlt of+ Just alt -> ", alt: " <> doubleQuoted alt+ Nothing -> mempty+ isData = "data:" `T.isPrefixOf` src'+ eitherImageData = if isData+ then runPure (fetchItem src)+ else Left $ PandocSomeError "not a data URI"+ toArray = parens . hcat . intersperse "," . map (literal . tshow) . B.unpack+ attrs = dimAttrs <> altAttr+ coreImage = "image" <> parens+ (case eitherImageData of+ Right (contents, Just "image/svg+xml")+ -> "bytes" <> parens (doubleQuoted (UTF8.toText contents)) <> attrs+ Right (bytes, _mime) -> "bytes" <> parens (toArray bytes) <> attrs+ Left _ -> doubleQuoted src' <> attrs)++-- | Extract alt text from image attributes and inlines.+-- Use explicit alt attribute if present; otherwise use inlines.+-- Empty alt="" means decorative image (no alt text).+getAlt :: Attr -> [Inline] -> Maybe Text+getAlt (_, _, kvs) imgInlines =+ case lookup "alt" kvs of+ Just "" -> Nothing -- decorative+ Just alt -> Just alt+ Nothing -> case imgInlines of+ [] -> Nothing+ _ -> Just (stringify imgInlines)++textstyle :: PandocMonad m => Doc Text -> [Inline] -> TW m (Doc Text)+textstyle s inlines = do+ (s <>) . brackets . fixInitialAfterBreakEscape+ <$> inlinesToTypst inlines++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 == "."+ where (ds, rest) = T.span isDigit t++escapeTypst :: Bool -> EscapeContext -> Text -> Doc Text+escapeTypst smart context t =+ (case T.uncons t of+ Just (c, rest)+ | c == ';' -> char '\\' -- see #9252+ | c == '.'+ , not (T.null rest) -> char '\\' -- see #11511+ | needsEscapeAtLineStart c || isOrderedListMarker t+ -> afterBreak "\\"+ _ -> mempty) <>+ literal (snd $ T.foldl' go ('\n', mempty) t)+ where+ go (lastc, t') c+ | needsEscape c = (c, t' <> escapeChar c)+ | c == '-', lastc == '-', smart = (c, t' <> T.pack ['\\',c])+ | c == '/', lastc == '/' = (c, t' <> T.pack ['\\',c])+ | otherwise = (c, T.snoc t' c)+ escapeChar c+ | c == '\160' = "~"+ | c == '\8216', smart = "'" -- left quote+ | c == '\8217', smart = "'" -- apostrophe+ | c == '\8220', smart = "\"" -- left double quote+ | c == '\8221', smart = "\"" -- right double quote+ | c == '\8212', smart = "---" -- em dash+ | c == '\8211', smart = "--" -- en dash+ | needsEscape c = "\\" <> T.singleton c+ | otherwise = T.singleton c+ needsEscape '\160' = True+ needsEscape '\8216' = smart+ needsEscape '\8217' = smart+ needsEscape '\8220' = smart+ needsEscape '\8221' = smart+ needsEscape '\8212' = smart+ needsEscape '\8211' = smart+ needsEscape '\'' = smart+ needsEscape '"' = smart+ needsEscape '[' = True+ needsEscape ']' = True+ needsEscape '#' = True+ needsEscape '<' = True+ needsEscape '>' = True+ needsEscape '@' = True+ needsEscape '$' = True+ needsEscape '\\' = True+ needsEscape '`' = True+ needsEscape '_' = True+ needsEscape '*' = True+ needsEscape '~' = True+ needsEscape ':' = context == TermContext+ needsEscape _ = False++needsEscapeAtLineStart :: Char -> Bool+needsEscapeAtLineStart '/' = True+needsEscapeAtLineStart '+' = True+needsEscapeAtLineStart '-' = True+needsEscapeAtLineStart '=' = True+needsEscapeAtLineStart _ = False++data LabelType =+ FreestandingLabel+ | ArgumentLabel+ deriving (Show, Eq)++toLabel :: LabelType -> Text -> Doc Text+toLabel labelType ident+ | T.null ident = mempty+ | T.all isIdentChar ident'+ = "<" <> literal ident' <> ">"+ | otherwise+ = case labelType of+ FreestandingLabel -> "#label" <> parens (doubleQuoted ident')+ ArgumentLabel -> "label" <> parens (doubleQuoted ident')+ where+ ident' = T.pack $ unEscapeString $ T.unpack ident++isIdentChar :: Char -> Bool+isIdentChar c = isXIDContinue c || c == '_' || c == '-' || c == '.' || c == ':'++toCite :: PandocMonad m => Citation -> TW m (Doc Text)+toCite cite = do+ let ident' = T.pack $ unEscapeString $ T.unpack $ citationId cite+ -- typst inserts comma and we get a doubled one if supplement contains it:+ let eatComma (Str "," : Space : xs) = xs+ eatComma xs = xs+ if citationMode cite == NormalCitation && T.all isIdentChar ident'+ then do+ suppl <- case citationSuffix cite of+ [] -> pure mempty+ suff -> brackets <$> inlinesToTypst (eatComma suff)+ pure $ "@" <> literal ident' <> suppl+ else do+ let label = if T.all isIdentChar ident'+ then "<" <> literal ident' <> ">"+ else "label" <> parens (doubleQuoted ident')+ let form = case citationMode cite of+ NormalCitation -> mempty+ SuppressAuthor -> ", form: \"year\""+ AuthorInText -> ", form: \"prose\""+ suppl <- case citationSuffix cite of+ [] -> pure mempty+ suff -> (", supplement: " <>) . brackets+ <$> inlinesToTypst (eatComma suff)+ pure $ (if citationMode cite == SuppressAuthor -- see #11044+ then parens+ else id)+ $ "#cite" <> parens (label <> form <> suppl)++doubleQuoted :: Text -> Doc Text+doubleQuoted = doubleQuotes . literal . escape+ where+ escape = T.concatMap escapeChar+ escapeChar '\\' = "\\\\"+ escapeChar '"' = "\\\""+ escapeChar c = T.singleton c++extractLabel :: Text -> Maybe Text+extractLabel = go . T.unpack+ where+ go [] = Nothing+ go ('\\':'l':'a':'b':'e':'l':'{':xs) = Just (T.pack (takeWhile (/='}') xs))+ go (_:xs) = go xs
@@ -0,0 +1,615 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Strict #-}++module Text.Pandoc.Writers.Vimdoc (writeVimdoc) where++import Control.Applicative (optional, (<|>))+import Control.Monad (forM)+import Control.Monad.Reader (MonadReader (..), ReaderT (..), asks)+import Control.Monad.State (MonadState (..), StateT, evalStateT, gets, modify)+import Data.Default (Default (..))+import Data.List (intercalate, intersperse, transpose)+import Data.List.NonEmpty (NonEmpty (..), nonEmpty)+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import qualified Data.Text as T+import Text.DocLayout hiding (char, link, text)+import Text.Pandoc.Class.PandocMonad ( report, PandocMonad )+import Text.Pandoc.Definition+import Text.Pandoc.Error (PandocError)+import Text.Pandoc.Logging (LogMessage (..))+import Text.Pandoc.Options (WrapOption (..), WriterOptions (..))+import Text.Pandoc.Parsing.General (many1Till, many1TillChar, readWith)+import Text.Pandoc.Shared (capitalize, onlySimpleTableCells, orderedListMarkers, isTightList, makeSections, removeFormatting, tshow)+import Text.Pandoc.Templates (renderTemplate)+import Text.Pandoc.URI (escapeURI, isURI)+import Text.Pandoc.Writers.Shared (defField, metaToContext, toLegacyTable)+import Text.Parsec (anyChar, char, eof, string, try)+import Text.Read (readMaybe)+import Text.Pandoc.Chunks (toTOCTree, SecInfo (..))+import Data.Tree (Tree(..))+import Data.Functor ((<&>))+import Data.Sequence (Seq, (|>), (<|))+import qualified Data.Sequence as Seq+import Data.Foldable (toList)++data WriterState = WriterState+ { indentLevel :: Int -- How much to indent the block. Inlines shouldn't+ -- be concerned with indent level (I guess?)+ , shiftWidth :: Int -- spaces per indentation level+ , writerOptions :: WriterOptions+ , vimdocPrefix :: Maybe Text+ }++instance Default WriterState where+ def =+ WriterState+ { indentLevel = 0+ , shiftWidth = 4+ , writerOptions = def+ , vimdocPrefix = Nothing+ }++indent :: (Monad m) => Int -> (VW m a) -> (VW m a)+indent n = local (\s -> s{indentLevel = indentLevel s + n})++type VW m = StateT (Seq (Doc Text)) (ReaderT WriterState m)++runRR :: (Monad m) => Seq (Doc Text) -> WriterState -> VW m a -> m a+runRR footnotes opts action = runReaderT (evalStateT action footnotes) opts++docShiftWidth :: Meta -> Maybe Int+docShiftWidth meta = case lookupMeta "shiftwidth" meta of+ Just (MetaInlines [Str sw]) -> readMaybe (T.unpack sw)+ Just (MetaString sw) -> readMaybe (T.unpack sw)+ _ -> Nothing++docVimdocPrefix :: Meta -> Maybe Text+docVimdocPrefix meta = case lookupMeta "vimdoc-prefix" meta of+ Just (MetaInlines [Str pref]) -> Just pref+ Just (MetaString pref) -> Just pref+ _ -> Nothing++{- | Build a vim modeline+>>> makeModeLine def+"vim:tw=72:sw=4:ts=4:ft=help:norl:et:"+-}+makeModeLine :: WriterState -> Text+makeModeLine ws =+ T.pack . intercalate ":" $+ [ "vim"+ , "tw=" <> show tw+ , "sw=" <> show sw+ , "ts=" <> show sw+ , "ft=help"+ , "norl" -- left-to-right text+ , "et:" -- expandtab and finishing ":"+ ]+ where+ tw = writerColumns . writerOptions $ ws+ sw = shiftWidth ws++-- | Build a single formatted TOC line+tocEntryToLine :: (PandocMonad m) => SecInfo -> VW m Text+tocEntryToLine secinfo = do+ rightRef <- mkVimdocRef (secId secinfo)+ let numberStr = case secNumber secinfo of+ Nothing -> ""+ Just x | '.' `T.elem` x -> x <> " "+ Just x -> x <> ". "+ title <- inlineListToVimdoc $ removeFormatting (secTitle secinfo)+ let titlePlain = render Nothing (title <> " ")++ -- length sub 2 because vertical bars are concealed+ let rightRefLen = max 0 (T.length rightRef - 2)+ let numberLen = T.length numberStr+ let leftLen = numberLen + T.length titlePlain+ let padForRight = 1+ textWidth <- asks (writerColumns . writerOptions)+ il <- asks indentLevel++ -- positive when we lack space (i.e. content is too long)+ let lack = (il + leftLen + padForRight + rightRefLen) - textWidth++ -- when lacking, truncate title reserving 3+ chars for ellipsis+ let finalTitle =+ if lack >= 0+ then+ let trunc = T.dropEnd (lack + 3) titlePlain+ stripped = T.stripEnd trunc+ ellipsis =+ T.replicate (3 + T.length trunc - T.length stripped) "."+ in stripped <> ellipsis+ else titlePlain++ -- Negative lack means we have an excess of space, so we fill it with dots+ let dots = T.replicate (negate lack) "."++ pure . T.concat $ [numberStr, finalTitle, dots, " ", rightRef]++vimdocTOC :: (PandocMonad m) => WriterState -> [Block] -> VW m (Doc Text)+vimdocTOC (WriterState{writerOptions = opts}) blocks = do+ let (Node _ subtrees) =+ toTOCTree $ makeSections (writerNumberSections opts) Nothing blocks+ let tocDepth = writerTOCDepth opts+ let isBelowTocDepth (Node sec _) = secLevel sec <= tocDepth++ let makeItem :: (PandocMonad m) => Tree SecInfo -> VW m (Doc Text)+ makeItem (Node secinfo xs) = do+ line <- tocEntryToLine secinfo+ -- When unnumbered, indent constantly by two,+ -- otherwise indent by (length of marker + 1)+ let markerLen = 1 + maybe 1 T.length (secNumber secinfo)+ childItems <-+ indent markerLen $+ traverse makeItem (filter isBelowTocDepth xs)+ pure (literal line $$ nest markerLen (vcat childItems))++ items <- traverse makeItem (filter isBelowTocDepth subtrees)+ pure $ vcat items++writeVimdoc :: (PandocMonad m) => WriterOptions -> Pandoc -> m Text+writeVimdoc opts document@(Pandoc meta _) =+ let+ sw = fromMaybe (shiftWidth def) $ docShiftWidth meta+ vp = docVimdocPrefix meta+ footnotes = Seq.empty+ initialEnv = def{shiftWidth = sw, writerOptions = opts, vimdocPrefix = vp}+ in+ runRR footnotes initialEnv $ pandocToVimdoc document++pandocToVimdoc :: (PandocMonad m) => Pandoc -> VW m Text+pandocToVimdoc (Pandoc meta body) = do+ st <- ask+ let opts = writerOptions st++ metadata <- metaToContext opts blockListToVimdoc inlineListToVimdoc meta+ main <- do+ body' <- blockListToVimdoc body+ footnotes <- get+ rule <- blockToVimdoc HorizontalRule+ let footnotes' = if Seq.null footnotes+ then Empty+ else vsep (toList $ rule <| footnotes)+ pure $ body' <> blankline <> footnotes'++ title <- inlineListToVimdoc $ docTitle meta+ authors <- traverse inlineListToVimdoc $ docAuthors meta+ let authors' = mconcat $ intersperse ("," <> space) (fmap nowrap authors)+ let tw = writerColumns . writerOptions $ st++ let combinedTitle =+ render (Just tw) . cblock tw $+ (title <> space)+ <> (if null authors' then "" else "by" <> space <> authors')++ -- This is placed here because I couldn't find a way to right-align text+ -- inside template to the width specified by a variable+ let toc_reminder =+ render Nothing . rblock tw $+ ("Type |gO| to see the table of contents." :: Doc Text)++ toc <- render (Just tw) <$> vimdocTOC st body++ let modeline = makeModeLine st+ let context =+ defField "body" main+ . defField "toc" (if writerTableOfContents opts then toc else "")+ . defField "modeline" modeline+ . defField "combined-title" combinedTitle+ . defField "toc-reminder" toc_reminder+ $ metadata++ pure $+ case writerTemplate opts of+ Just tpl -> render (Just tw) $ renderTemplate tpl context+ Nothing -> render (Just tw) main++blockListToVimdoc :: (PandocMonad m) => [Block] -> VW m (Doc Text)+blockListToVimdoc blocks = vcat <$> mapM blockToVimdoc blocks++blockToVimdoc :: (PandocMonad m) => Block -> VW m (Doc Text)++blockToVimdoc (Plain inlines) = inlineListToVimdoc inlines++blockToVimdoc (Para inlines) = do+ contents <- inlineListToVimdoc inlines+ pure $ contents <> blankline++blockToVimdoc (LineBlock inliness) = vcat <$> mapM inlineListToVimdoc inliness++blockToVimdoc (CodeBlock (_, cls, _) code) = do+ sw <- asks shiftWidth+ let lang = case cls of+ (lang' : _) -> lang'+ _ -> ""+ -- NOTE: No blankline after the codeblock because closing `<` is concealed+ pure . vcat $+ [ ">" <> literal lang+ , nest sw (literal code)+ , flush "<"+ ]++blockToVimdoc block@(RawBlock format raw) = case format of+ "vimdoc" -> pure $ literal raw+ _ -> "" <$ report (BlockNotRendered block)++blockToVimdoc (BlockQuote blocks) = do+ content <- blockListToVimdoc blocks+ pure $ nest 2 content <> blankline++blockToVimdoc (OrderedList listAttr items) = do+ let itemSpacer = if isTightList items then empty else blankline+ let itemsWithMarkers = zip (orderedListMarkers listAttr) items+ items' <- forM itemsWithMarkers $ \(marker, blocks) -> do+ let markerLen = T.length marker++ item' <- indent (markerLen + 1) $ blockListToVimdoc blocks+ pure $ literal marker <> space <> nest (markerLen + 1) item' <> itemSpacer+ pure $ vcat items' <> blankline++blockToVimdoc (BulletList items) = do+ let itemSpacer = if isTightList items then empty else blankline+ items' <- forM items $ \blocks -> do+ let marker = "-"+ item <- indent 2 $ blockListToVimdoc blocks+ pure $ marker <> " " <> nest 2 item <> itemSpacer+ pure $ vcat items' <> blankline++blockToVimdoc (DefinitionList items) = do+ sw <- asks shiftWidth+ let sepAll = if all (isTightList . snd) items then vcat else vsep+ items' <- forM items $ \(term, definitions) -> do+ let sepCur = if isTightList definitions then vcat else vsep+ labeledTerm <- mkVimdocDefinitionTerm term+ definitions' <- indent sw $ traverse blockListToVimdoc definitions+ pure $ labeledTerm <> cr <> nest sw (sepCur definitions')+ pure $ sepAll items' <> blankline++blockToVimdoc (Header level (ref, _, _) inlines) = do+ tw <- asks (writerColumns . writerOptions)+ let rule = case level of+ 1 -> T.replicate tw "="+ 2 -> T.replicate tw "-"+ _ -> ""+ title <- fmap (render Nothing) . inlineListToVimdoc $ case level of+ 3 -> capitalize inlines+ _ -> inlines++ label <- mkVimdocTag ref+ -- One manual space that ensures that even if spaceLeft is 0, title and ref+ -- don't touch each other+ let label' = " " <> label+ -- (+ 2) due to stars concealment+ let spaceLeft = tw - T.length title + 2++ pure $ vcat+ [ blankline+ , literal rule+ , literal $ title <> T.justifyRight spaceLeft ' ' label'+ , blankline+ ]++blockToVimdoc HorizontalRule = do+ tw <- asks (writerColumns . writerOptions)+ pure $ literal (T.replicate (tw `div` 2) " *") <> blankline++-- Based on blockToMarkdown' from Text.Pandoc.Writers.Markdown+blockToVimdoc t@(Table (_, _, _) blkCapt specs thead tbody tfoot) = do+ let isColRowSpans (Cell _ _ rs cs _) = rs > 1 || cs > 1+ let rowHasColRowSpans (Row _ cs) = any isColRowSpans cs+ let tbodyHasColRowSpans (TableBody _ _ rhs rs) =+ any rowHasColRowSpans rhs || any rowHasColRowSpans rs+ let theadHasColRowSpans (TableHead _ rs) = any rowHasColRowSpans rs+ let tfootHasColRowSpans (TableFoot _ rs) = any rowHasColRowSpans rs+ let hasColRowSpans =+ theadHasColRowSpans thead+ || any tbodyHasColRowSpans tbody+ || tfootHasColRowSpans tfoot+ let (caption, aligns, widths, headers, rows) =+ toLegacyTable blkCapt specs thead tbody tfoot+ let numcols =+ maximum $+ length aligns :| length widths : map length (headers : rows)+ caption' <- inlineListToVimdoc caption+ let caption''+ | null caption = blankline+ | otherwise = blankline $$ caption' $$ blankline+ let hasSimpleCells = onlySimpleTableCells $ headers : rows+ let isSimple = hasSimpleCells && all (== 0) widths && not hasColRowSpans+ let isPlainBlock (Plain _) = True+ isPlainBlock _ = False+ let hasBlocks = not (all (all (all isPlainBlock)) $ headers : rows)+ let padRow r = r ++ replicate x empty+ where+ x = numcols - length r+ let aligns' = aligns ++ replicate x AlignDefault+ where+ x = numcols - length aligns+ let widths' = widths ++ replicate x 0.0+ where+ x = numcols - length widths+ sw <- asks shiftWidth+ rawHeaders <- padRow <$> mapM blockListToVimdoc headers+ rawRows <- mapM (fmap padRow . mapM blockListToVimdoc) rows+ let hasHeader = all null headers+ if+ | isSimple -> do+ -- Simple table+ tbl <-+ indent sw $+ vimdocTable False hasHeader aligns' widths' rawHeaders rawRows+ pure $ nest sw (tbl $$ caption'') $$ blankline+ | not (hasBlocks || hasColRowSpans) -> do+ -- Multiline table+ tbl <-+ indent sw $+ vimdocTable True hasHeader aligns' widths' rawHeaders rawRows+ pure $ nest sw (tbl $$ caption'') $$ blankline+ | otherwise -> ("[TABLE]" $$ caption'') <$ report (BlockNotRendered t)++blockToVimdoc (Figure _ _ blocks) = blockListToVimdoc blocks++blockToVimdoc (Div _ blocks) = blockListToVimdoc blocks++{- | Create a vimdoc tag. Tag is prefixed with "$vimdocPrefix-" if vimdocPrefix+is a Just value.+>>> runReader (mkVimdocTag "abc") def+"*abc*"+>>> runReader (mkVimdocTag "abc") (def{vimdocPrefix = Just "myCoolProject"})+"*myCoolProject-abc*"+-}+mkVimdocTag :: (Monad m) => Text -> VW m Text+mkVimdocTag tag = do+ asks vimdocPrefix <&> \case+ _ | T.null tag -> ""+ Nothing -> "*" <> tag <> "*"+ Just pref' -> "*" <> pref' <> "-" <> tag <> "*"++{- | Create a hotlink for a tag, ie. a followable vimdoc link. Tag is prefixed+ - with "$vimdocPrefix-" if vimdocPrefix is a Just value+>>> runReader (mkVimdocRef "abc") def+"|abc|"+>>> runReader (mkVimdocRef "abc") (def{vimdocPrefix = Just "myCoolProject"})+"|myCoolProject-abc|"+-}+mkVimdocRef :: (Monad m) => Text -> VW m Text+mkVimdocRef ref =+ asks vimdocPrefix <&> \case+ _ | T.null ref -> ""+ Nothing -> "|" <> ref <> "|"+ Just pref' -> "|" <> pref' <> "-" <> ref <> "|"++mkVimdocDefinitionTerm ::+ (PandocMonad m) =>+ [Inline] ->+ VW m (Doc Text)+mkVimdocDefinitionTerm inlines = do+ il <- asks indentLevel+ tw <- asks (writerColumns . writerOptions)+ label <- case inlines of+ -- NOTE: commands in vim are unique, so they get no prefix+ [Code (ref, _, _) code]+ | T.isPrefixOf ":" code ->+ pure . Just $ "*" <> ref <> "*"+ [Code (ref, _, _) _] | not (T.null ref) -> Just <$> mkVimdocTag ref+ [Span (ref, _, _) _] | not (T.null ref) -> Just <$> mkVimdocTag ref+ _ -> pure Nothing++ term <- case inlines of+ [Code _ code] | T.isPrefixOf ":" code -> pure $ literal code+ _ -> inlineListToVimdoc inlines+ let termLen = offset term+ let labelLen = maybe 0 T.length label++ if il + termLen + labelLen > tw+ then+ pure . mconcat $+ [ case label of+ Nothing -> empty+ -- (+2) due to stars concealment+ Just l -> flush (rblock (tw + 2) $ literal l) <> cr+ , term+ ]+ else+ pure . mconcat $+ [ -- Since we calculated that label fits on the same line as+ -- term and since label actually must exceed textwidth to align+ -- properly, we disable wrapping.+ -- vvvvvvvv+ nowrap term+ , case label of+ Nothing -> empty+ -- (+2) due to stars concealment+ Just l -> rblock (tw - termLen - il + 2) (literal l)+ ]++-- | Write a vimdoc table+vimdocTable ::+ (Monad m) =>+ -- | whether this is a multiline table+ Bool ->+ -- | whether the table has a header+ Bool ->+ -- | column alignments+ [Alignment] ->+ -- | column widths+ [Double] ->+ -- | table header cells+ [Doc Text] ->+ -- | table body rows+ [[Doc Text]] ->+ VW m (Doc Text)+vimdocTable multiline headless aligns widths rawHeaders rawRows = do+ let isSimple = all (== 0) widths+ let alignHeader alignment = case alignment of+ AlignLeft -> lblock+ AlignCenter -> cblock+ AlignRight -> rblock+ AlignDefault -> lblock+ -- Number of characters per column necessary to output every cell+ -- without requiring a line break.+ -- The @+2@ is needed for specifying the alignment.+ let numChars = (+ 2) . maybe 0 maximum . nonEmpty . map offset+ -- Number of characters per column necessary to output every cell+ -- without requiring a line break *inside a word*.+ -- The @+2@ is needed for specifying the alignment.+ let minNumChars = (+ 2) . maybe 0 maximum . nonEmpty . map minOffset+ let columns = transpose (rawHeaders : rawRows)++ il <- asks indentLevel++ -- x = (2 * length columns) -- spaces for specifying the alignment+ -- y = (length columns - 1) -- spaces between the columns+ -- x + y = (3 * length columns - 1) -- total needed correction+ tw <- asks (writerColumns . writerOptions)+ let tw' = tw - il - 3 * length columns + 1+ wrap <- asks (writerWrapText . writerOptions)++ -- minimal column width without wrapping a single word+ let relWidth w col =+ max+ (floor $ fromIntegral (tw' - 1) * w)+ ( if wrap == WrapAuto+ then minNumChars col+ else numChars col+ )+ let widthsInChars+ | isSimple = map numChars columns+ | otherwise = zipWith relWidth widths columns+ let makeRow =+ hcat+ . intersperse (lblock 1 (literal " "))+ . zipWith3 alignHeader aligns widthsInChars+ let rows' = map makeRow rawRows+ -- TODO: reduce tw in case head is not empty+ let head' = makeRow rawHeaders <> " ~"+ let head'' =+ if headless+ then empty+ else head'+ let body =+ if multiline+ then+ vsep rows'+ $$ if length rows' < 2+ then blankline+ else empty+ else vcat rows'+ return $+ blankline+ $$ head''+ $$ (if multiline then blankline else empty)+ $$ body++-- | Replace Unicode characters with their ASCII representation+replaceSpecialStrings :: Text -> Text+replaceSpecialStrings =+ let expand c = case c of+ '\x00ad' -> ""+ '\x2013' -> "--"+ '\x2014' -> "---"+ '\x2019' -> "'"+ '\x2026' -> "..."+ _ -> T.singleton c+ in T.concatMap expand++inlineListToVimdoc :: (PandocMonad m) => [Inline] -> VW m (Doc Text)+inlineListToVimdoc inlines = hcat <$> mapM inlineToVimdoc inlines++inlineToVimdoc :: (PandocMonad m) => Inline -> VW m (Doc Text)++inlineToVimdoc (Str str) = pure . literal $ replaceSpecialStrings str++-- Neither `:h help-writing`, nor neovim's grammar.js for vimdoc and+-- highlights.scm say anything about styling text, so we strip all the+-- formatting+inlineToVimdoc (Emph inlines) = inlineListToVimdoc inlines+inlineToVimdoc (Underline inlines) = inlineListToVimdoc inlines+inlineToVimdoc (Strong inlines) = inlineListToVimdoc inlines+inlineToVimdoc (Strikeout inlines) = inlineListToVimdoc inlines+inlineToVimdoc (Superscript inlines) = inlineListToVimdoc inlines+inlineToVimdoc (Subscript inlines) = inlineListToVimdoc inlines+inlineToVimdoc (SmallCaps inlines) = inlineListToVimdoc inlines++inlineToVimdoc (Quoted typ inlines) =+ let quote = case typ of SingleQuote -> "'"; DoubleQuote -> "\""+ in inlineListToVimdoc inlines >>= \text -> pure (quote <> text <> quote)++inlineToVimdoc (Cite _citations inlines) = inlineListToVimdoc inlines++inlineToVimdoc (Code (_, cls, _) code) = do+ let hasNoLang = null cls+ pure . literal $ case T.words code of+ [":help", ref] | hasNoLang -> "|" <> ref <> "|"+ [":h", ref] | hasNoLang -> "|" <> ref <> "|"+ _ -> "`" <> code <> "`"++inlineToVimdoc Space = pure space+inlineToVimdoc SoftBreak =+ asks (writerWrapText . writerOptions) >>= \case+ WrapAuto -> pure space+ WrapNone -> pure " "+ WrapPreserve -> pure "\n"++inlineToVimdoc LineBreak = pure "\n"++inlineToVimdoc (Math _ math) = pure . literal $ "`$" <> math <> "$`"++inlineToVimdoc inline@(RawInline (Format format) text) = case format of+ "vimdoc" -> pure $ literal text+ _ -> "" <$ report (InlineNotRendered inline)++inlineToVimdoc (Link _ txt (src, _)) = do+ let srcSuffix = fromMaybe src (T.stripPrefix "mailto:" src)+ linkText <- render Nothing <$> inlineListToVimdoc txt++ let isAutolink = case txt of+ [Str x] | escapeURI x `elem` [src, srcSuffix] -> True+ _ -> False++ pure $ case refdocLinkToLink src of+ Right link | isAutolink -> "|" <> literal link <> "|"+ Right link ->+ literal (T.stripEnd linkText) <> space <> "|" <> literal link <> "|"+ Left _ | isURI src, isAutolink -> literal srcSuffix+ Left _ -> literal (T.stripEnd linkText) <> space <> literal srcSuffix++inlineToVimdoc (Image {}) = pure ""++inlineToVimdoc (Note blocks) = do+ newN <- gets (succ . Seq.length)+ contents <- blockListToVimdoc blocks+ tag <- mkVimdocTag ("footnote" <> tshow newN)+ tw <- asks (writerColumns . writerOptions)++ -- (+2) due to concealment of stars+ -- vvvvvvvv+ let taggedContents = rblock (tw + 2) (literal tag) $$ contents+ modify (|> taggedContents)++ ref <- mkVimdocRef ("footnote" <> tshow newN)+ pure $ space <> literal ref++inlineToVimdoc (Span _ inlines) = inlineListToVimdoc inlines+++refdocLinkToLink :: Text -> Either PandocError Text+refdocLinkToLink x = (\parser -> readWith parser Nothing x) $ do+ string "http" >> optional (char 's') >> string "://"++ let vimhelpP = do+ try (string "vimhelp.org/") <|> string "neo.vimhelp.org/"++ try (many1Till anyChar (char '#') >> many1TillChar anyChar eof)+ <|> many1TillChar anyChar (try $ string ".html" >> eof)++ let neovimP = do+ string "neovim.io/doc/user/"+ try (many1Till anyChar (char '#') >> many1TillChar anyChar eof)+ <|> do base <- many1TillChar anyChar (try $ string ".html" >> eof)+ pure $ base <> ".txt"++ try vimhelpP <|> neovimP
@@ -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')
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2008-2017 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2008-2024 John MacFarlane <jgm@berkeley.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +19,7 @@ {- | Module : Text.Pandoc.Writers.XWiki- Copyright : Copyright (C) 2008-2017 John MacFarlane+ Copyright : Copyright (C) 2008-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : Derek Chen-Becker <dchenbecker@gmail.com>@@ -42,8 +42,11 @@ import Text.Pandoc.Logging import Text.Pandoc.Options import Text.Pandoc.Shared+import Text.Pandoc.URI import Text.Pandoc.Writers.MediaWiki (highlightingLangs)-import Text.Pandoc.Writers.Shared (toLegacyTable)+import Text.Pandoc.Templates (renderTemplate)+import Text.Pandoc.Writers.Shared (defField, metaToContext, toLegacyTable)+import Text.DocLayout (render, literal) newtype WriterState = WriterState { listLevel :: Text -- String at the beginning of items@@ -53,9 +56,19 @@ -- | Convert Pandoc to XWiki. writeXWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text-writeXWiki _ (Pandoc _ blocks) =+writeXWiki opts (Pandoc meta blocks) = do let env = WriterState { listLevel = "" }- in runReaderT (blockListToXWiki blocks) env+ metadata <- metaToContext opts+ (fmap (literal . trimr) . (\bs -> runReaderT (blockListToXWiki bs) env))+ (fmap (literal . trimr) . (\is -> runReaderT (inlineListToXWiki is) env))+ meta+ body <- runReaderT (blockListToXWiki blocks) env+ let context = defField "body" body+ $ defField "toc" (writerTableOfContents opts) metadata+ return $+ case writerTemplate opts of+ Just tpl -> render Nothing $ renderTemplate tpl context+ Nothing -> body -- | Concatenates strings with line breaks between them. vcat :: [Text] -> Text@@ -74,8 +87,6 @@ blockToXWiki :: PandocMonad m => Block -> XWikiReader m Text -blockToXWiki Null = return ""- blockToXWiki (Div (id', _, _) blocks) = do content <- blockListToXWiki blocks return $ genAnchor id' <> content@@ -121,6 +132,12 @@ lev <- asks listLevel contents <- local (\s -> s { listLevel = listLevel s <> ";" }) $ mapM definitionListItemToMediaWiki items return $ vcat contents <> if Text.null lev then "\n" else ""++-- Create a group according to+-- https://www.xwiki.org/xwiki/bin/view/Documentation/UserGuide/Features/XWikiSyntax/?syntax=2.1§ion=Groups+blockToXWiki (Figure attr _ body) = do+ content <- blockToXWiki $ Div attr body+ return $ intercalate content ["(((\n", "\n)))"] -- TODO: support more features blockToXWiki (Table _ blkCapt specs thead tbody tfoot) = do
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.Writers.ZimWiki- Copyright : © 2008-2022 John MacFarlane,+ Copyright : © 2008-2024 John MacFarlane, 2017-2019 Alex Ivkin License : GNU GPL, version 2 or above @@ -32,7 +32,8 @@ import Text.Pandoc.Options (WrapOption (..), WriterOptions (writerTableOfContents, writerTemplate, writerWrapText))-import Text.Pandoc.Shared (escapeURI, isURI, linesToPara, removeFormatting, trimr)+import Text.Pandoc.Shared (figureDiv, linesToPara, removeFormatting, trimr)+import Text.Pandoc.URI (escapeURI, isURI) import Text.Pandoc.Templates (renderTemplate) import Text.Pandoc.Writers.Shared (defField, metaToContext, toLegacyTable) @@ -77,24 +78,12 @@ -- | Convert Pandoc block element to ZimWiki. blockToZimWiki :: PandocMonad m => WriterOptions -> Block -> ZW m Text -blockToZimWiki _ Null = return ""- blockToZimWiki opts (Div _attrs bs) = do contents <- blockListToZimWiki opts bs return $ contents <> "\n" blockToZimWiki opts (Plain inlines) = inlineListToZimWiki opts inlines --- ZimWiki doesn't support captions - so combine together alt and caption into alt-blockToZimWiki opts (SimpleFigure attr txt (src, tit)) = do- capt <- if null txt- then return ""- else (" " <>) `fmap` inlineListToZimWiki opts txt- let opt = if null txt- then ""- else "|" <> if T.null tit then capt else tit <> capt- return $ "{{" <> src <> imageDims opts attr <> opt <> "}}\n"- blockToZimWiki opts (Para inlines) = do indent <- gets stIndent -- useTags <- gets stUseTags@@ -139,7 +128,9 @@ c <- inlineListToZimWiki opts capt return $ "" <> c <> "\n" headers' <- if all null headers- then zipWithM (tableItemToZimWiki opts) aligns (head rows)+ then case rows of+ [] -> pure mempty+ (r:_) -> zipWithM (tableItemToZimWiki opts) aligns r else mapM (inlineListToZimWiki opts . removeFormatting)headers -- emphasis, links etc. are not allowed in table headers rows' <- mapM (zipWithM (tableItemToZimWiki opts) aligns) rows let widths = map (maybe 0 maximum . nonEmpty . map T.length) $@@ -178,6 +169,9 @@ blockToZimWiki opts (DefinitionList items) = do contents <- mapM (definitionListItemToZimWiki opts) items return $ vcat contents++blockToZimWiki opts (Figure attr capt body) = do+ blockToZimWiki opts (figureDiv attr capt body) definitionListItemToZimWiki :: PandocMonad m => WriterOptions
@@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Text.Pandoc.XML- Copyright : Copyright (C) 2006-2022 John MacFarlane+ Copyright : Copyright (C) 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -21,6 +21,7 @@ toEntities, toHtml5Entities, fromEntities,+ lookupEntity, html4Attributes, html5Attributes, rdfaAttributes ) where@@ -28,11 +29,13 @@ import Data.Char (isAscii, isSpace, ord, isLetter, isDigit) import Data.Text (Text) import qualified Data.Text as T-import Text.HTML.TagSoup.Entity (lookupEntity, htmlEntities)+import Commonmark.Entity (lookupEntity)+import Text.HTML.TagSoup.Entity (htmlEntities) import Text.DocLayout+ ( ($$), char, hcat, nest, text, Doc, HasChars ) import Text.Printf (printf) import qualified Data.Map as M-import Data.String+import Data.String ( IsString ) import qualified Data.Set as Set -- | Escape one character as needed for XML.@@ -117,8 +120,8 @@ (\new old -> if T.length new > T.length old then old else new) c ent' entmap- where ent' = T.takeWhile (/=';') (T.pack ent)- _ -> entmap+ where ent' = T.takeWhile (/=';') (T.pack ent)+ _ -> entmap -- | Converts a string into an NCName, i.e., an XML name without colons. -- Disallowed characters are escaped using @ux%x@, where @%x@ is the@@ -158,7 +161,7 @@ Just (';',ys) -> ys _ -> rest ent' = T.drop 1 ent <> ";"- in case T.pack <$> lookupEntity (T.unpack ent') of+ in case lookupEntity ent' of Just c -> c <> fromEntities rest' Nothing -> ent <> fromEntities rest @@ -205,6 +208,7 @@ , "draggable" , "enctype" , "enterkeyhint"+ , "fetchpriority" , "for" , "form" , "formaction"
@@ -1,114 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.XML.Light- Copyright : Copyright (C) 2021-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--xml-light, which we used in pandoc's the XML-based readers, has-some limitations: in particular, it produces nodes with String-instead of Text, and the parser falls over on processing instructions-(see #7091).--This module exports much of the API of xml-light, but using Text instead-of String. In addition, the xml-light parsers are replaced by xml-conduit's-well-tested parser. (The xml-conduit types are mapped to types-isomorphic to xml-light's, to avoid the need for massive code modifications-elsewhere.) Bridge functions to map xml-light types to this module's-types are also provided (since libraries like texmath still use xml-light).--Another advantage of the xml-conduit parser is that it gives us-detailed information on xml parse errors.--In the future we may want to move to using xml-conduit or another-xml library in the code base, but this change gives us-better performance and accuracy without much change in the-code that used xml-light.--}-module Text.Pandoc.XML.Light- ( module Text.Pandoc.XML.Light.Types- , module Text.Pandoc.XML.Light.Proc- , module Text.Pandoc.XML.Light.Output- -- * Replacement for xml-light's Text.XML.Input- , parseXMLElement- , parseXMLContents- -- * Versions that allow passing in a custom entity table- , parseXMLElementWithEntities- , parseXMLContentsWithEntities- ) where--import qualified Control.Exception as E-import qualified Text.XML as Conduit-import Text.XML.Unresolved (InvalidEventStream(..))-import qualified Data.Text as T-import qualified Data.Text.Lazy as TL-import qualified Data.Map as M-import Data.Maybe (mapMaybe)-import Text.Pandoc.XML.Light.Types-import Text.Pandoc.XML.Light.Proc-import Text.Pandoc.XML.Light.Output-import qualified Data.XML.Types as XML---- Drop in replacement for parseXMLDoc in xml-light.-parseXMLElement :: TL.Text -> Either T.Text Element-parseXMLElement = parseXMLElementWithEntities mempty---- Drop in replacement for parseXMLDoc in xml-light.-parseXMLElementWithEntities :: M.Map T.Text T.Text- -> TL.Text -> Either T.Text Element-parseXMLElementWithEntities entityMap t =- elementToElement . Conduit.documentRoot <$>- either (Left . T.pack . E.displayException) Right- (Conduit.parseText Conduit.def{ Conduit.psRetainNamespaces = True- , Conduit.psDecodeEntities = decodeEnts } t)- where- decodeEnts ref = case M.lookup ref entityMap of- Nothing -> XML.ContentEntity ref- Just t' -> XML.ContentText t'--parseXMLContents :: TL.Text -> Either T.Text [Content]-parseXMLContents = parseXMLContentsWithEntities mempty--parseXMLContentsWithEntities :: M.Map T.Text T.Text- -> TL.Text -> Either T.Text [Content]-parseXMLContentsWithEntities entityMap t =- case Conduit.parseText Conduit.def{ Conduit.psRetainNamespaces = True- , Conduit.psDecodeEntities = decodeEnts- } t of- Left e ->- case E.fromException e of- Just (ContentAfterRoot _) ->- elContent <$> parseXMLElementWithEntities entityMap- ("<wrapper>" <> t <> "</wrapper>")- _ -> Left . T.pack . E.displayException $ e- Right x -> Right [Elem . elementToElement . Conduit.documentRoot $ x]- where- decodeEnts ref = case M.lookup ref entityMap of- Nothing -> XML.ContentEntity ref- Just t' -> XML.ContentText t'--elementToElement :: Conduit.Element -> Element-elementToElement (Conduit.Element name attribMap nodes) =- Element (nameToQname name) attrs (mapMaybe nodeToContent nodes) Nothing- where- attrs = map (\(n,v) -> Attr (nameToQname n) v) $- M.toList attribMap- nameToQname (Conduit.Name localName mbns mbpref) =- case mbpref of- Nothing ->- case T.stripPrefix "xmlns:" localName of- Just rest -> QName rest mbns (Just "xmlns")- Nothing -> QName localName mbns mbpref- _ -> QName localName mbns mbpref--nodeToContent :: Conduit.Node -> Maybe Content-nodeToContent (Conduit.NodeElement el) =- Just (Elem (elementToElement el))-nodeToContent (Conduit.NodeContent t) =- Just (Text (CData CDataText t Nothing))-nodeToContent _ = Nothing-
@@ -1,234 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Text.Pandoc.XML.Light.Output- Copyright : Copyright (C) 2007 Galois, Inc., 2021-2022 John MacFarlane- License : GNU GPL, version 2 or above--- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable-- This code is based on code from xml-light, released under the BSD3 license.- We use a text Builder instead of ShowS.--}-module Text.Pandoc.XML.Light.Output- ( -- * Replacement for xml-light's Text.XML.Output- ppTopElement- , ppElement- , ppContent- , ppcElement- , ppcContent- , showTopElement- , showElement- , showContent- , useShortEmptyTags- , defaultConfigPP- , ConfigPP(..)- ) where--import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Text.Lazy as TL-import Data.Text.Lazy.Builder (Builder, singleton, fromText, toLazyText)-import Text.Pandoc.XML.Light.Types------- duplicates functinos from Text.XML.Output------- | The XML 1.0 header-xmlHeader :: Text-xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"------------------------------------------------------------------------------------data ConfigPP = ConfigPP- { shortEmptyTag :: QName -> Bool- , prettify :: Bool- }---- | Default pretty orinting configuration.--- * Always use abbreviate empty tags.-defaultConfigPP :: ConfigPP-defaultConfigPP = ConfigPP { shortEmptyTag = const True- , prettify = False- }---- | The predicate specifies for which empty tags we should use XML's--- abbreviated notation <TAG />. This is useful if we are working with--- some XML-ish standards (such as certain versions of HTML) where some--- empty tags should always be displayed in the <TAG></TAG> form.-useShortEmptyTags :: (QName -> Bool) -> ConfigPP -> ConfigPP-useShortEmptyTags p c = c { shortEmptyTag = p }----- | Specify if we should use extra white-space to make document more readable.--- WARNING: This adds additional white-space to text elements,--- and so it may change the meaning of the document.-useExtraWhiteSpace :: Bool -> ConfigPP -> ConfigPP-useExtraWhiteSpace p c = c { prettify = p }---- | A configuration that tries to make things pretty--- (possibly at the cost of changing the semantics a bit--- through adding white space.)-prettyConfigPP :: ConfigPP-prettyConfigPP = useExtraWhiteSpace True defaultConfigPP---------------------------------------------------------------------------------------- | Pretty printing renders XML documents faithfully,--- with the exception that whitespace may be added\/removed--- in non-verbatim character data.-ppTopElement :: Element -> Text-ppTopElement = ppcTopElement prettyConfigPP---- | Pretty printing elements-ppElement :: Element -> Text-ppElement = ppcElement prettyConfigPP---- | Pretty printing content-ppContent :: Content -> Text-ppContent = ppcContent prettyConfigPP---- | Pretty printing renders XML documents faithfully,--- with the exception that whitespace may be added\/removed--- in non-verbatim character data.-ppcTopElement :: ConfigPP -> Element -> Text-ppcTopElement c e = T.unlines [xmlHeader,ppcElement c e]---- | Pretty printing elements-ppcElement :: ConfigPP -> Element -> Text-ppcElement c = TL.toStrict . toLazyText . ppElementS c mempty---- | Pretty printing content-ppcContent :: ConfigPP -> Content -> Text-ppcContent c = TL.toStrict . toLazyText . ppContentS c mempty--ppcCData :: ConfigPP -> CData -> Text-ppcCData c = TL.toStrict . toLazyText . ppCDataS c mempty--type Indent = Builder---- | Pretty printing content using ShowT-ppContentS :: ConfigPP -> Indent -> Content -> Builder-ppContentS c i x = case x of- Elem e -> ppElementS c i e- Text t -> ppCDataS c i t- CRef r -> showCRefS r--ppElementS :: ConfigPP -> Indent -> Element -> Builder-ppElementS c i e = i <> tagStart (elName e) (elAttribs e) <>- (case elContent e of- [] | "?" `T.isPrefixOf` qName name -> fromText " ?>"- | shortEmptyTag c name -> fromText " />"- [Text t] -> singleton '>' <> ppCDataS c mempty t <> tagEnd name- cs -> singleton '>' <> nl <>- mconcat (map ((<> nl) . ppContentS c (sp <> i)) cs) <>- i <> tagEnd name- where (nl,sp) = if prettify c then ("\n"," ") else ("","")- )- where name = elName e--ppCDataS :: ConfigPP -> Indent -> CData -> Builder-ppCDataS c i t = i <> if cdVerbatim t /= CDataText || not (prettify c)- then showCDataS t- else foldr cons mempty (T.unpack (showCData t))- where cons :: Char -> Builder -> Builder- cons '\n' ys = singleton '\n' <> i <> ys- cons y ys = singleton y <> ys---------------------------------------------------------------------------------------- | Adds the <?xml?> header.-showTopElement :: Element -> Text-showTopElement c = xmlHeader <> showElement c--showContent :: Content -> Text-showContent = ppcContent defaultConfigPP--showElement :: Element -> Text-showElement = ppcElement defaultConfigPP--showCData :: CData -> Text-showCData = ppcCData defaultConfigPP---- Note: crefs should not contain '&', ';', etc.-showCRefS :: Text -> Builder-showCRefS r = singleton '&' <> fromText r <> singleton ';'---- | Convert a text element to characters.-showCDataS :: CData -> Builder-showCDataS cd =- case cdVerbatim cd of- CDataText -> escStr (cdData cd)- CDataVerbatim -> fromText "<![CDATA[" <> escCData (cdData cd) <>- fromText "]]>"- CDataRaw -> fromText (cdData cd)-----------------------------------------------------------------------------------escCData :: Text -> Builder-escCData t- | "]]>" `T.isPrefixOf` t =- fromText "]]]]><![CDATA[>" <> fromText (T.drop 3 t)-escCData t- = case T.uncons t of- Nothing -> mempty- Just (c,t') -> singleton c <> escCData t'--escChar :: Char -> Builder-escChar c = case c of- '<' -> fromText "<"- '>' -> fromText ">"- '&' -> fromText "&"- '"' -> fromText """- -- we use ' instead of ' because IE apparently has difficulties- -- rendering ' in xhtml.- -- Reported by Rohan Drape <rohan.drape@gmail.com>.- '\'' -> fromText "'"- _ -> singleton c-- {- original xml-light version:- -- NOTE: We escape '\r' explicitly because otherwise they get lost- -- when parsed back in because of then end-of-line normalization rules.- _ | isPrint c || c == '\n' -> singleton c- | otherwise -> showText "&#" . showsT oc . singleton ';'- where oc = ord c- -}--escStr :: Text -> Builder-escStr cs = if T.any needsEscape cs- then mconcat (map escChar (T.unpack cs))- else fromText cs- where- needsEscape '<' = True- needsEscape '>' = True- needsEscape '&' = True- needsEscape '"' = True- needsEscape '\'' = True- needsEscape _ = False--tagEnd :: QName -> Builder-tagEnd qn = fromText "</" <> showQName qn <> singleton '>'--tagStart :: QName -> [Attr] -> Builder-tagStart qn as = singleton '<' <> showQName qn <> as_str- where as_str = if null as- then mempty- else mconcat (map showAttr as)--showAttr :: Attr -> Builder-showAttr (Attr qn v) = singleton ' ' <> showQName qn <>- singleton '=' <>- singleton '"' <> escStr v <> singleton '"'--showQName :: QName -> Builder-showQName q =- case qPrefix q of- Nothing -> fromText (qName q)- Just p -> fromText p <> singleton ':' <> fromText (qName q)
@@ -1,139 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{- |- Module : Text.Pandoc.XML.Light.Proc- Copyright : Copyright (C) 2007 Galois, Inc., 2021-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable-- This code is taken from xml-light, released under the BSD3 license.--}-module Text.Pandoc.XML.Light.Proc- ( - -- * Replacement for xml-light's Text.XML.Proc- strContent- , onlyElems- , elChildren- , onlyText- , findChildren- , filterChildren- , filterChildrenName- , findChild- , filterChild- , filterChildName- , findElement- , filterElement- , filterElementName- , findElements- , filterElements- , filterElementsName- , findAttr- , lookupAttr- , lookupAttrBy- , findAttrBy- ) where--import Data.Text (Text)-import Data.Maybe (listToMaybe)-import Data.List(find)-import Text.Pandoc.XML.Light.Types------- copied from xml-light Text.XML.Proc------- | Get the text value of an XML element. This function--- ignores non-text elements, and concatenates all text elements.-strContent :: Element -> Text-strContent = mconcat . map cdData . onlyText . elContent---- | Select only the elements from a list of XML content.-onlyElems :: [Content] -> [Element]-onlyElems xs = [ x | Elem x <- xs ]---- | Select only the elements from a parent.-elChildren :: Element -> [Element]-elChildren e = [ x | Elem x <- elContent e ]---- | Select only the text from a list of XML content.-onlyText :: [Content] -> [CData]-onlyText xs = [ x | Text x <- xs ]---- | Find all immediate children with the given name.-findChildren :: QName -> Element -> [Element]-findChildren q e = filterChildren ((q ==) . elName) e---- | Filter all immediate children wrt a given predicate.-filterChildren :: (Element -> Bool) -> Element -> [Element]-filterChildren p e = filter p (onlyElems (elContent e))----- | Filter all immediate children wrt a given predicate over their names.-filterChildrenName :: (QName -> Bool) -> Element -> [Element]-filterChildrenName p e = filter (p.elName) (onlyElems (elContent e))----- | Find an immediate child with the given name.-findChild :: QName -> Element -> Maybe Element-findChild q e = listToMaybe (findChildren q e)---- | Find an immediate child with the given name.-filterChild :: (Element -> Bool) -> Element -> Maybe Element-filterChild p e = listToMaybe (filterChildren p e)---- | Find an immediate child with name matching a predicate.-filterChildName :: (QName -> Bool) -> Element -> Maybe Element-filterChildName p e = listToMaybe (filterChildrenName p e)---- | Find the left-most occurrence of an element matching given name.-findElement :: QName -> Element -> Maybe Element-findElement q e = listToMaybe (findElements q e)---- | Filter the left-most occurrence of an element wrt. given predicate.-filterElement :: (Element -> Bool) -> Element -> Maybe Element-filterElement p e = listToMaybe (filterElements p e)---- | Filter the left-most occurrence of an element wrt. given predicate.-filterElementName :: (QName -> Bool) -> Element -> Maybe Element-filterElementName p e = listToMaybe (filterElementsName p e)---- | Find all non-nested occurrences of an element.--- (i.e., once we have found an element, we do not search--- for more occurrences among the element's children).-findElements :: QName -> Element -> [Element]-findElements qn e = filterElementsName (qn==) e---- | Find all non-nested occurrences of an element wrt. given predicate.--- (i.e., once we have found an element, we do not search--- for more occurrences among the element's children).-filterElements :: (Element -> Bool) -> Element -> [Element]-filterElements p e- | p e = [e]- | otherwise = concatMap (filterElements p) $ onlyElems $ elContent e---- | Find all non-nested occurrences of an element wrt a predicate over element names.--- (i.e., once we have found an element, we do not search--- for more occurrences among the element's children).-filterElementsName :: (QName -> Bool) -> Element -> [Element]-filterElementsName p e = filterElements (p.elName) e---- | Lookup the value of an attribute.-findAttr :: QName -> Element -> Maybe Text-findAttr x e = lookupAttr x (elAttribs e)---- | Lookup attribute name from list.-lookupAttr :: QName -> [Attr] -> Maybe Text-lookupAttr x = lookupAttrBy (x ==)---- | Lookup the first attribute whose name satisfies the given predicate.-lookupAttrBy :: (QName -> Bool) -> [Attr] -> Maybe Text-lookupAttrBy p as = attrVal `fmap` find (p . attrKey) as---- | Lookup the value of the first attribute whose name--- satisfies the given predicate.-findAttrBy :: (QName -> Bool) -> Element -> Maybe Text-findAttrBy p e = lookupAttrBy p (elAttribs e)--
@@ -1,193 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE DeriveDataTypeable #-}-{- |- Module : Text.Pandoc.XML.Light.Types- Copyright : Copyright (C) 2007 Galois, Inc., 2021-2022 John MacFarlane- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable-- This code is taken from xml-light, released under the BSD3 license.- It has been modified to use Text instead of String, and the fromXL*- functions have been added.--}-module Text.Pandoc.XML.Light.Types- ( -- * Basic types, duplicating those from xml-light but with Text- -- instead of String- Line- , Content(..)- , Element(..)- , Attr(..)- , CData(..)- , CDataKind(..)- , QName(..)- , Node(..)- , unode- , unqual- , add_attr- , add_attrs- -- * Conversion functions from xml-light types- , fromXLQName- , fromXLCData- , fromXLElement- , fromXLAttr- , fromXLContent- ) where--import Data.Text (Text)-import qualified Data.Text as T-import Data.Data (Data)-import Data.Typeable (Typeable)-import qualified Text.XML.Light as XL------- type definitions lightly modified from xml-light------- | A line is an Integer-type Line = Integer---- | XML content-data Content = Elem Element- | Text CData- | CRef Text- deriving (Show, Typeable, Data, Ord, Eq)---- | XML elements-data Element = Element {- elName :: QName,- elAttribs :: [Attr],- elContent :: [Content],- elLine :: Maybe Line- } deriving (Show, Typeable, Data, Ord, Eq)---- | XML attributes-data Attr = Attr {- attrKey :: QName,- attrVal :: Text- } deriving (Eq, Ord, Show, Typeable, Data)---- | XML CData-data CData = CData {- cdVerbatim :: CDataKind,- cdData :: Text,- cdLine :: Maybe Line- } deriving (Show, Typeable, Data, Ord, Eq)--data CDataKind- = CDataText -- ^ Ordinary character data; pretty printer escapes &, < etc.- | CDataVerbatim -- ^ Unescaped character data; pretty printer embeds it in <![CDATA[..- | CDataRaw -- ^ As-is character data; pretty printer passes it along without any escaping or CDATA wrap-up.- deriving ( Eq, Ord, Show, Typeable, Data )---- | XML qualified names-data QName = QName {- qName :: Text,- qURI :: Maybe Text,- qPrefix :: Maybe Text- } deriving (Show, Typeable, Data)---instance Eq QName where- q1 == q2 = compare q1 q2 == EQ--instance Ord QName where- compare q1 q2 =- case compare (qName q1) (qName q2) of- EQ -> case (qURI q1, qURI q2) of- (Nothing,Nothing) -> compare (qPrefix q1) (qPrefix q2)- (u1,u2) -> compare u1 u2- x -> x--class Node t where- node :: QName -> t -> Element--instance Node ([Attr],[Content]) where- node n (attrs,cont) = Element { elName = n- , elAttribs = attrs- , elContent = cont- , elLine = Nothing- }--instance Node [Attr] where node n as = node n (as,[]::[Content])-instance Node Attr where node n a = node n [a]-instance Node () where node n () = node n ([]::[Attr])--instance Node [Content] where node n cs = node n ([]::[Attr],cs)-instance Node Content where node n c = node n [c]-instance Node ([Attr],Content) where node n (as,c) = node n (as,[c])-instance Node (Attr,Content) where node n (a,c) = node n ([a],[c])--instance Node ([Attr],[Element]) where- node n (as,cs) = node n (as,map Elem cs)--instance Node ([Attr],Element) where node n (as,c) = node n (as,[c])-instance Node (Attr,Element) where node n (a,c) = node n ([a],c)-instance Node [Element] where node n es = node n ([]::[Attr],es)-instance Node Element where node n e = node n [e]--instance Node ([Attr],[CData]) where- node n (as,cs) = node n (as,map Text cs)--instance Node ([Attr],CData) where node n (as,c) = node n (as,[c])-instance Node (Attr,CData) where node n (a,c) = node n ([a],c)-instance Node [CData] where node n es = node n ([]::[Attr],es)-instance Node CData where node n e = node n [e]--instance Node ([Attr],Text) where- node n (as,t) = node n (as, CData { cdVerbatim = CDataText- , cdData = t- , cdLine = Nothing })--instance Node (Attr,Text ) where node n (a,t) = node n ([a],t)-instance Node Text where node n t = node n ([]::[Attr],t)---- | Create node with unqualified name-unode :: Node t => Text -> t -> Element-unode = node . unqual--unqual :: Text -> QName-unqual x = QName x Nothing Nothing---- | Add an attribute to an element.-add_attr :: Attr -> Element -> Element-add_attr a e = add_attrs [a] e---- | Add some attributes to an element.-add_attrs :: [Attr] -> Element -> Element-add_attrs as e = e { elAttribs = as ++ elAttribs e }------- conversion from xml-light-----fromXLQName :: XL.QName -> QName-fromXLQName qn = QName { qName = T.pack $ XL.qName qn- , qURI = T.pack <$> XL.qURI qn- , qPrefix = T.pack <$> XL.qPrefix qn }--fromXLCData :: XL.CData -> CData-fromXLCData cd = CData { cdVerbatim = case XL.cdVerbatim cd of- XL.CDataText -> CDataText- XL.CDataVerbatim -> CDataVerbatim- XL.CDataRaw -> CDataRaw- , cdData = T.pack $ XL.cdData cd- , cdLine = XL.cdLine cd }--fromXLElement :: XL.Element -> Element-fromXLElement el = Element { elName = fromXLQName $ XL.elName el- , elAttribs = map fromXLAttr $ XL.elAttribs el- , elContent = map fromXLContent $ XL.elContent el- , elLine = XL.elLine el }--fromXLAttr :: XL.Attr -> Attr-fromXLAttr (XL.Attr qn s) = Attr (fromXLQName qn) (T.pack s)--fromXLContent :: XL.Content -> Content-fromXLContent (XL.Elem el) = Elem $ fromXLElement el-fromXLContent (XL.Text cd) = Text $ fromXLCData cd-fromXLContent (XL.CRef s) = CRef (T.pack s)--
@@ -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"
@@ -1,51 +0,0 @@-flags:- pandoc:- embed_data_files: true- QuickCheck:- old-random: false-packages:-- '.'-extra-deps:-- skylighting-core-0.13-- skylighting-0.13-- skylighting-format-ansi-0.1-- skylighting-format-latex-0.1-- skylighting-format-blaze-html-0.1-- emojis-0.1.2-- gridtables-0.0.3.0-- lpeg-1.0.3-- hslua-2.2.1-- hslua-aeson-2.2.1-- hslua-classes-2.2.0-- hslua-core-2.2.1-- hslua-marshalling-2.2.1-- hslua-module-doclayout-1.0.4-- hslua-module-path-1.0.3-- hslua-module-system-1.0.2-- hslua-module-text-1.0.2-- hslua-module-version-1.0.2-- hslua-objectorientation-2.2.1-- hslua-packaging-2.2.1-- lua-2.2.1-- lua-arbitrary-1.0.1-- tasty-hslua-1.0.2-- tasty-lua-1.0.2-- pandoc-lua-marshal-0.1.7-- aeson-pretty-0.8.9-- unicode-transforms-0.4.0.1-- unicode-data-0.3.0-- commonmark-pandoc-0.2.1.2-- ipynb-0.2-- pandoc-types-1.22.2.1-- commonmark-0.2.2-- commonmark-extensions-0.2.3.2-- doclayout-0.4-- doctemplates-0.10.0.2-- citeproc-0.8.0.1-- texmath-0.12.5.2--ghc-options:- "$locals": -fhide-source-paths -Wno-missing-home-modules-resolver: lts-18.10-nix:- packages: [zlib]
@@ -1,7 +1,7 @@ {-# LANGUAGE BangPatterns #-} {- | Module : Tests.Command- Copyright : © 2006-2022 John MacFarlane+ Copyright : © 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu>@@ -31,7 +31,7 @@ contain "=> " followed by the exit status. -}-module Tests.Command (runTest, tests)+module Tests.Command (tests) where import Data.Maybe (fromMaybe)@@ -76,21 +76,6 @@ "| " ++ "test-pandoc --emulate" ++ pandocToEmulate False cs pandocToEmulate _ (c:cs) = c : pandocToEmulate False cs pandocToEmulate _ [] = []---- | Run a test, return True if test passed.-runTest :: String -- ^ Path to test executable- -> String -- ^ Title of test- -> String -- ^ Shell command- -> String -- ^ Input text- -> String -- ^ Expected output- -> TestTree-runTest testExePath testname cmd inp norm = testCase testname $ do- (_ec, out) <- execTest testExePath cmd inp- result <- if out == norm- then return TestPassed- else return $ TestFailed cmd "expected"- $ getDiff (lines out) (lines norm)- assertBool (show result) (result == TestPassed) tests :: TestTree {-# NOINLINE tests #-}
@@ -3,7 +3,7 @@ {-# LANGUAGE FlexibleInstances #-} {- | Module : Tests.Helpers- Copyright : © 2006-2022 John MacFarlane+ Copyright : © 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu>@@ -16,6 +16,7 @@ , TestResult(..) , setupEnvironment , showDiff+ , nativeDiff , testGolden , (=?>) , purely@@ -89,12 +90,14 @@ mldpath <- Env.lookupEnv "LD_LIBRARY_PATH" mdyldpath <- Env.lookupEnv "DYLD_LIBRARY_PATH" mpdd <- Env.lookupEnv "pandoc_datadir"+ mbpath <- Env.lookupEnv "PATH" -- Note that Cabal sets the pandoc_datadir environment variable -- to point to the source directory, since otherwise getDataFilename -- will look in the data directory into which pandoc will be installed -- (but has not yet been). So when we spawn a new process with -- pandoc, we need to make sure this environment variable is set.- return $ ("PATH",takeDirectory testExePath) :+ return $ ("PATH",takeDirectory testExePath <>+ maybe mempty (searchPathSeparator:) mbpath) : ("TMP",".") : ("LANG","en_US.UTF-8") : ("HOME", "./") :@@ -130,6 +133,19 @@ vividize (First s) = "- " ++ s vividize (Second s) = "+ " ++ s +nativeDiff :: FilePath -> Pandoc -> Pandoc -> IO (Maybe String)+nativeDiff normPath expectedNative actualNative+ | expectedNative == actualNative = return Nothing+ | otherwise = Just <$> do+ expected <- T.unpack <$> runIOorExplode (writeNative def expectedNative)+ actual <- T.unpack <$> runIOorExplode (writeNative def actualNative)+ let dash = replicate 72 '-'+ let diff = getDiff (lines actual) (lines expected)+ return $ '\n' : dash +++ "\n--- " ++ normPath +++ "\n+++ " ++ "test" ++ "\n" +++ showDiff (1,1) diff ++ dash+ purely :: (b -> PandocPure a) -> b -> a purely f = either (error . show) id . runPure . f @@ -155,7 +171,7 @@ toString = toString . B.fromList instance ToString Block where- toString = toString . B.singleton + toString = toString . B.singleton instance ToString Inlines where toString = unpack . trimr . purely (writeNative def) . toPandoc
@@ -1,247 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{- |- Module : Tests.Lua- Copyright : © 2017-2022 Albert Krewinkel- License : GNU GPL, version 2 or above-- Maintainer : Albert Krewinkel <albert@zeitkraut.de>- Stability : alpha- Portability : portable--Unit and integration tests for pandoc's Lua subsystem.--}-module Tests.Lua ( runLuaTest, tests ) where--import HsLua as Lua hiding (Operation (Div), error)-import System.FilePath ((</>))-import Test.Tasty (TestTree, testGroup)-import Test.Tasty.HUnit ((@=?), Assertion, HasCallStack, assertEqual, testCase)-import Text.Pandoc.Arbitrary ()-import Text.Pandoc.Builder (bulletList, definitionList, displayMath, divWith,- doc, doubleQuoted, emph, header, lineBlock,- linebreak, math, orderedList, para, plain, rawBlock,- singleQuoted, space, str, strong,- HasMeta (setMeta))-import Text.Pandoc.Class (runIOorExplode, setUserDataDir)-import Text.Pandoc.Definition (Attr, Block (BlockQuote, Div, Para), Pandoc,- Inline (Emph, Str), pandocTypesVersion)-import Text.Pandoc.Error (PandocError (PandocLuaError))-import Text.Pandoc.Filter (Filter (LuaFilter), applyFilters)-import Text.Pandoc.Lua (Global (..), runLua, setGlobals)-import Text.Pandoc.Options (def)-import Text.Pandoc.Shared (pandocVersion)--import qualified Control.Monad.Catch as Catch-import qualified Data.Text as T-import qualified Data.Text.Encoding as TE--tests :: [TestTree]-tests =- [ testCase "macro expansion via filter" $- assertFilterConversion "a '{{helloworld}}' string is expanded"- "strmacro.lua"- (doc . para $ str "{{helloworld}}")- (doc . para . emph $ str "Hello, World")-- , testCase "convert all plains to paras" $- assertFilterConversion "plains become para"- "plain-to-para.lua"- (doc $ bulletList [plain (str "alfa"), plain (str "bravo")])- (doc $ bulletList [para (str "alfa"), para (str "bravo")])-- , testCase "convert display math to inline math" $- assertFilterConversion "display math becomes inline math"- "math.lua"- (doc $ para (displayMath "5+5"))- (doc $ para (math "5+5"))-- , testCase "make hello world document" $- assertFilterConversion "Document contains 'Hello, World!'"- "hello-world-doc.lua"- (doc . para $ str "Hey!" <> linebreak <> str "What's up?")- (doc . para $ str "Hello," <> space <> str "World!")-- , testCase "implicit doc filter" $- assertFilterConversion "Document contains 'Hello, World!'"- "implicit-doc-filter.lua"- (doc . plain $ linebreak)- (doc . para $ str "Hello," <> space <> str "World!")-- , testCase "parse raw markdown blocks" $- assertFilterConversion "raw markdown block is converted"- "markdown-reader.lua"- (doc $ rawBlock "markdown" "*charly* **delta**")- (doc . para $ emph "charly" <> space <> strong "delta")-- , testCase "allow shorthand functions for quote types" $- assertFilterConversion "single quoted becomes double quoted string"- "single-to-double-quoted.lua"- (doc . para . singleQuoted $ str "simple")- (doc . para . doubleQuoted $ str "simple")-- , testCase "Count inlines via metatable catch-all" $- assertFilterConversion "filtering with metatable catch-all failed"- "metatable-catch-all.lua"- (doc . para $ "four words, three spaces")- (doc . para $ str "7")-- , testCase "Count blocks via Block-specific catch-all" $- assertFilterConversion "filtering with Block catch-all failed"- "block-count.lua"- (doc $ para "one" <> para "two")- (doc $ para "2")-- , testCase "Smart constructors" $- assertFilterConversion "smart constructors returned a wrong result"- "smart-constructors.lua"- (doc $ para "")- (doc $ mconcat- [ bulletList [para "Hello", para "World"]- , definitionList [("foo", [para "placeholder"])]- , lineBlock ["Moin", "Welt"]- , orderedList [plain "one", plain "two"]- ])-- , testCase "Convert header upper case" $- assertFilterConversion "converting header to upper case failed"- "uppercase-header.lua"- (doc $ header 1 "les états-unis" <> para "text")- (doc $ header 1 "LES ÉTATS-UNIS" <> para "text")-- , testCase "Attribute lists are convenient to use" $- let kv_before = [("one", "1"), ("two", "2"), ("three", "3")]- kv_after = [("one", "eins"), ("three", "3"), ("five", "5")]- in assertFilterConversion "Attr doesn't behave as expected"- "attr-test.lua"- (doc $ divWith ("", [], kv_before) (para "nil"))- (doc $ divWith ("", [], kv_after) (para "nil"))-- , testCase "Filter list of inlines" $- assertFilterConversion "List of inlines"- "inlines-filter.lua"- (doc $ para ("Hello," <> linebreak <> "World! Wassup?"))- (doc $ para "Hello, World! Wassup?")-- , testCase "Filter list of blocks" $- assertFilterConversion "List of blocks"- "blocks-filter.lua"- (doc $ para "one." <> para "two." <> para "three.")- (doc $ plain "3")-- , testCase "Filter Meta" $- let setMetaBefore = setMeta "old" ("old" :: T.Text)- . setMeta "bool" False- setMetaAfter = setMeta "new" ("new" :: T.Text)- . setMeta "bool" True- in assertFilterConversion "Meta filtering"- "meta.lua"- (setMetaBefore . doc $ mempty)- (setMetaAfter . doc $ mempty)-- , testCase "Script filename is set" $- assertFilterConversion "unexpected script name"- "script-name.lua"- (doc $ para "ignored")- (doc $ para (str $ T.pack $ "lua" </> "script-name.lua"))-- , testCase "Pandoc version is set" . runLuaTest $ do- Lua.getglobal "PANDOC_VERSION"- Lua.liftIO .- assertEqual "pandoc version is wrong" (TE.encodeUtf8 pandocVersion)- =<< Lua.tostring' Lua.top-- , testCase "Pandoc types version is set" . runLuaTest $ do- Lua.getglobal "PANDOC_API_VERSION"- Lua.liftIO . assertEqual "pandoc-types version is wrong" pandocTypesVersion- =<< Lua.peek Lua.top-- , testCase "require file" $- assertFilterConversion "requiring file failed"- "require-file.lua"- (doc $ para "ignored")- (doc $ para (str . T.pack $ "lua" </> "require-file.lua"))-- , testCase "Allow singleton inline in constructors" . runLuaTest $ do- Lua.liftIO . assertEqual "Not the expected Emph"- (Emph [Str "test"]) =<< do- Lua.OK <- Lua.dostring "return pandoc.Emph"- Lua.push @Inline (Str "test")- Lua.call 1 1- Lua.peek @Inline top- Lua.liftIO . assertEqual "Unexpected element"- (Para [Str "test"]) =<< do- Lua.getglobal' "pandoc.Para"- Lua.pushString "test"- Lua.call 1 1- Lua.peek @Block top- Lua.liftIO . assertEqual "Unexptected element"- (BlockQuote [Para [Str "foo"]]) =<< (- do- Lua.getglobal' "pandoc.BlockQuote"- Lua.push (Para [Str "foo"])- _ <- Lua.call 1 1- Lua.peek @Block Lua.top- )-- , testCase "Elements with Attr have `attr` accessor" . runLuaTest $ do- Lua.push (Div ("hi", ["moin"], [])- [Para [Str "ignored"]])- Lua.getfield Lua.top "attr"- Lua.liftIO . assertEqual "no accessor" (("hi", ["moin"], []) :: Attr)- =<< Lua.peek @Attr Lua.top-- , testCase "module `pandoc.system` is present" . runLuaTest $ do- Lua.getglobal' "pandoc.system"- ty <- Lua.ltype Lua.top- Lua.liftIO $ assertEqual "module should be a table" Lua.TypeTable ty-- , testGroup "global modules"- [ testCase "module 'lpeg' is loaded into a global" . runLuaTest $ do- s <- Lua.dostring "assert(type(lpeg)=='table')"- Lua.liftIO $ Lua.OK @=? s-- , testCase "module 're' is loaded into a global" . runLuaTest $ do- s <- Lua.dostring "assert(type(re)=='table')"- Lua.liftIO $ Lua.OK @=? s-- , testCase "module 'lpeg' is available via `require`" . runLuaTest $ do- s <- Lua.dostring- "package.path = ''; package.cpath = ''; require 'lpeg'"- Lua.liftIO $ Lua.OK @=? s-- , testCase "module 're' is available via `require`" . runLuaTest $ do- s <- Lua.dostring- "package.path = ''; package.cpath = ''; require 're'"- Lua.liftIO $ Lua.OK @=? s- ]-- , testCase "informative error messages" . runLuaTest $ do- Lua.pushboolean True- -- Lua.newtable- eitherPandoc <- Catch.try (peek @Pandoc Lua.top)- case eitherPandoc of- Left (PandocLuaError msg) -> do- let expectedMsg = "Pandoc expected, got boolean\n"- <> "\twhile retrieving Pandoc"- Lua.liftIO $ assertEqual "unexpected error message" expectedMsg msg- Left e -> error ("Expected a Lua error, but got " <> show e)- Right _ -> error "Getting a Pandoc element from a bool should fail."- ]--assertFilterConversion :: String -> FilePath -> Pandoc -> Pandoc -> Assertion-assertFilterConversion msg filterPath docIn expectedDoc = do- actualDoc <- runIOorExplode $ do- setUserDataDir (Just "../data")- applyFilters def [LuaFilter ("lua" </> filterPath)] ["HTML"] docIn- assertEqual msg expectedDoc actualDoc--runLuaTest :: HasCallStack => Lua.LuaE PandocError a -> IO a-runLuaTest op = runIOorExplode $ do- res <- runLua $ do- setGlobals [ PANDOC_WRITER_OPTIONS def ]- op- case res of- Left e -> error (show e)- Right x -> return x
@@ -1,41 +0,0 @@-{- |-Module : Tests.Lua.Module-Copyright : © 2019-2022 Albert Krewinkel-License : GNU GPL, version 2 or above--Maintainer : Albert Krewinkel <albert@zeitkraut.de>-Stability : alpha-Portability : portable--Lua module tests--}-module Tests.Lua.Module (tests) where--import System.FilePath ((</>))-import Test.Tasty (TestName, TestTree)-import Test.Tasty.Lua (testLuaFile)--import Tests.Lua (runLuaTest)--tests :: [TestTree]-tests =- [ testPandocLua "pandoc"- ("lua" </> "module" </> "pandoc.lua")- , testPandocLua "pandoc.List"- ("lua" </> "module" </> "pandoc-list.lua")- , testPandocLua "pandoc.mediabag"- ("lua" </> "module" </> "pandoc-mediabag.lua")- , testPandocLua "pandoc.path"- ("lua" </> "module" </> "pandoc-path.lua")- , testPandocLua "pandoc.template"- ("lua" </> "module" </> "pandoc-template.lua")- , testPandocLua "pandoc.types"- ("lua" </> "module" </> "pandoc-types.lua")- , testPandocLua "pandoc.utils"- ("lua" </> "module" </> "pandoc-utils.lua")- , testPandocLua "globals"- ("lua" </> "module" </> "globals.lua")- ]--testPandocLua :: TestName -> FilePath -> TestTree-testPandocLua = testLuaFile runLuaTest
@@ -0,0 +1,56 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.MediaBag (tests) where++import Test.Tasty+import Test.Tasty.HUnit+-- import Tests.Helpers+import Text.Pandoc.Class.IO (extractMedia)+import Text.Pandoc.Class (fillMediaBag, runIOorExplode)+import System.IO.Temp (withTempDirectory)+import System.FilePath+import Text.Pandoc.Builder as B+import qualified Data.Text as T+import System.Directory (doesFileExist, makeAbsolute)++tests :: [TestTree]+tests = [+ testCase "test fillMediaBag & extractMedia" $+ withTempDirectory "." "extractMediaTest" $ \tmpdir -> do+ -- Use absolute paths so the test does not need to change+ -- the process-wide current directory (which is not thread-safe+ -- and breaks other tests running in parallel).+ absTmpdir <- makeAbsolute tmpdir+ absLalune <- makeAbsolute "lalune.jpg"+ let d = B.doc $+ -- simple relative path -> extracted with original name+ B.para (B.image "lalune.jpg" "" mempty) <>+ -- absolute path -> extracted with hashed name+ B.para (B.image (T.pack absLalune) "" mempty) <>+ B.para (B.image "data:image/png;base64,cHJpbnQgImhlbGxvIgo=;.lua+%2f%2e%2e%2f%2e%2e%2fa%2elua" "" mempty) <>+ B.para (B.image "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" "" mempty)+ let fooDir = absTmpdir </> "foo"+ runIOorExplode $ do+ fillMediaBag d+ extractMedia fooDir d+ exists1 <- doesFileExist (fooDir </> "lalune.jpg")+ assertBool "file in directory is not extracted with original name" exists1+ exists2 <- doesFileExist (fooDir </> "f9d88c3dbe18f6a7f5670e994a947d51216cdf0e.jpg")+ assertBool "file with absolute path is not extracted with hashed name" exists2+ exists3 <- doesFileExist (fooDir </> "2a0eaa89f43fada3e6c577beea4f2f8f53ab6a1d.png")+ exists4 <- doesFileExist (absTmpdir </> "a.lua")+ assertBool "data uri with malicious payload gets written outside of destination dir"+ (exists3 && not exists4)+ exists5 <- doesFileExist (fooDir </> "d5fceb6532643d0d84ffe09c40c481ecdf59e15a.gif")+ assertBool "data uri with gif is not properly decoded" exists5+ -- double-encoded version:+ let e = B.doc $+ B.para (B.image "data:image/png;base64,cHJpbnQgInB3bmVkIgo=;.lua+%252f%252e%252e%252f%252e%252e%252fb%252elua" "" mempty)+ let barDir = absTmpdir </> "bar"+ runIOorExplode $ do+ fillMediaBag e+ extractMedia barDir e+ exists6 <- doesFileExist (barDir </> "772ceca21a2751863ec46cb23db0e7fc35b9cff8.png")+ exists7 <- doesFileExist (absTmpdir </> "b.lua")+ assertBool "data uri with double-encoded malicious payload gets written outside of destination dir"+ (exists6 && not exists7)+ ]
@@ -1,6 +1,6 @@ {- | Module : Tests.Old- Copyright : © 2006-2022 John MacFarlane+ Copyright : © 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu>@@ -26,7 +26,7 @@ tests pandocPath = [ testGroup "markdown" [ testGroup "writer"- $ writerTests' "markdown" ++ lhsWriterTests' "markdown"+ $ writerTests' "markdown" ++ lhsWriterTests' "markdown" ++ extWriterTests' "markdown" , testGroup "reader" [ test' "basic" ["-r", "markdown", "-w", "native", "-s"] "testsuite.txt" "testsuite.native"@@ -78,11 +78,24 @@ , s5WriterTest' "inserts" ["-s", "-H", "insert", "-B", "insert", "-A", "insert", "-c", "main.css"] "html4" ]+ , testGroup "asciidoc"+ [ testGroup "writer" (writerTests' "asciidoc" +++ writerTests' "asciidoc_legacy")+ , testGroup "reader"+ [ test' "basic" ["-f", "asciidoc", "-t", "native", "-s"]+ "asciidoc-reader.adoc" "asciidoc-reader.native"+ ]+ ] , testGroup "textile" [ testGroup "writer" $ writerTests' "textile" , test' "reader" ["-r", "textile", "-w", "native", "-s"] "textile-reader.textile" "textile-reader.native" ]+ , testGroup "djot"+ [ testGroup "writer" $ writerTests' "djot"+ , test' "reader" ["-f", "djot", "-t" ,"native", "-s"]+ "djot-reader.djot" "djot-reader.native"+ ] , testGroup "docbook" [ testGroup "writer" $ writerTests' "docbook4" , test' "reader" ["-r", "docbook", "-w", "native", "-s"]@@ -128,7 +141,10 @@ , fb2WriterTest' "testsuite" [] "testsuite.native" "writer.fb2" ] , testGroup "mediawiki"- [ testGroup "writer" $ writerTests' "mediawiki"+ [ testGroup "writer" $ mconcat [+ writerTests' "mediawiki"+ , extWriterTests' "mediawiki"+ ] , test' "reader" ["-r", "mediawiki", "-w", "native", "-s"] "mediawiki-reader.wiki" "mediawiki-reader.native" ]@@ -160,11 +176,11 @@ [ test' "reader" ["-r", "t2t", "-w", "native", "-s"] "txt2tags.t2t" "txt2tags.native" ] , testGroup "epub" [- test' "features" ["-r", "epub", "-w", "native"]+ test' "features" ["-r", "epub", "-w", "native", "-s"] "epub/features.epub" "epub/features.native"- , test' "wasteland" ["-r", "epub", "-w", "native"]+ , test' "wasteland" ["-r", "epub", "-w", "native", "-s"] "epub/wasteland.epub" "epub/wasteland.native"- , test' "formatting" ["-r", "epub", "-w", "native"]+ , test' "formatting" ["-r", "epub", "-w", "native", "-s"] "epub/formatting.epub" "epub/formatting.native" ] , testGroup "twiki"@@ -175,9 +191,7 @@ "tikiwiki-reader.tikiwiki" "tikiwiki-reader.native" ] , testGroup "other writers" $ map (\f -> testGroup f $ writerTests' f) [ "opendocument" , "context" , "texinfo", "icml", "tei"- , "man" , "plain" , "asciidoc", "asciidoctor"- , "xwiki", "zimwiki"- ]+ , "man" , "plain" , "xwiki", "zimwiki" ] , testGroup "writers-lang-and-dir" [ test' "latex" ["-f", "native", "-t", "latex", "-s"] "writers-lang-and-dir.native" "writers-lang-and-dir.latex"@@ -188,18 +202,27 @@ [ testGroup "writer" $ writerTests' "muse" ] , testGroup "ms"- [ testGroup "writer" $ writerTests' "ms"+ [ test' "basic" ["-f", "native", "-t", "ms", "--columns=80",+ "--variable", "pandoc-version=",+ "--pdf-engine", "pdfroff", "-s"]+ "testsuite.native" "writer.ms"+ , test' "tables" ["-f", "native", "-t", "ms", "--columns=80",+ "--variable", "pandoc-version=",+ "--pdf-engine", "pdfroff"]+ "tables.native" "tables.ms" ]+ , testGroup "typst"+ [ testGroup "writer" $ writerTests' "typst" ++ extWriterTests' "typst"+ , testGroup "reader"+ [ test' "typst-reader" ["-r", "typst", "-w", "native", "-s"]+ "typst-reader.typ" "typst-reader.native"+ ]+ ]+ , testGroup "creole" [ test' "reader" ["-r", "creole", "-w", "native", "-s"] "creole-reader.txt" "creole-reader.native" ]- , testGroup "custom writer"- [ test' "basic" ["-f", "native", "-t", "../data/sample.lua"]- "testsuite.native" "writer.custom"- , test' "tables" ["-f", "native", "-t", "../data/sample.lua"]- "tables.native" "tables.custom"- ] , testGroup "man" [ test' "reader" ["-r", "man", "-w", "native", "-s"] "man-reader.man" "man-reader.native"@@ -232,6 +255,33 @@ "ipynb/rank.ipynb" "ipynb/rank.out.html" ] , testGroup "markua" [ testGroup "writer" $ writerTests' "markua"]+ , testGroup "ansi"+ [ test' "ansi" ["-f", "markdown", "-t", "ansi"]+ "ansi-test.txt" "ansi-test.ansi"+ ]+ , testGroup "pod"+ [ test' "pod" ["-f", "pod", "-t", "native"]+ "pod-reader.pod" "pod-reader.native"+ ]+ , testGroup "vimdoc" [ testGroup "writer" $+ writerTests' "vimdoc" +++ [ test' "vimdoc-specific definition lists"+ ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78"]+ "vimdoc/definition-lists.markdown" "vimdoc/definition-lists.vimdoc"+ , test' "linking to docs"+ ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78"]+ "vimdoc/vim-online-doc.markdown" "vimdoc/vim-online-doc.vimdoc"+ , test' "unnumbered TOC up to level 2 headers"+ ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78",+ "--toc-depth=2"]+ "vimdoc/headers.markdown" "vimdoc/headers.vimdoc"+ , test' "numbered TOC"+ ["-s", "-r", "markdown", "-w", "vimdoc", "--toc", "--columns=78",+ "-N"]+ "vimdoc/headers.markdown" "vimdoc/headers-numbered.vimdoc"+ ]+ ]+ , testGroup "bbcode" [testGroup "writer" $ writerTests' "bbcode"] ] where test' = test pandocPath@@ -254,7 +304,7 @@ ] where t n f = test pandocPath- n ["--wrap=preserve", "-r", "native", "-s",+ n ["--wrap=preserve", "-r", "native", "--markdown-headings=setext", "-w", f] "lhs-test.native" ("lhs-test" <.> f) @@ -294,7 +344,7 @@ s5WriterTest :: FilePath -> String -> [String] -> String -> TestTree s5WriterTest pandocPath modifier opts format = test pandocPath (format ++ " writer (" ++ modifier ++ ")")- (["-r", "native", "-w", format] ++ opts)+ (["-r", "native", "-w", format] ++ opts ++ ["--variable", "pandoc-version="]) "s5.native" ("s5-" ++ modifier <.> "html") fb2WriterTest :: FilePath -> String -> [String] -> String -> String -> TestTree
@@ -2,7 +2,7 @@ {- | Module : Tests.Readers.Creole Copyright : © 2017 Sascha Wilde- 2017-2022 John MacFarlane+ 2017-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : Sascha Wilde <wilde@sha-bang.de>
@@ -15,11 +15,11 @@ import Codec.Archive.Zip import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as B-import qualified Data.Map as M import qualified Data.Text as T import Data.Maybe import System.IO.Unsafe import Test.Tasty+import Test.Tasty.Golden.Advanced import Test.Tasty.HUnit import Tests.Helpers import Text.Pandoc@@ -27,52 +27,24 @@ import qualified Text.Pandoc.MediaBag as MB import Text.Pandoc.UTF8 as UTF8 --- We define a wrapper around pandoc that doesn't normalize in the--- tests. Since we do our own normalization, we want to make sure--- we're doing it right.--newtype NoNormPandoc = NoNormPandoc {unNoNorm :: Pandoc}- deriving Show--noNorm :: Pandoc -> NoNormPandoc-noNorm = NoNormPandoc- defopts :: ReaderOptions defopts = def{ readerExtensions = getDefaultExtensions "docx" } -instance ToString NoNormPandoc where- toString d = T.unpack $ purely (writeNative def{ writerTemplate = s }) $ toPandoc d- where s = case d of- NoNormPandoc (Pandoc (Meta m) _)- | M.null m -> Nothing- | otherwise -> Just mempty -- need this to get meta output--instance ToPandoc NoNormPandoc where- toPandoc = unNoNorm--compareOutput :: ReaderOptions- -> FilePath- -> FilePath- -> IO (NoNormPandoc, NoNormPandoc)-compareOutput opts docxFile nativeFile = do- df <- B.readFile docxFile- nf <- UTF8.toText <$> BS.readFile nativeFile- p <- runIOorExplode $ readDocx opts df- df' <- runIOorExplode $ readNative def nf- return (noNorm p, noNorm df')--testCompareWithOptsIO :: ReaderOptions -> String -> FilePath -> FilePath -> IO TestTree-testCompareWithOptsIO opts name docxFile nativeFile = do- (dp, np) <- compareOutput opts docxFile nativeFile- return $ test id name (dp, np)--testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree-testCompareWithOpts opts name docxFile nativeFile =- unsafePerformIO $ testCompareWithOptsIO opts name docxFile nativeFile- testCompare :: String -> FilePath -> FilePath -> TestTree testCompare = testCompareWithOpts defopts +testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree+testCompareWithOpts opts testName docxFP nativeFP =+ goldenTest+ testName+ (do nf <- UTF8.toText <$> BS.readFile nativeFP+ runIOorExplode (readNative def nf))+ (do df <- B.readFile docxFP+ runIOorExplode (readDocx opts df))+ (nativeDiff nativeFP)+ (\a -> runIOorExplode (writeNative def{ writerTemplate = Just mempty} a)+ >>= BS.writeFile nativeFP . UTF8.fromText)+ testForWarningsWithOptsIO :: ReaderOptions -> String -> FilePath -> [String] -> IO TestTree testForWarningsWithOptsIO opts name docxFile expected = do df <- B.readFile docxFile@@ -235,6 +207,26 @@ "collapse overlapping targets (anchor spans)" "docx/overlapping_targets.docx" "docx/overlapping_targets.native"+ , testCompare+ "anchor in header after anchor"+ "docx/anchor_header_after_anchor.docx"+ "docx/anchor_header_after_anchor.native"+ , testCompare+ "text in shape format"+ "docx/text_in_shape_format.docx"+ "docx/text_in_shape_format.native"+ , testCompare+ "image inside textbox content"+ "docx/textbox_image.docx"+ "docx/textbox_image.native"+ , testCompare+ "image inside textbox content with duplicate encoding"+ "docx/textbox_image_duplicate_encoding.docx"+ "docx/textbox_image_duplicate_encoding.native"+ , testCompare+ "image with textbox caption in same paragraph"+ "docx/image_with_textbox_caption.docx"+ "docx/image_with_textbox_caption.native" ] , testGroup "blocks" [ testCompare@@ -294,6 +286,10 @@ "docx/definition_list.docx" "docx/definition_list.native" , testCompare+ "task lists"+ "docx/task_list.docx"+ "docx/task_list.native"+ , testCompare "custom defined lists in styles" "docx/german_styled_lists.docx" "docx/german_styled_lists.native"@@ -316,7 +312,7 @@ , testCompare "blockquotes (parsing indent as blockquote)" "docx/block_quotes.docx"- "docx/block_quotes_parse_indent.native"+ "docx/block_quotes.native" , testCompare "blockquotes (parsing indent relative to the indent of the parent style as blockquote)" "docx/relative_indentation_blockquotes.docx"@@ -334,6 +330,10 @@ "docx/table_with_list_cell.docx" "docx/table_with_list_cell.native" , testCompare+ "a table with gridBefore"+ "docx/table_gridbefore.docx"+ "docx/table_gridbefore.native"+ , testCompare "a table with a header which contains rowspans greater than 1" "docx/table_header_rowspan.docx" "docx/table_header_rowspan.native"@@ -475,11 +475,25 @@ "comment warnings (all)" "docx/comments_warning.docx" ["Docx comment 1 will not retain formatting"]+ , testForWarningsWithOpts def{readerTrackChanges=AllChanges,+ readerExtensions=extensionsFromList [Ext_styles]}+ "comments (with styles extension)"+ "docx/comments.docx"+ [] ] , testGroup "media" [ testMediaBag "image extraction" "docx/image.docx"+ , testMediaBag+ "image inside textbox content populates media bag"+ "docx/textbox_image.docx"+ , testMediaBag+ "image inside textbox content with duplicate encoding populates media bag"+ "docx/textbox_image_duplicate_encoding.docx"+ , testMediaBag+ "image with textbox caption in same paragraph populates media bag"+ "docx/image_with_textbox_caption.docx" ] , testGroup "custom styles" [ testCompare
@@ -71,10 +71,11 @@ para (strikeout "deleted") , "Inline code" =: "foo <code java>public static void main</code> bar" =?>- para (text "foo " <> codeWith ("", ["java"], []) "public static void main" <> text " bar")+ para (text "foo") <> codeBlockWith ("", ["java"], []) "public static void main"+ <> para (text "bar") , "Inline file" =: "foo <file></code></file> bar" =?>- para (text "foo " <> code "</code>" <> text " bar")+ para (text "foo") <> codeBlock "</code>" <> para (text "bar") , "Inline HTML" =: "<html>\nThis is some <span style=\"color:red;font-size:150%;\">inline HTML</span>\n</html>" =?> para (rawInline "html" "\nThis is some <span style=\"color:red;font-size:150%;\">inline HTML</span>\n")@@ -167,10 +168,10 @@ para (imageWith ("", ["align-center"], []) "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png")) , "Image with width" =: "{{wiki:dokuwiki-128.png?50}}" =?>- para (imageWith ("", [], [("width", "50")]) "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png"))+ para (imageWith ("", [], [("width", "50"), ("query", "?50")]) "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png")) , "Image with width and height" =: "{{wiki:dokuwiki-128.png?nocache&50x100}}" =?>- para (imageWith ("", [], [("width", "50"), ("height", "100")]) "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png"))+ para (imageWith ("", [], [("width", "50"), ("height", "100"), ("query", "?nocache&50x100")]) "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png")) , "Linkonly" =: "{{wiki:dokuwiki-128.png?linkonly}}" =?> para (link "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png"))@@ -245,7 +246,7 @@ ] =?> orderedList [ plain "first item" , plain ("second item with linebreak" <> linebreak <> " second line")- , plain ("third item with code: " <> code "some code\ncomes here\n")+ , plain "third item with code: " <> codeBlock "some code\ncomes here\n" , plain "fourth item" ] ]@@ -268,9 +269,9 @@ , ">> baz" , "> bat" ] =?>- blockQuote (plain "foo" <>- plain "no space is required after >" <>- plain "bar" <>+ blockQuote (plain (text "foo" <> linebreak <>+ text "no space is required after >" <> linebreak <>+ text "bar") <> blockQuote (plain "baz") <> plain "bat") , "Code block" =:
@@ -1,6 +1,6 @@ {- | Module : Tests.Readers.EPUB- Copyright : © 2006-2022 John MacFarlane+ Copyright : © 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.eu>
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.HTML- Copyright : © 2006-2022 John MacFarlane+ Copyright : © 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -87,17 +87,29 @@ setMeta "lang" (text "es") (doc (plain (text "hola"))) ] , testGroup "main"- [ test htmlNativeDivs "<main> becomes <div role=main>" $ "<main>hello</main>" =?>- doc (divWith ("", [], [("role", "main")]) (plain (text "hello")))+ [ test htmlNativeDivs "<main> contents are parsed" $ "<header>ignore me</header><nav><p>ignore me</p><main>hello</main><footer>ignore me</footer>" =?>+ doc (plain (text "hello")) , test htmlNativeDivs "<main role=X> becomes <div role=X>" $ "<main role=foobar>hello</main>" =?> doc (divWith ("", [], [("role", "foobar")]) (plain (text "hello"))) , test htmlNativeDivs "<main> has attributes preserved" $ "<main id=foo class=bar data-baz=qux>hello</main>" =?> doc (divWith ("foo", ["bar"], [("role", "main"), ("baz", "qux")]) (plain (text "hello"))) , test htmlNativeDivs "<main> closes <p>" $ "<p>hello<main>main content</main>" =?>- doc (para (text "hello") <> divWith ("", [], [("role", "main")]) (plain (text "main content")))+ doc (plain (text "main content")) , test htmlNativeDivs "<main> followed by text" $ "<main>main content</main>non-main content" =?>- doc (divWith ("", [], [("role", "main")]) (plain (text "main content")) <> plain (text "non-main content"))+ doc (plain (text "main content")) ]+ , testGroup "code"+ [+ test html "inline code block" $+ "<code>Answer is 42</code>" =?>+ plain (codeWith ("",[],[]) "Answer is 42")+ ]+ , testGroup "tt"+ [+ test html "inline tt block" $+ "<tt>Answer is 42</tt>" =?>+ plain (codeWith ("",[],[]) "Answer is 42")+ ] , testGroup "samp" [ test html "inline samp block" $@@ -112,16 +124,16 @@ , testGroup "header" [ test htmlNativeDivs "<header> is parsed as a div" $ "<header id=\"title\">Title</header>" =?>- divWith ("title", mempty, mempty) (plain "Title")+ divWith ("title", ["header"], mempty) (plain "Title") ] , testGroup "code block" [ test html "attributes in pre > code element" $ "<pre><code id=\"a\" class=\"python\">\nprint('hi')\n</code></pre>" =?>- codeBlockWith ("a", ["python"], []) "print('hi')"+ codeBlockWith ("a", ["python"], []) "\nprint('hi')" , test html "attributes in pre take precedence" $- "<pre id=\"c\"><code id=\"d\">\nprint('hi mom!')\n</code></pre>"+ "<pre id=\"c\"><code id=\"d\">print('hi mom!')\n</code></pre>" =?> codeBlockWith ("c", [], []) "print('hi mom!')" ]
@@ -27,7 +27,6 @@ tests :: [TestTree] tests = [ testGroup "inline code" [ test jats "basic" $ "<p>\n <monospace>@&</monospace>\n</p>" =?> para (code "@&")- , test jats "lang" $ "<p>\n <code language=\"c\">@&</code>\n</p>" =?> para (codeWith ("", ["c"], []) "@&") ] , testGroup "block code" [ test jats "basic" $ "<preformat>@&</preformat>" =?> codeBlock "@&"@@ -36,6 +35,42 @@ , testGroup "images" [ test jats "basic" $ "<graphic mimetype=\"image\" mime-subtype=\"\" xlink:href=\"/url\" xlink:title=\"title\" />" =?> para (image "/url" "title" mempty)+ , test jats "alt-text" $ + "<graphic id=\"graphic001\"\n\+ \ xlink:href=\"https://lh3.googleusercontent.com/dB7iirJ3ncQaVMBGE2YX-WCeoAVIChb6NAzoFcKCFChMsrixJvD7ZRbvcaC-ceXEzXYaoH4K5vaoRDsUyBHFkpIDPnsn3bnzovbvi0a2Gg=s660\"\n\+ \ xlink:title=\"This is the title of the graphic\"\n\+ \ xlink:role=\"This is the role of the graphic\">\n\+ \ <alt-text>Alternative text of the graphic</alt-text>\n\+ \ <caption>\n\+ \ <title>This is the title of the caption</title>\n\+ \ <p>Google doodle from 14 March 2003</p></caption>\n\+ \ </graphic>"+ =?> Para [ Image+ ( "graphic001"+ , [ "This"+ , "is"+ , "the"+ , "role"+ , "of"+ , "the"+ , "graphic"+ ]+ , []+ )+ [ Str "Alternative"+ , Space+ , Str "text"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "graphic"+ ]+ ( "https://lh3.googleusercontent.com/dB7iirJ3ncQaVMBGE2YX-WCeoAVIChb6NAzoFcKCFChMsrixJvD7ZRbvcaC-ceXEzXYaoH4K5vaoRDsUyBHFkpIDPnsn3bnzovbvi0a2Gg=s660"+ , "This is the title of the graphic"+ )+ ] ] , test jats "bullet list" $ "<list list-type=\"bullet\">\n\
@@ -2,10 +2,10 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Tests.Readers.Jira- Copyright : © 2019-2022 Albert Krewinel+ Copyright : © 2019-2024 Albert Krewinel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <tarleb@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.LaTeX- Copyright : © 2006-2022 John MacFarlane+ Copyright : © 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -2,7 +2,7 @@ {- | Module : Tests.Readers.Man Copyright : © 2018-2019 Yan Pas <yanp.bugz@gmail.com>,- 2018-2022 John MacFarlane+ 2018-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -20,7 +20,6 @@ import Text.Pandoc import Text.Pandoc.Arbitrary () import Text.Pandoc.Builder-import Text.Pandoc.Readers.Man man :: Text -> Pandoc man = purely $ readMan def
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Markdown- Copyright : © 2006-2022 John MacFarlane+ Copyright : © 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -29,13 +29,9 @@ 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 = githubMarkdownExtensions }+markdownGH = purely $ readMarkdown def {readerExtensions = enableExtension+ Ext_wikilinks_title_before_pipe githubMarkdownExtensions } markdownMMD :: Text -> Pandoc markdownMMD = purely $ readMarkdown def {@@ -58,6 +54,9 @@ autolinkWith attr s = linkWith attr s' "" (str s') where s' = T.pack s +wikilink :: Attr+wikilink = (mempty, ["wikilink"], mempty)+ bareLinkTests :: [(Text, Inlines)] bareLinkTests = [ ("http://google.com is a search engine.",@@ -185,7 +184,6 @@ , ("after literal backticks", ["`x``- x`" ], [code "x``- x" ]) ] lis = ["`text","y","x`"]- lis' = ["text","y","x"] bldLsts w lsts txts = let (res, res', f) = foldr (\((_, _, lt), lc) (acc, tacc, t) ->@@ -207,18 +205,12 @@ =?> bldLsts plain lsts lis | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists] ]- <> [ "lists with newlines and indent in backticks" =:- T.intercalate ("\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis lsts)- =?> let (_, _, f) = head lsts- in f [plain $ code $ T.intercalate (T.replicate 5 " ") $ head lis' : zipWith (\i (_, lt, _) -> lt <> i) (tail lis') (tail lsts)]- | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]- ] <> [ "lists with blank lines and indent in backticks" =:- T.intercalate ("\n\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis lsts)+ T.intercalate ("\n\n" <> T.replicate 4 " ") (zipWith (\i (_, lt, _) -> lt <> i) lis (l:ls)) <> "\n"- =?> let (_, _, f) = head lsts- in f . pure $ (para . text $ head lis) <> bldLsts para (tail lsts) (tail lis)- | lsts <- [ [i, j, k] | i <- lists, j <- lists, k <- lists]+ =?> let (_, _, f) = l+ in f . pure $ (para . text $ "`text") <> bldLsts para ls (drop 1 lis)+ | (l:ls) <- [ [i, j, k] | i <- lists, j <- lists, k <- lists] ] , testGroup "emph and strong" [ "two strongs in emph" =:@@ -309,6 +301,26 @@ "[https://example.org(](url)" =?> para (link "url" "" (text "https://example.org(")) ]+ , testGroup "Github wiki links"+ [ test markdownGH "autolink" $+ "[[https://example.org]]" =?>+ para (linkWith wikilink "https://example.org" "" (str "https://example.org"))+ , test markdownGH "link with title" $+ "[[title|https://example.org]]" =?>+ para (linkWith wikilink "https://example.org" "" (str "title"))+ , test markdownGH "bad link with title" $+ "[[title|random string]]" =?>+ para (linkWith wikilink "random string" "" (str "title"))+ , test markdownGH "autolink not being a link" $+ "[[Name of page]]" =?>+ para (linkWith wikilink "Name of page" "" (text "Name of page"))+ , test markdownGH "autolink not being a link with a square bracket" $+ "[[Name of ]page]]" =?>+ para (linkWith wikilink "Name of ]page" "" (text "Name of ]page"))+ , test markdownGH "link with inline start should be a link" $+ "[[t`i*t_le|https://example.org]]" =?>+ para (linkWith wikilink "https://example.org" "" (str "t`i*t_le"))+ ] , testGroup "Headers" [ "blank line before header" =: "\n# Header\n"@@ -363,6 +375,12 @@ , test markdownSmart "unclosed double quote" ("**this should \"be bold**" =?> para (strong "this should \8220be bold"))+ , test markdownSmart "single quote in inline note within single quotes" $ -- issue #11613+ "'a^['b'.] c.'" =?>+ para (singleQuoted ("a" <> note (para (singleQuoted "b" <> ".")) <> space <> "c."))+ , test markdownSmart "double quote in inline note within double quotes" $ -- issue #11613+ "\"a^[\"b\".] c.\"" =?>+ para (doubleQuoted ("a" <> note (para (doubleQuoted "b" <> ".")) <> space <> "c.")) ] , testGroup "sub- and superscripts" [@@ -429,7 +447,7 @@ <> codeBlockWith ("",["haskell"],[]) "b" <>- rawBlock "html" "<div>\n\n"+ divWith ("",[],[]) mempty ] -- the round-trip properties frequently fail -- , testGroup "round trip"@@ -445,14 +463,14 @@ , "blank space before first def" =: "foo1\n\n : bar\n\nfoo2\n\n : bar2\n : bar3\n" =?> definitionList [ (text "foo1", [para (text "bar")])- , (text "foo2", [para (text "bar2"),- plain (text "bar3")])+ , (text "foo2", [plain (text "bar2"),+ para (text "bar3")]) ] , "blank space before second def" =: "foo1\n : bar\n\nfoo2\n : bar2\n\n : bar3\n" =?> definitionList [ (text "foo1", [plain (text "bar")]) , (text "foo2", [plain (text "bar2"),- para (text "bar3")])+ plain (text "bar3")]) ] , "laziness" =: "foo1\n : bar\nbaz\n : bar2\n" =?>@@ -462,8 +480,8 @@ ] , "no blank space before first of two paragraphs" =: "foo1\n : bar\n\n baz\n" =?>- definitionList [ (text "foo1", [para (text "bar") <>- para (text "baz")])+ definitionList [ (text "foo1", [plain (text "bar") <>+ plain (text "baz")]) ] , "first line not indented" =: "foo\n: bar\n" =?>@@ -476,14 +494,6 @@ divWith nullAttr (definitionList [ (text "foo", [bulletList [plain (text "bar")]]) ]) ]- , testGroup "+compact_definition_lists"- [ test markdownCDL "basic compact list" $- "foo1\n: bar\n baz\nfoo2\n: bar2\n" =?>- definitionList [ (text "foo1", [plain (text "bar" <> softbreak <>- text "baz")])- , (text "foo2", [plain (text "bar2")])- ]- ] , testGroup "lists" [ "issue #1154" =: " - <div>\n first div breaks\n </div>\n\n <button>if this button exists</button>\n\n <div>\n with this div too.\n </div>\n"@@ -574,4 +584,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")) ]+ ]
@@ -0,0 +1,321 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Tests.Readers.Mdoc+ Copyright : © 2024 Evan Silberman+ License : GNU GPL, version 2 or above++ Maintainer : + Stability : alpha+ Portability : portable++Tests for the Mdoc reader.+-}++module Tests.Readers.Mdoc (tests) where++import Data.Text (Text)+import qualified Data.Text as T+import Test.Tasty+import Test.Tasty.HUnit (HasCallStack)+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++mdoc :: Text -> Pandoc+mdoc = purely $ readMdoc def++infix 4 =:+(=:) :: (ToString c, HasCallStack)+ => String -> (Text, c) -> TestTree+(=:) = test mdoc++cls :: Text -> Attr+cls x = (mempty, [x], mempty)++tests :: [TestTree]+tests = [+ testGroup "one-line enclosures"+ [ "Dq" =:+ ".Dq hello world" =?>+ para (doubleQuoted "hello world")+ , "Sq" =:+ ".Sq hello world" =?>+ para (singleQuoted "hello world")+ , "empty" =:+ ".Dq" =?>+ para (doubleQuoted mempty)+ , "nested" =:+ ".Dq Pq hello world" =?>+ para (doubleQuoted "(hello world)")+ , "nested with closing delimiters" =:+ ".Dq Pq hi mom !" =?>+ para (doubleQuoted "(hi mom)" <> "!")+ , "nested multiline enclosure" =:+ ".Dq Po a \\&; b \\&; c Pc ." =?>+ para (doubleQuoted "(a ; b ; c)" <> ".")+ , "with inlines" =:+ ".Dq hello Sy world ." =?>+ para (doubleQuoted ("hello" <> space <> strong "world" <> "."))+ , "with text production" =:+ ".Dq I love the St -iso8601 standard!" =?>+ para (doubleQuoted "I love the ISO 8601 standard!")+ , "with Ns" =:+ ".Op , Ns Ar value ..." =?>+ para ("[," <> (codeWith (cls "variable") "value ...") <> "]")+ , "ending with open delimiter" =:+ ".Dq hi (" =?>+ para (doubleQuoted "hi (")+ ]+ , testGroup "multiline enclosures"+ [ "nested multiline" =:+ T.unlines [".Bo", ".Po", "hi", ".Pc", ".Bc"] =?>+ para ("[(hi)]")+ , "nested on one line" =:+ ".Bo Po hi Pc Bc" =?>+ para ("[(hi)]")+ , "with wacky delimiters" =:+ ".Bo ( | hi ! Bc ?" =?>+ para ("([| hi!]?")+ ]+ , testGroup "simple inlines"+ [ "Sy" =:+ ".Sy hello world" =?>+ para (strong "hello world")+ , "Em" =:+ ".Em hello world" =?>+ para (emph "hello world")+ , "Ev" =:+ ".Ev HELLO_WORLD ," =?>+ para (codeWith (cls "Ev") "HELLO_WORLD" <> ",")+ , "Ar" =:+ ".Ar ) z" =?>+ para (codeWith (cls "variable") "file ..." <> ") " <> codeWith (cls "variable") "z")+ , "In" =:+ ".In ( math.h ) b c" =?>+ para ("(" <> codeWith (cls "In") "<math.h>" <> ") b c")+ , "Mt" =:+ ".Mt a@example.org , b@example.org" =?>+ para ((link "mailto:a@example.org" "" "a@example.org") <>+ "," <> space <> (link "mailto:b@example.org" "" "b@example.org"))+ , "No" =:+ ".No ( hello , world ! )" =?>+ para "(hello, world!)"+ , "empty Pa with closing punctuation" =:+ ".Pa ) z" =?>+ para (spanWith (cls "Pa") "~" <> ")" <> space <> spanWith (mempty, ["Pa"], mempty) "z")+ , "delimiters" =:+ ".Sy ( hello world )" =?>+ para (mconcat ["(", strong "hello world", ")"])+ , "multiple" =:+ ".Sy hello Em world" =?>+ para (strong "hello" <> space <> emph "world")+ ]+ , testGroup "Fl"+ [ "simple" =:+ ".Fl w" =?>+ para (codeWith (cls "Fl") "-w")+ , "multiple" =:+ ".Fl W all" =?>+ para (codeWith (cls "Fl") "-W" <> space <> codeWith (cls "Fl") "-all")+ , "empty with following macro" =:+ ".Fl Cm x" =?>+ para (codeWith (cls "Fl") "-" <> codeWith (cls "Cm") "x")+ , "enclosed with following macro" =:+ ".Pq Fl Cm x" =?>+ para ("(" <> codeWith (cls "Fl") "-" <> codeWith (cls "Cm") "x" <> ")")+ -- XXX this is a mandoc delta, the period is meant to land outside+ -- the enclosure. parseInline has learned how to defer eols but not+ -- closing delimiters+ , "enclosed with following delimiters" =:+ ".Pq Fl x ." =?>+ para ("(" <> codeWith (cls "Fl") "-x" <> ".)")+ , "following Ns" =:+ ".Fl W Ns Cm all" =?>+ para (codeWith (cls "Fl") "-W" <> codeWith (cls "Cm") "all")+ , "GNU" =:+ ".Fl -help" =?>+ para (codeWith (cls "Fl") "--help")+ , "GNU escaped" =:+ ".Fl \\-help" =?>+ para (codeWith (cls "Fl") "--help")+ , "GNU Fl Fl" =:+ ".Fl Fl help" =?>+ para (codeWith (cls "Fl") "--help")+ , "punctuation" =:+ ".Op Fl a | b" =?>+ para ("[" <> codeWith (cls "Fl") "-a" <> " | " <> codeWith (cls "Fl") "-b" <> "]")+ , "middle close paren" =:+ ".Fl a ) z" =?>+ para (codeWith (cls "Fl") "-a" <> ") " <> codeWith (cls "Fl") "-z")+ , "empty with close paren" =:+ ".Fl ) z" =?>+ para (codeWith (cls "Fl") "-" <> ") " <> codeWith (cls "Fl") "-z")+ , "empty with pipe" =:+ ".Fl | z" =?>+ para (codeWith (cls "Fl") "-" <> " | " <> codeWith (cls "Fl") "-z")+ , "empty with parens" =:+ ".Fl ( )" =?>+ para ("(" <> codeWith (cls "Fl") "-" <> ")")+ ]+ , testGroup "links"+ [ "basic" =:+ ".Lk href name" =?>+ para (link "href" "" "name")+ , "complicated" =:+ ".Lk , ( href name )" =?>+ para ("," <> space <> "(" <> link "href" "" "name" <> ")")+ , "unnamed" =:+ ".Lk href" =?>+ para (link "href" "" "href")+ ]+ , testGroup "Ns macro"+ [ "at the beginning of a macro line (mandoc delta)" =:+ T.unlines [".Op before", ".Ns Op after"] =?>+ para "[before] [after]" -- mandoc: warning+ , "after a block closing macro" =:+ T.unlines [".Oo before", ".Oc Ns Op after"] =?>+ para "[before][after]"+ , "in the middle of a macro line" =:+ ".Oo before Oc Ns Op after" =?>+ para "[before][after]"+ , "before closing punctuation" =:+ ".Oo before Oc Ns : Op after" =?>+ para "[before]: [after]" -- mandoc: warning+ , "after closing punctuation" =:+ ".Oo before Oc : Ns Op after" =?>+ para "[before]:[after]"+ , "at the end of a macro line" =:+ T.unlines [".Oo before Oc Ns", ".Op after"] =?>+ para "[before][after]"+ , "at the end of a partial-implicit line" =:+ T.unlines [".Op before Ns", ".Op after"] =?>+ para "[before][after]"+ , "normal words" =:+ ".No no Ns ns No no" =?>+ para ("nons" <> space <> "no")+ , "opening punctuation" =:+ ".No no Ns \"(\" ns No no" =?>+ para ("no(ns" <> space <> "no")+ , "closing punctuation" =:+ ".No no \"Ns\" ns \")\" No no" =?>+ para ("nons)" <> space <> "no")+ ]+ , testGroup "spacing mode"+ [ "all text" =:+ T.unlines ["a", ".Sm off", "b c", "d", ".Sm on", "e"] =?>+ para ("a b c d e")+ , "text around macro" =:+ T.unlines ["a", ".Sm off", ".Sy b c", ".Sm on", "d"] =?>+ para ("a" <> space <> strong "bc" <> space <> "d")+ , "mulitple macros" =:+ T.unlines ["a", ".Sm off", ".Sy b Em c", ".Sm on", "d"] =?>+ para ("a" <> space <> strong "b" <> emph "c" <> space <> "d")+ , "mulitple control lines" =:+ T.unlines ["a", ".Sm off", ".Sy b", ".Em c", ".Sm on", "d"] =?>+ para ("a" <> space <> strong "b" <> emph "c" <> space <> "d")+ , "mixed control and text lines" =:+ T.unlines ["a", ".Sm off", ".Sy b", "c", ".Em d", ".Sm on", "d"] =?>+ para ("a" <> space <> strong "b" <> "c" <> emph "d" <> space <> "d")+ , "delimiters" =:+ T.unlines [".Sm off", ".Em a ", ".Em [ b | c ]", ".Sm on"] =?>+ para (emph "a" <> "[" <> emph "b" <> "|" <> emph "c" <> "]")+ ]+ , testGroup "Ap macro"+ [ "in the middle of a macro line" =:+ ".Xr mandoc 1 Ap s" =?>+ para (spanWith (cls "Xr") "mandoc(1)" <> "'s")+ -- mandoc difference: the edge case of "Ap (" tested in this mandoc regress+ -- isn't present in any actual OpenBSD base system manuals, where Ap is+ -- only ever followed by a letter. Furthermore, "Ap" is generally uncommon+ -- compared to "Ns '" (e.g. ".Xr mandoc 1 Ns 's"). I'm accepting a+ -- difference from mandoc here because correctly suppressing space after+ -- the "(" here would require more refactoring than I feel like doing at+ -- time of writing.+ -- per mandoc, should be: para (strong "bold" <> "'(" <> strong "bold")+ , "with punctuation and called macro" =:+ ".Sy bold Ap ( \"Sy\" bold" =?>+ para (strong "bold" <> "'( " <> strong "bold")+ ]+ , testGroup "Pf macro"+ [ "closing punctuation" =:+ ".Pf . right ." =?>+ para ".right."+ , "double punctuation" =:+ ".Pf . . double" =?>+ para ".. double"+ , "opening punctuation" =:+ ".Pf ( left ." =?>+ para "(left."+ , "unparsed argument" =:+ ".Pf Ar Sy gument " =?>+ para ("Ar" <> strong "gument")+ ]+ , testGroup "text production"+ [ "early NetBSD versions" =:+ T.unlines [".Nx 0.9a", "and", ".Nx 9.4b"] =?>+ para "NetBSD 0.9A and NetBSD 9.4b"+ , "with Ns" =:+ ".Ox Ns -specific" =?>+ para "OpenBSD-specific"+ , "with punctuation" =:+ ".Fx ," =?>+ para "FreeBSD,"+ , "with argument and punctuation" =:+ ".Fx 12.0 ." =?>+ para "FreeBSD 12.0."+ , "BSD alone" =:+ ".Bx ." =?>+ para "BSD."+ , "BSD with macro" =:+ ".Bx No rocks" =?>+ para "BSD rocks"+ , "BSD with version" =:+ ".Bx 4.4 ," =?>+ para "4.4BSD,"+ , "BSD with variant" =:+ ".Bx 4.3 tahoe !" =?>+ para "4.3BSD-Tahoe!"+ ]+ , testGroup "inline punctuation"+ [ testGroup "leading punctuation"+ [ "open paren" =: ".Em ( b" =?> para ("(" <> emph "b")+ , "open square bracket" =: ".Em \"[\" b" =?> para ("[" <> emph "b")+ , "pipe" =: ".Em | b" =?> para ("|" <> space <> emph "b")+ , "period" =: ".Em . b" =?> para ("." <> space <> emph "b")+ , "comma" =: ".Em , b" =?> para ("," <> space <> emph "b")+ , "semicolon" =: ".Em ; b" =?> para (";" <> space <> emph "b")+ , "colon" =: ".Em : b" =?> para (":" <> space <> emph "b")+ , "question mark" =: ".Em ? b" =?> para ("?" <> space <> emph "b")+ , "exclamation" =: ".Em ! b" =?> para ("!" <> space <> emph "b")+ , "close paren" =: ".Em ) b" =?> para (")" <> space <> emph "b")+ , "close square bracket" =: ".Em \"]\" b" =?> para ("]" <> space <> emph "b")+ ]+ , testGroup "trailing punctuation"+ [ "open paren" =: ".Em a (" =?> para (emph "a" <> space <> "(")+ , "open square bracket" =: ".Em a [" =?> para (emph "a" <> space <> "[")+ , "pipe" =: ".Em a |" =?> para (emph "a" <> space <> "|")+ , "period" =: ".Em a ." =?> para (emph "a" <> ".")+ , "comma" =: ".Em a ," =?> para (emph "a" <> ",")+ , "semicolon" =: ".Em a ;" =?> para (emph "a" <> ";")+ , "colon" =: ".Em a :" =?> para (emph "a" <> ":")+ , "question mark" =: ".Em a ?" =?> para (emph "a" <> "?")+ , "exclamation" =: ".Em a !" =?> para (emph "a" <> "!")+ , "close parens" =: ".Em a \")\"" =?> para (emph "a" <> ")")+ , "close square bracket" =: ".Em a ]" =?> para (emph "a" <> "]")+ ]+ , testGroup "middle punctuation"+ [ "open paren" =: ".Em a ( b" =?> para (mconcat [emph "a", space, "(", emph "b"])+ , "open square bracket" =: ".Em a [ b" =?> para (mconcat [emph "a", space, "[", emph "b"])+ , "pipe" =: ".Em a \"|\" b" =?> para (mconcat [emph "a", space, "|", space, emph "b"])+ , "period" =: ".Em a . b" =?> para (mconcat [emph "a", ".", space, emph "b"])+ , "comma" =: ".Em a , b" =?> para (mconcat [emph "a", ",", space, emph "b"])+ , "semicolon" =: ".Em a ; b" =?> para (mconcat [emph "a", ";", space, emph "b"])+ , "colon" =: ".Em a \":\" b" =?> para (mconcat [emph "a", ":", space, emph "b"])+ , "question mark" =: ".Em a ? b" =?> para (mconcat [emph "a", "?", space, emph "b"])+ , "exclamation" =: ".Em a ! b" =?> para (mconcat [emph "a", "!", space, emph "b"])+ , "close paren" =: ".Em a ) b" =?> para (mconcat [emph "a", ")", space, emph "b"])+ , "close square bracket" =: ".Em a ] b" =?> para (mconcat [emph "a", "]", space, emph "b"])+ ]+ ]+ ]
@@ -0,0 +1,196 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Tests.Readers.ODT+ Copyright : © 2015-2024 John MacFarlane+ 2015 Martin Linnemann+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++Tests for the ODT reader.+-}+module Tests.Readers.ODT (tests) where++import Control.Monad (liftM)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as B+import qualified Data.Map as M+import Data.Text (unpack)+import System.IO.Unsafe (unsafePerformIO)+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import qualified Text.Pandoc.UTF8 as UTF8++defopts :: ReaderOptions+defopts = def{ readerExtensions = getDefaultExtensions "odt" }++tests :: [TestTree]+tests = testsComparingToMarkdown ++ testsComparingToNative++testsComparingToMarkdown :: [TestTree]+testsComparingToMarkdown = map nameToTest namesOfTestsComparingToMarkdown+ where nameToTest name = createTest+ compareODTToMarkdown+ name+ (toODTPath name)+ (toMarkdownPath name)+ toODTPath name = "odt/odt/" ++ name ++ ".odt"+ toMarkdownPath name = "odt/markdown/" ++ name ++ ".md"++testsComparingToNative :: [TestTree]+testsComparingToNative = map nameToTest namesOfTestsComparingToNative+ where nameToTest name = createTest+ compareODTToNative+ name+ (toODTPath name)+ (toNativePath name)+ toODTPath name = "odt/odt/" ++ name ++ ".odt"+ toNativePath name = "odt/native/" ++ name ++ ".native"+++newtype NoNormPandoc = NoNormPandoc {unNoNorm :: Pandoc}+ deriving ( Show )++instance ToString NoNormPandoc where+ toString d = unpack $+ purely (writeNative def{ writerTemplate = s }) $ toPandoc d+ where s = case d of+ NoNormPandoc (Pandoc (Meta m) _)+ | M.null m -> Nothing+ | otherwise -> Just mempty -- need this for Meta output++instance ToPandoc NoNormPandoc where+ toPandoc = unNoNorm++getNoNormVia :: (a -> Pandoc) -> String -> Either PandocError a -> NoNormPandoc+getNoNormVia _ readerName (Left _) = error (readerName ++ " reader failed")+getNoNormVia f _ (Right a) = NoNormPandoc (f a)++type TestCreator = ReaderOptions+ -> FilePath -> FilePath+ -> IO (NoNormPandoc, NoNormPandoc)++compareODTToNative :: TestCreator+compareODTToNative opts odtPath nativePath = do+ nativeFile <- UTF8.toText <$> BS.readFile nativePath+ odtFile <- B.readFile odtPath+ native <- getNoNormVia id "native" <$> runIO (readNative def nativeFile)+ odt <- getNoNormVia id "odt" <$> runIO (readODT opts odtFile)+ return (odt,native)++compareODTToMarkdown :: TestCreator+compareODTToMarkdown opts odtPath markdownPath = do+ markdownFile <- UTF8.toText <$> BS.readFile markdownPath+ odtFile <- B.readFile odtPath+ markdown <- getNoNormVia id "markdown" <$>+ runIO (readMarkdown def{ readerExtensions = pandocExtensions }+ markdownFile)+ odt <- getNoNormVia id "odt" <$> runIO (readODT opts odtFile)+ return (odt,markdown)+++createTest :: TestCreator+ -> TestName+ -> FilePath -> FilePath+ -> TestTree+createTest creator name path1 path2 =+ unsafePerformIO $ liftM (test id name) (creator defopts path1 path2)++{-+--++getMedia :: FilePath -> FilePath -> IO (Maybe B.ByteString)+getMedia archivePath mediaPath = do+ zf <- B.readFile archivePath >>= return . toArchive+ return $ findEntryByPath ("Pictures/" ++ mediaPath) zf >>= (Just . fromEntry)++compareMediaPathIO :: FilePath -> MediaBag -> FilePath -> IO Bool+compareMediaPathIO mediaPath mediaBag odtPath = do+ odtMedia <- getMedia odtPath mediaPath+ let mbBS = case lookupMedia mediaPath mediaBag of+ Just (_, bs) -> bs+ Nothing -> error ("couldn't find " +++ mediaPath +++ " in media bag")+ odtBS = case odtMedia of+ Just bs -> bs+ Nothing -> error ("couldn't find " +++ mediaPath +++ " in media bag")+ return $ mbBS == odtBS++compareMediaBagIO :: FilePath -> IO Bool+compareMediaBagIO odtFile = do+ df <- B.readFile odtFile+ let (_, mb) = readODT def df+ bools <- mapM+ (\(fp, _, _) -> compareMediaPathIO fp mb odtFile)+ (mediaDirectory mb)+ return $ and bools++testMediaBagIO :: String -> FilePath -> IO TestTree+testMediaBagIO name odtFile = do+ outcome <- compareMediaBagIO odtFile+ return $ testCase name (assertBool+ ("Media didn't match media bag in file " ++ odtFile)+ outcome)++testMediaBag :: String -> FilePath -> TestTree+testMediaBag name odtFile = buildTest $ testMediaBagIO name odtFile+-}+--++++namesOfTestsComparingToMarkdown :: [ String ]+namesOfTestsComparingToMarkdown = [ "blockquote2"+ , "bold"+-- , "citation"+ , "endnote"+ , "externalLink"+ , "footnote"+ , "formula"+ , "headers"+-- , "horizontalRule"+ , "italic"+-- , "listBlocks"+ , "paragraph"+ , "strikeout"+-- , "trackedChanges"+ , "underlined"+ ]++namesOfTestsComparingToNative :: [ String ]+namesOfTestsComparingToNative = [ "blockquote"+ , "image"+ , "imageIndex"+ , "imageRelative"+ , "imageWithCaption"+ , "inlinedCode"+ , "listContinueNumbering"+ , "listContinueNumbering2"+ , "orderedListMixed"+ , "orderedListRoman"+ , "orderedListSimple"+ , "orderedListHeader"+ , "preformattedText"+ , "preformattedTextParentStyle"+ , "referenceToChapter"+ , "referenceToListItem"+ , "referenceToText"+ , "simpleTable"+ , "simpleTableWithCaption"+ , "simpleTableWithHeader"+ , "simpleTableWithMultipleHeaderRows"+ , "tab"+-- , "table"+ , "textMixedStyles"+ , "tableWithContents"+ , "tableWithSpans"+ , "unicode"+ , "unorderedList"+ , "unorderedListHeader"+ ]
@@ -1,187 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{- |- Module : Tests.Readers.Odt- Copyright : © 2015-2022 John MacFarlane- 2015 Martin Linnemann- License : GNU GPL, version 2 or above-- Maintainer : John MacFarlane <jgm@berkeley.edu>- Stability : alpha- Portability : portable--Tests for the ODT reader.--}-module Tests.Readers.Odt (tests) where--import Control.Monad (liftM)-import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as B-import qualified Data.Map as M-import Data.Text (unpack)-import System.IO.Unsafe (unsafePerformIO)-import Test.Tasty-import Tests.Helpers-import Text.Pandoc-import qualified Text.Pandoc.UTF8 as UTF8--defopts :: ReaderOptions-defopts = def{ readerExtensions = getDefaultExtensions "odt" }--tests :: [TestTree]-tests = testsComparingToMarkdown ++ testsComparingToNative--testsComparingToMarkdown :: [TestTree]-testsComparingToMarkdown = map nameToTest namesOfTestsComparingToMarkdown- where nameToTest name = createTest- compareOdtToMarkdown- name- (toOdtPath name)- (toMarkdownPath name)- toOdtPath name = "odt/odt/" ++ name ++ ".odt"- toMarkdownPath name = "odt/markdown/" ++ name ++ ".md"--testsComparingToNative :: [TestTree]-testsComparingToNative = map nameToTest namesOfTestsComparingToNative- where nameToTest name = createTest- compareOdtToNative- name- (toOdtPath name)- (toNativePath name)- toOdtPath name = "odt/odt/" ++ name ++ ".odt"- toNativePath name = "odt/native/" ++ name ++ ".native"---newtype NoNormPandoc = NoNormPandoc {unNoNorm :: Pandoc}- deriving ( Show )--instance ToString NoNormPandoc where- toString d = unpack $- purely (writeNative def{ writerTemplate = s }) $ toPandoc d- where s = case d of- NoNormPandoc (Pandoc (Meta m) _)- | M.null m -> Nothing- | otherwise -> Just mempty -- need this for Meta output--instance ToPandoc NoNormPandoc where- toPandoc = unNoNorm--getNoNormVia :: (a -> Pandoc) -> String -> Either PandocError a -> NoNormPandoc-getNoNormVia _ readerName (Left _) = error (readerName ++ " reader failed")-getNoNormVia f _ (Right a) = NoNormPandoc (f a)--type TestCreator = ReaderOptions- -> FilePath -> FilePath- -> IO (NoNormPandoc, NoNormPandoc)--compareOdtToNative :: TestCreator-compareOdtToNative opts odtPath nativePath = do- nativeFile <- UTF8.toText <$> BS.readFile nativePath- odtFile <- B.readFile odtPath- native <- getNoNormVia id "native" <$> runIO (readNative def nativeFile)- odt <- getNoNormVia id "odt" <$> runIO (readOdt opts odtFile)- return (odt,native)--compareOdtToMarkdown :: TestCreator-compareOdtToMarkdown opts odtPath markdownPath = do- markdownFile <- UTF8.toText <$> BS.readFile markdownPath- odtFile <- B.readFile odtPath- markdown <- getNoNormVia id "markdown" <$>- runIO (readMarkdown def{ readerExtensions = pandocExtensions }- markdownFile)- odt <- getNoNormVia id "odt" <$> runIO (readOdt opts odtFile)- return (odt,markdown)---createTest :: TestCreator- -> TestName- -> FilePath -> FilePath- -> TestTree-createTest creator name path1 path2 =- unsafePerformIO $ liftM (test id name) (creator defopts path1 path2)--{------getMedia :: FilePath -> FilePath -> IO (Maybe B.ByteString)-getMedia archivePath mediaPath = do- zf <- B.readFile archivePath >>= return . toArchive- return $ findEntryByPath ("Pictures/" ++ mediaPath) zf >>= (Just . fromEntry)--compareMediaPathIO :: FilePath -> MediaBag -> FilePath -> IO Bool-compareMediaPathIO mediaPath mediaBag odtPath = do- odtMedia <- getMedia odtPath mediaPath- let mbBS = case lookupMedia mediaPath mediaBag of- Just (_, bs) -> bs- Nothing -> error ("couldn't find " ++- mediaPath ++- " in media bag")- odtBS = case odtMedia of- Just bs -> bs- Nothing -> error ("couldn't find " ++- mediaPath ++- " in media bag")- return $ mbBS == odtBS--compareMediaBagIO :: FilePath -> IO Bool-compareMediaBagIO odtFile = do- df <- B.readFile odtFile- let (_, mb) = readOdt def df- bools <- mapM- (\(fp, _, _) -> compareMediaPathIO fp mb odtFile)- (mediaDirectory mb)- return $ and bools--testMediaBagIO :: String -> FilePath -> IO TestTree-testMediaBagIO name odtFile = do- outcome <- compareMediaBagIO odtFile- return $ testCase name (assertBool- ("Media didn't match media bag in file " ++ odtFile)- outcome)--testMediaBag :: String -> FilePath -> TestTree-testMediaBag name odtFile = buildTest $ testMediaBagIO name odtFile--}-------namesOfTestsComparingToMarkdown :: [ String ]-namesOfTestsComparingToMarkdown = [ "bold"--- , "citation"- , "endnote"- , "externalLink"- , "footnote"- , "formula"- , "headers"--- , "horizontalRule"- , "italic"--- , "listBlocks"- , "paragraph"- , "strikeout"--- , "trackedChanges"- , "underlined"- ]--namesOfTestsComparingToNative :: [ String ]-namesOfTestsComparingToNative = [ "blockquote"- , "image"- , "imageIndex"- , "imageWithCaption"- , "inlinedCode"- , "orderedListMixed"- , "orderedListRoman"- , "orderedListSimple"- , "orderedListHeader"- , "referenceToChapter"- , "referenceToListItem"- , "referenceToText"- , "simpleTable"- , "simpleTableWithCaption"- , "tab"--- , "table"- , "textMixedStyles"- , "tableWithContents"- , "unicode"- , "unorderedList"- , "unorderedListHeader"- ]
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Shared- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Block- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -43,7 +43,7 @@ T.unlines [ ": echo hello" , ": echo dear tester" ] =?>- codeBlockWith ("", ["example"], []) "echo hello\necho dear tester\n"+ codeBlockWith ("", [], []) "echo hello\necho dear tester\n" , "Example block surrounded by text" =: T.unlines [ "Greetings"@@ -52,7 +52,7 @@ , "Bye" ] =?> mconcat [ para "Greetings"- , codeBlockWith ("", ["example"], [])+ , codeBlockWith ("", [], []) "echo hello\necho dear tester\n" , para "Bye" ]@@ -169,26 +169,24 @@ rawBlock "html" "<samp>Hello, World!</samp>\n" , "LaTeX fragment" =:- T.unlines [ "\\begin{equation}"- , "X_i = \\begin{cases}"- , " G_{\\alpha(i)} & \\text{if }\\alpha(i-1) = \\alpha(i)\\\\"- , " C_{\\alpha(i)} & \\text{otherwise}"- , " \\end{cases}"- , "\\end{equation}"- ] =?>- rawBlock "latex"- (T.unlines [ "\\begin{equation}"- , "X_i = \\begin{cases}"- , " G_{\\alpha(i)} & \\text{if }\\alpha(i-1) =" <>- " \\alpha(i)\\\\"- , " C_{\\alpha(i)} & \\text{otherwise}"- , " \\end{cases}"- , "\\end{equation}"- ])+ "\\begin{equation}\n\+ \X_i = \\begin{cases}\n\+ \ G_{\\alpha(i)} & \\text{if }\\alpha(i-1) = \\alpha(i)\\\\\n\+ \ C_{\\alpha(i)} & \\text{otherwise}\n\+ \ \\end{cases}\n\+ \\\end{equation}"+ =?>+ para (rawInline "latex"+ "\\begin{equation}\n\+ \X_i = \\begin{cases}\n\+ \ G_{\\alpha(i)} & \\text{if }\\alpha(i-1) = \\alpha(i)\\\\\n\+ \ C_{\\alpha(i)} & \\text{otherwise}\n\+ \ \\end{cases}\n\+ \\\end{equation}") , "One-line LaTeX fragment" =: "\\begin{equation} 2 + 3 \\end{equation}" =?>- rawBlock "latex" "\\begin{equation} 2 + 3 \\end{equation}\n"+ para (rawInline "latex" "\\begin{equation} 2 + 3 \\end{equation}") , "LaTeX fragment with more arguments" =: T.unlines [ "\\begin{tikzcd}[ampersand replacement=\\&]"
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Block.CodeBlock- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -99,7 +99,7 @@ results' = "65\n" in codeBlockWith ("", classes, params) code' <>- codeBlockWith ("", ["example"], []) results'+ codeBlockWith ("", [], []) results' , "Source block with results and :exports code" =: T.unlines [ "#+begin_src emacs-lisp :exports code"@@ -126,7 +126,7 @@ , "#+RESULTS:" , ": 65" ] =?> let results' = "65\n"- in codeBlockWith ("", ["example"], []) results'+ in codeBlockWith ("", [], []) results' , "Source block with results and :exports none" =: T.unlines [ "#+begin_src emacs-lisp :exports none"@@ -171,7 +171,7 @@ , "a rule." , "#+eND_exAMPle" ] =?>- codeBlockWith ("", ["example"], [])+ codeBlockWith ("", [], []) "A chosen representation of\na rule.\n" , "Code block with caption" =:
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Block.Figure- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -15,31 +15,36 @@ import Test.Tasty (TestTree) import Tests.Helpers ((=?>)) import Tests.Readers.Org.Shared ((=:))-import Text.Pandoc.Builder (image, imageWith, para)+import Text.Pandoc.Builder ( emptyCaption, figure, figureWith, image+ , plain, simpleCaption, simpleFigure ) import qualified Data.Text as T tests :: [TestTree] tests = [ "Figure" =:- T.unlines [ "#+caption: A very courageous man."- , "#+name: goodguy"+ T.unlines [ "#+caption: A courageous man."+ , "#+name: ed" , "[[file:edward.jpg]]" ] =?>- para (image "edward.jpg" "fig:goodguy" "A very courageous man.")+ figureWith ("ed", mempty, mempty)+ (plainCaption "A courageous man.")+ (plain $ image "edward.jpg" mempty "") , "Figure with no name" =: T.unlines [ "#+caption: I've been through the desert on this" , "[[file:horse.png]]" ] =?>- para (image "horse.png" "fig:" "I've been through the desert on this")+ figure (plainCaption "I've been through the desert on this")+ (plain $ image "horse.png" "" "") , "Figure with `fig:` prefix in name" =: T.unlines [ "#+caption: Used as a metapher in evolutionary biology." , "#+name: fig:redqueen" , "[[./the-red-queen.jpg]]" ] =?>- para (image "./the-red-queen.jpg" "fig:redqueen"- "Used as a metapher in evolutionary biology.")+ figureWith ("fig:redqueen", mempty, mempty)+ (plainCaption "Used as a metapher in evolutionary biology.")+ (plain $ image "./the-red-queen.jpg" mempty "") , "Figure with HTML attributes" =: T.unlines [ "#+caption: mah brain just explodid"@@ -48,28 +53,33 @@ , "[[file:lambdacat.jpg]]" ] =?> let kv = [("style", "color: blue"), ("role", "button")]- name = "fig:lambdacat"- caption = "mah brain just explodid"- in para (imageWith (mempty, mempty, kv) "lambdacat.jpg" name caption)+ name = "lambdacat"+ capt = plain "mah brain just explodid"+ in figureWith (name, mempty, kv) (simpleCaption capt)+ (plain $ image "lambdacat.jpg" mempty "") , "LaTeX attributes are ignored" =: T.unlines [ "#+caption: Attribute after caption" , "#+attr_latex: :float nil" , "[[file:test.png]]" ] =?>- para (image "test.png" "fig:" "Attribute after caption")+ simpleFigure "Attribute after caption"+ "test.png" "" , "Labelled figure" =: T.unlines [ "#+caption: My figure" , "#+label: fig:myfig" , "[[file:blub.png]]" ] =?>- let attr = ("fig:myfig", mempty, mempty)- in para (imageWith attr "blub.png" "fig:" "My figure")+ figureWith ("fig:myfig", mempty, mempty)+ (simpleCaption $ plain "My figure")+ (plain (image "blub.png" "" "")) , "Figure with empty caption" =: T.unlines [ "#+caption:" , "[[file:guess.jpg]]" ] =?>- para (image "guess.jpg" "fig:" "")+ figure emptyCaption (plain (image "guess.jpg" "" "")) ]+ where+ plainCaption = simpleCaption . plain
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Block.Header- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -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" =:
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Block.Header- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Block.Table- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Directive- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -188,7 +188,7 @@ T.unlines [ "#+OPTIONS: tex:t" , "Hello \\emph{Name}" ] =?>- para ("Hello" <> space <> emph "Name")+ para ("Hello" <> space <> rawInline "latex" "\\emph{Name}") , "Alpha" =: T.unlines [ "#+OPTIONS: tex:t"@@ -197,15 +197,15 @@ para "α" , "equation environment" =:- T.unlines [ "#+OPTIONS: tex:t"- , "\\begin{equation}"- , "f(x) = x^2"- , "\\end{equation}"- ] =?>- rawBlock "latex" (T.unlines [ "\\begin{equation}"- , "f(x) = x^2"- , "\\end{equation}"- ])+ "#+OPTIONS: tex:t\n\+ \\\begin{equation}\n\+ \f(x) = x^2\n\+ \\\end{equation}"+ =?>+ para (rawInline "latex"+ "\\begin{equation}\n\+ \f(x) = x^2\n\+ \\\end{equation}") ] , testGroup "Ignore LaTeX fragments"@@ -227,7 +227,7 @@ , "f(x) = x^2" , "\\end{equation}" ] =?>- (mempty :: Blocks)+ (para mempty) ] , testGroup "Verbatim LaTeX"
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Inline- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -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")@@ -96,6 +100,14 @@ "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" =?> para ("line" <> linebreak <> "break")@@ -104,8 +116,10 @@ "[fn::Schreib mir eine E-Mail]" =?> para (note $ para "Schreib mir eine E-Mail") - , "Markup-chars not occurring on word break are symbols" =:- T.unlines [ "this+that+ +so+on"+ , "By default, markup-chars not occurring on word break are symbols" =:+ T.unlines [ "#+pandoc-emphasis-pre:"+ , "#+pandoc-emphasis-post:"+ , "this+that+ +so+on" , "seven*eight* nine*" , "+not+funny+" ] =?>@@ -118,12 +132,13 @@ para (spcSep [ "//", "**", "__", "<>", "==", "~~", "$$" ]) , "Adherence to Org's rules for markup borders" =:- "/t/& a/ / ./r/ (*l*) /e/! /b/." =?>+ "/t/& a/ / ./r/ (*l*) /e/! ze\x200b/r/\x200bo /b/." =?> para (spcSep [ emph $ "t/&" <> space <> "a" , "/" , "./r/" , "(" <> strong "l" <> ")" , emph "e" <> "!"+ , "ze\x200b" <> emph "r" <> "\x200bo" , emph "b" <> "." ]) @@ -135,6 +150,10 @@ "/nada /" =?> para "/nada /" + , "Zero width spaces are forbidden border chars" =:+ "/emph\x200b/asis" =?>+ para "/emph\x200b/asis"+ , "Markup should work properly after a blank line" =: T.unlines ["foo", "", "/bar/"] =?> para (text "foo") <>@@ -335,7 +354,7 @@ , "Inline LaTeX command with spaces" =: "\\emph{Emphasis mine}" =?>- para (emph "Emphasis mine")+ para (rawInline "latex" "\\emph{Emphasis mine}") , "Inline math symbols" =: "\\tau \\oplus \\alpha" =?>@@ -386,6 +405,11 @@ , "{{{HELLO()}}}" ] =?> para "Foo Bar"+ , "Macro called with an escaped comma" =:+ T.unlines [ "#+MACRO: HELLO Foo $1"+ , "{{{HELLO(moin\\, niom)}}}"+ ] =?>+ para "Foo moin, niom" , testGroup "Citations" Citation.tests , testGroup "Footnotes" Note.tests
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Inline.Citation- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -201,13 +201,6 @@ , "LaTeX citation" =: "\\cite{Coffee}" =?>- let citation = Citation- { citationId = "Coffee"- , citationPrefix = []- , citationSuffix = []- , citationMode = NormalCitation- , citationNoteNum = 0- , citationHash = 0}- in (para . cite [citation] $ rawInline "latex" "\\cite{Coffee}")+ para (rawInline "latex" "\\cite{Coffee}") ]
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Inline.Note- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Inline.Smart- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -46,6 +46,10 @@ , test orgSmart "Dashes are allowed at the borders of emphasis'" ("/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/'" =?>
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Meta- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable @@ -208,12 +208,19 @@ ] , testGroup "emphasis config"- [ "Changing pre and post chars for emphasis" =:- T.unlines [ "#+pandoc-emphasis-pre: \"[)\""- , "#+pandoc-emphasis-post: \"]\\n\""- , "([/emph/])*foo*"+ [ "Changing pre chars for emphasis" =:+ T.unlines [ "#+pandoc-emphasis-pre: \"[)$a1%\""+ , "[/emph/.)*strong*.a~code~" ] =?>- para ("([" <> emph "emph" <> "])" <> strong "foo")+ para ("[" <> emph "emph" <> ".)" <> strong "strong" <>+ ".a" <> code "code")++ , "Changing post chars for emphasis" =:+ T.unlines [ "#+pandoc-emphasis-post: \"(]$a1%\""+ , "/emph/('*strong*]'~code~a"+ ] =?>+ para (emph "emph" <> "('" <> strong "strong" <> "]'" <>+ code "code" <> "a") , "setting an invalid value restores the default" =: T.unlines [ "#+pandoc-emphasis-pre: \"[\""
@@ -1,10 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Org.Shared- Copyright : © 2014-2022 Albert Krewinkel+ Copyright : © 2014-2024 Albert Krewinkel License : GNU GPL, version 2 or above - Maintainer : Albert Krewinkel <albert@zeitkraut.de>+ Maintainer : Albert Krewinkel <albert+pandoc@tarleb.com> Stability : alpha Portability : portable
@@ -0,0 +1,187 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Tests.Readers.Pod+ Copyright : © 2024 Evan Silberman+ License : GNU GPL, version 2 or above++ Maintainer : + Stability : alpha+ Portability : portable++Tests for the Pod reader.+-}++module Tests.Readers.Pod (tests) where++import Data.Text (Text, pack)+import Test.Tasty+import Test.Tasty.HUnit (HasCallStack)+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++pod :: Text -> Pandoc+pod t = (purely $ readPod def) ("=pod\n\n" <> t <> "\n\n=cut\n")++manLink :: Text -> Maybe Text -> Inlines -> Inlines+manLink nm Nothing = linkWith (mempty, mempty, [("manual", nm)]) "" ""+manLink nm (Just sc) = linkWith (mempty, mempty, [("manual", nm), ("section", sc)]) "" ""++bogusEntity :: String -> TestTree+bogusEntity t = t =: "E<" <> pack t <> ">" =?> para ("E<" <> str (pack t) <> ">")++infix 4 =:+(=:) :: (ToString c, HasCallStack)+ => String -> (Text, c) -> TestTree+(=:) = test pod++tests :: [TestTree]+tests = [+ testGroup "inlines"+ [ "code with nested inlines" =:+ "C</I<A> (*PRUNE) I<B>/>" =?>+ para (code "/A (*PRUNE) B/")+ , "compact in compact" =:+ "I<B<strong> emphasis>" =?>+ para (emph $ (strong "strong") <> " emphasis")+ , "expanded in compact" =:+ "I<B<< strong >> emphasis>" =?>+ para (emph $ (strong "strong") <> " emphasis")+ , "compact in expanded" =:+ "I<<< B<strong> emphasis >>>" =?>+ para (emph $ (strong "strong") <> " emphasis")+ , "expanded in expanded" =:+ "I<<< B<<< strong >>> emphasis >>>" =?>+ para (emph $ (strong "strong") <> " emphasis")+ ]+ , testGroup "links"+ [ testGroup "compact"+ [ "URL" =:+ "L<https://example.org>" =?>+ para (link "https://example.org" "" "https://example.org")+ , "URL with link text" =:+ "L<link|https://example.org/index.html>" =?>+ para (link "https://example.org/index.html" "" "link")+ , "perl manual" =:+ "L<Foo::Bar>" =?>+ para (manLink "Foo::Bar" Nothing "Foo::Bar")+ , "manual with quoted section" =:+ "L<crontab(5)/\"DESCRIPTION\">" =?>+ para (manLink "crontab(5)" (Just "DESCRIPTION") (doubleQuoted "DESCRIPTION" <> " in crontab(5)"))+ , "manual with section and formatted link text" =:+ "L<B<< extravagant >> link|HTTP::Simple/is_info>" =?>+ para (manLink "HTTP::Simple" (Just "is_info") (strong "extravagant" <> " link"))+ , "internal link" =:+ "L</section name>" =?>+ para (link "#section-name" "" (doubleQuoted "section name"))+ , "internal link with formatting" =:+ "L</The C<pod2html> command>" =?>+ para (link "#the-pod2html-command" "" (doubleQuoted ("The " <> code "pod2html" <> " command")))+ , "link with angle bracket" =:+ "L<m<>" =?>+ para (manLink "m<" Nothing "m<")+ , "empty name" =:+ "L<|https://example.org>" =?>+ para (link "https://example.org" "" mempty)+ ]+ , testGroup "expanded"+ [ "URL" =:+ "L<< https://example.org >>" =?>+ para (link "https://example.org" "" "https://example.org")+ , "URL with link text" =:+ "L<< link|https://example.org/index.html >>" =?>+ para (link "https://example.org/index.html" "" "link")+ , "perl manual" =:+ "L<<< Foo::Bar >>>" =?>+ para (manLink "Foo::Bar" Nothing "Foo::Bar")+ , "manual with quoted section" =:+ "L<< crontab(5)/\"DESCRIPTION\" >>" =?>+ para (manLink "crontab(5)" (Just "DESCRIPTION") (doubleQuoted "DESCRIPTION" <> " in crontab(5)"))+ , "manual with section and formatted link text" =:+ "L<< B<< extravagant >> link|HTTP::Simple/is_info >>" =?>+ para (manLink "HTTP::Simple" (Just "is_info") (strong "extravagant" <> " link"))+ , "internal link" =:+ "L<< /section name >>" =?>+ para (link "#section-name" "" (doubleQuoted "section name"))+ , "internal link with formatting" =:+ "L<<<<< /The C<pod2html> command >>>>>" =?>+ para (link "#the-pod2html-command" "" (doubleQuoted ("The " <> code "pod2html" <> " command")))+ , "link with angle bracket" =:+ "L<< m< >>" =?>+ para (manLink "m<" Nothing "m<")+ , "empty name" =:+ "L<< |https://example.org >>" =?>+ para (link "https://example.org" "" mempty)+ ]+ ]+ , testGroup "entities"+ [ testGroup "required"+ [ "quot" =:+ "E<quot>" =?>+ para "\""+ , "amp" =:+ "E<amp>" =?>+ para "&"+ , "apos" =:+ "E<apos>" =?>+ para "'"+ , "lt" =:+ "E<lt>" =?>+ para "<"+ , "gt" =:+ "E<gt>" =?>+ para ">"+ , "sol" =:+ "E<sol>" =?>+ para "/"+ , "verbar" =:+ "E<verbar>" =?>+ para "|"+ , "lchevron" =:+ "E<lchevron>" =?>+ para "«"+ , "rchevron" =:+ "E<rchevron>" =?>+ para "»"+ ]+ , testGroup "html"+ [ "trade" =:+ "E<trade>" =?>+ para "™"+ , "ccaron" =:+ "E<ccaron>" =?>+ para "č"+ , "cent" =:+ "E<cent>" =?>+ para "¢"+ ]+ , testGroup "numeric"+ [ "decimal" =:+ "E<162>" =?>+ para "¢"+ , "octal" =:+ "E<0242>" =?>+ para "¢"+ , "hexadecimal" =:+ "E<0xA2>" =?>+ para "¢"+ , "hexadecimal variant" =:+ "E<0x00A2>" =?>+ para "¢"+ , "actually decimal" =:+ "E<099>" =?>+ para "c"+ ]+ , testGroup "bogus"+ [ bogusEntity "0XA2"+ , bogusEntity "not a real entity"+ , bogusEntity "162 1"+ , bogusEntity "99 bottles of beer"+ , bogusEntity "0xhh"+ , bogusEntity "077x"+ , bogusEntity "0x63 skidoo"+ , bogusEntity "trade;"+ ]+ ]+ ]
@@ -0,0 +1,48 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Tests.Readers.Pptx+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++Tests for the PPTX reader.+-}+module Tests.Readers.Pptx (tests) where++import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as B+import Test.Tasty+import Test.Tasty.Golden.Advanced+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.UTF8 as UTF8++defopts :: ReaderOptions+defopts = def{ readerExtensions = getDefaultExtensions "pptx" }++testCompare :: String -> FilePath -> FilePath -> TestTree+testCompare = testCompareWithOpts defopts++testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree+testCompareWithOpts opts testName pptxFP nativeFP =+ goldenTest+ testName+ (do nf <- UTF8.toText <$> BS.readFile nativeFP+ runIOorExplode (readNative def nf))+ (do df <- B.readFile pptxFP+ runIOorExplode (readPptx opts df))+ (nativeDiff nativeFP)+ (\a -> runIOorExplode (writeNative def{ writerTemplate = Just mempty} a)+ >>= BS.writeFile nativeFP . UTF8.fromText)++tests :: [TestTree]+tests = [ testGroup "basic"+ [ testCompare+ "text extraction"+ "pptx-reader/basic.pptx"+ "pptx-reader/basic.native"+ ]+ ]
@@ -2,7 +2,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | Module : Tests.Readers.RST- Copyright : © 2006-2022 John MacFarlane+ Copyright : © 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley.edu>@@ -50,13 +50,13 @@ , " on two lines" ] =?> doc (para "para" <>- definitionList [ (str "Hostname", [para "media08"])- , (text "IP address", [para "10.0.0.19"])- , (str "Size", [para "3ru"])- , (str "Version", [para "1"])- , (str "Indentation", [para "Since the field marker may be quite long, the second\nand subsequent lines of the field body do not have to line up\nwith the first line, but they must be indented relative to the\nfield name marker, and they must line up with each other."])- , (text "Parameter i", [para "integer"])- , (str "Final", [para "item\non two lines"])+ definitionList [ (str "Hostname", [plain "media08"])+ , (text "IP address", [plain "10.0.0.19"])+ , (str "Size", [plain "3ru"])+ , (str "Version", [plain "1"])+ , (str "Indentation", [plain "Since the field marker may be quite long, the second\nand subsequent lines of the field body do not have to line up\nwith the first line, but they must be indented relative to the\nfield name marker, and they must line up with each other."])+ , (text "Parameter i", [plain "integer"])+ , (str "Final", [plain "item\non two lines"]) ]) , "metadata" =: T.unlines [ "====="@@ -69,7 +69,7 @@ , ":Version: 1" ] =?>- setMeta "version" (para "1") (setMeta "title" ("Title" :: Inlines)+ setMeta "version" (str "1") (setMeta "title" ("Title" :: Inlines) $ setMeta "subtitle" ("Subtitle" :: Inlines) $ doc mempty) , "with inline markup" =: T.unlines@@ -87,10 +87,10 @@ ] =?> setMeta "date" (str "today") (doc- $ definitionList [ (emph "one", [para "emphasis"])- , (link "http://example.com" "" "two", [para "reference"])- , (link "http://example.org" "" "three", [para "another one"])- , (code "four", [para "literal"])+ $ definitionList [ (emph "one", [plain "emphasis"])+ , (link "http://example.com" "" "two", [plain "reference"])+ , (link "http://example.org" "" "three", [plain "another one"])+ , (code "four", [plain "literal"]) ]) ] , "URLs with following punctuation" =:
@@ -1,6 +1,6 @@ {- | Module : Tests.Readers.RTF- Copyright : © 2021-2022 John MacFarlane+ Copyright : © 2021-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : jgm@berkeley.edu@@ -39,4 +39,3 @@ , "table_simple" , "table_error_codes" ]-
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Readers.Txt2Tags- Copyright : © 2014-2022 John MacFarlane,+ Copyright : © 2014-2024 John MacFarlane, © 2014 Matthew Pickering License : GNU GPL, version 2 or above
@@ -0,0 +1,48 @@+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Tests.Readers.Xlsx+ Copyright : © 2025 Anton Antic+ License : GNU GPL, version 2 or above++ Maintainer : Anton Antic <anton@everworker.ai>+ Stability : alpha+ Portability : portable++Tests for the XLSX reader.+-}+module Tests.Readers.Xlsx (tests) where++import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as B+import Test.Tasty+import Test.Tasty.Golden.Advanced+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.UTF8 as UTF8++defopts :: ReaderOptions+defopts = def{ readerExtensions = getDefaultExtensions "xlsx" }++testCompare :: String -> FilePath -> FilePath -> TestTree+testCompare = testCompareWithOpts defopts++testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree+testCompareWithOpts opts testName xlsxFP nativeFP =+ goldenTest+ testName+ (do nf <- UTF8.toText <$> BS.readFile nativeFP+ runIOorExplode (readNative def nf))+ (do df <- B.readFile xlsxFP+ runIOorExplode (readXlsx opts df))+ (nativeDiff nativeFP)+ (\a -> runIOorExplode (writeNative def{ writerTemplate = Just mempty} a)+ >>= BS.writeFile nativeFP . UTF8.fromText)++tests :: [TestTree]+tests = [ testGroup "basic"+ [ testCompare+ "sheet extraction"+ "xlsx-reader/basic.xlsx"+ "xlsx-reader/basic.native"+ ]+ ]
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {- | Module : Tests.Shared- Copyright : © 2006-2022 John MacFarlane+ Copyright : © 2006-2024 John MacFarlane License : GNU GPL, version 2 or above Maintainer : John MacFarlane <jgm@berkeley@edu>@@ -51,7 +51,8 @@ in d' == makeSections False Nothing d' givesTOC :: String -> (Blocks, Blocks) -> TestTree-givesTOC desc (blocks, toc) = test (toTableOfContents def) desc (toList blocks, head . toList $ toc)+givesTOC desc (blocks, toc) =+ test (singleton . toTableOfContents def) desc (toList blocks, toc) linkId :: T.Text -> T.Text -> T.Text -> Inlines -> Inlines linkId lId = linkWith (lId,[],[])@@ -73,11 +74,11 @@ bulletList [plain "H1a" <> bulletList [plain "H2"]] , givesTOC "only referenced headers" $ header 1 "H1a" <> headerId "h2" 2 "H2" =?>- bulletList [plain "H1a" <> + bulletList [plain "H1a" <> bulletList [plain $ linkId "toc-h2" "#h2" "" "H2"]] , givesTOC "section id used as backup" $ divWith ("sec",["section"],[]) (header 1 "H1") =?>- bulletList [plain $ linkId "toc-sec" "#sec" "" "H1"] + bulletList [plain $ linkId "toc-sec" "#sec" "" "H1"] ] testCollapse :: [TestTree]
@@ -9,10 +9,10 @@ import Text.Pandoc.Builder asciidoc :: (ToPandoc a) => a -> String-asciidoc = unpack . purely (writeAsciiDoc def) . toPandoc+asciidoc = unpack . purely (writeAsciiDocLegacy def) . toPandoc asciidoctor :: (ToPandoc a) => a -> String-asciidoctor = unpack . purely (writeAsciiDoctor def) . toPandoc+asciidoctor = unpack . purely (writeAsciiDoc def) . toPandoc testAsciidoc :: (ToString a, ToPandoc a) => String@@ -36,7 +36,7 @@ "__foo__bar" , testAsciidoc "emph quoted" $ para (doubleQuoted (emph (text "foo"))) =?>- "``__foo__''"+ "``_foo_''" , testAsciidoc "strong word before" $ para (text "foo" <> strong (text "bar")) =?> "foo**bar**"@@ -45,7 +45,7 @@ "**foo**bar" , testAsciidoc "strong quoted" $ para (singleQuoted (strong (text "foo"))) =?>- "`**foo**'"+ "`*foo*'" ] , testGroup "blocks" [ testAsciidoc "code block without line numbers" $@@ -62,6 +62,19 @@ , "foo" , "----" ]+ , testAsciidoc "sidebar block" $+ divWith ("sidebar_id", ["sidebar"], [])+ (divWith ("", ["title"], [])+ (plain "Sidebar Title")+ <> para "Sidebar paragraph"+ ) =?> unlines+ [ "[[sidebar_id]]"+ , "[SIDEBAR]"+ , ".Sidebar Title"+ , "****"+ , "Sidebar paragraph"+ , "****"+ ] ] , testGroup "tables" [ testAsciidoc "empty cells" $@@ -93,4 +106,3 @@ ] ] ]-
@@ -0,0 +1,355 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-}++module Tests.Writers.BBCode (tests) where++import Data.Maybe (isNothing)+import Data.Text as T+import Test.Tasty+import Test.Tasty.HUnit (HasCallStack)+import Test.Tasty.QuickCheck+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder+import Text.Pandoc.Shared (tshow)+import Text.Read (readMaybe)++bbcodeDefault+ , bbcodeSteam+ , bbcodePhpBB+ , bbcodeFluxBB+ , bbcodeHubzilla+ , bbcodeXenforo ::+ (ToPandoc a) => a -> Text+bbcodeDefault = purely (writeBBCode def) . toPandoc+bbcodeSteam = purely (writeBBCodeSteam def) . toPandoc+bbcodePhpBB = purely (writeBBCodePhpBB def) . toPandoc+bbcodeFluxBB = purely (writeBBCodeFluxBB def) . toPandoc+bbcodeHubzilla = purely (writeBBCodeHubzilla def) . toPandoc+bbcodeXenforo = purely (writeBBCodeXenforo def) . toPandoc++infix 4 =:, `steam`, `phpbb`, `fluxbb`, `hubzilla`, `xenforo`+(=:)+ , steam+ , phpbb+ , fluxbb+ , hubzilla+ , xenforo ::+ (ToString a, ToPandoc a, HasCallStack) =>+ String ->+ (a, Text) ->+ TestTree+(=:) = test bbcodeDefault+steam = test bbcodeSteam+phpbb = test bbcodePhpBB+fluxbb = test bbcodeFluxBB+hubzilla = test bbcodeHubzilla+xenforo = test bbcodeXenforo++spanClasses :: [Text] -> Inlines -> Inlines+spanClasses cls = spanWith ("", cls, [])++spanAttrs :: [(Text, Text)] -> Inlines -> Inlines+spanAttrs kvList = spanWith ("", [], kvList)++divClasses :: [Text] -> Blocks -> Blocks+divClasses cls = divWith ("", cls, [])++divAttrs :: [(Text, Text)] -> Blocks -> Blocks+divAttrs kvList = divWith ("", [], kvList)++tests :: [TestTree]+tests =+ [ testGroup+ "spans classes"+ [ "left" =: spanClasses ["left"] "foo" =?> "foo"+ , "center" =: spanClasses ["center"] "foo" =?> "foo"+ , "right" =: spanClasses ["right"] "foo" =?> "foo"+ , "spoiler" =: spanClasses ["spoiler"] "foo" =?> "foo"+ ]+ , testGroup+ "spans attributes"+ [ testProperty "incorrect size ignored" . property $ do+ n <- arbitrary @String+ let nInt = readMaybe @Int n+ let actual = bbcodeDefault (spanAttrs [("size", T.pack n)] "foo")+ pure $ isNothing nInt ==> actual === "foo"+ , testProperty "size<=0 ignored" . property $ do+ NonPositive n <- arbitrary @(NonPositive Int)+ let actual = bbcodeDefault (spanAttrs [("size", tshow n)] "foo")+ pure $ actual === "foo"+ , testProperty "size>0" . property $ do+ Positive n <- arbitrary @(Positive Int)+ let actual = bbcodeDefault (spanAttrs [("size", tshow n)] "foo")+ let expected = "[size=" <> tshow n <> "]" <> "foo[/size]"+ pure $ actual === expected+ , "size=20" =: spanAttrs [("size", "20")] "foo" =?> "[size=20]foo[/size]"+ , "color=#AAAAAA"+ =: spanAttrs [("color", "#AAAAAA")] "foo"+ =?> "[color=#AAAAAA]foo[/color]"+ , "spoiler ignored"+ =: spanAttrs [("spoiler", "name with spaces and ]brackets[]")] "foo"+ =?> "foo"+ ]+ , testGroup+ "divs classes"+ [ "left"+ =: divClasses ["left"] (para "foo")+ =?> "[left]foo[/left]"+ , "center"+ =: divClasses ["center"] (para "foo")+ =?> "[center]foo[/center]"+ , "right"+ =: divClasses ["right"] (para "foo")+ =?> "[right]foo[/right]"+ , "spoiler"+ =: divClasses ["spoiler"] (para "foo")+ =?> "[spoiler]foo[/spoiler]"+ ]+ , testGroup+ "divs attributes"+ [ testProperty "incorrect size ignored" . property $ do+ n <- arbitrary @String+ let nInt = readMaybe @Int n+ let actual = bbcodeDefault (divAttrs [("size", T.pack n)] $ para "foo")+ pure $ isNothing nInt ==> actual === "foo"+ , testProperty "size<=0 ignored" . property $ do+ NonPositive n <- arbitrary @(NonPositive Int)+ let actual = bbcodeDefault (divAttrs [("size", tshow n)] $ para "foo")+ pure $ actual === "foo"+ , testProperty "size>0" . property $ do+ Positive n <- arbitrary @(Positive Int)+ let actual = bbcodeDefault (divAttrs [("size", tshow n)] $ para "foo")+ let expected = "[size=" <> tshow n <> "]" <> "foo[/size]"+ pure $ actual === expected+ , "size=20"+ =: divAttrs [("size", "20")] (para "foo")+ =?> "[size=20]foo[/size]"+ , "color=#AAAAAA"+ =: divAttrs [("color", "#AAAAAA")] (para "foo")+ =?> "[color=#AAAAAA]foo[/color]"+ , "spoiler"+ =: divAttrs+ [("spoiler", "name with spaces and ]brackets[]")]+ (para "foo")+ =?> "[spoiler=name with spaces and brackets]foo[/spoiler]"+ ]+ , testGroup+ "default flavor"+ [ "link"+ =: link "https://example.com" "title" "label"+ =?> "[url=https://example.com]label[/url]"+ , "autolink"+ =: link "https://example.com" "title" "https://example.com"+ =?> "[url]https://example.com[/url]"+ , "email autolink"+ =: link+ "mailto:example@example.com"+ "title"+ "example@example.com"+ =?> "[email]example@example.com[/email]"+ , "named email"+ =: link "mailto:example@example.com" "title" "example email"+ =?> "[email=example@example.com]example email[/email]"+ , "h0" =: header 0 "heading 0" =?> "[u][b]heading 0[/b][/u]"+ , "h1" =: header 1 "heading 1" =?> "[u][b]heading 1[/b][/u]"+ , "h2" =: header 2 "heading 2" =?> "[b]heading 2[/b]"+ , "h3" =: header 3 "heading 3" =?> "[u]heading 3[/u]"+ , "h4" =: header 4 "heading 4" =?> "heading 4"+ , "h5" =: header 5 "heading 5" =?> "heading 5"+ ]+ , testGroup+ "steam"+ [ test bbcodeSteam "dename spoiler" $+ divAttrs [("spoiler", "bar")] (para "foo")+ =?> ("[spoiler]foo[/spoiler]" :: Text)+ , testProperty "ordered list styleless" . property $ do+ let listItems = [para "foo", para "bar", para "baz"]+ attrsRand <- (,,) <$> arbitrary <*> arbitrary <*> arbitrary+ let actual = bbcodeSteam $ orderedListWith attrsRand listItems+ let expected = "[olist]\n[*]foo\n[*]bar\n[*]baz\n[/olist]"+ pure $ actual === expected+ , "h0" `steam` header 0 "heading 0" =?> "[h1]heading 0[/h1]"+ , "h1" `steam` header 1 "heading 1" =?> "[h1]heading 1[/h1]"+ , "h2" `steam` header 2 "heading 2" =?> "[h2]heading 2[/h2]"+ , "h3" `steam` header 3 "heading 3" =?> "[h3]heading 3[/h3]"+ , "h4" `steam` header 4 "heading 4" =?> "[h3]heading 4[/h3]"+ , "code"+ `steam` codeWith ("id", ["haskell"], []) "map (2^) [1..5]"+ =?> "[noparse]map (2^) [1..5][/noparse]"+ ]+ , testGroup+ "phpBB"+ [ "image"+ `phpbb` imageWith+ ("id", [], [("width", "100")])+ "https://example.com"+ "title"+ "alt text"+ =?> "[img]https://example.com[/img]"+ ]+ , testGroup+ "FluxBB"+ [ "image"+ `fluxbb` imageWith+ ("id", [], [("width", "100")])+ "https://example.com"+ "title"+ "alt text"+ =?> "[img=alt text]https://example.com[/img]"+ , testProperty "ordered list" . property $ do+ let listItems = [para "foo", para "bar", para "baz"]+ attrsRand <- (,,) <$> arbitrary <*> arbitrary <*> arbitrary+ let actual = bbcodeFluxBB $ orderedListWith attrsRand listItems+ let opening = case attrsRand of+ (_, LowerAlpha, _) -> "[list=a]"+ (_, UpperAlpha, _) -> "[list=a]"+ _ -> "[list=1]"+ let expected = opening <> "\n[*]foo\n[*]bar\n[*]baz\n[/list]"+ pure $ actual === expected+ , "ulist > BlockQuote not rendered"+ `fluxbb` bulletList [blockQuote (para "foo") <> para "bar"]+ =?> "[list]\n[*]bar\n[/list]"+ , "code block"+ `fluxbb` codeBlockWith+ ("id", ["haskell"], [])+ ( T.intercalate "\n" $+ [ "vals ="+ , " take 10"+ , " . filter (\\x -> (x - 5) `mod` 3 == 0)"+ , " $ map (2 ^) [1 ..]"+ ]+ )+ =?> T.intercalate+ "\n"+ [ "[code]vals ="+ , " take 10"+ , " . filter (\\x -> (x - 5) `mod` 3 == 0)"+ , " $ map (2 ^) [1 ..]"+ , "[/code]"+ ]+ ]+ , testGroup+ "Hubzilla"+ [ "unordered list"+ `hubzilla` bulletList [para "foo", para "bar", para "baz"]+ =?> "[ul]\n[*]foo\n[*]bar\n[*]baz\n[/ul]"+ , testProperty "ordered list" . property $ do+ let listItems = [para "foo", para "bar", para "baz"]+ attrsRand <- (,,) <$> arbitrary <*> arbitrary <*> arbitrary+ let actual = bbcodeHubzilla $ orderedListWith attrsRand listItems+ let (opening, closing) = case attrsRand of+ (_, Decimal, _) -> ("[list=1]", "[/list]")+ (_, DefaultStyle, _) -> ("[ol]", "[/ol]")+ (_, Example, _) -> ("[ol]", "[/ol]")+ (_, LowerAlpha, _) -> ("[list=a]", "[/list]")+ (_, UpperAlpha, _) -> ("[list=A]", "[/list]")+ (_, LowerRoman, _) -> ("[list=i]", "[/list]")+ (_, UpperRoman, _) -> ("[list=I]", "[/list]")+ let expected =+ opening <> "\n[*]foo\n[*]bar\n[*]baz\n" <> closing+ pure $ actual === expected+ , "definition list"+ `hubzilla` definitionList+ [ ("term_foo", [para "def_foo1", para "def_foo2"])+ , ("term_bar", [para "def_bar1", para "def_bar2"])+ , ("term_baz", [para "def_baz1", para "def_baz2"])+ ]+ =?> mconcat+ [ "[dl terms=\"b\"]\n"+ , "[*= term_foo]\ndef_foo1\ndef_foo2\n"+ , "[*= term_bar]\ndef_bar1\ndef_bar2\n"+ , "[*= term_baz]\ndef_baz1\ndef_baz2\n"+ , "[/dl]"+ ]+ , "h0" `hubzilla` header 0 "heading 0" =?> "[h1]heading 0[/h1]"+ , "h1" `hubzilla` header 1 "heading 1" =?> "[h1]heading 1[/h1]"+ , "h2" `hubzilla` header 2 "heading 2" =?> "[h2]heading 2[/h2]"+ , "h3" `hubzilla` header 3 "heading 3" =?> "[h3]heading 3[/h3]"+ , "h4" `hubzilla` header 4 "heading 4" =?> "[h4]heading 4[/h4]"+ , "h5" `hubzilla` header 5 "heading 5" =?> "[h5]heading 5[/h5]"+ , "h6" `hubzilla` header 6 "heading 6" =?> "[h6]heading 6[/h6]"+ , "h7" `hubzilla` header 7 "heading 7" =?> "[h6]heading 7[/h6]"+ , "link"+ `hubzilla` link "https://example.com" "title" "label"+ =?> "[url=https://example.com]label[/url]"+ , "autolink"+ `hubzilla` link "https://example.com" "title" "https://example.com"+ =?> "[url]https://example.com[/url]"+ , "email autolink"+ `hubzilla` link+ "mailto:example@example.com"+ "title"+ "example@example.com"+ =?> "[url=mailto:example@example.com]example@example.com[/url]"+ , "named email"+ `hubzilla` link "mailto:example@example.com" "title" "example email"+ =?> "[url=mailto:example@example.com]example email[/url]"+ , "inline code"+ `hubzilla` ( "inline code: "+ <> codeWith ("id", ["haskell"], []) "map (2^) [1..5]"+ )+ =?> "inline code: [code]map (2^) [1..5][/code]"+ , "font"+ `hubzilla` divAttrs [("font", "serif")] (para "foo")+ =?> "[font=serif]foo[/font]"+ ]+ , testGroup+ "xenForo"+ [ "unordered list"+ `xenforo` bulletList [para "foo", para "bar", para "baz"]+ =?> "[list]\n[*]foo\n[*]bar\n[*]baz\n[/list]"+ , testProperty "ordered list styleless" . property $ do+ let listItems = [para "foo", para "bar", para "baz"]+ attrsRand <- (,,) <$> arbitrary <*> arbitrary <*> arbitrary+ let actual = bbcodeXenforo $ orderedListWith attrsRand listItems+ let expected = "[list=1]\n[*]foo\n[*]bar\n[*]baz\n[/list]"+ pure $ actual === expected+ , "h0" `xenforo` header 0 "heading 0" =?> "[heading=1]heading 0[/heading]"+ , "h1" `xenforo` header 1 "heading 1" =?> "[heading=1]heading 1[/heading]"+ , "h2" `xenforo` header 2 "heading 2" =?> "[heading=2]heading 2[/heading]"+ , "h3" `xenforo` header 3 "heading 3" =?> "[heading=3]heading 3[/heading]"+ , "h4" `xenforo` header 4 "heading 4" =?> "[heading=4]heading 4[/heading]"+ , "link"+ `xenforo` link "https://example.com" "title" "label"+ =?> "[url=https://example.com]label[/url]"+ , "autolink"+ `xenforo` link "https://example.com" "title" "https://example.com"+ =?> "[url]https://example.com[/url]"+ , "email autolink"+ `xenforo` link+ "mailto:example@example.com"+ "title"+ "example@example.com"+ =?> "[email]example@example.com[/email]"+ , "named email"+ `xenforo` link "mailto:example@example.com" "title" "example email"+ =?> "[email=example@example.com]example email[/email]"+ , "inline code"+ `xenforo` ( "inline code: "+ <> codeWith ("id", ["haskell"], []) "map (2^) [1..5]"+ )+ =?> "inline code: [icode]map (2^) [1..5][/icode]"+ , "font"+ `xenforo` divAttrs [("font", "serif")] (para "foo")+ =?> "[font=serif]foo[/font]"+ , "inline spoiler"+ `xenforo` ("It was " <> spanClasses ["spoiler"] ("DNS") <> "!")+ =?> "It was [ispoiler]DNS[/ispoiler]!"+ , "image w=50% h=50%"+ `xenforo` imageWith+ ("", [], [("width", "50%"), ("height", "50%")])+ "https://example.com"+ "title text"+ "alt text"+ =?> "[img alt=\"alt text\" title=\"title text\" width=50%]https://example.com[/img]"+ , "image w=50 h=50"+ `xenforo` imageWith+ ("", [], [("width", "50"), ("height", "50")])+ "https://example.com"+ ""+ ""+ =?> "[img]https://example.com[/img]"+ ]+ ]
@@ -9,6 +9,7 @@ import Text.Pandoc import Text.Pandoc.Arbitrary () import Text.Pandoc.Builder+import qualified Data.Text as T context :: (ToPandoc a) => a -> String context = unpack . purely (writeConTeXt def) . toPandoc@@ -44,16 +45,17 @@ tests :: [TestTree] tests = [ testGroup "inline code"- [ "with '}'" =: code "}" =?> "\\mono{\\}}"+ [ "with '}'" =: code "}" =?> "\\type\"}\"" , "without '}'" =: code "]" =?> "\\type{]}" , "span with ID" =: spanWith ("city", [], []) "Berlin" =?> "\\reference[city]{}Berlin"- , testProperty "code property" $ \s -> null s || '\n' `elem` s ||- if '{' `elem` s || '}' `elem` s- then context' (code $ pack s) == "\\mono{" ++- context' (str $ pack s) ++ "}"- else context' (code $ pack s) == "\\type{" ++ s ++ "}"+ , testProperty "code property" $ \s ->+ null s || '\n' `elem` s ||+ case T.stripPrefix "\\type" (pack $ context' (code $ pack s))+ >>= T.uncons of+ Just (c, _) -> c `notElem` s+ Nothing -> False ] , testGroup "headers" [ "level 1" =:
@@ -0,0 +1,431 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Writers.DocBook (tests) where++import Data.Text (unpack)+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++docbook :: (ToPandoc a) => a -> String+docbook = docbookWithOpts def{ writerWrapText = WrapNone }++docbook5 :: (ToPandoc a) => a -> String+docbook5 = docbook5WithOpts def{ writerWrapText = WrapNone }++docbookWithOpts :: ToPandoc a => WriterOptions -> a -> String+docbookWithOpts opts = unpack . purely (writeDocBook4 opts) . toPandoc++docbook5WithOpts :: ToPandoc a => WriterOptions -> a -> String+docbook5WithOpts opts = unpack . purely (writeDocBook5 opts) . toPandoc+{-+ "my test" =: X =?> Y++is shorthand for++ test docbook "my test" $ X =?> Y++which is in turn shorthand for++ test docbook "my test" (X,Y)+-}++infix 4 =:+(=:), testDb4, testDb5 :: (ToString a, ToPandoc a)+ => String -> (a, String) -> TestTree+(=:) = test docbook+testDb4 = test docbook+testDb5 = test docbook5++lineblock :: Blocks+lineblock = para ("some text" <> linebreak <>+ "and more lines" <> linebreak <>+ "and again")+lineblock_out :: [String]+lineblock_out = [ "<literallayout>some text"+ , "and more lines"+ , "and again</literallayout>"+ ]++tests :: [TestTree]+tests = [ testGroup "inline elements"+ [ testGroup "links"+ [ testDb4 "db4 external link" $ link "https://example.com" "" "Hello"+ =?> "<ulink url=\"https://example.com\">Hello</ulink>"+ , testDb5 "db5 external link" $ link "https://example.com" "" "Hello"+ =?> "<link xlink:href=\"https://example.com\">Hello</link>"+ , testDb5 "anchor" $ link "#foo" "" "Hello"+ =?> "<link linkend=\"foo\">Hello</link>"+ , testDb5 "automatic anchor" $ link "#foo" "" ""+ =?> "<xref linkend=\"foo\"></xref>"+ ]+ ]+ , testGroup "line blocks"+ [ "none" =: para "This is a test"+ =?> unlines+ [ "<para>"+ , " This is a test"+ , "</para>"+ ]+ , "basic" =: lineblock+ =?> unlines lineblock_out+ , "blockquote" =: blockQuote lineblock+ =?> unlines+ ( [ "<blockquote>" ] +++ lineblock_out +++ [ "</blockquote>" ]+ )+ , "footnote" =: para ("This is a test" <>+ note lineblock <>+ " of footnotes")+ =?> unlines+ ( [ "<para>"+ , " This is a test<footnote>" ] +++ lineblock_out +++ [ " </footnote> of footnotes"+ , "</para>" ]+ )+ ]+ , testGroup "divs"+ [ "admonition" =: divWith ("foo", ["warning"], []) (para "This is a test")+ =?> unlines+ [ "<warning id=\"foo\">"+ , " <para>"+ , " This is a test"+ , " </para>"+ , "</warning>"+ ]+ , "admonition-with-title" =:+ divWith ("foo", ["note"], []) (+ divWith ("foo", ["title"], [])+ (plain (text "This is title")) <>+ para "This is a test"+ )+ =?> unlines+ [ "<note id=\"foo\">"+ , " <title>This is title</title>"+ , " <para>"+ , " This is a test"+ , " </para>"+ , "</note>"+ ]+ , "admonition-with-title-in-para" =:+ divWith ("foo", ["note"], []) (+ divWith ("foo", ["title"], [])+ (para "This is title") <>+ para "This is a test"+ )+ =?> unlines+ [ "<note id=\"foo\">"+ , " <title>This is title</title>"+ , " <para>"+ , " This is a test"+ , " </para>"+ , "</note>"+ ]+ , "single-child" =:+ divWith ("foo", [], []) (para "This is a test")+ =?> unlines+ [ "<para id=\"foo\">"+ , " This is a test"+ , "</para>"+ ]+ , "single-literal-child" =:+ divWith ("foo", [], []) lineblock+ =?> unlines+ [ "<literallayout id=\"foo\">some text"+ , "and more lines"+ , "and again</literallayout>"+ ]+ , "multiple-children" =:+ divWith ("foo", [], []) (+ para "This is a test" <>+ para "This is an another test"+ )+ =?> unlines+ [ "<anchor id=\"foo\" />"+ , "<para>"+ , " This is a test"+ , "</para>"+ , "<para>"+ , " This is an another test"+ , "</para>"+ ]+ ]+ , testGroup "compact lists"+ [ testGroup "bullet"+ [ "compact" =: bulletList [plain "a", plain "b", plain "c"]+ =?> unlines+ [ "<itemizedlist spacing=\"compact\">"+ , " <listitem>"+ , " <para>"+ , " a"+ , " </para>"+ , " </listitem>"+ , " <listitem>"+ , " <para>"+ , " b"+ , " </para>"+ , " </listitem>"+ , " <listitem>"+ , " <para>"+ , " c"+ , " </para>"+ , " </listitem>"+ , "</itemizedlist>"+ ]+ , "loose" =: bulletList [para "a", para "b", para "c"]+ =?> unlines+ [ "<itemizedlist>"+ , " <listitem>"+ , " <para>"+ , " a"+ , " </para>"+ , " </listitem>"+ , " <listitem>"+ , " <para>"+ , " b"+ , " </para>"+ , " </listitem>"+ , " <listitem>"+ , " <para>"+ , " c"+ , " </para>"+ , " </listitem>"+ , "</itemizedlist>"+ ]+ ]+ , testGroup "ordered"+ [ "compact" =: orderedList [plain "a", plain "b", plain "c"]+ =?> unlines+ [ "<orderedlist spacing=\"compact\">"+ , " <listitem>"+ , " <para>"+ , " a"+ , " </para>"+ , " </listitem>"+ , " <listitem>"+ , " <para>"+ , " b"+ , " </para>"+ , " </listitem>"+ , " <listitem>"+ , " <para>"+ , " c"+ , " </para>"+ , " </listitem>"+ , "</orderedlist>"+ ]+ , "loose" =: orderedList [para "a", para "b", para "c"]+ =?> unlines+ [ "<orderedlist>"+ , " <listitem>"+ , " <para>"+ , " a"+ , " </para>"+ , " </listitem>"+ , " <listitem>"+ , " <para>"+ , " b"+ , " </para>"+ , " </listitem>"+ , " <listitem>"+ , " <para>"+ , " c"+ , " </para>"+ , " </listitem>"+ , "</orderedlist>"+ ]+ ]+ , testGroup "definition"+ [ "compact" =: definitionList [ ("an", [plain "apple" ])+ , ("a", [plain "banana"])+ , ("an", [plain "orange"])]+ =?> unlines+ [ "<variablelist spacing=\"compact\">"+ , " <varlistentry>"+ , " <term>"+ , " an"+ , " </term>"+ , " <listitem>"+ , " <para>"+ , " apple"+ , " </para>"+ , " </listitem>"+ , " </varlistentry>"+ , " <varlistentry>"+ , " <term>"+ , " a"+ , " </term>"+ , " <listitem>"+ , " <para>"+ , " banana"+ , " </para>"+ , " </listitem>"+ , " </varlistentry>"+ , " <varlistentry>"+ , " <term>"+ , " an"+ , " </term>"+ , " <listitem>"+ , " <para>"+ , " orange"+ , " </para>"+ , " </listitem>"+ , " </varlistentry>"+ , "</variablelist>"+ ]+ , "loose" =: definitionList [ ("an", [para "apple" ])+ , ("a", [para "banana"])+ , ("an", [para "orange"])]+ =?> unlines+ [ "<variablelist>"+ , " <varlistentry>"+ , " <term>"+ , " an"+ , " </term>"+ , " <listitem>"+ , " <para>"+ , " apple"+ , " </para>"+ , " </listitem>"+ , " </varlistentry>"+ , " <varlistentry>"+ , " <term>"+ , " a"+ , " </term>"+ , " <listitem>"+ , " <para>"+ , " banana"+ , " </para>"+ , " </listitem>"+ , " </varlistentry>"+ , " <varlistentry>"+ , " <term>"+ , " an"+ , " </term>"+ , " <listitem>"+ , " <para>"+ , " orange"+ , " </para>"+ , " </listitem>"+ , " </varlistentry>"+ , "</variablelist>"+ ]+ ]+ ]+ , testGroup "writer options"+ [ testGroup "top-level division" $+ let+ headers = header 1 (text "header1")+ <> header 2 (text "header2")+ <> header 3 (text "header3")++ docbookTopLevelDiv :: (ToPandoc a)+ => TopLevelDivision -> a -> String+ docbookTopLevelDiv division =+ docbookWithOpts def{ writerTopLevelDivision = division }+ in+ [ test (docbookTopLevelDiv TopLevelSection) "sections as top-level" $+ headers =?>+ unlines [ "<sect1>"+ , " <title>header1</title>"+ , " <sect2>"+ , " <title>header2</title>"+ , " <sect3>"+ , " <title>header3</title>"+ , " <para>"+ , " </para>"+ , " </sect3>"+ , " </sect2>"+ , "</sect1>"+ ]+ , test (docbookTopLevelDiv TopLevelChapter) "chapters as top-level" $+ headers =?>+ unlines [ "<chapter>"+ , " <title>header1</title>"+ , " <sect1>"+ , " <title>header2</title>"+ , " <sect2>"+ , " <title>header3</title>"+ , " <para>"+ , " </para>"+ , " </sect2>"+ , " </sect1>"+ , "</chapter>"+ ]+ , test (docbookTopLevelDiv TopLevelPart) "parts as top-level" $+ headers =?>+ unlines [ "<part>"+ , " <title>header1</title>"+ , " <chapter>"+ , " <title>header2</title>"+ , " <sect1>"+ , " <title>header3</title>"+ , " <para>"+ , " </para>"+ , " </sect1>"+ , " </chapter>"+ , "</part>"+ ]+ , test (docbookTopLevelDiv TopLevelDefault) "default top-level" $+ headers =?>+ unlines [ "<sect1>"+ , " <title>header1</title>"+ , " <sect2>"+ , " <title>header2</title>"+ , " <sect3>"+ , " <title>header3</title>"+ , " <para>"+ , " </para>"+ , " </sect3>"+ , " </sect2>"+ , "</sect1>"+ ]+ ]+ ]+ , testGroup "section attributes" $+ let+ headers = headerWith ("myid1",["unnumbered","ignored"],[("role","internal"),("xml:id","anotherid"),("dir","rtl")]) 1 "header1"+ <> headerWith ("myid2",["unnumbered"],[("invalidname","value"),("arch","linux"),("dir","invaliddir")]) 1 "header2"+ <> headerWith ("myid3",["ignored"],[]) 1 "header3"+ in+ [ test docbook5 "sections with attributes (db5)" $+ headers =?>+ unlines [ "<section xmlns=\"http://docbook.org/ns/docbook\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:id=\"myid1\" role=\"unnumbered internal\" dir=\"rtl\">"+ , " <title>header1</title>"+ , " <para>"+ , " </para>"+ , "</section>"+ , "<section xmlns=\"http://docbook.org/ns/docbook\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:id=\"myid2\" role=\"unnumbered\">"+ , " <title>header2</title>"+ , " <para>"+ , " </para>"+ , "</section>"+ , "<section xmlns=\"http://docbook.org/ns/docbook\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:id=\"myid3\">"+ , " <title>header3</title>"+ , " <para>"+ , " </para>"+ , "</section>"+ ]+ , test docbook "sections with attributes (db4)" $+ headers =?>+ unlines [ "<sect1 id=\"myid1\" role=\"unnumbered internal\">"+ , " <title>header1</title>"+ , " <para>"+ , " </para>"+ , "</sect1>"+ , "<sect1 id=\"myid2\" role=\"unnumbered\" arch=\"linux\">"+ , " <title>header2</title>"+ , " <para>"+ , " </para>"+ , "</sect1>"+ , "<sect1 id=\"myid3\">"+ , " <title>header3</title>"+ , " <para>"+ , " </para>"+ , "</sect1>"+ ]+ ]+ ]
@@ -1,420 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-module Tests.Writers.Docbook (tests) where--import Data.Text (unpack)-import Test.Tasty-import Tests.Helpers-import Text.Pandoc-import Text.Pandoc.Arbitrary ()-import Text.Pandoc.Builder--docbook :: (ToPandoc a) => a -> String-docbook = docbookWithOpts def{ writerWrapText = WrapNone }--docbook5 :: (ToPandoc a) => a -> String-docbook5 = docbook5WithOpts def{ writerWrapText = WrapNone }--docbookWithOpts :: ToPandoc a => WriterOptions -> a -> String-docbookWithOpts opts = unpack . purely (writeDocbook4 opts) . toPandoc--docbook5WithOpts :: ToPandoc a => WriterOptions -> a -> String-docbook5WithOpts opts = unpack . purely (writeDocbook5 opts) . toPandoc-{-- "my test" =: X =?> Y--is shorthand for-- test docbook "my test" $ X =?> Y--which is in turn shorthand for-- test docbook "my test" (X,Y)--}--infix 4 =:-(=:), testDb4, testDb5 :: (ToString a, ToPandoc a)- => String -> (a, String) -> TestTree-(=:) = test docbook-testDb4 = test docbook-testDb5 = test docbook5--lineblock :: Blocks-lineblock = para ("some text" <> linebreak <>- "and more lines" <> linebreak <>- "and again")-lineblock_out :: [String]-lineblock_out = [ "<literallayout>some text"- , "and more lines"- , "and again</literallayout>"- ]--tests :: [TestTree]-tests = [ testGroup "inline elements"- [ testGroup "links"- [ testDb4 "db4 external link" $ link "https://example.com" "" "Hello"- =?> "<ulink url=\"https://example.com\">Hello</ulink>"- , testDb5 "db5 external link" $ link "https://example.com" "" "Hello"- =?> "<link xlink:href=\"https://example.com\">Hello</link>"- , testDb5 "anchor" $ link "#foo" "" "Hello"- =?> "<link linkend=\"foo\">Hello</link>"- , testDb5 "automatic anchor" $ link "#foo" "" ""- =?> "<xref linkend=\"foo\"></xref>"- ]- ]- , testGroup "line blocks"- [ "none" =: para "This is a test"- =?> unlines- [ "<para>"- , " This is a test"- , "</para>"- ]- , "basic" =: lineblock- =?> unlines lineblock_out- , "blockquote" =: blockQuote lineblock- =?> unlines- ( [ "<blockquote>" ] ++- lineblock_out ++- [ "</blockquote>" ]- )- , "footnote" =: para ("This is a test" <>- note lineblock <>- " of footnotes")- =?> unlines- ( [ "<para>"- , " This is a test<footnote>" ] ++- lineblock_out ++- [ " </footnote> of footnotes"- , "</para>" ]- )- ]- , testGroup "divs"- [ "admonition" =: divWith ("foo", ["warning"], []) (para "This is a test")- =?> unlines- [ "<warning id=\"foo\">"- , " <para>"- , " This is a test"- , " </para>"- , "</warning>"- ]- , "admonition-with-title" =:- divWith ("foo", ["note"], []) (- divWith ("foo", ["title"], [])- (plain (text "This is title")) <>- para "This is a test"- )- =?> unlines- [ "<note id=\"foo\">"- , " <title>This is title</title>"- , " <para>"- , " This is a test"- , " </para>"- , "</note>"- ]- , "admonition-with-title-in-para" =:- divWith ("foo", ["note"], []) (- divWith ("foo", ["title"], [])- (para "This is title") <>- para "This is a test"- )- =?> unlines- [ "<note id=\"foo\">"- , " <title>This is title</title>"- , " <para>"- , " This is a test"- , " </para>"- , "</note>"- ]- , "single-child" =:- divWith ("foo", [], []) (para "This is a test")- =?> unlines- [ "<para id=\"foo\">"- , " This is a test"- , "</para>"- ]- , "single-literal-child" =:- divWith ("foo", [], []) lineblock- =?> unlines- [ "<literallayout id=\"foo\">some text"- , "and more lines"- , "and again</literallayout>"- ]- , "multiple-children" =:- divWith ("foo", [], []) (- para "This is a test" <>- para "This is an another test"- )- =?> unlines- [ "<anchor id=\"foo\" />"- , "<para>"- , " This is a test"- , "</para>"- , "<para>"- , " This is an another test"- , "</para>"- ]- ]- , testGroup "compact lists"- [ testGroup "bullet"- [ "compact" =: bulletList [plain "a", plain "b", plain "c"]- =?> unlines- [ "<itemizedlist spacing=\"compact\">"- , " <listitem>"- , " <para>"- , " a"- , " </para>"- , " </listitem>"- , " <listitem>"- , " <para>"- , " b"- , " </para>"- , " </listitem>"- , " <listitem>"- , " <para>"- , " c"- , " </para>"- , " </listitem>"- , "</itemizedlist>"- ]- , "loose" =: bulletList [para "a", para "b", para "c"]- =?> unlines- [ "<itemizedlist>"- , " <listitem>"- , " <para>"- , " a"- , " </para>"- , " </listitem>"- , " <listitem>"- , " <para>"- , " b"- , " </para>"- , " </listitem>"- , " <listitem>"- , " <para>"- , " c"- , " </para>"- , " </listitem>"- , "</itemizedlist>"- ]- ]- , testGroup "ordered"- [ "compact" =: orderedList [plain "a", plain "b", plain "c"]- =?> unlines- [ "<orderedlist spacing=\"compact\">"- , " <listitem>"- , " <para>"- , " a"- , " </para>"- , " </listitem>"- , " <listitem>"- , " <para>"- , " b"- , " </para>"- , " </listitem>"- , " <listitem>"- , " <para>"- , " c"- , " </para>"- , " </listitem>"- , "</orderedlist>"- ]- , "loose" =: orderedList [para "a", para "b", para "c"]- =?> unlines- [ "<orderedlist>"- , " <listitem>"- , " <para>"- , " a"- , " </para>"- , " </listitem>"- , " <listitem>"- , " <para>"- , " b"- , " </para>"- , " </listitem>"- , " <listitem>"- , " <para>"- , " c"- , " </para>"- , " </listitem>"- , "</orderedlist>"- ]- ]- , testGroup "definition"- [ "compact" =: definitionList [ ("an", [plain "apple" ])- , ("a", [plain "banana"])- , ("an", [plain "orange"])]- =?> unlines- [ "<variablelist spacing=\"compact\">"- , " <varlistentry>"- , " <term>"- , " an"- , " </term>"- , " <listitem>"- , " <para>"- , " apple"- , " </para>"- , " </listitem>"- , " </varlistentry>"- , " <varlistentry>"- , " <term>"- , " a"- , " </term>"- , " <listitem>"- , " <para>"- , " banana"- , " </para>"- , " </listitem>"- , " </varlistentry>"- , " <varlistentry>"- , " <term>"- , " an"- , " </term>"- , " <listitem>"- , " <para>"- , " orange"- , " </para>"- , " </listitem>"- , " </varlistentry>"- , "</variablelist>"- ]- , "loose" =: definitionList [ ("an", [para "apple" ])- , ("a", [para "banana"])- , ("an", [para "orange"])]- =?> unlines- [ "<variablelist>"- , " <varlistentry>"- , " <term>"- , " an"- , " </term>"- , " <listitem>"- , " <para>"- , " apple"- , " </para>"- , " </listitem>"- , " </varlistentry>"- , " <varlistentry>"- , " <term>"- , " a"- , " </term>"- , " <listitem>"- , " <para>"- , " banana"- , " </para>"- , " </listitem>"- , " </varlistentry>"- , " <varlistentry>"- , " <term>"- , " an"- , " </term>"- , " <listitem>"- , " <para>"- , " orange"- , " </para>"- , " </listitem>"- , " </varlistentry>"- , "</variablelist>"- ]- ]- ]- , testGroup "writer options"- [ testGroup "top-level division" $- let- headers = header 1 (text "header1")- <> header 2 (text "header2")- <> header 3 (text "header3")-- docbookTopLevelDiv :: (ToPandoc a)- => TopLevelDivision -> a -> String- docbookTopLevelDiv division =- docbookWithOpts def{ writerTopLevelDivision = division }- in- [ test (docbookTopLevelDiv TopLevelSection) "sections as top-level" $- headers =?>- unlines [ "<sect1>"- , " <title>header1</title>"- , " <sect2>"- , " <title>header2</title>"- , " <sect3>"- , " <title>header3</title>"- , " <para>"- , " </para>"- , " </sect3>"- , " </sect2>"- , "</sect1>"- ]- , test (docbookTopLevelDiv TopLevelChapter) "chapters as top-level" $- headers =?>- unlines [ "<chapter>"- , " <title>header1</title>"- , " <sect1>"- , " <title>header2</title>"- , " <sect2>"- , " <title>header3</title>"- , " <para>"- , " </para>"- , " </sect2>"- , " </sect1>"- , "</chapter>"- ]- , test (docbookTopLevelDiv TopLevelPart) "parts as top-level" $- headers =?>- unlines [ "<part>"- , " <title>header1</title>"- , " <chapter>"- , " <title>header2</title>"- , " <sect1>"- , " <title>header3</title>"- , " <para>"- , " </para>"- , " </sect1>"- , " </chapter>"- , "</part>"- ]- , test (docbookTopLevelDiv TopLevelDefault) "default top-level" $- headers =?>- unlines [ "<sect1>"- , " <title>header1</title>"- , " <sect2>"- , " <title>header2</title>"- , " <sect3>"- , " <title>header3</title>"- , " <para>"- , " </para>"- , " </sect3>"- , " </sect2>"- , "</sect1>"- ]- ]- ]- , testGroup "section attributes" $- let- headers = headerWith ("myid1",[],[("role","internal"),("xml:id","anotherid"),("dir","rtl")]) 1 "header1"- <> headerWith ("myid2",[],[("invalidname","value"),("arch","linux"),("dir","invaliddir")]) 1 "header2"- in- [ test docbook5 "sections with attributes (db5)" $- headers =?>- unlines [ "<section xmlns=\"http://docbook.org/ns/docbook\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:id=\"myid1\" role=\"internal\" dir=\"rtl\">"- , " <title>header1</title>"- , " <para>"- , " </para>"- , "</section>"- , "<section xmlns=\"http://docbook.org/ns/docbook\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:id=\"myid2\">"- , " <title>header2</title>"- , " <para>"- , " </para>"- , "</section>"- ]- , test docbook "sections with attributes (db4)" $- headers =?>- unlines [ "<sect1 id=\"myid1\" role=\"internal\">"- , " <title>header1</title>"- , " <para>"- , " </para>"- , "</sect1>"- , "<sect1 id=\"myid2\" arch=\"linux\">"- , " <title>header2</title>"- , " <para>"- , " </para>"- , "</sect1>"- ]- ]- ]
@@ -1,10 +1,18 @@+{-# LANGUAGE OverloadedStrings #-} module Tests.Writers.Docx (tests) where -import Text.Pandoc+import Codec.Archive.Zip (findEntryByPath, fromEntry, toArchive)+import qualified Data.ByteString.Lazy as BL+import Data.List (isInfixOf, isPrefixOf)+import qualified Data.Map as M+import Data.Text (Text)+import qualified Data.Text as Text+import qualified Data.Text.IO as T import Test.Tasty-import Tests.Writers.OOXML import Test.Tasty.HUnit-import Data.List (isPrefixOf)+import Tests.Writers.OOXML+import Text.Pandoc+import Text.XML.Light (QName(QName), findAttr, findElements, parseXMLDoc) -- we add an extra check to make sure that we're not writing in the -- toplevel docx directory. We don't want to accidentally overwrite an@@ -98,6 +106,16 @@ "docx/definition_list.native" "docx/golden/definition_list.docx" , docxTest+ "task lists"+ def+ "docx/task_list.native"+ "docx/golden/task_list.docx"+ , docxTest+ "issue 9994"+ def+ "docx/lists_9994.native"+ "docx/golden/lists_9994.docx"+ , docxTest "footnotes and endnotes" def "docx/notes.native"@@ -110,7 +128,7 @@ , docxTest "blockquotes" def- "docx/block_quotes_parse_indent.native"+ "docx/block_quotes.native" "docx/golden/block_quotes.docx" , docxTest "tables"@@ -203,5 +221,157 @@ def "docx/document-properties-short-desc.native" "docx/golden/document-properties-short-desc.docx"+ ]+ , testGroup "top-level-division"+ -- Helper to count occurrences of a substring+ -- Note: counts by splitting on "<w:sectPr" which marks section properties+ [ testCase "no section break before first chapter (#10578)" $ do+ -- With --top-level-division=chapter, there should be no section+ -- break before the first chapter (to avoid blank first page)+ let opts = def{ writerTopLevelDivision = TopLevelChapter }+ bs <- runIOorExplode $ do+ setVerbosity ERROR+ let doc = Pandoc mempty+ [ Header 1 ("ch1", [], []) [Str "Chapter", Space, Str "1"]+ , Para [Str "First", Space, Str "chapter."]+ ]+ writeDocx opts doc+ let archive = toArchive bs+ entry <- case findEntryByPath "word/document.xml" archive of+ Nothing -> assertFailure "Missing word/document.xml in output docx"+ Just e -> return e+ let docXml = show (fromEntry entry)+ -- Count occurrences of "<w:sectPr" (opening tag for section properties)+ let countOccurrences needle haystack =+ length (filter (needle `isPrefixOf`) (tails haystack))+ where tails [] = []; tails s@(_:xs) = s : tails xs+ let sectPrCount = countOccurrences "<w:sectPr" docXml+ -- Should have exactly 1 sectPr (the final document section),+ -- not 2 (which would mean one before the chapter heading)+ assertBool ("Expected 1 sectPr (final section only), found " ++ show sectPrCount)+ (sectPrCount == 1)+ , testCase "section breaks between chapters (#11482)" $ do+ -- With --top-level-division=chapter, there should be section+ -- breaks between chapters (but not before the first one)+ let opts = def{ writerTopLevelDivision = TopLevelChapter }+ bs <- runIOorExplode $ do+ setVerbosity ERROR+ let doc = Pandoc mempty+ [ Header 1 ("ch1", [], []) [Str "Chapter", Space, Str "1"]+ , Para [Str "First", Space, Str "chapter."]+ , Header 1 ("ch2", [], []) [Str "Chapter", Space, Str "2"]+ , Para [Str "Second", Space, Str "chapter."]+ , Header 1 ("ch3", [], []) [Str "Chapter", Space, Str "3"]+ , Para [Str "Third", Space, Str "chapter."]+ ]+ writeDocx opts doc+ let archive = toArchive bs+ entry <- case findEntryByPath "word/document.xml" archive of+ Nothing -> assertFailure "Missing word/document.xml in output docx"+ Just e -> return e+ let docXml = show (fromEntry entry)+ -- Count occurrences of "<w:sectPr" (opening tag for section properties)+ let countOccurrences needle haystack =+ length (filter (needle `isPrefixOf`) (tails haystack))+ where tails [] = []; tails s@(_:xs) = s : tails xs+ let sectPrCount = countOccurrences "<w:sectPr" docXml+ -- Should have 3 sectPr elements:+ -- - 1 before chapter 2+ -- - 1 before chapter 3+ -- - 1 final document section+ -- (No section break before chapter 1)+ assertBool ("Expected 3 sectPr elements, found " ++ show sectPrCount)+ (sectPrCount == 3)+ ]+ , testGroup "reference docx"+ [ testCase "no media directory override in content types" $ do+ let opts = def{ writerReferenceDoc = Just "docx/inline_images.docx" }+ txt <- T.readFile "docx/inline_formatting.native"+ bs <- runIOorExplode $ do+ mblang <- toLang (Just (Text.pack "en-US") :: Maybe Text)+ maybe (return ()) setTranslations mblang+ setVerbosity ERROR+ readNative def txt >>= writeDocx opts+ let archive = toArchive bs+ entry <- case findEntryByPath "[Content_Types].xml" archive of+ Nothing -> assertFailure "Missing [Content_Types].xml in output docx"+ Just e -> return e+ doc <- case parseXMLDoc (fromEntry entry) of+ Nothing -> assertFailure "Failed to parse [Content_Types].xml"+ Just d -> return d+ let partNameAttr = QName "PartName" Nothing Nothing+ let overrideName = QName "Override" Nothing Nothing+ let overrides = findElements overrideName doc+ let hasBadOverride =+ any (\el -> findAttr partNameAttr el == Just "/word/media/")+ overrides+ assertBool "Found invalid /word/media/ Override in [Content_Types].xml"+ (not hasBadOverride)+ , testCase "language from reference docx is preserved" $ do+ -- First, verify that the german-reference.docx actually has de-DE+ refBs <- BL.readFile "docx/german-reference.docx"+ let refArchive = toArchive refBs+ refEntry <- case findEntryByPath "word/styles.xml" refArchive of+ Nothing -> assertFailure "Missing word/styles.xml in german-reference.docx"+ Just e -> return e+ let refStylesXml = show (fromEntry refEntry)+ let getLangLines = filter ("w:lang" `isInfixOf`) . lines+ assertBool ("german-reference.docx w:lang line: " +++ unlines (getLangLines refStylesXml))+ (any ("de-DE" `isInfixOf`) (getLangLines refStylesXml))+ -- Now test that using this reference preserves the language+ let opts = def{ writerReferenceDoc = Just "docx/german-reference.docx" }+ txt <- T.readFile "docx/inline_formatting.native"+ bs <- runIOorExplode $ do+ setVerbosity ERROR+ readNative def txt >>= writeDocx opts+ let archive = toArchive bs+ entry <- case findEntryByPath "word/styles.xml" archive of+ Nothing -> assertFailure "Missing word/styles.xml in output docx"+ Just e -> return e+ let stylesXml = show (fromEntry entry)+ -- Find the w:lang line for debugging+ -- Check that the styles.xml contains the German language+ assertBool ("Language from reference docx not preserved. w:lang lines: " ++ unlines (getLangLines stylesXml))+ (any ("de-DE" `isInfixOf`) (getLangLines stylesXml))+ , testCase "language from metadata overrides reference docx" $ do+ -- Use a reference docx with German language, but specify French in metadata+ let opts = def{ writerReferenceDoc = Just "docx/german-reference.docx" }+ bs <- runIOorExplode $ do+ setVerbosity ERROR+ -- Create a document with French language metadata+ let doc = Pandoc (Meta $ M.fromList [("lang", MetaString "fr-FR")])+ [Para [Str "Test"]]+ writeDocx opts doc+ let archive = toArchive bs+ entry <- case findEntryByPath "word/styles.xml" archive of+ Nothing -> assertFailure "Missing word/styles.xml in output docx"+ Just e -> return e+ let stylesXml = show (fromEntry entry)+ -- Check that the styles.xml contains the French language (not German)+ let getLangLines = filter ("w:lang" `isInfixOf`) . lines+ assertBool "Language from metadata did not override reference docx (expected fr-FR)"+ (any ("fr-FR" `isInfixOf`) (getLangLines stylesXml))+ ]+ , testGroup "paragraph styles"+ [ testCase "FirstParagraph after heading with footnote (#11573)" $ do+ let opts = def+ bs <- runIOorExplode $ do+ setVerbosity ERROR+ let doc = Pandoc mempty+ [ Header 3 ("heading-with-note", [], [])+ [Note [Para [Str "note"]], Str "Heading"]+ , Para [Str "Para", Space, Str "after."]+ ]+ writeDocx opts doc+ let archive = toArchive bs+ entry <- case findEntryByPath "word/document.xml" archive of+ Nothing -> assertFailure "Missing word/document.xml in output docx"+ Just e -> return e+ let docXml = show (fromEntry entry)+ assertBool+ ("Expected FirstParagraph style after heading with footnote, got: "+ ++ docXml)+ ("FirstParagraph" `isInfixOf` docXml) ] ]
@@ -84,6 +84,11 @@ doubleQuoted (spanWith ("", [], [("cite", "http://example.org")]) (str "examples")) =?> "<q cite=\"http://example.org\">examples</q>" ]+ , testGroup "code"+ [ "code should be rendered correctly" =:+ plain (codeWith ("",[],[]) "Answer is 42") =?>+ "<code>Answer is 42</code>"+ ] , testGroup "sample" [ "sample should be rendered correctly" =: plain (codeWith ("",["sample"],[]) "Answer is 42") =?>@@ -97,13 +102,13 @@ , testGroup "sample with style" [ "samp should wrap highlighted code" =: codeWith ("",["sample","haskell"],[]) ">>="- =?> ("<samp><code class=\"sourceCode haskell\">" +++ =?> ("<samp><code class=\"sourceCode haskell sample\">" ++ "<span class=\"op\">>>=</span></code></samp>") ] , testGroup "variable with style" [ "var should wrap highlighted code" =: codeWith ("",["haskell","variable"],[]) ">>="- =?> ("<var><code class=\"sourceCode haskell\">" +++ =?> ("<var><code class=\"sourceCode haskell variable\">" ++ "<span class=\"op\">>>=</span></code></var>") ] , testGroup "footnotes"@@ -188,13 +193,13 @@ , "<p>A note inside a block quote.<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\"><sup>2</sup></a></p>" , "<p>A second paragraph.</p>" , "</blockquote>"- , "</div>" , "<div class=\"footnotes footnotes-end-of-section\">" , "<hr />" , "<ol>" , "<li id=\"fn1\"><p>Down here.<a href=\"#fnref1\" class=\"footnote-back\">↩︎</a></p></li>" , "<li id=\"fn2\"><p>The second note.<a href=\"#fnref2\" class=\"footnote-back\">↩︎</a></p></li>" , "</ol>"+ , "</div>" , "</div>" , "<div class=\"section level2\">" , "<h2>Second section</h2>"
@@ -11,7 +11,7 @@ import qualified Data.Text as T jats :: (ToPandoc a) => a -> Text-jats = purely (writeJATS def{ writerWrapText = WrapNone })+jats = purely (writeJatsArchiving def{ writerWrapText = WrapNone }) . toPandoc jatsArticleAuthoring :: (ToPandoc a) => a -> Text@@ -40,7 +40,6 @@ tests = [ testGroup "inline code" [ "basic" =: code "@&" =?> "<p><monospace>@&</monospace></p>"- , "lang" =: codeWith ("", ["c"], []) "@&" =?> "<p><code language=\"c\">@&</code></p>" ] , testGroup "block code" [ "basic" =: codeBlock "@&" =?> "<preformat>@&</preformat>"@@ -88,7 +87,7 @@ , " <fig>" , " <caption><p>caption</p></caption>" , " <graphic mimetype=\"image\" mime-subtype=\"png\"" <>- " xlink:href=\"a.png\" xlink:title=\"\" />"+ " xlink:href=\"a.png\" />" , " </fig>" , " </p>" , " </list-item>"@@ -134,7 +133,9 @@ , "containing image" =: header 1 (image "imgs/foo.jpg" "" (text "Alt text")) =?> "<sec>\n\- \ <title><inline-graphic mimetype=\"image\" mime-subtype=\"jpeg\" xlink:href=\"imgs/foo.jpg\" /></title>\n\+ \ <title><inline-graphic mimetype=\"image\" mime-subtype=\"jpeg\" xlink:href=\"imgs/foo.jpg\">\n\+ \ <alt-text>Alt text</alt-text>\n\+ \ </inline-graphic></title>\n\ \</sec>" ]
@@ -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@@ -50,7 +50,7 @@ , testGroup "definition lists" [ "with internal link" =: definitionList [(link "#go" "" (str "testing"), [plain (text "hi there")])] =?>- "\\begin{description}\n\\tightlist\n\\item[{\\protect\\hyperlink{go}{testing}}]\nhi there\n\\end{description}"+ "\\begin{description}\n\\tightlist\n\\item[{\\hyperref[go]{testing}}]\nhi there\n\\end{description}" ] , testGroup "math" [ "escape |" =: para (math "\\sigma|_{\\{x\\}}") =?>@@ -60,7 +60,7 @@ [ "unnumbered header" =: headerWith ("foo",["unnumbered"],[]) 1 (text "Header 1" <> note (plain $ text "note")) =?>- "\\hypertarget{foo}{%\n\\section*{\\texorpdfstring{Header 1\\footnote{note}}{Header 1}}\\label{foo}}\n\\addcontentsline{toc}{section}{Header 1}\n"+ "\\section*{\\texorpdfstring{Header 1\\footnote{note}}{Header 1}}\\label{foo}\n\\addcontentsline{toc}{section}{Header 1}\n" , "in list item" =: bulletList [header 2 (text "foo")] =?> "\\begin{itemize}\n\\item ~\n \\subsection{foo}\n\\end{itemize}"@@ -70,22 +70,90 @@ "\\begin{description}\n\\item[foo] ~ \n\\subsection{bar}\n\nbaz\n\\end{description}" , "containing image" =: header 1 (image "imgs/foo.jpg" "" (text "Alt text")) =?>- "\\section{\\texorpdfstring{\\protect\\includegraphics{imgs/foo.jpg}}{Alt text}}"+ "\\section{\\texorpdfstring{\\protect\\pandocbounded{\\includegraphics[keepaspectratio,alt={Alt text}]{imgs/foo.jpg}}}{Alt text}}" ] , testGroup "inline code" [ "struck out and highlighted" =: strikeout (codeWith ("",["haskell"],[]) "foo" <> space <> str "bar") =?>- "\\sout{\\mbox{\\VERB|\\NormalTok{foo}|} bar}"+ "\\st{\\mbox{\\VERB|\\NormalTok{foo}|} bar}" , "struck out and not highlighted" =: strikeout (code "foo" <> space <> str "bar") =?>- "\\sout{\\mbox{\\texttt{foo}} bar}"+ "\\st{\\mbox{\\texttt{foo}} bar}" , "single quotes" =: code "dog's" =?> "\\texttt{dog\\textquotesingle{}s}" , "backtick" =: code "`nu?`" =?> "\\texttt{\\textasciigrave{}nu?\\textasciigrave{}}" ]+ , testGroup "inline note"+ [ "Big note in emph" =:+ emph (str "This sentence"+ <> note (para (str "paragraph1")+ <> para (str "paragraph2"))+ <> str " has footnote.")+ =?>+ "\\emph{This sentence}\\footnote{paragraph1\n\n paragraph2}"+ <> "\\emph{ has footnote.}"+ , "Big note in strong" =:+ strong (str "This sentence"+ <> note (para (str "paragraph1")+ <> para (str "paragraph2"))+ <> str " has footnote.")+ =?>+ "\\textbf{This sentence}\\footnote{paragraph1\n\n paragraph2}"+ <> "\\textbf{ has footnote.}"++ , "Big note in underline" =:+ underline (str "This sentence"+ <> note (para (str "paragraph1")+ <> para (str "paragraph2"))+ <> str " has footnote.")+ =?>+ "\\ul{This sentence}\\footnote{paragraph1\n\n paragraph2}"+ <> "\\ul{ has footnote.}"++ , "Big note in strikeout" =:+ strikeout (str "This sentence"+ <> note (para (str "paragraph1")+ <> para (str "paragraph2"))+ <> str " has footnote.")+ =?>+ "\\st{This sentence}\\footnote{paragraph1\n\n paragraph2}"+ <> "\\st{ has footnote.}"++ , "Small note in emph" =:+ emph (str "This sentence"+ <> note (para (str "paragraph"))+ <> str " has footnote.")+ =?>+ "\\emph{This sentence\\footnote{paragraph} has footnote.}"++ , "Big note nested in emph and strong" =:+ emph (str "This "+ <> strong (str "nested sentence "+ <> note (para (str "paragraph1")+ <> para (str "paragraph2"))+ <> str "has ")+ <> str "footnote."+ )+ =?>+ "\\emph{This \\textbf{nested sentence }}\\footnote{paragraph1\n\n"+ <> " paragraph2}\\emph{\\textbf{has }footnote.}"++ , "Two Big notes in emph" =:+ emph (str "This sentence"+ <> note (para (str "1-paragraph1")+ <> para (str "1-paragraph2"))+ <> str " has"+ <> note (para (str "2-paragraph1")+ <> para (str "2-paragraph2"))+ <> str " footnote.")+ =?>+ "\\emph{This sentence}\\footnote{1-paragraph1\n\n 1-paragraph2}"+ <> "\\emph{ has}\\footnote{2-paragraph1\n\n 2-paragraph2}"+ <> "\\emph{ footnote.}"+ ] , testGroup "writer options" [ testGroup "top-level division" $ let@@ -173,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}" ] ]
@@ -41,11 +41,14 @@ tests :: [TestTree] tests = [ "indented code after list" =: (orderedList [ para "one" <> para "two" ] <> codeBlock "test")- =?> "1. one\n\n two\n\n```{=html}\n<!-- -->\n```\n test"+ =?> "1. one\n\n two\n\n<!-- -->\n\n test" , "list with tight sublist" =: bulletList [ plain "foo" <> bulletList [ plain "bar" ], plain "baz" ]- =?> "- foo\n - bar\n- baz\n"+ =?> "- foo\n - bar\n- baz\n"+ , "emph/strong with spaces (#10696)"+ =: emph (str "f" <> strong (space <> str "d" <> space)) <> str "l" =?>+ "*f **d*** l" ] ++ [noteTests] ++ [shortcutLinkRefsTests] {-
@@ -430,7 +430,6 @@ , "div with bullet list" =: divWith nullAttr (bulletList [para "foo"]) =?> unlines [ " - foo" ] -- Making sure bullets are indented- -- Null is trivial ] , testGroup "inline elements" [ testGroup "string"
@@ -45,6 +45,11 @@ (Comparison { mine = sort (elAttribs myElem) , good = sort (elAttribs goodElem) })))+ <|> (if length (elContent myElem) == length (elContent goodElem)+ then Nothing+ else Just+ (ElemChildrenDiffer+ (Comparison { mine = elContent myElem, good = elContent goodElem}))) <|> asum (zipWith compareXML (elContent myElem) (elContent goodElem)) compareXML (Text goodCData) (Text myCData) = (if cdVerbatim myCData == cdVerbatim goodCData@@ -60,6 +65,7 @@ data XMLDifference = ElemNamesDiffer (Comparison QName) | ElemAttributesDiffer (Comparison [Attr])+ | ElemChildrenDiffer (Comparison [Content]) | CDatasDiffer (Comparison CData) | CRefsDiffer (Comparison String) | OtherContentsDiffer (Comparison Content)
@@ -102,6 +102,14 @@ def "pptx/two-column/text-and-image/input.native" "pptx/two-column/text-and-image/output.pptx"+ , pptxTests "single column text"+ def+ "pptx/single-column/text/input.native"+ "pptx/single-column/text/output.pptx"+ , pptxTests "single column image"+ def+ "pptx/single-column/image/input.native"+ "pptx/single-column/image/output.pptx" , pptxTests "speaker notes" def "pptx/speaker-notes/input.native"@@ -118,6 +126,10 @@ def "pptx/speaker-notes-after-metadata/input.native" "pptx/speaker-notes-after-metadata/output.pptx"+ , pptxTests "speaker notes from metadata field"+ def+ "pptx/metadata-speaker-notes/input.native"+ "pptx/metadata-speaker-notes/output.pptx" , pptxTests "remove empty slides" def "pptx/remove-empty-slides/input.native"@@ -268,5 +280,17 @@ def {writerReferenceDoc = Just "pptx/reference-deleted-layouts.pptx"} "pptx/layouts/input.native" "pptx/layouts/deleted.pptx"+ , ooxmlTest+ writePowerpoint+ "Slides can be missing from the reference doc"+ def {writerReferenceDoc = Just "pptx/reference-no-slides.pptx"}+ "pptx/reference-no-slides/add-slides/input.native"+ "pptx/reference-no-slides/add-slides/output.pptx"+ , ooxmlTest+ writePowerpoint+ "Notes are placed at the right position with a reference doc without slides"+ def {writerReferenceDoc = Just "pptx/reference-no-slides.pptx"}+ "pptx/reference-no-slides/with-notes/input.native"+ "pptx/reference-no-slides/with-notes/output.pptx" ] in regularTests <> referenceSpecificTests
@@ -32,7 +32,7 @@ tests = [ testGroup "rubrics" [ "in list item" =: bulletList [header 2 (text "foo")] =?>- "- .. rubric:: foo"+ "- .. rubric:: foo" , "in definition list item" =: definitionList [(text "foo", [header 2 (text "bar"), para $ text "baz"])] =?>@@ -60,7 +60,7 @@ [ "a list is closed by a comment before a quote" =: -- issue 4248 bulletList [plain "bulleted"] <> blockQuote (plain "quoted") =?> unlines- [ "- bulleted"+ [ "- bulleted" , "" , ".." , ""
@@ -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]
@@ -0,0 +1,122 @@+[1m[23m[39m[49m[24m[29mLEVEL 1 HEADING[0m++Text++[1m[23m[39m[49m[24m[29mLevel 2 heading[0m++Text++[22m[3m[39m[49m[24m[29mLevel 3 heading[0m++Text++[22m[3m[39m[49m[24m[29mLevel 4 heading[0m++Text++[22m[3m[39m[49m[24m[29mLevel 5 heading[0m++Text++• list++ • nested++ 1) numbered++ continuation paragraph++[22m[23m[36m[49m[4m[29m]8;;http://example.com\link[0m]8;;\++[22m[23m[36m[49m[4m[29m]8;;mailto:mail@example.com\mail@example.com[0m]8;;\++│ Block quote+│+│ │ Nested block quote++Multiline table with caption:++Centered Left Right Default aligned+Header Aligned Aligned +─────────── ────────── ──────────── ──────────────────────────+First row 12.0 Example of a row that+ spans multiple lines.+Second row 5.0 Here’s another one. Note+ the blank line between+ rows.+─────────── ────────── ──────────── ──────────────────────────++ Here’s the caption. It may span multiple lines.++Multiline table without caption:++Centered Left Right Default aligned+Header Aligned Aligned +─────────── ────────── ──────────── ──────────────────────────+First row 12.0 Example of a row that+ spans multiple lines.+Second row 5.0 Here’s another one. Note+ the blank line between+ rows.+─────────── ────────── ──────────── ──────────────────────────++Table without column headers:++───────────────── ───────────────── ───────────────── ─────────────────+12 12 12 12+123 123 123 123+1 1 1 1+───────────────── ───────────────── ───────────────── ─────────────────++Footnote¹++Multiple blocks in a cell++────────────────── ─────────── ────────────+[1m[23m[39m[49m[24m[29mCOL 1[0m [1m[23m[39m[49m[24m[29mCOL 2[0m [1m[23m[39m[49m[24m[29mCOL 3[0m+ +col 1 col 2 col 3+r1 a • b c c 2 c 2+ +r1 bis • b 2 + + • b 2 +────────────────── ─────────── ────────────++East Asian characters have double width++── ────+魚 fish+── ────++This is inline code: [22m[23m[31m[47m[24m[29m x >>= y ++ 3 [0m.++ [22m[23m[31m[49m[24m[29mcode block[0m+ [22m[23m[31m[49m[24m[29m >>> ## ``[0m++Highlighted:++ [0m[0m[22;23;24m[31;22;23;24m<[0m[22;23;24m[32;1;23;24mp[0m[22;23;24m[31;22;23;24m><[0m[22;23;24m[32;1;23;24ma[0m[22;23;24m[32;22;23;24m href[0m[22;23;24m[90;22;23;24m=[0m[22;23;24m[36;22;23;24m"foobar"[0m[22;23;24m[32;22;23;24m title[0m[22;23;24m[90;22;23;24m=[0m[22;23;24m[36;22;23;24m"title"[0m[22;23;24m[31;22;23;24m>[0m[22;23;24m[0m[22;23;24mThis is a link[0m[22;23;24m[31;22;23;24m</[0m[22;23;24m[32;1;23;24ma[0m[22;23;24m[31;22;23;24m></[0m[22;23;24m[32;1;23;24mp[0m[22;23;24m[31;22;23;24m>[0m[22;23;24m+ [90;22;3;24m<!-- comment -->[0m[22;23;24m[0m++Math: $\pi^2 = \frac{1}{2}$++[22m[3m[39m[49m[24m[29me[0m = [22m[3m[39m[49m[24m[29mmc[0m²++────────────────────++More text.++[1m[23m[39m[49m[24m[29mboldface text[0m, [22m[23m[39m[49m[4m[29munderlined text[0m, [22m[3m[39m[49m[24m[29memphasized text[0m.++small caps++We see a log₁₀ reduction in 2⁹ seconds.++Hello++Goodbye++ ────────────────────++ 1. Here’s the note.[0m]8;;\
@@ -0,0 +1,127 @@+---+title: My Document+author: John Doe+date: July 25, 1933+...++# Level 1 heading++Text++## Level 2 heading++Text++### Level 3 heading++Text++#### Level 4 heading++Text++##### Level 5 heading++Text++- list+ - nested+ 1) numbered++ continuation paragraph++[link](http://example.com)++<mail@example.com>++> Block quote+>+> > Nested block quote++Multiline table with caption:++: Here's the caption.+It may span multiple lines.++---------------------------------------------------------------+ Centered Left Right+ Header Aligned Aligned Default aligned+---------- --------- ----------- ---------------------------+ First row 12.0 Example of a row that spans+ multiple lines.++ Second row 5.0 Here's another one. Note+ the blank line between rows.+---------------------------------------------------------------++Multiline table without caption:++---------------------------------------------------------------+ Centered Left Right+ Header Aligned Aligned Default aligned+---------- --------- ----------- ---------------------------+ First row 12.0 Example of a row that spans+ multiple lines.++ Second row 5.0 Here's another one. Note+ the blank line between rows.+---------------------------------------------------------------++Table without column headers:++------- ------ ---------- -------+ 12 12 12 12+ 123 123 123 123+ 1 1 1 1+------- ------ ---------- -------++Footnote^[Here's the note.]++Multiple blocks in a cell+++------------------+-----------+------------++| # col 1 | # col 2 | # col 3 |+| col 1 | col 2 | col 3 |++------------------+-----------+------------++| r1 a | - b | c |+| | - b 2 | c 2 |+| r1 bis | - b 2 | c 2 |++------------------+-----------+------------+++East Asian characters have double width+++--+----++|魚|fish|++--+----+++This is inline code: `x >>= y ++ 3`.++```+code block+ >>> ## ``+```++Highlighted:++```html+<p><a href="foobar" title="title">This is a link</a></p>+<!-- comment -->+```++Math: $\pi^2 = \frac{1}{2}$++$$e = mc^2$$++----++More text.++**boldface text**, [underlined text]{.underline}, *emphasized text*.++[small caps]{.smallcaps}++We see a log~10~ reduction in 2^9^ seconds.++| Hello+|+| Goodbye
@@ -0,0 +1,4 @@+This is a test!++. one+.. two
@@ -0,0 +1,4 @@+# A function+def foo+ return 42+end
@@ -0,0 +1,908 @@+// Some comment here.+= AsciiDoc reader test+John MacFarlane <jgm@berkeley.edu>; John Doe <doe@example.com>+v1.0, 2025-11-24+:custom: Foo bar \+baz+:flag:+:stem: latexmath++[#firsty]+== Inline markup++=== Characters and escapes++Dog's has a curved apostrophe, but dog\'s does not.++An escaped symbol: \*star\*.++Character references: ä ⋠ ++=== Line breaks++This is a hard ++break.++Or set it for a whole paragraph++[%hardbreaks]+These are+all+hard+breaks.++=== Autolinks++http://example.com/foobar?a=333&b=no%20body, me@example.com++<http://example.com/foobar?a=333&b=no%20body>, <me@example.com>++=== Cross-reference++See <<firsty>>++See <<firsty,My great section on Inline markup>>++Go to <<anch,an inline anchor>>++=== Anchors++An [[anch]]inline anchor.++[[[bibanchor]]Doe, John. A Book.++=== Inline macros++kbd:[F11]++kbd:[Ctrl+Shift+F]++menu:File[Save]++menu:Reader[Markdown > Pandoc]++btn:[Cancel]++icon:heart[2x,role=red]++anchor:tiger++pass:[<b>*bold*</b>]++link:downloads/report.pdf[Get Report]++link:tools.html#editors[]++link:file:///home/username[Your files]++Tricky cases:++link:pass:[My Documents/report.pdf][Get Report]++link:My Documents/report.pdf[Get Report]++link:My%20Documents/report.pdf[Get Report]++link:++https://example.org/now_this__link_works.html++[]++mailto:join@discuss.example.org[Subscribe]++mailto:join@discuss.example.org["Click, subscribe, and participate!",role=mail]++xref:link-macro-attributes[use attributes within the link macro]++image::sunset.jpg[Sunset]++image::name.png[]++image::sunset.jpg[Sunset,300,400]++image::sunset.jpg[alt=Sunset,width=300,height=400]++[latexmath]++++++e=mc^2+++++++[asciimath]++++++sin n / 3+++++++[stem]++++++e^i+++++++=== Attribute substitutions++{custom}++{nonexistent}++Built in: x{blank}y{empty}z{sp}a{nbsp}b{zwsp}c{apos}d{lsquo}++=== Bold and italic++Constrained: *this is bold _and italic_*.++Unconstrained: wild**content__with italic__stuff**.++=== Monospace++`simple`++`complex *with bold* text and a link:foo.html[]`++unconstrained``wwow``okay++=== Span and inline attributes++[.red]#Bonjour *monsieur*#++Un[.red]##constrained##content++With #no attribute# it's highlighted.++=== Sub and superscript++H~2~O++H~a{sp}b~O++Not subscript: H~a b~O.++H^2&O++H^a{sp}b^O++Not subscript: H^a b^O.++=== Passthrough++Here the special characters just come through as literal:+++<b>*test*</b>+++xx++<b>*test*</b>++xx++But here they are passed through:++xx+++<b>*test*</b>+++xx++=== Quoted++"`double quoted`"++'`single quoted`'++=== Footnotes++Doublefootnote:[The double hail-and-rainbow level makes my toes tingle.]++A bold statement!footnote:disclaimer[Opinions are my own.]+Another outrageous statement.footnote:disclaimer[]++== Block markup++=== Sections++==== Another level++===== Level 5++#### Markdown style++##### Level 5++=== Discrete heading++[discrete]+==== A discrete heading, not a section++=== Paragraph++This is a paragraph+whose source fits on two lines.++{.This is my title}+A paragraph with a title.++=== Example block++.Optional title+[example]+This is an example of an example block.++.Optional title+====+Paragraph *one*.++Paragraph *two*.+====++=== Admonition++Simple form:++WARNING: This is very dangerous.+Don't do it unless you understand the risks.++[IMPORTANT]+.Title of the admonition+====+Remember:++. Don't do this.+. And don't do that.+====++=== Sidebar++[sidebar]+A simple sidebar.++.Optional Title *with strong emphasis*+****+Here is a sidebar.++TIP: It can contain any type of content.+****++=== Literal block++Short indented code:++ $ ls -a+ $ cat /foo/bar/baz \+ /bi/bim/bop++[literal]+This is+ a literal block too.++....+ Fenced+ $+ *a* literal++****+not a sidebar+****+....++=== Listing++[source,ruby]+----+require 'sinatra'++get '/hi' do+ "Hello World!"+end+----++Implied:++[source,ruby]+----+require 'sinatra'++get '/hi' do+ "Hello World!"+end+----++[,ruby]+----+include::asciidoc-reader-include.rb[]+----++[#hello.haskell]+----+putStrLn $ unwords ["Hello", "world"]+----++Line numbering:++[%linenums,ruby]+----+puts 1+puts 2+puts 3+----++----+This doesn't have a language.+ +="hi"+----++And with a callout list:++[source,ruby]+----+require 'sinatra' <1>++get '/hi' do <2> <3>+ "Hello World!"+end+----+<1> Library import+<2> URL mapping+<3> Response block++Markdown-style fenced:++```ruby+def foo+ return 5+end+```++=== Verse++[verse,Carl Sandburg, two lines from the poem Fog]+The fog comes+on little cat feet.++[verse,Carl Sandburg,Fog]+____+The fog comes+on little cat feet.+It sits looking+over harbor and city+on silent haunches+and then moves on.+____++=== Collapsible++Click here for more.+[%collapsible%open]+====+This is collapsible.++It can be hidden.+====++.Click me!+[%collapsible]+This paragraph is+also collapsible.++=== Quote++[quote,Captain James T. Kirk,Star Trek IV: The Voyage Home]+Everybody remember where we parked.++[quote,Monty Python and the Holy Grail]+____+Dennis: Come and see the violence inherent in the system. Help! Help! I'm being+repressed.++King Arthur: Bloody peasant!++Dennis: Oh, what a giveaway! Did you hear that? Did you hear that, eh? That's what I'm+on about! Did you see him repressing me? You saw him, Didn't you?+____++[quote.movie#roads,Dr. Emmett Brown]+____+Roads? Where we're going, we don't need roads.+____++=== Pass+++++++<p>pass <em>through</em>+ </p>+++++++=== Open block++.A title.+[key="a value"]+--+Any content can go here:++. one+. two+--++=== Anchor++[[goals]]+* one+* two++=== Breaks++Asciidoc thematic break:++'''++Markdown style:++---+- - -+***+* * *++Page breaks:++<<<++[%always]+<<<++=== List++* Edgar Allan Poe+* Sheri S. Tepper+* Bill Bryson++// titled++.Kizmet's Favorite Authors+* Edgar Allan Poe+* Sheri S. Tepper+* Bill Bryson++// hyphen++- Edgar Allan Poe+- Sheri S. Tepper+- Bill Bryson++. Nested list+* West wood maze+** Maze heart+*** Reflection pool+** Secret exit+* Level 1 list item+** Level 2 list item+*** Level 3 list item+**** Level 4 list item+***** Level 5 list item+****** etc.+* Level 1 list item++// attributes++[square]+* one+* two+* three++// ordered with actual numbers++1. Protons+2. Electrons+3. Neutrons++// ordered with .++. Protons+. Electrons+. Neutrons++Start with 4:++4. Step four+5. Step five+6. Step six++or++[start=4]+. Step four+. Step five+. Step six++Reversed:++[%reversed]+.Parts of an atom+. Protons+. Electrons+. Neutrons++Nested++. Step 1+. Step 2+.. Step 2a+.. Step 2b+. Step 3++Mixed nested++. Linux+* Fedora+* Ubuntu+* Slackware+. BSD+* FreeBSD+* NetBSD++With spacing++. Linux+* Fedora+* Ubuntu+* Slackware+. BSD+* FreeBSD+* NetBSD++With number styles++[lowerroman,start=5]+. Five+. Six+[loweralpha]+.. a+.. b+.. c+. Seven++Checklist++* [*] checked+* [x] also checked+* [ ] not checked+* normal list item++Separate lists with block attribute++* Apples+* Oranges+[]+. Wash+. Slice++Multiline items++* Blah blah.+Blah blah.+* The document header in AsciiDoc is optional.+If present, it must start with a document title.++* Optional author and revision information lines+immediately follow the document title.++* The document header must be separated from+ the remainder of the document by one or more+ empty lines and it cannot contain empty lines.++Complex item++* The header in AsciiDoc must start with a document title.+++----+= Document Title+----+++Keep in mind that the header is optional.+* Optional author and revision information lines immediately follow the document+title.+++----+= Document Title+Doc Writer <doc.writer@asciidoc.org>+v1.0, 2022-01-01+----+* Second item++Empty principle element:++. {empty}+++----+test+----++=== Table++==== Simple with column specs++[cols="3,2,3"]+|===+|This content is placed in the first cell of column 1+|This line starts with a vertical bar so this content is placed in a new cell in+column 2 |When the processor encounters a whitespace followed by a vertical bar it+ends the previous cell and starts a new cell+|===++==== Repeated column in specs++[cols="2*"]+|===+>s|This cell's specifier indicates that this cell's content is right-aligned and bold.+|The cell specifier on this cell hasn't been set explicitly, so the default+properties are applied.+|===++==== Simple without column specs++|===+|Column 1, header row |Column 2, header row++|Cell in column 1, row 2+|Cell in column 2, row 2++|Cell in column 1, row 3+|Cell in column 2, row 3+|===++==== With caption++.My cool table.+|===+|Column 1, header row |Column 2, header row++|Cell in column 1, row 2+|Cell in column 2, row 2++|Cell in column 1, row 3+|Cell in column 2, row 3+|===++==== No header++By default the first line should turn into the header, but this+can be disabled:++[%noheader]+|===+|Cell in column 1, row 1 |Cell in column 2, row 1+|Cell in column 1, row 2 |Cell in column 2, row 2+|===++And also explicitly enabled:++[%header%footer%autowidth,cols=2*~]+|===+|Cell A1 |Cell B1+|Cell A2 |Cell B2+|Cell A3 |Cell B3+|===++==== Footer++[%header%footer,cols="2,2,1"]+|===+|Column 1, header row+|Column 2, header row+|Column 3, header row+|Cell in column 1, row 2+|Cell in column 2, row 2+|Cell in column 3, row 2+|Column 1, footer row+|Column 2, footer row+|Column 3, footer row+|===++or++[options="footer"]+|===+|Column 1, header row |Column 2, header row+|Cell in column 1, row 2+|Cell in column 2, row 2+|Cell in column 1, row 3+|Cell in column 2, row 3+|Column 1, footer row+|Column 2, footer row+|===++==== Alignment++|===+|Column Name |Column Name+2+^|This cell spans two columns, and its content is horizontally centered because the+cell specifier includes the `+^+` operator.+2*^|This content is duplicated in two adjacent columns.+Its content is horizontally centered because the cell specifier+includes the `+^+` operator.+|===++==== Multiple paragraphs in cells++|===++|Single paragraph on row 1++|First paragraph on row 2++Second paragraph on row 2+|===++==== Complex table++|===++2*>m|This content is duplicated across two columns.++It is aligned right horizontally.++And it is monospaced.++.3+^.>s|This cell spans 3 rows. The content is centered horizontally, aligned to the bottom of the cell, and strong.+e|This content is emphasized.++.^l|This content is aligned to the top of the cell and literal.++a|+[source]+puts "This is a source block!"++|===++==== Column styles++[cols="m,m"]+|===+|monospace | mono+d|default | mono+|===++==== Block elements in cells++|===+|Normal Style |AsciiDoc Style+|This cell isn't prefixed with an `a`, so the processor doesn't interpret the+following lines as an AsciiDoc list.++* List item 1+* List item 2+* List item 3++a|This cell is prefixed with an `a`, so the processor interprets the following lines+as an AsciiDoc list.++* List item 1+* List item 2+* List item 3++|This cell isn't prefixed with an `a`, so the processor doesn't interpret the listing+block delimiters or the `source` style.++[source,python]+----+import os+print ("%s" %(os.uname()))+----++a|This cell is prefixed with an `a`, so the listing block is processed and rendered+according to the `source` style rules.++[source,python]+----+import os+print "%s" %(os.uname())+----+|===++==== Col and rowspan++|===+|Column 1, header row |Column 2, header row | Column 3, header row+2.2+|This cell spans 2 cols and 2 rows+|Cell in column 3, row 2+|Cell in column 3, row 3+3+|Cell in column 1-3, row 4+|===++==== CSV table++[%header,format=csv]+|===+Artist,Track,Genre+Baauer,Harlem Shake,Hip Hop+The Lumineers,Ho Hey,Folk Rock+|===++or++,===+Artist,Track,Genre+Baauer,Harlem Shake,Hip Hop+,===++==== DSV table++[format=dsv,separator=;]+|===+a;b;c+d;e;f+|===++or++:===+Artist:Track:Genre+Robyn:Indestructible:Dance+:===++=== Definition list++CPU:: The brain of the computer.+Hard drive:: Permanent storage for operating system and/or user files.++Mixed++Dairy::+* Milk+* Eggs+Bakery::+* Bread+Produce::+* Bananas++With spaces++Dairy::++ * Milk+ * Eggs++Bakery::++ * Bread++Produce::++ * Bananas++Nested++Operating Systems::+Linux:::+ . Fedora+ * Desktop+ . Ubuntu+ * Desktop+ * Server+BSD:::+ . FreeBSD+ . NetBSD+Cloud Providers::+ PaaS:::+ . OpenShift+ . CloudBees+ IaaS:::+ . Amazon EC2++This just affects the output:++[horizontal,labelwidth=25,itemwidth=75]+CPU:: The brain of the computer.+RAM:: Temporarily stores information the CPU uses during operation.++Q&A list++[qanda]+What is the answer?::+This is the answer.+Are cameras allowed?::+Are backpacks allowed?::+No.++Ordered description list (with numbers)++[ordered]+&:: ampersand+>:: greater than++=== Block macros++image::sunset.jpg[Sunset,300,200]++video::mymovie.mp4[]++audio::mysong.mp3[]++toc::[]++include::asciidoc-reader-include.adoc[]+
@@ -0,0 +1,4418 @@+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "author"+ , MetaList+ [ MetaInlines+ [ Str "John"+ , Space+ , Str "MacFarlane"+ , Space+ , Str "("+ , Link+ ( "" , [] , [] )+ [ Str "jgm@berkeley.edu" ]+ ( "mailto:jgm@berkeley.edu" , "" )+ , Str ")"+ ]+ , MetaInlines+ [ Str "John"+ , Space+ , Str "Doe"+ , Space+ , Str "("+ , Link+ ( "" , [] , [] )+ [ Str "doe@example.com" ]+ ( "mailto:doe@example.com" , "" )+ , Str ")"+ ]+ ]+ )+ , ( "custom" , MetaString "Foo bar baz" )+ , ( "date" , MetaString "2025-11-24" )+ , ( "flag" , MetaBool True )+ , ( "title"+ , MetaInlines+ [ Str "AsciiDoc"+ , Space+ , Str "reader"+ , Space+ , Str "test"+ ]+ )+ , ( "version" , MetaString "1.0" )+ ]+ }+ [ Header+ 1+ ( "firsty" , [] , [] )+ [ Str "Inline" , Space , Str "markup" ]+ , Header+ 2+ ( "_characters_and_escapes" , [] , [] )+ [ Str "Characters"+ , Space+ , Str "and"+ , Space+ , Str "escapes"+ ]+ , Para+ [ Str "Dog\8217s"+ , Space+ , Str "has"+ , Space+ , Str "a"+ , Space+ , Str "curved"+ , Space+ , Str "apostrophe,"+ , Space+ , Str "but"+ , Space+ , Str "dog's"+ , Space+ , Str "does"+ , Space+ , Str "not."+ ]+ , Para+ [ Str "An"+ , Space+ , Str "escaped"+ , Space+ , Str "symbol:"+ , Space+ , Str "*star*."+ ]+ , Para+ [ Str "Character"+ , Space+ , Str "references:"+ , Space+ , Str "\228\160\8928"+ ]+ , Header+ 2+ ( "_line_breaks" , [] , [] )+ [ Str "Line" , Space , Str "breaks" ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "hard"+ , LineBreak+ , Str "break."+ ]+ , Para+ [ Str "Or"+ , Space+ , Str "set"+ , Space+ , Str "it"+ , Space+ , Str "for"+ , Space+ , Str "a"+ , Space+ , Str "whole"+ , Space+ , Str "paragraph"+ ]+ , Div+ ( ""+ , []+ , [ ( "wrapper" , "1" ) , ( "options" , "hardbreaks" ) ]+ )+ [ Para+ [ Str "These"+ , Space+ , Str "are"+ , LineBreak+ , Str "all"+ , LineBreak+ , Str "hard"+ , LineBreak+ , Str "breaks."+ ]+ ]+ , Header 2 ( "_autolinks" , [] , [] ) [ Str "Autolinks" ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "http://example.com/foobar?a=333&b=no%20body" ]+ ( "http://example.com/foobar?a=333&b=no%20body" , "" )+ , Str ","+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "me@example.com" ]+ ( "me@example.com" , "" )+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "http://example.com/foobar?a=333&b=no%20body" ]+ ( "http://example.com/foobar?a=333&b=no%20body" , "" )+ , Str ","+ , Space+ , Str "<"+ , Link+ ( "" , [] , [] )+ [ Str "me@example.com" ]+ ( "me@example.com" , "" )+ , Str ">"+ ]+ , Header+ 2 ( "_cross_reference" , [] , [] ) [ Str "Cross-reference" ]+ , Para+ [ Str "See"+ , Space+ , Link+ ( "" , [ "cross-reference" ] , [] )+ [ Str "Inline" , Space , Str "markup" ]+ ( "#firsty" , "" )+ ]+ , Para+ [ Str "See"+ , Space+ , Link+ ( "" , [ "cross-reference" ] , [] )+ [ Str "My"+ , Space+ , Str "great"+ , Space+ , Str "section"+ , Space+ , Str "on"+ , Space+ , Str "Inline"+ , Space+ , Str "markup"+ ]+ ( "#firsty" , "" )+ ]+ , Para+ [ Str "Go"+ , Space+ , Str "to"+ , Space+ , Link+ ( "" , [ "cross-reference" ] , [] )+ [ Str "an" , Space , Str "inline" , Space , Str "anchor" ]+ ( "#anch" , "" )+ ]+ , Header 2 ( "_anchors" , [] , [] ) [ Str "Anchors" ]+ , Para+ [ Str "An"+ , Space+ , Span ( "anch" , [] , [] ) []+ , Str "inline"+ , Space+ , Str "anchor."+ ]+ , Para+ [ Span ( "[bibanchor" , [] , [] ) []+ , Str "Doe,"+ , Space+ , Str "John."+ , Space+ , Str "A"+ , Space+ , Str "Book."+ ]+ , Header+ 2+ ( "_inline_macros" , [] , [] )+ [ Str "Inline" , Space , Str "macros" ]+ , Para+ [ Span ( "" , [ "kbd" ] , [] ) [ Strong [ Str "F11" ] ] ]+ , Para+ [ Span ( "" , [ "kbd" ] , [] ) [ Strong [ Str "Ctrl" ] ]+ , Str "+"+ , Span ( "" , [ "kbd" ] , [] ) [ Strong [ Str "Shift" ] ]+ , Str "+"+ , Span ( "" , [ "kbd" ] , [] ) [ Strong [ Str "F" ] ]+ ]+ , Para+ [ Span+ ( "" , [ "menu" ] , [] )+ [ Strong [ Str "File\160\8250\160Save" ] ]+ ]+ , Para+ [ Span+ ( "" , [ "menu" ] , [] )+ [ Strong+ [ Str "Reader\160\8250\160Markdown\160\8250\160Pandoc" ]+ ]+ ]+ , Para+ [ Span+ ( "" , [ "button" ] , [] ) [ Strong [ Str "[Cancel]" ] ]+ ]+ , Para+ [ Image+ ( "" , [ "red icon" ] , [] )+ []+ ( "./images/icons/heart.png" , "" )+ ]+ , Para [ Str "anchor:tiger" ]+ , Para [ Strong [ Str "*bold*" ] ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "Get" , Space , Str "Report" ]+ ( "downloads/report.pdf" , "" )+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "tools.html#editors" ]+ ( "tools.html#editors" , "" )+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "Your" , Space , Str "files" ]+ ( "file:///home/username" , "" )+ ]+ , Para [ Str "Tricky" , Space , Str "cases:" ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "Get" , Space , Str "Report" ]+ ( "My Documents/report.pdf" , "" )+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "Get" , Space , Str "Report" ]+ ( "My Documents/report.pdf" , "" )+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "Get" , Space , Str "Report" ]+ ( "My%20Documents/report.pdf" , "" )+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "https://example.org/now_this__link_works.html" ]+ ( "https://example.org/now_this__link_works.html" , "" )+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "Subscribe" ]+ ( "join@discuss.example.org" , "" )+ ]+ , Para+ [ Link+ ( "" , [ "mail" ] , [] )+ [ Str "Click,"+ , Space+ , Str "subscribe,"+ , Space+ , Str "and"+ , Space+ , Str "participate!"+ ]+ ( "join@discuss.example.org" , "" )+ ]+ , Para+ [ Link+ ( "" , [ "cross-reference" ] , [] )+ [ Str "use"+ , Space+ , Str "attributes"+ , Space+ , Str "within"+ , Space+ , Str "the"+ , Space+ , Str "link"+ , Space+ , Str "macro"+ ]+ ( "#link-macro-attributes" , "" )+ ]+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [])+ [ Plain+ [ Image+ ( "" , [] , [] ) [ Str "Sunset" ] ( "sunset.jpg" , "" )+ ]+ ]+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [])+ [ Plain [ Image ( "" , [] , [] ) [] ( "name.png" , "" ) ] ]+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [])+ [ Plain+ [ Image+ ( ""+ , []+ , [ ( "width" , "300px" ) , ( "height" , "400px" ) ]+ )+ [ Str "Sunset" ]+ ( "sunset.jpg" , "" )+ ]+ ]+ , Div+ ( ""+ , []+ , [ ( "wrapper" , "1" )+ , ( "alt" , "Sunset" )+ , ( "height" , "400" )+ , ( "width" , "300" )+ ]+ )+ [ Figure+ ( "" , [] , [] )+ (Caption Nothing [])+ [ Plain [ Image ( "" , [] , [] ) [] ( "sunset.jpg" , "" ) ]+ ]+ ]+ , Para [ Math DisplayMath "e=mc^2\n" ]+ , Para [ Math DisplayMath "sin n / 3\n" ]+ , Para [ Math DisplayMath "e^i\n" ]+ , Header+ 2+ ( "_attribute_substitutions" , [] , [] )+ [ Str "Attribute" , Space , Str "substitutions" ]+ , Para [ Str "Foo" , Space , Str "bar" , Space , Str "baz" ]+ , Para [ Str "{nonexistent}" ]+ , Para+ [ Str "Built"+ , Space+ , Str "in:"+ , Space+ , Str "xyz"+ , Space+ , Str "a\160b\8203c'd\8216"+ ]+ , Header+ 2+ ( "_bold_and_italic" , [] , [] )+ [ Str "Bold" , Space , Str "and" , Space , Str "italic" ]+ , Para+ [ Str "Constrained:"+ , Space+ , Strong+ [ Str "this"+ , Space+ , Str "is"+ , Space+ , Str "bold"+ , Space+ , Emph [ Str "and" , Space , Str "italic" ]+ ]+ , Str "."+ ]+ , Para+ [ Str "Unconstrained:"+ , Space+ , Str "wild"+ , Strong+ [ Str "content"+ , Emph [ Str "with" , Space , Str "italic" ]+ , Str "stuff"+ ]+ , Str "."+ ]+ , Header 2 ( "_monospace" , [] , [] ) [ Str "Monospace" ]+ , Para [ Code ( "" , [] , [] ) "simple" ]+ , Para+ [ Code ( "" , [] , [] ) "complex"+ , Space+ , Strong+ [ Code ( "" , [] , [] ) "with"+ , Space+ , Code ( "" , [] , [] ) "bold"+ ]+ , Space+ , Code ( "" , [] , [] ) "text"+ , Space+ , Code ( "" , [] , [] ) "and"+ , Space+ , Code ( "" , [] , [] ) "a"+ , Space+ , Link+ ( "" , [] , [] )+ [ Code ( "" , [] , [] ) "foo.html" ]+ ( "foo.html" , "" )+ ]+ , Para+ [ Str "unconstrained"+ , Code ( "" , [] , [] ) "wwow"+ , Str "okay"+ ]+ , Header+ 2+ ( "_span_and_inline_attributes" , [] , [] )+ [ Str "Span"+ , Space+ , Str "and"+ , Space+ , Str "inline"+ , Space+ , Str "attributes"+ ]+ , Para+ [ Span+ ( "" , [ "red" ] , [] )+ [ Str "Bonjour" , Space , Strong [ Str "monsieur" ] ]+ ]+ , Para+ [ Str "Un"+ , Span ( "" , [ "red" ] , [] ) [ Str "constrained" ]+ , Str "content"+ ]+ , Para+ [ Str "With"+ , Space+ , Span+ ( "" , [ "mark" ] , [] )+ [ Str "no" , Space , Str "attribute" ]+ , Space+ , Str "it\8217s"+ , Space+ , Str "highlighted."+ ]+ , Header+ 2+ ( "_sub_and_superscript" , [] , [] )+ [ Str "Sub"+ , Space+ , Str "and"+ , Space+ , Str "superscript"+ ]+ , Para [ Str "H" , Subscript [ Str "2" ] , Str "O" ]+ , Para+ [ Str "H"+ , Subscript [ Str "a" , Space , Str "b" ]+ , Str "O"+ ]+ , Para+ [ Str "Not"+ , Space+ , Str "subscript:"+ , Space+ , Str "H~a"+ , Space+ , Str "b~O."+ ]+ , Para [ Str "H^2&O" ]+ , Para+ [ Str "H"+ , Superscript [ Str "a" , Space , Str "b" ]+ , Str "O"+ ]+ , Para+ [ Str "Not"+ , Space+ , Str "subscript:"+ , Space+ , Str "H^a"+ , Space+ , Str "b^O."+ ]+ , Header+ 2 ( "_passthrough" , [] , [] ) [ Str "Passthrough" ]+ , Para+ [ Str "Here"+ , Space+ , Str "the"+ , Space+ , Str "special"+ , Space+ , Str "characters"+ , Space+ , Str "just"+ , Space+ , Str "come"+ , Space+ , Str "through"+ , Space+ , Str "as"+ , Space+ , Str "literal:"+ ]+ , Para [ Str "<b>*test*</b>" ]+ , Para [ Str "xx<b>*test*</b>xx" ]+ , Para+ [ Str "But"+ , Space+ , Str "here"+ , Space+ , Str "they"+ , Space+ , Str "are"+ , Space+ , Str "passed"+ , Space+ , Str "through:"+ ]+ , Para [ Str "xx" , Strong [ Str "*test*" ] , Str "xx" ]+ , Header 2 ( "_quoted" , [] , [] ) [ Str "Quoted" ]+ , Para+ [ Quoted DoubleQuote [ Str "double" , Space , Str "quoted" ]+ ]+ , Para+ [ Quoted SingleQuote [ Str "single" , Space , Str "quoted" ]+ ]+ , Header 2 ( "_footnotes" , [] , [] ) [ Str "Footnotes" ]+ , Para+ [ Str "Double"+ , Note+ [ Para+ [ Str "The"+ , Space+ , Str "double"+ , Space+ , Str "hail-and-rainbow"+ , Space+ , Str "level"+ , Space+ , Str "makes"+ , Space+ , Str "my"+ , Space+ , Str "toes"+ , Space+ , Str "tingle."+ ]+ ]+ ]+ , Para+ [ Str "A"+ , Space+ , Str "bold"+ , Space+ , Str "statement!"+ , Note+ [ Para+ [ Str "Opinions"+ , Space+ , Str "are"+ , Space+ , Str "my"+ , Space+ , Str "own."+ ]+ ]+ , SoftBreak+ , Str "Another"+ , Space+ , Str "outrageous"+ , Space+ , Str "statement."+ , Note+ [ Para+ [ Str "Opinions"+ , Space+ , Str "are"+ , Space+ , Str "my"+ , Space+ , Str "own."+ ]+ ]+ ]+ , Header+ 1+ ( "_block_markup" , [] , [] )+ [ Str "Block" , Space , Str "markup" ]+ , Header 2 ( "_sections" , [] , [] ) [ Str "Sections" ]+ , Header+ 3+ ( "_another_level" , [] , [] )+ [ Str "Another" , Space , Str "level" ]+ , Header+ 4 ( "_level_5" , [] , [] ) [ Str "Level" , Space , Str "5" ]+ , Header+ 3+ ( "_markdown_style" , [] , [] )+ [ Str "Markdown" , Space , Str "style" ]+ , Header+ 4+ ( "_level_5_2" , [] , [] )+ [ Str "Level" , Space , Str "5" ]+ , Header+ 2+ ( "_discrete_heading" , [] , [] )+ [ Str "Discrete" , Space , Str "heading" ]+ , Header+ 3+ ( "" , [] , [] )+ [ Str "A"+ , Space+ , Str "discrete"+ , Space+ , Str "heading,"+ , Space+ , Str "not"+ , Space+ , Str "a"+ , Space+ , Str "section"+ ]+ , Header 2 ( "_paragraph" , [] , [] ) [ Str "Paragraph" ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "paragraph"+ , SoftBreak+ , Str "whose"+ , Space+ , Str "source"+ , Space+ , Str "fits"+ , Space+ , Str "on"+ , Space+ , Str "two"+ , Space+ , Str "lines."+ ]+ , Para+ [ Str "{.This"+ , Space+ , Str "is"+ , Space+ , Str "my"+ , Space+ , Str "title}"+ , SoftBreak+ , Str "A"+ , Space+ , Str "paragraph"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "title."+ ]+ , Header+ 2+ ( "_example_block" , [] , [] )+ [ Str "Example" , Space , Str "block" ]+ , Div+ ( "" , [] , [] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Para [ Str "Optional" , Space , Str "title" ] ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "an"+ , Space+ , Str "example"+ , Space+ , Str "of"+ , Space+ , Str "an"+ , Space+ , Str "example"+ , Space+ , Str "block."+ ]+ ]+ , Div+ ( "" , [ "example" ] , [] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Para [ Str "Optional" , Space , Str "title" ] ]+ , Para+ [ Str "Paragraph" , Space , Strong [ Str "one" ] , Str "." ]+ , Para+ [ Str "Paragraph" , Space , Strong [ Str "two" ] , Str "." ]+ ]+ , Header 2 ( "_admonition" , [] , [] ) [ Str "Admonition" ]+ , Para [ Str "Simple" , Space , Str "form:" ]+ , Div+ ( "" , [ "warning" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Warning" ] ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "very"+ , Space+ , Str "dangerous."+ , SoftBreak+ , Str "Don\8217t"+ , Space+ , Str "do"+ , Space+ , Str "it"+ , Space+ , Str "unless"+ , Space+ , Str "you"+ , Space+ , Str "understand"+ , Space+ , Str "the"+ , Space+ , Str "risks."+ ]+ ]+ , Div+ ( "" , [ "important" ] , [] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Para+ [ Str "Title"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "admonition"+ ]+ ]+ , Para [ Str "Remember:" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para+ [ Str "Don\8217t"+ , Space+ , Str "do"+ , Space+ , Str "this."+ ]+ ]+ , [ Para+ [ Str "And"+ , Space+ , Str "don\8217t"+ , Space+ , Str "do"+ , Space+ , Str "that."+ ]+ ]+ ]+ ]+ , Header 2 ( "_sidebar" , [] , [] ) [ Str "Sidebar" ]+ , Para+ [ Str "A" , Space , Str "simple" , Space , Str "sidebar." ]+ , Div+ ( "" , [ "sidebar" ] , [] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Para+ [ Str "Optional"+ , Space+ , Str "Title"+ , Space+ , Strong+ [ Str "with"+ , Space+ , Str "strong"+ , Space+ , Str "emphasis"+ ]+ ]+ ]+ , Para+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "sidebar."+ ]+ , Div+ ( "" , [ "tip" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Tip" ] ]+ , Para+ [ Str "It"+ , Space+ , Str "can"+ , Space+ , Str "contain"+ , Space+ , Str "any"+ , Space+ , Str "type"+ , Space+ , Str "of"+ , Space+ , Str "content."+ ]+ ]+ ]+ , Header+ 2+ ( "_literal_block" , [] , [] )+ [ Str "Literal" , Space , Str "block" ]+ , Para+ [ Str "Short"+ , Space+ , Str "indented"+ , Space+ , Str "code:"+ ]+ , CodeBlock+ ( "" , [] , [] )+ "$ ls -a\n$ cat /foo/bar/baz \\\n /bi/bim/bop\n"+ , CodeBlock+ ( "" , [] , [] ) "This is\n a literal block too.\n"+ , CodeBlock+ ( "" , [] , [] )+ " Fenced\n $+ *a* literal\n\n****\nnot a sidebar\n****\n"+ , Header 2 ( "_listing" , [] , [] ) [ Str "Listing" ]+ , CodeBlock+ ( "" , [ "ruby" ] , [] )+ "require 'sinatra'\n\nget '/hi' do\n \"Hello World!\"\nend"+ , Para [ Str "Implied:" ]+ , CodeBlock+ ( "" , [ "ruby" ] , [] )+ "require 'sinatra'\n\nget '/hi' do\n \"Hello World!\"\nend"+ , CodeBlock+ ( "" , [ "ruby" ] , [] )+ "# A function\ndef foo\n return 42\nend"+ , CodeBlock+ ( "hello" , [ "haskell" ] , [] )+ "putStrLn $ unwords [\"Hello\", \"world\"]"+ , Para [ Str "Line" , Space , Str "numbering:" ]+ , CodeBlock+ ( "" , [] , [ ( "options" , "linenums" ) ] )+ "puts 1\nputs 2\nputs 3"+ , CodeBlock+ ( "" , [] , [] ) "This doesn't have a language.\n +=\"hi\""+ , Para+ [ Str "And"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "callout"+ , Space+ , Str "list:"+ ]+ , CodeBlock+ ( "" , [ "ruby" ] , [] )+ "require 'sinatra' \9312\n\nget '/hi' do \9313 \9314\n \"Hello World!\"\nend"+ , Div+ ( "" , [ "callout-list" ] , [] )+ [ OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Library" , Space , Str "import" ] ]+ , [ Para [ Str "URL" , Space , Str "mapping" ] ]+ , [ Para [ Str "Response" , Space , Str "block" ] ]+ ]+ ]+ , Para [ Str "Markdown-style" , Space , Str "fenced:" ]+ , CodeBlock+ ( "" , [ "ruby" ] , [] ) "def foo\n return 5\nend"+ , Header 2 ( "_verse" , [] , [] ) [ Str "Verse" ]+ , BlockQuote+ [ Para+ [ Str "The"+ , Space+ , Str "fog"+ , Space+ , Str "comes"+ , LineBreak+ , Str "on"+ , Space+ , Str "little"+ , Space+ , Str "cat"+ , Space+ , Str "feet."+ ]+ , Para+ [ Str "\8212"+ , Space+ , Str "Carl"+ , Space+ , Str "Sandburg,"+ , Space+ , Str "two"+ , Space+ , Str "lines"+ , Space+ , Str "from"+ , Space+ , Str "the"+ , Space+ , Str "poem"+ , Space+ , Str "Fog"+ ]+ ]+ , BlockQuote+ [ Para+ [ Str "The"+ , Space+ , Str "fog"+ , Space+ , Str "comes"+ , LineBreak+ , Str "on"+ , Space+ , Str "little"+ , Space+ , Str "cat"+ , Space+ , Str "feet."+ , LineBreak+ , Str "It"+ , Space+ , Str "sits"+ , Space+ , Str "looking"+ , LineBreak+ , Str "over"+ , Space+ , Str "harbor"+ , Space+ , Str "and"+ , Space+ , Str "city"+ , LineBreak+ , Str "on"+ , Space+ , Str "silent"+ , Space+ , Str "haunches"+ , LineBreak+ , Str "and"+ , Space+ , Str "then"+ , Space+ , Str "moves"+ , Space+ , Str "on."+ ]+ , Para+ [ Str "\8212"+ , Space+ , Str "Carl"+ , Space+ , Str "Sandburg,"+ , Space+ , Str "Fog"+ ]+ ]+ , Header+ 2 ( "_collapsible" , [] , [] ) [ Str "Collapsible" ]+ , Para+ [ Str "Click"+ , Space+ , Str "here"+ , Space+ , Str "for"+ , Space+ , Str "more."+ ]+ , Div+ ( ""+ , [ "example" ]+ , [ ( "options" , "collapsible,open" ) ]+ )+ [ Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "collapsible."+ ]+ , Para+ [ Str "It"+ , Space+ , Str "can"+ , Space+ , Str "be"+ , Space+ , Str "hidden."+ ]+ ]+ , Div+ ( "" , [] , [ ( "options" , "collapsible" ) ] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Para [ Str "Click" , Space , Str "me!" ] ]+ , Para+ [ Str "This"+ , Space+ , Str "paragraph"+ , Space+ , Str "is"+ , SoftBreak+ , Str "also"+ , Space+ , Str "collapsible."+ ]+ ]+ , Header 2 ( "_quote" , [] , [] ) [ Str "Quote" ]+ , BlockQuote+ [ Para+ [ Str "Everybody"+ , Space+ , Str "remember"+ , Space+ , Str "where"+ , Space+ , Str "we"+ , Space+ , Str "parked."+ ]+ , Para+ [ Str "\8212"+ , Space+ , Str "Captain"+ , Space+ , Str "James"+ , Space+ , Str "T."+ , Space+ , Str "Kirk,"+ , Space+ , Str "Star"+ , Space+ , Str "Trek"+ , Space+ , Str "IV:"+ , Space+ , Str "The"+ , Space+ , Str "Voyage"+ , Space+ , Str "Home"+ ]+ ]+ , BlockQuote+ [ Para+ [ Str "Dennis:"+ , Space+ , Str "Come"+ , Space+ , Str "and"+ , Space+ , Str "see"+ , Space+ , Str "the"+ , Space+ , Str "violence"+ , Space+ , Str "inherent"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "system."+ , Space+ , Str "Help!"+ , Space+ , Str "Help!"+ , Space+ , Str "I\8217m"+ , Space+ , Str "being"+ , SoftBreak+ , Str "repressed."+ ]+ , Para+ [ Str "King"+ , Space+ , Str "Arthur:"+ , Space+ , Str "Bloody"+ , Space+ , Str "peasant!"+ ]+ , Para+ [ Str "Dennis:"+ , Space+ , Str "Oh,"+ , Space+ , Str "what"+ , Space+ , Str "a"+ , Space+ , Str "giveaway!"+ , Space+ , Str "Did"+ , Space+ , Str "you"+ , Space+ , Str "hear"+ , Space+ , Str "that?"+ , Space+ , Str "Did"+ , Space+ , Str "you"+ , Space+ , Str "hear"+ , Space+ , Str "that,"+ , Space+ , Str "eh?"+ , Space+ , Str "That\8217s"+ , Space+ , Str "what"+ , Space+ , Str "I\8217m"+ , SoftBreak+ , Str "on"+ , Space+ , Str "about!"+ , Space+ , Str "Did"+ , Space+ , Str "you"+ , Space+ , Str "see"+ , Space+ , Str "him"+ , Space+ , Str "repressing"+ , Space+ , Str "me?"+ , Space+ , Str "You"+ , Space+ , Str "saw"+ , Space+ , Str "him,"+ , Space+ , Str "Didn\8217t"+ , Space+ , Str "you?"+ ]+ , Para+ [ Str "\8212"+ , Space+ , Str "Monty"+ , Space+ , Str "Python"+ , Space+ , Str "and"+ , Space+ , Str "the"+ , Space+ , Str "Holy"+ , Space+ , Str "Grail"+ ]+ ]+ , Div+ ( "roads" , [ "movie" ] , [ ( "wrapper" , "1" ) ] )+ [ BlockQuote+ [ Para+ [ Str "Roads?"+ , Space+ , Str "Where"+ , Space+ , Str "we\8217re"+ , Space+ , Str "going,"+ , Space+ , Str "we"+ , Space+ , Str "don\8217t"+ , Space+ , Str "need"+ , Space+ , Str "roads."+ ]+ , Para+ [ Str "\8212"+ , Space+ , Str "Dr."+ , Space+ , Str "Emmett"+ , Space+ , Str "Brown"+ ]+ ]+ ]+ , Header 2 ( "_pass" , [] , [] ) [ Str "Pass" ]+ , Para [ Str "pass" , Space , Emph [ Str "through" ] ]+ , Header+ 2+ ( "_open_block" , [] , [] )+ [ Str "Open" , Space , Str "block" ]+ , Div+ ( "" , [] , [ ( "key" , "a value" ) ] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Para [ Str "A" , Space , Str "title." ] ]+ , Para+ [ Str "Any"+ , Space+ , Str "content"+ , Space+ , Str "can"+ , Space+ , Str "go"+ , Space+ , Str "here:"+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "one" ] ] , [ Para [ Str "two" ] ] ]+ ]+ , Header 2 ( "_anchor" , [] , [] ) [ Str "Anchor" ]+ , Div+ ( "goals" , [] , [ ( "wrapper" , "1" ) ] )+ [ BulletList+ [ [ Para [ Str "one" ] ] , [ Para [ Str "two" ] ] ]+ ]+ , Header 2 ( "_breaks" , [] , [] ) [ Str "Breaks" ]+ , Para+ [ Str "Asciidoc"+ , Space+ , Str "thematic"+ , Space+ , Str "break:"+ ]+ , HorizontalRule+ , Para [ Str "Markdown" , Space , Str "style:" ]+ , HorizontalRule+ , HorizontalRule+ , HorizontalRule+ , HorizontalRule+ , Para [ Str "Page" , Space , Str "breaks:" ]+ , Div+ ( "" , [ "page-break" ] , [ ( "wrapper" , "1" ) ] )+ [ HorizontalRule ]+ , Div+ ( ""+ , [ "page-break" ]+ , [ ( "options" , "always" ) , ( "wrapper" , "1" ) ]+ )+ [ HorizontalRule ]+ , Header 2 ( "_list" , [] , [] ) [ Str "List" ]+ , BulletList+ [ [ Para+ [ Str "Edgar" , Space , Str "Allan" , Space , Str "Poe" ]+ ]+ , [ Para+ [ Str "Sheri" , Space , Str "S." , Space , Str "Tepper" ]+ ]+ , [ Para [ Str "Bill" , Space , Str "Bryson" ] ]+ ]+ , Div+ ( "" , [] , [] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Para+ [ Str "Kizmet\8217s"+ , Space+ , Str "Favorite"+ , Space+ , Str "Authors"+ ]+ ]+ , BulletList+ [ [ Para+ [ Str "Edgar"+ , Space+ , Str "Allan"+ , Space+ , Str "Poe"+ ]+ ]+ , [ Para+ [ Str "Sheri"+ , Space+ , Str "S."+ , Space+ , Str "Tepper"+ ]+ ]+ , [ Para [ Str "Bill" , Space , Str "Bryson" ] ]+ ]+ ]+ , BulletList+ [ [ Para+ [ Str "Edgar" , Space , Str "Allan" , Space , Str "Poe" ]+ ]+ , [ Para+ [ Str "Sheri" , Space , Str "S." , Space , Str "Tepper" ]+ ]+ , [ Para [ Str "Bill" , Space , Str "Bryson" ] ]+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Nested" , Space , Str "list" ]+ , BulletList+ [ [ Para+ [ Str "West"+ , Space+ , Str "wood"+ , Space+ , Str "maze"+ ]+ , BulletList+ [ [ Para [ Str "Maze" , Space , Str "heart" ]+ , BulletList+ [ [ Para+ [ Str "Reflection" , Space , Str "pool" ]+ ]+ ]+ ]+ , [ Para [ Str "Secret" , Space , Str "exit" ] ]+ ]+ ]+ , [ Para+ [ Str "Level"+ , Space+ , Str "1"+ , Space+ , Str "list"+ , Space+ , Str "item"+ ]+ , BulletList+ [ [ Para+ [ Str "Level"+ , Space+ , Str "2"+ , Space+ , Str "list"+ , Space+ , Str "item"+ ]+ , BulletList+ [ [ Para+ [ Str "Level"+ , Space+ , Str "3"+ , Space+ , Str "list"+ , Space+ , Str "item"+ ]+ , BulletList+ [ [ Para+ [ Str "Level"+ , Space+ , Str "4"+ , Space+ , Str "list"+ , Space+ , Str "item"+ ]+ , BulletList+ [ [ Para+ [ Str "Level"+ , Space+ , Str "5"+ , Space+ , Str "list"+ , Space+ , Str "item"+ ]+ , BulletList+ [ [ Para [ Str "etc." ] ] ]+ ]+ ]+ ]+ ]+ ]+ ]+ ]+ ]+ ]+ , [ Para+ [ Str "Level"+ , Space+ , Str "1"+ , Space+ , Str "list"+ , Space+ , Str "item"+ ]+ ]+ ]+ ]+ ]+ , BulletList+ [ [ Para [ Str "one" ] ]+ , [ Para [ Str "two" ] ]+ , [ Para [ Str "three" ] ]+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Protons" ] ]+ , [ Para [ Str "Electrons" ] ]+ , [ Para [ Str "Neutrons" ] ]+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Protons" ] ]+ , [ Para [ Str "Electrons" ] ]+ , [ Para [ Str "Neutrons" ] ]+ ]+ , Para+ [ Str "Start" , Space , Str "with" , Space , Str "4:" ]+ , OrderedList+ ( 4 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Step" , Space , Str "four" ] ]+ , [ Para [ Str "Step" , Space , Str "five" ] ]+ , [ Para [ Str "Step" , Space , Str "six" ] ]+ ]+ , Para [ Str "or" ]+ , OrderedList+ ( 4 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Step" , Space , Str "four" ] ]+ , [ Para [ Str "Step" , Space , Str "five" ] ]+ , [ Para [ Str "Step" , Space , Str "six" ] ]+ ]+ , Para [ Str "Reversed:" ]+ , Div+ ( "" , [] , [ ( "options" , "reversed" ) ] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Para+ [ Str "Parts"+ , Space+ , Str "of"+ , Space+ , Str "an"+ , Space+ , Str "atom"+ ]+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Protons" ] ]+ , [ Para [ Str "Electrons" ] ]+ , [ Para [ Str "Neutrons" ] ]+ ]+ ]+ , Para [ Str "Nested" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Step" , Space , Str "1" ] ]+ , [ Para [ Str "Step" , Space , Str "2" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Step" , Space , Str "2a" ] ]+ , [ Para [ Str "Step" , Space , Str "2b" ] ]+ ]+ ]+ , [ Para [ Str "Step" , Space , Str "3" ] ]+ ]+ , Para [ Str "Mixed" , Space , Str "nested" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Linux" ]+ , BulletList+ [ [ Para [ Str "Fedora" ] ]+ , [ Para [ Str "Ubuntu" ] ]+ , [ Para [ Str "Slackware" ] ]+ ]+ ]+ , [ Para [ Str "BSD" ]+ , BulletList+ [ [ Para [ Str "FreeBSD" ] ] , [ Para [ Str "NetBSD" ] ] ]+ ]+ ]+ , Para [ Str "With" , Space , Str "spacing" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Linux" ]+ , BulletList+ [ [ Para [ Str "Fedora" ] ]+ , [ Para [ Str "Ubuntu" ] ]+ , [ Para [ Str "Slackware" ] ]+ ]+ ]+ , [ Para [ Str "BSD" ]+ , BulletList+ [ [ Para [ Str "FreeBSD" ] ] , [ Para [ Str "NetBSD" ] ] ]+ ]+ ]+ , Para+ [ Str "With" , Space , Str "number" , Space , Str "styles" ]+ , OrderedList+ ( 5 , LowerRoman , DefaultDelim )+ [ [ Para [ Str "Five" ] ]+ , [ Para [ Str "Six" ]+ , OrderedList+ ( 1 , LowerAlpha , DefaultDelim )+ [ [ Para [ Str "a" ] ]+ , [ Para [ Str "b" ] ]+ , [ Para [ Str "c" ] ]+ ]+ ]+ , [ Para [ Str "Seven" ] ]+ ]+ , Para [ Str "Checklist" ]+ , BulletList+ [ [ Para [ Str "\9746" , Space , Str "checked" ] ]+ , [ Para+ [ Str "\9746" , Space , Str "also" , Space , Str "checked" ]+ ]+ , [ Para+ [ Str "\9744" , Space , Str "not" , Space , Str "checked" ]+ ]+ , [ Para+ [ Str "normal" , Space , Str "list" , Space , Str "item" ]+ ]+ ]+ , Para+ [ Str "Separate"+ , Space+ , Str "lists"+ , Space+ , Str "with"+ , Space+ , Str "block"+ , Space+ , Str "attribute"+ ]+ , BulletList+ [ [ Para [ Str "Apples" ] ]+ , [ Para [ Str "Oranges" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Wash" ] ] , [ Para [ Str "Slice" ] ] ]+ ]+ ]+ , Para [ Str "Multiline" , Space , Str "items" ]+ , BulletList+ [ [ Para+ [ Str "Blah"+ , Space+ , Str "blah."+ , SoftBreak+ , Str "Blah"+ , Space+ , Str "blah."+ ]+ ]+ , [ Para+ [ Str "The"+ , Space+ , Str "document"+ , Space+ , Str "header"+ , Space+ , Str "in"+ , Space+ , Str "AsciiDoc"+ , Space+ , Str "is"+ , Space+ , Str "optional."+ , SoftBreak+ , Str "If"+ , Space+ , Str "present,"+ , Space+ , Str "it"+ , Space+ , Str "must"+ , Space+ , Str "start"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "document"+ , Space+ , Str "title."+ ]+ ]+ ]+ , BulletList+ [ [ Para+ [ Str "Optional"+ , Space+ , Str "author"+ , Space+ , Str "and"+ , Space+ , Str "revision"+ , Space+ , Str "information"+ , Space+ , Str "lines"+ , SoftBreak+ , Str "immediately"+ , Space+ , Str "follow"+ , Space+ , Str "the"+ , Space+ , Str "document"+ , Space+ , Str "title."+ ]+ ]+ ]+ , BulletList+ [ [ Para+ [ Str "The"+ , Space+ , Str "document"+ , Space+ , Str "header"+ , Space+ , Str "must"+ , Space+ , Str "be"+ , Space+ , Str "separated"+ , Space+ , Str "from"+ , SoftBreak+ , Str "the"+ , Space+ , Str "remainder"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "document"+ , Space+ , Str "by"+ , Space+ , Str "one"+ , Space+ , Str "or"+ , Space+ , Str "more"+ , SoftBreak+ , Str "empty"+ , Space+ , Str "lines"+ , Space+ , Str "and"+ , Space+ , Str "it"+ , Space+ , Str "cannot"+ , Space+ , Str "contain"+ , Space+ , Str "empty"+ , Space+ , Str "lines."+ ]+ ]+ ]+ , Para [ Str "Complex" , Space , Str "item" ]+ , BulletList+ [ [ Para+ [ Str "The"+ , Space+ , Str "header"+ , Space+ , Str "in"+ , Space+ , Str "AsciiDoc"+ , Space+ , Str "must"+ , Space+ , Str "start"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "document"+ , Space+ , Str "title."+ ]+ , CodeBlock ( "" , [] , [] ) "= Document Title"+ , Para+ [ Str "Keep"+ , Space+ , Str "in"+ , Space+ , Str "mind"+ , Space+ , Str "that"+ , Space+ , Str "the"+ , Space+ , Str "header"+ , Space+ , Str "is"+ , Space+ , Str "optional."+ ]+ ]+ , [ Para+ [ Str "Optional"+ , Space+ , Str "author"+ , Space+ , Str "and"+ , Space+ , Str "revision"+ , Space+ , Str "information"+ , Space+ , Str "lines"+ , Space+ , Str "immediately"+ , Space+ , Str "follow"+ , Space+ , Str "the"+ , Space+ , Str "document"+ , SoftBreak+ , Str "title."+ ]+ , CodeBlock+ ( "" , [] , [] )+ "= Document Title\nDoc Writer <doc.writer@asciidoc.org>\nv1.0, 2022-01-01"+ ]+ , [ Para [ Str "Second" , Space , Str "item" ] ]+ ]+ , Para+ [ Str "Empty"+ , Space+ , Str "principle"+ , Space+ , Str "element:"+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [] , CodeBlock ( "" , [] , [] ) "test" ] ]+ , Header 2 ( "_table" , [] , [] ) [ Str "Table" ]+ , Header+ 3+ ( "_simple_with_column_specs" , [] , [] )+ [ Str "Simple"+ , Space+ , Str "with"+ , Space+ , Str "column"+ , Space+ , Str "specs"+ ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 0.375 )+ , ( AlignDefault , ColWidth 0.25 )+ , ( AlignDefault , ColWidth 0.375 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "This"+ , Space+ , Str "content"+ , Space+ , Str "is"+ , Space+ , Str "placed"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "first"+ , Space+ , Str "cell"+ , Space+ , Str "of"+ , Space+ , Str "column"+ , Space+ , Str "1"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "This"+ , Space+ , Str "line"+ , Space+ , Str "starts"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "vertical"+ , Space+ , Str "bar"+ , Space+ , Str "so"+ , Space+ , Str "this"+ , Space+ , Str "content"+ , Space+ , Str "is"+ , Space+ , Str "placed"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "new"+ , Space+ , Str "cell"+ , Space+ , Str "in"+ , SoftBreak+ , Str "column"+ , Space+ , Str "2"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "When"+ , Space+ , Str "the"+ , Space+ , Str "processor"+ , Space+ , Str "encounters"+ , Space+ , Str "a"+ , Space+ , Str "whitespace"+ , Space+ , Str "followed"+ , Space+ , Str "by"+ , Space+ , Str "a"+ , Space+ , Str "vertical"+ , Space+ , Str "bar"+ , Space+ , Str "it"+ , SoftBreak+ , Str "ends"+ , Space+ , Str "the"+ , Space+ , Str "previous"+ , Space+ , Str "cell"+ , Space+ , Str "and"+ , Space+ , Str "starts"+ , Space+ , Str "a"+ , Space+ , Str "new"+ , Space+ , Str "cell"+ ]+ ]+ ]+ ])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot ( "" , [] , [] ) [])+ , Header+ 3+ ( "_repeated_column_in_specs" , [] , [] )+ [ Str "Repeated"+ , Space+ , Str "column"+ , Space+ , Str "in"+ , Space+ , Str "specs"+ ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Strong+ [ Str "This"+ , Space+ , Str "cell\8217s"+ , Space+ , Str "specifier"+ , Space+ , Str "indicates"+ , Space+ , Str "that"+ , Space+ , Str "this"+ , Space+ , Str "cell\8217s"+ , Space+ , Str "content"+ , Space+ , Str "is"+ , Space+ , Str "right-aligned"+ , Space+ , Str "and"+ , Space+ , Str "bold."+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "The"+ , Space+ , Str "cell"+ , Space+ , Str "specifier"+ , Space+ , Str "on"+ , Space+ , Str "this"+ , Space+ , Str "cell"+ , Space+ , Str "hasn\8217t"+ , Space+ , Str "been"+ , Space+ , Str "set"+ , Space+ , Str "explicitly,"+ , Space+ , Str "so"+ , Space+ , Str "the"+ , Space+ , Str "default"+ , SoftBreak+ , Str "properties"+ , Space+ , Str "are"+ , Space+ , Str "applied."+ ]+ ]+ ]+ ])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot ( "" , [] , [] ) [])+ , Header+ 3+ ( "_simple_without_column_specs" , [] , [] )+ [ Str "Simple"+ , Space+ , Str "without"+ , Space+ , Str "column"+ , Space+ , Str "specs"+ ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "1,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "2,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "1,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "2,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "1,"+ , Space+ , Str "row"+ , Space+ , Str "3"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "2,"+ , Space+ , Str "row"+ , Space+ , Str "3"+ ]+ ]+ ]+ ])+ , Header+ 3+ ( "_with_caption" , [] , [] )+ [ Str "With" , Space , Str "caption" ]+ , Table+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "My" , Space , Str "cool" , Space , Str "table." ]+ ])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "1,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "2,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "1,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "2,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "1,"+ , Space+ , Str "row"+ , Space+ , Str "3"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "2,"+ , Space+ , Str "row"+ , Space+ , Str "3"+ ]+ ]+ ]+ ])+ , Header+ 3+ ( "_no_header" , [] , [] )+ [ Str "No" , Space , Str "header" ]+ , Para+ [ Str "By"+ , Space+ , Str "default"+ , Space+ , Str "the"+ , Space+ , Str "first"+ , Space+ , Str "line"+ , Space+ , Str "should"+ , Space+ , Str "turn"+ , Space+ , Str "into"+ , Space+ , Str "the"+ , Space+ , Str "header,"+ , Space+ , Str "but"+ , Space+ , Str "this"+ , SoftBreak+ , Str "can"+ , Space+ , Str "be"+ , Space+ , Str "disabled:"+ ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "1,"+ , Space+ , Str "row"+ , Space+ , Str "1"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "2,"+ , Space+ , Str "row"+ , Space+ , Str "1"+ ]+ ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "1,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "2,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ ]+ ])+ , Para+ [ Str "And"+ , Space+ , Str "also"+ , Space+ , Str "explicitly"+ , Space+ , Str "enabled:"+ ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Cell" , Space , Str "A1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Cell" , Space , Str "B1" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Cell" , Space , Str "A2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Cell" , Space , Str "B2" ] ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Cell" , Space , Str "A3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Cell" , Space , Str "B3" ] ]+ ]+ ])+ , Header 3 ( "_footer" , [] , [] ) [ Str "Footer" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 0.4 )+ , ( AlignDefault , ColWidth 0.4 )+ , ( AlignDefault , ColWidth 0.2 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "1,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "2,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "3,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "1,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "2,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "3,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "1,"+ , Space+ , Str "footer"+ , Space+ , Str "row"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "2,"+ , Space+ , Str "footer"+ , Space+ , Str "row"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "3,"+ , Space+ , Str "footer"+ , Space+ , Str "row"+ ]+ ]+ ]+ ])+ , Para [ Str "or" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "1,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "2,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "1,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "2,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "1,"+ , Space+ , Str "row"+ , Space+ , Str "3"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "2,"+ , Space+ , Str "row"+ , Space+ , Str "3"+ ]+ ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "1,"+ , Space+ , Str "footer"+ , Space+ , Str "row"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "2,"+ , Space+ , Str "footer"+ , Space+ , Str "row"+ ]+ ]+ ]+ ])+ , Header 3 ( "_alignment" , [] , [] ) [ Str "Alignment" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Column" , Space , Str "Name" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Column" , Space , Str "Name" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 1)+ (ColSpan 2)+ [ Para+ [ Str "This"+ , Space+ , Str "cell"+ , Space+ , Str "spans"+ , Space+ , Str "two"+ , Space+ , Str "columns,"+ , Space+ , Str "and"+ , Space+ , Str "its"+ , Space+ , Str "content"+ , Space+ , Str "is"+ , Space+ , Str "horizontally"+ , Space+ , Str "centered"+ , Space+ , Str "because"+ , Space+ , Str "the"+ , SoftBreak+ , Str "cell"+ , Space+ , Str "specifier"+ , Space+ , Str "includes"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "^"+ , Space+ , Str "operator."+ ]+ ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "This"+ , Space+ , Str "content"+ , Space+ , Str "is"+ , Space+ , Str "duplicated"+ , Space+ , Str "in"+ , Space+ , Str "two"+ , Space+ , Str "adjacent"+ , Space+ , Str "columns."+ , SoftBreak+ , Str "Its"+ , Space+ , Str "content"+ , Space+ , Str "is"+ , Space+ , Str "horizontally"+ , Space+ , Str "centered"+ , Space+ , Str "because"+ , Space+ , Str "the"+ , Space+ , Str "cell"+ , Space+ , Str "specifier"+ , SoftBreak+ , Str "includes"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "^"+ , Space+ , Str "operator."+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "This"+ , Space+ , Str "content"+ , Space+ , Str "is"+ , Space+ , Str "duplicated"+ , Space+ , Str "in"+ , Space+ , Str "two"+ , Space+ , Str "adjacent"+ , Space+ , Str "columns."+ , SoftBreak+ , Str "Its"+ , Space+ , Str "content"+ , Space+ , Str "is"+ , Space+ , Str "horizontally"+ , Space+ , Str "centered"+ , Space+ , Str "because"+ , Space+ , Str "the"+ , Space+ , Str "cell"+ , Space+ , Str "specifier"+ , SoftBreak+ , Str "includes"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "^"+ , Space+ , Str "operator."+ ]+ ]+ ]+ ])+ , Header+ 3+ ( "_multiple_paragraphs_in_cells" , [] , [] )+ [ Str "Multiple"+ , Space+ , Str "paragraphs"+ , Space+ , Str "in"+ , Space+ , Str "cells"+ ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault ) ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Single"+ , Space+ , Str "paragraph"+ , Space+ , Str "on"+ , Space+ , Str "row"+ , Space+ , Str "1"+ ]+ ]+ ]+ ])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "First"+ , Space+ , Str "paragraph"+ , Space+ , Str "on"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ , Para+ [ Str "Second"+ , Space+ , Str "paragraph"+ , Space+ , Str "on"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ ]+ ])+ , Header+ 3+ ( "_complex_table" , [] , [] )+ [ Str "Complex" , Space , Str "table" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Code ( "" , [] , [] ) "This"+ , Space+ , Code ( "" , [] , [] ) "content"+ , Space+ , Code ( "" , [] , [] ) "is"+ , Space+ , Code ( "" , [] , [] ) "duplicated"+ , Space+ , Code ( "" , [] , [] ) "across"+ , Space+ , Code ( "" , [] , [] ) "two"+ , Space+ , Code ( "" , [] , [] ) "columns."+ ]+ , Para+ [ Code ( "" , [] , [] ) "It"+ , Space+ , Code ( "" , [] , [] ) "is"+ , Space+ , Code ( "" , [] , [] ) "aligned"+ , Space+ , Code ( "" , [] , [] ) "right"+ , Space+ , Code ( "" , [] , [] ) "horizontally."+ ]+ , Para+ [ Code ( "" , [] , [] ) "And"+ , Space+ , Code ( "" , [] , [] ) "it"+ , Space+ , Code ( "" , [] , [] ) "is"+ , Space+ , Code ( "" , [] , [] ) "monospaced."+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Code ( "" , [] , [] ) "This"+ , Space+ , Code ( "" , [] , [] ) "content"+ , Space+ , Code ( "" , [] , [] ) "is"+ , Space+ , Code ( "" , [] , [] ) "duplicated"+ , Space+ , Code ( "" , [] , [] ) "across"+ , Space+ , Code ( "" , [] , [] ) "two"+ , Space+ , Code ( "" , [] , [] ) "columns."+ ]+ , Para+ [ Code ( "" , [] , [] ) "It"+ , Space+ , Code ( "" , [] , [] ) "is"+ , Space+ , Code ( "" , [] , [] ) "aligned"+ , Space+ , Code ( "" , [] , [] ) "right"+ , Space+ , Code ( "" , [] , [] ) "horizontally."+ ]+ , Para+ [ Code ( "" , [] , [] ) "And"+ , Space+ , Code ( "" , [] , [] ) "it"+ , Space+ , Code ( "" , [] , [] ) "is"+ , Space+ , Code ( "" , [] , [] ) "monospaced."+ ]+ ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 2)+ (ColSpan 1)+ [ Para+ [ Strong+ [ Str "This"+ , Space+ , Str "cell"+ , Space+ , Str "spans"+ , Space+ , Str "3"+ , Space+ , Str "rows."+ , Space+ , Str "The"+ , Space+ , Str "content"+ , Space+ , Str "is"+ , Space+ , Str "centered"+ , Space+ , Str "horizontally,"+ , Space+ , Str "aligned"+ , Space+ , Str "to"+ , Space+ , Str "the"+ , Space+ , Str "bottom"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "cell,"+ , Space+ , Str "and"+ , Space+ , Str "strong."+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Emph+ [ Str "This"+ , Space+ , Str "content"+ , Space+ , Str "is"+ , Space+ , Str "emphasized."+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "This content is aligned to the top of the cell and literal.\n\n"+ ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] ) "puts \"This is a source block!\""+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ []+ ]+ ])+ , Header+ 3+ ( "_column_styles" , [] , [] )+ [ Str "Column" , Space , Str "styles" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Code ( "" , [] , [] ) "monospace" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Code ( "" , [] , [] ) "mono" ] ]+ ]+ ])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "default" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Code ( "" , [] , [] ) "mono" ] ]+ ]+ ])+ , Header+ 3+ ( "_block_elements_in_cells" , [] , [] )+ [ Str "Block"+ , Space+ , Str "elements"+ , Space+ , Str "in"+ , Space+ , Str "cells"+ ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Normal" , Space , Str "Style" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "AsciiDoc" , Space , Str "Style" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "This"+ , Space+ , Str "cell"+ , Space+ , Str "isn\8217t"+ , Space+ , Str "prefixed"+ , Space+ , Str "with"+ , Space+ , Str "an"+ , Space+ , Code ( "" , [] , [] ) "a"+ , Str ","+ , Space+ , Str "so"+ , Space+ , Str "the"+ , Space+ , Str "processor"+ , Space+ , Str "doesn\8217t"+ , Space+ , Str "interpret"+ , Space+ , Str "the"+ , SoftBreak+ , Str "following"+ , Space+ , Str "lines"+ , Space+ , Str "as"+ , Space+ , Str "an"+ , Space+ , Str "AsciiDoc"+ , Space+ , Str "list."+ ]+ , Para+ [ Str "*"+ , Space+ , Str "List"+ , Space+ , Str "item"+ , Space+ , Str "1"+ , SoftBreak+ , Str "*"+ , Space+ , Str "List"+ , Space+ , Str "item"+ , Space+ , Str "2"+ , SoftBreak+ , Str "*"+ , Space+ , Str "List"+ , Space+ , Str "item"+ , Space+ , Str "3"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "This"+ , Space+ , Str "cell"+ , Space+ , Str "is"+ , Space+ , Str "prefixed"+ , Space+ , Str "with"+ , Space+ , Str "an"+ , Space+ , Code ( "" , [] , [] ) "a"+ , Str ","+ , Space+ , Str "so"+ , Space+ , Str "the"+ , Space+ , Str "processor"+ , Space+ , Str "interprets"+ , Space+ , Str "the"+ , Space+ , Str "following"+ , Space+ , Str "lines"+ , SoftBreak+ , Str "as"+ , Space+ , Str "an"+ , Space+ , Str "AsciiDoc"+ , Space+ , Str "list."+ ]+ , BulletList+ [ [ Para+ [ Str "List"+ , Space+ , Str "item"+ , Space+ , Str "1"+ ]+ ]+ , [ Para+ [ Str "List"+ , Space+ , Str "item"+ , Space+ , Str "2"+ ]+ ]+ , [ Para+ [ Str "List"+ , Space+ , Str "item"+ , Space+ , Str "3"+ ]+ ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "This"+ , Space+ , Str "cell"+ , Space+ , Str "isn\8217t"+ , Space+ , Str "prefixed"+ , Space+ , Str "with"+ , Space+ , Str "an"+ , Space+ , Code ( "" , [] , [] ) "a"+ , Str ","+ , Space+ , Str "so"+ , Space+ , Str "the"+ , Space+ , Str "processor"+ , Space+ , Str "doesn\8217t"+ , Space+ , Str "interpret"+ , Space+ , Str "the"+ , Space+ , Str "listing"+ , SoftBreak+ , Str "block"+ , Space+ , Str "delimiters"+ , Space+ , Str "or"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "source"+ , Space+ , Str "style."+ ]+ , Para+ [ Str "----"+ , SoftBreak+ , Str "import"+ , Space+ , Str "os"+ , SoftBreak+ , Str "print"+ , Space+ , Str "(\"%s\""+ , Space+ , Str "%(os.uname()))"+ , SoftBreak+ , Str "----"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "This"+ , Space+ , Str "cell"+ , Space+ , Str "is"+ , Space+ , Str "prefixed"+ , Space+ , Str "with"+ , Space+ , Str "an"+ , Space+ , Code ( "" , [] , [] ) "a"+ , Str ","+ , Space+ , Str "so"+ , Space+ , Str "the"+ , Space+ , Str "listing"+ , Space+ , Str "block"+ , Space+ , Str "is"+ , Space+ , Str "processed"+ , Space+ , Str "and"+ , Space+ , Str "rendered"+ , SoftBreak+ , Str "according"+ , Space+ , Str "to"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "source"+ , Space+ , Str "style"+ , Space+ , Str "rules."+ ]+ , CodeBlock+ ( "" , [ "python" ] , [] )+ "import os\nprint \"%s\" %(os.uname())"+ ]+ ]+ ])+ , Header+ 3+ ( "_col_and_rowspan" , [] , [] )+ [ Str "Col" , Space , Str "and" , Space , Str "rowspan" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "1,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "2,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Column"+ , Space+ , Str "3,"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+ ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 2)+ [ Para+ [ Str "This"+ , Space+ , Str "cell"+ , Space+ , Str "spans"+ , Space+ , Str "2"+ , Space+ , Str "cols"+ , Space+ , Str "and"+ , Space+ , Str "2"+ , Space+ , Str "rows"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "3,"+ , Space+ , Str "row"+ , Space+ , Str "2"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "3,"+ , Space+ , Str "row"+ , Space+ , Str "3"+ ]+ ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 3)+ [ Para+ [ Str "Cell"+ , Space+ , Str "in"+ , Space+ , Str "column"+ , Space+ , Str "1-3,"+ , Space+ , Str "row"+ , Space+ , Str "4"+ ]+ ]+ ]+ ])+ , Header+ 3+ ( "_csv_table" , [] , [] )+ [ Str "CSV" , Space , Str "table" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Artist" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Track" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Genre" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Baauer" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Harlem" , Space , Str "Shake" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Hip" , Space , Str "Hop" ] ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "The" , Space , Str "Lumineers" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Ho" , Space , Str "Hey" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Folk" , Space , Str "Rock" ] ]+ ]+ ])+ , Para [ Str "or" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Artist" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Track" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Genre" ] ]+ ]+ ])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Baauer" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Harlem" , Space , Str "Shake" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Hip" , Space , Str "Hop" ] ]+ ]+ ])+ , Header+ 3+ ( "_dsv_table" , [] , [] )+ [ Str "DSV" , Space , Str "table" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "a" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "b" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "c" ] ]+ ]+ ])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "d" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "e" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "f" ] ]+ ]+ ])+ , Para [ Str "or" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Artist" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Track" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Genre" ] ]+ ]+ ])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Robyn" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Indestructible" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Dance" ] ]+ ]+ ])+ , Header+ 2+ ( "_definition_list" , [] , [] )+ [ Str "Definition" , Space , Str "list" ]+ , DefinitionList+ [ ( [ Str "CPU" ]+ , [ [ Para+ [ Str "The"+ , Space+ , Str "brain"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "computer."+ ]+ ]+ ]+ )+ , ( [ Str "Hard" , Space , Str "drive" ]+ , [ [ Para+ [ Str "Permanent"+ , Space+ , Str "storage"+ , Space+ , Str "for"+ , Space+ , Str "operating"+ , Space+ , Str "system"+ , Space+ , Str "and/or"+ , Space+ , Str "user"+ , Space+ , Str "files."+ ]+ ]+ ]+ )+ ]+ , Para [ Str "Mixed" ]+ , DefinitionList+ [ ( [ Str "Dairy" ]+ , [ [ BulletList+ [ [ Para [ Str "Milk" ] ]+ , [ Para [ Str "Eggs" ]+ , DefinitionList [ ( [ Str "Bakery" ] , [ [] ] ) ]+ ]+ , [ Para [ Str "Bread" ]+ , DefinitionList [ ( [ Str "Produce" ] , [ [] ] ) ]+ ]+ , [ Para [ Str "Bananas" ] ]+ ]+ ]+ ]+ )+ ]+ , Para [ Str "With" , Space , Str "spaces" ]+ , DefinitionList [ ( [ Str "Dairy" ] , [ [] ] ) ]+ , BulletList+ [ [ Para [ Str "Milk" ] ] , [ Para [ Str "Eggs" ] ] ]+ , DefinitionList [ ( [ Str "Bakery" ] , [ [] ] ) ]+ , BulletList [ [ Para [ Str "Bread" ] ] ]+ , DefinitionList [ ( [ Str "Produce" ] , [ [] ] ) ]+ , BulletList [ [ Para [ Str "Bananas" ] ] ]+ , Para [ Str "Nested" ]+ , DefinitionList+ [ ( [ Str "Operating" , Space , Str "Systems" ]+ , [ [ DefinitionList+ [ ( [ Str "Linux" ]+ , [ [ OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Fedora" ]+ , BulletList [ [ Para [ Str "Desktop" ] ] ]+ ]+ , [ Para [ Str "Ubuntu" ]+ , BulletList+ [ [ Para [ Str "Desktop" ] ]+ , [ Para [ Str "Server" ] ]+ ]+ ]+ ]+ ]+ ]+ )+ , ( [ Str "BSD" ]+ , [ [ OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "FreeBSD" ] ]+ , [ Para [ Str "NetBSD" ]+ , DefinitionList+ [ ( [ Str "Cloud"+ , Space+ , Str "Providers"+ ]+ , [ [ DefinitionList+ [ ( [ Str "PaaS" ] , [ [] ] )+ ]+ ]+ ]+ )+ ]+ ]+ , [ Para [ Str "OpenShift" ] ]+ , [ Para [ Str "CloudBees" ] ]+ ]+ ]+ ]+ )+ , ( [ Str "IaaS" ]+ , [ [ OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Amazon" , Space , Str "EC2" ]+ ]+ ]+ ]+ ]+ )+ ]+ , Para+ [ Str "This"+ , Space+ , Str "just"+ , Space+ , Str "affects"+ , Space+ , Str "the"+ , Space+ , Str "output:"+ ]+ ]+ ]+ )+ ]+ , Div+ ( ""+ , []+ , [ ( "wrapper" , "1" )+ , ( "itemwidth" , "75" )+ , ( "labelwidth" , "25" )+ ]+ )+ [ DefinitionList+ [ ( [ Str "CPU" ]+ , [ [ Para+ [ Str "The"+ , Space+ , Str "brain"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "computer."+ ]+ ]+ ]+ )+ , ( [ Str "RAM" ]+ , [ [ Para+ [ Str "Temporarily"+ , Space+ , Str "stores"+ , Space+ , Str "information"+ , Space+ , Str "the"+ , Space+ , Str "CPU"+ , Space+ , Str "uses"+ , Space+ , Str "during"+ , Space+ , Str "operation."+ ]+ ]+ ]+ )+ ]+ ]+ , Para [ Str "Q&A" , Space , Str "list" ]+ , DefinitionList+ [ ( [ Str "What"+ , Space+ , Str "is"+ , Space+ , Str "the"+ , Space+ , Str "answer?"+ ]+ , [ [ Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "the"+ , Space+ , Str "answer."+ ]+ ]+ ]+ )+ , ( [ Str "Are"+ , Space+ , Str "cameras"+ , Space+ , Str "allowed?"+ ]+ , [ [] ]+ )+ , ( [ Str "Are"+ , Space+ , Str "backpacks"+ , Space+ , Str "allowed?"+ ]+ , [ [ Para [ Str "No." ] ] ]+ )+ ]+ , Para+ [ Str "Ordered"+ , Space+ , Str "description"+ , Space+ , Str "list"+ , Space+ , Str "(with"+ , Space+ , Str "numbers)"+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ DefinitionList+ [ ( [ Str "&" ] , [ [ Para [ Str "ampersand" ] ] ] ) ]+ ]+ , [ DefinitionList+ [ ( [ Str ">" ]+ , [ [ Para [ Str "greater" , Space , Str "than" ] ] ]+ )+ ]+ ]+ ]+ , Header+ 2+ ( "_block_macros" , [] , [] )+ [ Str "Block" , Space , Str "macros" ]+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [])+ [ Plain+ [ Image+ ( ""+ , []+ , [ ( "width" , "300px" ) , ( "height" , "200px" ) ]+ )+ [ Str "Sunset" ]+ ( "sunset.jpg" , "" )+ ]+ ]+ , Plain+ [ Image+ ( "" , [] , [] )+ [ Str "mymovie.mp4" ]+ ( "mymovie.mp4" , "" )+ ]+ , Plain+ [ Image+ ( "" , [] , [] ) [ Str "mysong.mp3" ] ( "mysong.mp3" , "" )+ ]+ , Div ( "toc" , [] , [] ) []+ , Div+ ( ""+ , [ "included" ]+ , [ ( "path" , "asciidoc-reader-include.adoc" ) ]+ )+ [ Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "test!"+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "one" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "two" ] ] ]+ ]+ ]+ ]+ ]
@@ -0,0 +1,203 @@+````+% pandoc -f native -t opendocument+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 3)+ [ Plain+ [ Str "First"+ , Space+ , Str "Header"+ , Space+ , Str "Row"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Second" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Row" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header - Table" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header - Body" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header - Row" ] ]+ ]+ ]+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Table" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Row" ] ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 3)+ [ Plain+ [ Str "First"+ , Space+ , Str "Footer"+ , Space+ , Str "Row"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Second" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Footer" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Row" ] ]+ ]+ ])+]+^D+<table:table table:name="Table1" table:style-name="Table1">+ <table:table-column table:style-name="Table1.A" />+ <table:table-column table:style-name="Table1.B" />+ <table:table-column table:style-name="Table1.C" />+ <table:table-header-rows>+ <table:table-row>+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string" table:number-columns-spanned="3">+ <text:p text:style-name="Table_20_Heading">First Header+ Row</text:p>+ </table:table-cell>+ </table:table-row>+ <table:table-row>+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Heading">Second</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Heading">Header</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableHeaderRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Heading">Row</text:p>+ </table:table-cell>+ </table:table-row>+ </table:table-header-rows>+ <table:table-row>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Heading">Header - Table</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Heading">Header - Body</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Heading">Header - Row</text:p>+ </table:table-cell>+ </table:table-row>+ <table:table-row>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Table</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Body</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Row</text:p>+ </table:table-cell>+ </table:table-row>+ <table:table-row>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string" table:number-columns-spanned="3">+ <text:p text:style-name="Table_20_Contents">First Footer+ Row</text:p>+ </table:table-cell>+ </table:table-row>+ <table:table-row>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Second</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Footer</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Row</text:p>+ </table:table-cell>+ </table:table-row>+</table:table>+````
@@ -0,0 +1,6 @@+```+% pandoc --natbib -t latex+We all love the famous proof by @BenjaminHornigold [p. 42].+^D+We all love the famous proof by \citet[p.~42]{BenjaminHornigold}.+```
@@ -0,0 +1,10 @@+```+% pandoc -t asciidoc+### section++##### five+^D+==== section++====== five+```
@@ -0,0 +1,15 @@+Leading tabs must be preserved in org mode *src* blocks with the `-i`+flag when pandoc is called with `-p`/`--preserve-tabs`.++```+% pandoc -f org -t native --preserve-tabs+#+begin_src makefile -i+%.o: %.cpp+ $(CXX) -o $@ $<+#+end_src+^D+[ CodeBlock+ ( "" , [ "makefile" ] , [] )+ "%.o: %.cpp\n\t$(CXX)\t-o\t$@\t$<\n"+]+```
@@ -0,0 +1,53 @@+```+% pandoc -f rst+========== ====+Function 1 +========== ====+a yes +b +========== ====+^D+<table>+<thead>+<tr>+<th>Function</th>+<th>1</th>+</tr>+</thead>+<tbody>+<tr>+<td>a</td>+<td>yes</td>+</tr>+<tr>+<td>b</td>+<td></td>+</tr>+</tbody>+</table>+```++```+% pandoc -f rst+========== ====+Function 1 +========== ====+a yes + & no+========== ====+^D+<table>+<thead>+<tr>+<th>Function</th>+<th>1</th>+</tr>+</thead>+<tbody>+<tr>+<td>a</td>+<td>yes & no</td>+</tr>+</tbody>+</table>+```
@@ -0,0 +1,47 @@+```+% pandoc -f rst -t markdown_strict+.. table:: Test Table++ ================================== ====+ Functions for tests 1 + ================================== ====+ a yes + b + c + d yes+ e + ================================== ====+^D+<table>+<caption>Test Table</caption>+<thead>+<tr>+<th>Functions for tests</th>+<th>1</th>+</tr>+</thead>+<tbody>+<tr>+<td>a</td>+<td>yes</td>+</tr>+<tr>+<td>b</td>+<td></td>+</tr>+<tr>+<td>c</td>+<td></td>+</tr>+<tr>+<td>d</td>+<td>yes</td>+</tr>+<tr>+<td>e</td>+<td></td>+</tr>+</tbody>+</table>++```
@@ -0,0 +1,8 @@+```+% pandoc -t asciidoc --wrap=preserve+[link](https://example.com)+[link](ftps://example.com)+^D+https://example.com[link]+link:ftps://example.com[link]+```
@@ -0,0 +1,713 @@+RST Reader++```+% pandoc -f rst -t native+===== ===== ======+ Inputs Output+------------ ------+ A B A or B+===== ===== ======+False False False+True False True+False True True+True True True+===== ===== ======++Table with trailing whitespaces to ensure they don't interfere with col span parsing.++=============== ============ ===================== +Full column header+---------------------------------------------------- +Header One Header Two Header 3+=============== ============ ===================== +Row With col span 2 on the right+--------------- ----------------------------------- +Full column row+----------------------------------------------------+Row with Col spans For visual separation+--------------- ------------ --------------------- +Row with col span 2 On the left+----------------------------- ---------------------+Final row+=============== ============ =====================+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "Inputs" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Output" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "A" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "B" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "A" , Space , Str "or" , Space , Str "B" ]+ ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "False" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "False" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "False" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "False" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "False" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+, Para+ [ Str "Table"+ , Space+ , Str "with"+ , Space+ , Str "trailing"+ , Space+ , Str "whitespaces"+ , Space+ , Str "to"+ , Space+ , Str "ensure"+ , Space+ , Str "they"+ , Space+ , Str "don't"+ , Space+ , Str "interfere"+ , Space+ , Str "with"+ , Space+ , Str "col"+ , Space+ , Str "span"+ , Space+ , Str "parsing."+ ]+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 3)+ [ Plain+ [ Str "Full"+ , Space+ , Str "column"+ , Space+ , Str "header"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header" , Space , Str "One" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header" , Space , Str "Two" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header" , Space , Str "3" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Row" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain+ [ Str "With"+ , Space+ , Str "col"+ , Space+ , Str "span"+ , Space+ , Str "2"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Str "right"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 3)+ [ Plain+ [ Str "Full"+ , Space+ , Str "column"+ , Space+ , Str "row"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Row" , Space , Str "with" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Col" , Space , Str "spans" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain+ [ Str "For"+ , Space+ , Str "visual"+ , Space+ , Str "separation"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain+ [ Str "Row"+ , Space+ , Str "with"+ , Space+ , Str "col"+ , Space+ , Str "span"+ , Space+ , Str "2"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain+ [ Str "On"+ , Space+ , Str "the"+ , Space+ , Str "left"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Final" , Space , Str "row" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+```++RST Writer+```+% pandoc -f native -t rst+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "Inputs" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Output" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "A" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "B" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "A" , Space , Str "or" , Space , Str "B" ]+ ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "False" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "False" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "False" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "False" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "False" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "True" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 3)+ [ Plain+ [ Str "Full"+ , Space+ , Str "column"+ , Space+ , Str "header"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header" , Space , Str "One" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header" , Space , Str "Two" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header" , Space , Str "3" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Row" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain+ [ Str "With"+ , Space+ , Str "col"+ , Space+ , Str "span"+ , Space+ , Str "2"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Str "right"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 3)+ [ Plain+ [ Str "Full"+ , Space+ , Str "column"+ , Space+ , Str "row"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain+ [ Str "Row"+ , Space+ , Str "with"+ , Space+ , Str "col"+ , Space+ , Str "span"+ , Space+ , Str "2"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain+ [ Str "On"+ , Space+ , Str "the"+ , Space+ , Str "left"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Final" , Space , Str "row" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] ) + [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Footer" , Space , Str "Row" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "at" , Space , Str "the" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "bottom" ] ]+ ]+ ])+]+^D+====== ===== ======+Inputs Output+------------ ------+A B A or B+====== ===== ======+False False False+True False True+False True True+True True True+====== ===== ======++=================== ============================ ===========+Full column header +------------------------------------------------------------+Header One Header Two Header 3+=================== ============================ ===========+Row With col span 2 on the right +------------------- ----------------------------------------+Full column row +------------------------------------------------------------+Row with col span 2 On the left+------------------------------------------------ -----------+Final row +Footer Row at the bottom+=================== ============================ ===========+```
@@ -0,0 +1,24 @@+```+% pandoc -f rtf -t native+{\rtf1\ansi\deff0{\fonttbl{\f0 \fswiss Helvetica;}{\f1 \fmodern Courier;}}+{\colortbl;\red255\green0\blue0;\red0\green0\blue255;}+\widowctrl\hyphauto++{\pard \ql \f0 \sa0 \li0 \fi0 {\shp{\*\shpinst\shpwr2\shpwrk3\shpbypara\shpbyignore\shptop1320\shpbottom7745\shpbxcolumn\shpbxignore\shpleft0\shpright9638{\sp{\sn shapeType}{\sv 75}}{\sp{\sn wzDescription}{\sv }}{\sp{\sn wzName}{\sv }}{\sp{\sn pib}{\sv {\pict\jpegblip\picw20\pich22\picwgoal400\pichgoal440 ffd8ffe000104a46494600010101004800480000fffe0050546869732061727420697320696e20746865207075626c696320646f6d61696e2e204b6576696e204875676865732c206b6576696e68406569742e636f6d2c2053657074656d6265722031393935ffdb00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101ffdb00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101ffc00011080016001403012200021101031101ffc4001a000100020301000000000000000000000000080905060a07ffc400231000010501000300010500000000000000060304050708020001090a11153976b7ffc400160101010100000000000000000000000000060800ffc400261101000102050109000000000000000000010200030405061121b33134365154717475b4ffda000c03010002110311003f00a90cf388f366a62aa720ed6ae07f96901f3831d973452b8cf36fe3570fc908e46d466433e5dd954f2e96992d9e498c7753faa44916e016ca91cc7d88b38fe60a5b97737defcbcc539c98d336a57f4fc2ca9a486bf07ab575ad9a3af4df221d8215e36df86c4504ff0024574551b3d687ee0575757b3ad64e311ee62bd94158d37e24198c43973099f1fc0c41614d950246513a081abf76cfe7061f6863281e6352fd1670949c148dd6dfb0d25f5b3689b1d5c965b0eacbf4e0932ad28e22ab9ae945633f4744bd3c8cee0a7fdf085b9000f449c5f7afa30b83e0b6fd7b0c8429c9467ff9715347c891e25fa24a205861aa715e6a09bd0488237dc2723414d9891381524e8ca7c0894664f835653631ab55ee7e3de433e4ff001b30949124e4c10c8b6ad0a479b3f9c937b2cf5bc0095ad600a0a41a0e9faee174a1c605e161c6c7a313539650b0113190f1a8368e60d5b24f30ff008ea7f0bf867fa6595feeb6978f1fe0f9c26177f4d63a51a9235184750e7d18811339cd000000c75f000e00380380ae390c350def826ed42ad051fa6f501c50f9b699c3b69cbeb76476d202bf3ac985b6e0e968be66572893e6a744540bd9722e5c87956848629bc2559306bd113e8653d3b6aff651dfad7a3ac8b02958cba02a93ccf525757039bae6cff090e1d90688e8aa233ee86a4c4a3e0586d6b2340522e47dcb7d0046d8a5acb05a123ee25d2b230b2ada6e2e2f9ede3c05202520ec2487b0d56562529d8b3393bca76adca4ec1bca508abb001babc007915d84fe3dd14e207e3c62f8379da2a3b861fb6629d28dba53b6ea388ebfed866bf6dfb553455e91ed547ae92e9445253a4fdf3efb4f8ebdfbe7d3c78f1ee0bb9e13e358e942a4ed49e22cff00eeb35fdd7ebfffd9}}}}}\par}+{\pard \ql \f0 \sa0 \li0 \fi0 moon\par}+}+^D+[ Para+ [ Image+ ( ""+ , []+ , [ ( "width" , "0.2777777777777778in" )+ , ( "height" , "0.3055555555555556in" )+ ]+ )+ [ Str "image" ]+ ( "9ea9761885249909bcd8a610706eef51b54dc351.jpg" , "" )+ ]+, Para [ Str "moon" ]+]+```
@@ -0,0 +1,18 @@+```+% pandoc -t typst+See [@MyPaper].++See [@MyPaper, Equation 1] for details.++See [@MyPaper, Equation 1].++See [@MyPaper, Equation 1; @Other, Figure 1].+^D+See @MyPaper.++See @MyPaper[Equation 1] for details.++See @MyPaper[Equation 1].++See @MyPaper[Equation 1]@Other[Figure 1].+```
@@ -0,0 +1,296 @@+Row spans+```+% pandoc -f html --columns 24 -t ansi+<table>+ <thead>+ <tr>+ <td rowspan="3">1</td>+ <td>2</td>+ <td>3</td>+ <td>4</td>+ <td rowspan="4">5</td>+ <td>6</td>+ </tr>+ <tr>+ <td>2</td>+ <td colspan="2" rowspan="2">3</td>+ <td>6</td>+ </tr>+ <tr>+ <td rowspan="2">2</td>+ <td>6</td>+ </tr>+ <tr>+ <td>1</td>+ <td>3</td>+ <td>4</td>+ <td>6</td>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td colspan="2">a</td>+ <td rowspan="2">c</td>+ <td>d</td>+ <td>e</td>+ <td>f</td>+ </tr>+ <tr>+ <td>a</td>+ <td>b</td>+ <td colspan="3" rowspan="2">d</td>+ </tr>+ <tr>+ <td>a</td>+ <td>b</td>+ <td>c</td>+ </tr>+ </tbody>+ <tfoot>+ <tr>+ <td colspan="2" rowspan="4">A</td>+ <td>C</td>+ <td>D</td>+ <td colspan="2" rowspan="3">E</td>+ </tr>+ <tr>+ <td>C</td>+ <td>D</td>+ </tr>+ <tr>+ <td>C</td>+ <td>D</td>+ </tr>+ <tr>+ <td>C</td>+ <td>D</td>+ <td>E</td>+ <td>F</td>+ </tr>+ </tfoot>+</table>+^D+1 2 3 4 5 6+ 2 3 6+ 2 6+1 3 4 6+─── ─── ─── ─── ─── ───+a c d e f+a b d+a b c+─── ─── ─── ─── ─── ───+A C D E+ C D+ C D+ C D E F[0m]8;;\+```++Empty rows+```+% pandoc -f native --columns 12 -t ansi+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 3)+ (ColSpan 2)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row ( "" , [] , [] ) []+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 4)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row ( "" , [] , [] ) []+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row ( "" , [] , [] ) []+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 3)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ ]+ , Row ( "" , [] , [] ) []+ ])+]+^D+1 3+ 3+1 2 3+─── ─── ───+1 2 3+1 2+1 3+1 3+─── ─── ───+1 2 3+1 2 3+1 2[0m]8;;\+```
@@ -0,0 +1,446 @@+# CRediT Roles++This document contains tests and examples for enabling+export of roles to JATS. It was added for+[Issue #10152](https://github.com/jgm/pandoc/issues/10152)+and corresponding [Pull Request #10153](https://github.com/jgm/pandoc/pull/10153).++In the first example, we show a fully qualified CRediT role.+An explicit name isn't given, so the CRediT name is used.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+ - name: Max Mustermann+ affiliation: [ 1 ]+ roles:+ - credit: software+ credit-name: Software+ degree: Lead+affiliation:+- id: 1+ name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role vocab="credit" degree-contribution="Lead"+ vocab-identifier="https://credit.niso.org/"+ vocab-term-identifier="https://credit.niso.org/contributor-roles/software/"+ vocab-term="Software"+>Software</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In the second example, we show a fully qualified CRediT role.+An explicit name is given in a different language.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+ - name: Max Mustermann+ affiliation: [ 1 ]+ roles:+ - credit: software+ credit-name: Software+ degree: Lead+ name: Programas+affiliation:+- id: 1+ name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role vocab="credit" degree-contribution="Lead"+ vocab-identifier="https://credit.niso.org/"+ vocab-term-identifier="https://credit.niso.org/contributor-roles/software/"+ vocab-term="Software"+>Programas</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In this example, we show a partially qualified CRediT role+that does not have a `degree`:++```+% pandoc -s -t jats+---+title: CRediT Test+author:+ - name: Max Mustermann+ affiliation: [ 1 ]+ roles:+ - credit: software+ credit-name: Software+affiliation:+- id: 1+ name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role vocab="credit"+ vocab-identifier="https://credit.niso.org/"+ vocab-term-identifier="https://credit.niso.org/contributor-roles/software/"+ vocab-term="Software"+>Software</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In this example, we show a more stripped-down data that requires automatic lookup of the+`credit-name`.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+ - name: Max Mustermann+ affiliation: [ 1 ]+ roles:+ - credit: software+affiliation:+- id: 1+ name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role vocab="credit"+ vocab-identifier="https://credit.niso.org/"+ vocab-term-identifier="https://credit.niso.org/contributor-roles/software/"+ vocab-term="Software"+>Software</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In this example, we test the correct XML encoding of+the CRediT role [Writing – review & editing](https://credit.niso.org/contributor-roles/writing-review-editing/),+which annoyingly contains an ampersand in its label.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+ - name: Max Mustermann+ affiliation: [ 1 ]+ roles:+ - credit: writing-review-editing+ credit-name: Writing – review & editing+ degree: Lead+affiliation:+- id: 1+ name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role vocab="credit" degree-contribution="Lead"+ vocab-identifier="https://credit.niso.org/"+ vocab-term-identifier="https://credit.niso.org/contributor-roles/writing-review-editing/"+ vocab-term="Writing – review & editing"+>Writing – review & editing</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In this example, we show a role that isn't qualified with CRediT.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+ - name: Max Mustermann+ affiliation: [ 1 ]+ roles:+ - name: Dolphin Catcher+affiliation:+- id: 1+ name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<role>Dolphin Catcher</role>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```++In this example, we show a role that neither has a CRediT identifer,+nor a name, so it's ignored.++```+% pandoc -s -t jats+---+title: CRediT Test+author:+ - name: Max Mustermann+ affiliation: [ 1 ]+ roles:+ - irrelevant-key: Dolphin Catcher+affiliation:+- id: 1+ name: Silverlight University+---+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>CRediT Test</article-title>+</title-group>+<contrib-group>+<contrib contrib-type="author">+<string-name>Max Mustermann</string-name>+<xref ref-type="aff" rid="aff-1"/>+</contrib>+<aff id="aff-1">+<institution-wrap>+<institution>Silverlight University</institution>+</institution-wrap>+</aff>+</contrib-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>++</body>+<back>+</back>+</article>+```
@@ -0,0 +1,15 @@+```+% pandoc -f latex -t native+\begin{equation}+ [0,1)+\end{equation}++\begin{table}[h]+\end{table}+^D+[ Para+ [ Math+ DisplayMath "\\begin{equation}\n [0,1)\n\\end{equation}"+ ]+]+```
@@ -0,0 +1,46 @@+```+% pandoc -t latex --citeproc+Lorem ipsum++# References++::: {#refs}+:::+^D+Lorem ipsum++\section{References}\label{references}++\protect\phantomsection\label{refs}+```++```+% pandoc -t latex --citeproc+---+references:+- id: foo+ type: book+ title: The Title+ author: John Doe+...++Lorem ipsum [@foo].++# References++::: {#refs}+:::+^D+Lorem ipsum (John Doe, n.d.).++\section{References}\label{references}++\protect\phantomsection\label{refs}+\begin{CSLReferences}{1}{1}+\bibitem[\citeproctext]{ref-foo}+John Doe. n.d. \emph{The Title}.++\end{CSLReferences}++```+
@@ -0,0 +1,80 @@+```+% pandoc -t rst+- > test+ >+ > para 2+^D+- ..++ test++ para 2+```++```+% pandoc -t rst+1. > test+ >+ > para 2+^D+1. ..++ test++ para 2+```++```+% pandoc -t rst+::: caution+> test+:::+^D+.. caution::++ ..++ test+```++```+% pandoc -f native -t rst --list-tables+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 0.26 ) ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ BlockQuote+ [ Para [ Emph [ Str "Level" , Space , Str "0:" ] ]+ , Para+ [ Emph [ Str "Incomplete" , Space , Str "process" ]+ ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+^D+.. list-table::+ :widths: 19++ * - ..++ *Level 0:*++ *Incomplete process*+```+
@@ -0,0 +1,29 @@+```+% pandoc -f markdown+smart -t typst+smart+"don't do it---"+^D+"don't do it---"++```+```+% pandoc -f markdown+smart -t typst-smart+"don't do it---"+^D+“don’t do it—”++```+```+% pandoc -f markdown-smart -t typst+smart+"don't do it---"+^D+\"don\'t do it-\-\-\"++```+```+% pandoc -f markdown-smart -t typst-smart+"don't do it---"+^D+"don't do it---"++```+
@@ -0,0 +1,9 @@+```+% pandoc -f rst+See `the full compatibility guidelines <https://+example.com>`_ for more information.+^D+<p>See <a href="https://example.com">the full compatibility+guidelines</a> for more information.</p>++```
@@ -0,0 +1,68 @@+```+% pandoc -f rst -t native+`Want Speed? Pass by Value`_++.. note::+ For more information about the pass-by-value idiom, read: `Want Speed? Pass by Value`_.++ .. _Want Speed? Pass by Value: https://web.archive.org/web/20140205194657/http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/+^D+[ Para+ [ Link+ ( "" , [] , [] )+ [ Str "Want"+ , Space+ , Str "Speed?"+ , Space+ , Str "Pass"+ , Space+ , Str "by"+ , Space+ , Str "Value"+ ]+ ( "https://web.archive.org/web/20140205194657/http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/"+ , ""+ )+ ]+, Div+ ( "" , [ "note" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Note" ] ]+ , Para+ [ Str "For"+ , Space+ , Str "more"+ , Space+ , Str "information"+ , Space+ , Str "about"+ , Space+ , Str "the"+ , Space+ , Str "pass-by-value"+ , Space+ , Str "idiom,"+ , Space+ , Str "read:"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "Want"+ , Space+ , Str "Speed?"+ , Space+ , Str "Pass"+ , Space+ , Str "by"+ , Space+ , Str "Value"+ ]+ ( "https://web.archive.org/web/20140205194657/http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/"+ , ""+ )+ , Str "."+ ]+ ]+]++```+
@@ -0,0 +1,84 @@+```+% pandoc -f rst -t html5+-a Output all.+-c arg Output just arg.+--long Output all day long.+/V A VMS/DOS-style option.++-p This option has two paragraphs in the description.+ This is the first.++ This is the second.+ Blank lines may be omitted between options+ (as above) or left in (as here and below).++--very-long-option A VMS-style option. Note the adjustment+ for the required two spaces.++--an-even-longer-option+ The description can also start on the next line.++-2, --two This option has two variants.++-f FILE, --file=FILE These two options are synonyms; both have+ arguments.++-f <[path]file> Option argument placeholders must start with+ a letter or be wrapped in angle brackets.++-d <src dest> Angle brackets are also required if an option+ expects more than one argument.+^D+<dl>+<dt><code>-a</code></dt>+<dd>+<p>Output all.</p>+</dd>+<dt><code>-c arg</code></dt>+<dd>+<p>Output just arg.</p>+</dd>+<dt><code>--long</code></dt>+<dd>+<p>Output all day long.</p>+</dd>+<dt><code>/V</code></dt>+<dd>+<p>A VMS/DOS-style option.</p>+</dd>+<dt><code>-p</code></dt>+<dd>+<p>This option has two paragraphs in the description. This is the+first.</p>+<p>This is the second. Blank lines may be omitted between options (as+above) or left in (as here and below).</p>+</dd>+<dt><code>--very-long-option</code></dt>+<dd>+<p>A VMS-style option. Note the adjustment for the required two+spaces.</p>+</dd>+<dt><code>--an-even-longer-option</code></dt>+<dd>+<p>The description can also start on the next line.</p>+</dd>+<dt><code>-2, --two</code></dt>+<dd>+<p>This option has two variants.</p>+</dd>+<dt><code>-f FILE, --file=FILE</code></dt>+<dd>+<p>These two options are synonyms; both have arguments.</p>+</dd>+<dt><code>-f <[path]file></code></dt>+<dd>+<p>Option argument placeholders must start with a letter or be wrapped+in angle brackets.</p>+</dd>+<dt><code>-d <src dest></code></dt>+<dd>+<p>Angle brackets are also required if an option expects more than one+argument.</p>+</dd>+</dl>+```
@@ -0,0 +1,37 @@+Unwrap divs if they only have the `nonincremental` or `incremental` classes.++```+% pandoc --incremental --from=markdown --to=revealjs+## First slide++::: nonincremental++1. Note 1+2. Note 2+3. Note 3++:::++## Second Slide++1. Note 1+2. Note 2+3. Note 3+^D+<section id="first-slide" class="slide level2">+<h2>First slide</h2>+<ol type="1">+<li>Note 1</li>+<li>Note 2</li>+<li>Note 3</li>+</ol>+</section>+<section id="second-slide" class="slide level2">+<h2>Second Slide</h2>+<ol type="1">+<li class="fragment">Note 1</li>+<li class="fragment">Note 2</li>+<li class="fragment">Note 3</li>+</ol>+</section>+```
@@ -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,22 @@+````+% pandoc -t asciidoc+C+ C++ C+++ `++`++`` ` `` \`hi\`++`hi\there`` ok`++```+++`+```+^D+C{plus} C{plus}{plus} C{plus}{plus}{plus} `{plus}{plus}`++`++`++` ++`++hi++`++++`hi++\++there++``++ ok`++....+++`+....+````
@@ -0,0 +1,23 @@+```+% pandoc -f mediawiki+ {| class="wikitable"+ |+ Overview of basic table markup+ ! Key+ |-+ | Value+ |}+^D+<table>+<caption>Overview of basic table markup</caption>+<thead>+<tr>+<th><p>Key</p></th>+</tr>+</thead>+<tbody>+<tr>+<td><p>Value</p></td>+</tr>+</tbody>+</table>+```
@@ -0,0 +1,6 @@+```+% pandoc -f textile -t html+from 30.-100. text, inside - after dash+^D+<p>from 30.–100. text, inside - after dash</p>+```
@@ -0,0 +1,11 @@+```+% pandoc -s --shift-heading-level-by=-1 -f djot -t native+# hi+^D+Pandoc+ Meta+ { unMeta =+ fromList [ ( "title" , MetaInlines [ Str "hi" ] ) ]+ }+ [ Div ( "hi" , [ "section" ] , [] ) [] ]+```
@@ -0,0 +1,22 @@+```+% pandoc -frst -tmarkdown_strict+- One issue fixed: `issue 123`_.++- One change merged: `Big change <pull 234_>`_.++- Improved the `home page <https://example.com/homepage>`_.++- One more `small change`__.++.. _issue 123: https://github.com/joe/project/issues/123+.. _pull 234: https://github.com/joe/project/pull/234+__ https://github.com/joe/project/issues/999++^D+- One issue fixed: [issue+ 123](https://github.com/joe/project/issues/123).+- One change merged: [Big+ change](https://github.com/joe/project/pull/234).+- Improved the [home page](https://example.com/homepage).+- One more [small change](https://github.com/joe/project/issues/999).+```
@@ -0,0 +1,50 @@+```+% pandoc -f mediawiki -t html+{|class="wikitable" style="text-align: center;"+|-+!rowspan=3 style=""|Witness program version+!colspan=4 style=""|Hash size+|-+!Mainnet+!Testnet+!Mainnet+!Testnet+|-+|0||p2||QW||7Xh||T7n+|-+|1||p4||QY||7Xq||T7w+|}+^D+<table>+<thead>+<tr>+<th style=""><p>Witness program version</p></th>+<th colspan="4" style=""><p>Hash size</p></th>+</tr>+</thead>+<tbody>+<tr>+<td><p>Mainnet</p></td>+<td><p>Testnet</p></td>+<td><p>Mainnet</p></td>+<td><p>Testnet</p></td>+<td></td>+</tr>+<tr>+<td><p>0</p></td>+<td><p>p2</p></td>+<td><p>QW</p></td>+<td><p>7Xh</p></td>+<td><p>T7n</p></td>+</tr>+<tr>+<td><p>1</p></td>+<td><p>p4</p></td>+<td><p>QY</p></td>+<td><p>7Xq</p></td>+<td><p>T7w</p></td>+</tr>+</tbody>+</table>++```
@@ -0,0 +1,35 @@+```+% pandoc -f mediawiki -t gfm+{| class="wikitable"+|-+!+!0+!1+!2+!3+!4+!5+!6+!7+|-+!+0+|q||p||z||r||y||9||x||8+|-+!+8+|g||f||2||t||v||d||w||0+|-+!+16+|s||3||j||n||5||4||k||h+|-+!+24+|c||e||6||m||u||a||7||l+|}+^D+| | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |+|-----|-----|-----|-----|-----|-----|-----|-----|-----|+| +0 | q | p | z | r | y | 9 | x | 8 |+| +8 | g | f | 2 | t | v | d | w | 0 |+| +16 | s | 3 | j | n | 5 | 4 | k | h |+| +24 | c | e | 6 | m | u | a | 7 | l |++```
@@ -0,0 +1,13 @@+```+% pandoc -f rst+a.__b__++a__b__++__foo__+^D+<p>a.__b__</p>+<p>a__b__</p>+<p>__foo__</p>+```+
@@ -0,0 +1,24 @@+```+% pandoc -f pod -t html+=encoding utf8++=head1 NAME++Test document+^D+<h1>NAME</h1>+<p>Test document</p>+```++```+% pandoc -f pod -t html+=encoding utf8+++=head1 NAME++Test document+^D+<h1>NAME</h1>+<p>Test document</p>+```
@@ -0,0 +1,28 @@+```+% pandoc -f docbook -t native+<orderedlist numeration="loweralpha">+<title>header inside listing</title> // not rendered in any output format!+<listitem>+<simpara>first step</simpara>+</listitem>+</orderedlist>+^D+[ Div+ ( "" , [] , [] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Plain+ [ Str "header"+ , Space+ , Str "inside"+ , Space+ , Str "listing"+ ]+ ]+ , OrderedList+ ( 1 , LowerAlpha , DefaultDelim )+ [ [ Para [ Str "first" , Space , Str "step" ] ] ]+ ]+]++```
@@ -0,0 +1,7 @@+```+% pandoc -f markdown -t html+[test](url+"title")+^D+<p><a href="url" title="title">test</a></p>+```
@@ -0,0 +1,8 @@+GFM has funny treatment of escaped braces, requiring `\\{` instead of `\{`.++```+% pandoc -f gfm -t markdown+$\\{x,y\\}$+^D+$\{x,y\}$+```
@@ -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,11 @@+```+% pandoc -f html -t native+<p>A<style></style>B</p>+^D+[ Para+ [ Str "A"+ , RawInline (Format "html") "<style></style>"+ , Str "B"+ ]+]+```
@@ -0,0 +1,9 @@+```+% pandoc -t typst --wrap=preserve+1\. I don't want this to be an enumerated list.+2\. No, I don't: only a number before a paragraph.+^D+\1. I don't want this to be an enumerated list.+\2. No, I don't: only a number before a paragraph.+```+
@@ -0,0 +1,45 @@+```+% pandoc -f latex -t native+\includegraphics[+width=5cm,+]{abc.jpg}+^D+[ Para+ [ Image+ ( "" , [] , [ ( "width" , "5cm" ) ] )+ [ Str "image" ]+ ( "abc.jpg" , "" )+ ]+]+```++```+% pandoc -f latex -t native+\includegraphics[%+width=5cm,%+]{abc.jpg}+^D+[ Para+ [ Image+ ( "" , [] , [ ( "width" , "5cm" ) ] )+ [ Str "image" ]+ ( "abc.jpg" , "" )+ ]+]+```++```+% pandoc -f latex -t native+\includegraphics[width=5cm]{%+abc.jpg%+}+^D+[ Para+ [ Image+ ( "" , [] , [ ( "width" , "5cm" ) ] )+ [ Str "image" ]+ ( "abc.jpg" , "" )+ ]+]+```+
@@ -0,0 +1,26 @@+```+% pandoc+| This | Is |+|:-----|:---|+| With \+| Cells+^D+<table>+<thead>+<tr>+<th style="text-align: left;">This</th>+<th style="text-align: left;">Is</th>+</tr>+</thead>+<tbody>+<tr>+<td style="text-align: left;">With \</td>+<td style="text-align: left;"></td>+</tr>+<tr>+<td style="text-align: left;">Cells</td>+<td style="text-align: left;"></td>+</tr>+</tbody>+</table>+```
@@ -0,0 +1,24 @@+```+% pandoc -f html -t mediawiki+<dl>+<dt>Case 1: Both subsets are non-empty</dt>+<dd>+In this case, …+</dd>+</dl>+^D+; Case 1<nowiki>:</nowiki> Both subsets are non-empty+: In this case, …+```++```+% pandoc -f mediawiki -t html+; term : definition+^D+<dl>+<dt>term</dt>+<dd>+definition+</dd>+</dl>+```
@@ -0,0 +1,7 @@+```+% pandoc -f org -t native+=hi+there=+^D+[ Para [ Code ( "" , [ "verbatim" ] , [] ) "hi there" ] ]+```
@@ -0,0 +1,6 @@+```+% pandoc -t typst+[Mark]{.mark}+^D+#highlight[Mark]+```
@@ -0,0 +1,71 @@+```+% pandoc -f native -t markdown+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing [ Para [ Str "An" , Space , Str "image." ] ])+ [ Plain+ [ Image+ ( ""+ , []+ , []+ )+ [ Str "An" , Space , Str "image." ]+ ( "media/rId20.jpg" , "" )+ ]+ ]+]+^D++```++```+% pandoc -f native -t markdown -t markdown-implicit_figures+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing [ Para [ Str "An" , Space , Str "image." ] ])+ [ Plain+ [ Image+ ( ""+ , []+ , []+ )+ [ Str "An" , Space , Str "image." ]+ ( "media/rId20.jpg" , "" )+ ]+ ]+]+^D+<figure>+<img src="media/rId20.jpg" alt="An image." />+<figcaption aria-hidden="true"><p>An image.</p></figcaption>+</figure>+```++```+% pandoc -f native -t markdown -t markdown-implicit_figures-raw_html+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing [ Para [ Str "An" , Space , Str "image." ] ])+ [ Plain+ [ Image+ ( ""+ , []+ , []+ )+ [ Str "An" , Space , Str "image." ]+ ( "media/rId20.jpg" , "" )+ ]+ ]+]+^D+:::: figure+++::: caption+An image.+:::+::::+```
@@ -0,0 +1,21 @@+```+% pandoc -f native -t markdown+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Para [ Str "Foo" , Space , Emph [ Str "emphasis" ] ] ])+ [ Plain+ [ Image+ ( ""+ , []+ , []+ )+ [ Str "Foo" , Space , Str "emphasis" ]+ ( "media/rId20.jpg" , "" )+ ]+ ]+]+^D++```
@@ -0,0 +1,8 @@+```+% pandoc -f latex -t markdown --wrap=preserve+This is \texttt{--flag} with dashes.+This is the same --flag without a code.+^D+This is `--flag` with dashes.+This is the same --flag without a code.+```
@@ -0,0 +1,15 @@+```+% pandoc -t opendocument+Aboard **the luxury cruise ship Heart of the Ocean[^1] in the Atlantic Ocean**...++[^1]: **Heart of the Ocean** (海洋之心) – The Heart of the Ocean+^D+<text:p text:style-name="Text_20_body">Aboard+<text:span text:style-name="Strong_20_Emphasis">the luxury cruise ship+Heart of the+Ocean</text:span><text:note text:id="ftn0" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote"><text:span text:style-name="Strong_20_Emphasis">Heart+of the Ocean</text:span> (海洋之心) – The Heart of the+Ocean</text:p></text:note-body></text:note><text:span text:style-name="Strong_20_Emphasis">+in the Atlantic Ocean</text:span>…</text:p>++```
@@ -0,0 +1,19 @@+```+% pandoc -t typst -f latex+\begin{equation}+ \label{eq:U}+ U = A+\end{equation}+^D+$ U = A $<eq:U>+```++```+% pandoc -t typst -f latex+\begin{equation}+ \label{eq:U 2}+ U = A+\end{equation}+^D+$ U = A $#label("eq:U 2")+```
@@ -0,0 +1,41 @@+Check that the `four_space_rule` extension works for plain writer.++```+% pandoc -f markdown -t plain+four_space_rule+This is the title++Here we fix:++- a+- b+- c+^D+This is the title++Here we fix:++- a+- b+- c+```++Check that the `four_space_rule` extension is off by default.++```+% pandoc -f markdown -t plain+This is the title++Here we fix:++- a+- b+- c+^D+This is the title++Here we fix:++- a+- b+- c+```
@@ -0,0 +1,7 @@+```+% pandoc -f markdown -t typst+# Test①+^D+= Test①+#label("test①")+```
@@ -0,0 +1,39 @@+```+% pandoc -f docbook -t html+<?xml version="1.0" encoding="utf-8"?>+<book xmlns="http://docbook.org/ns/docbook" version="5.0">+ <info><title>Literallayout test</title></info>+ <chapter>+ <info><title>Literallayout without class</title></info>+ <literallayout>First line.+Second line.+ Third line, indented two spaces.</literallayout>+ </chapter>+ <chapter>+ <info><title>Literallayout with normal class</title></info>+ <literallayout class="normal">First line.+Second line.+ Third line, indented two spaces.</literallayout>+ </chapter>+ <chapter>+ <info><title>Literallayout with monospaced</title></info>+ <literallayout class="monospaced">First line.+Second line.+ Third line, indented two spaces.</literallayout>+ </chapter>+</book>+^D+<h1>Literallayout without class</h1>+<div class="line-block">First line.<br />+Second line.<br />+ Third line, indented two spaces.</div>+<h1>Literallayout with normal class</h1>+<div class="line-block">First line.<br />+Second line.<br />+ Third line, indented two spaces.</div>+<h1>Literallayout with monospaced</h1>+<pre><code>First line.+Second line.+ Third line, indented two spaces.</code></pre>++```
@@ -0,0 +1,12 @@+```+% pandoc -f org -t latex+Some equation here+\begin{equation}+x = y+\end{equation}+where $x$ is something important.+^D+Some equation here \begin{equation}+x = y+\end{equation} where \(x\) is something important.+```
@@ -0,0 +1,82 @@+```+% pandoc -f html -t markdown+<table>+<tr>+<td colspan="3">A</td>+<td rowspan="1" colspan="2">F</td>+</tr>+<tr>+<td>C</td>+<td colspan="2">B</td>+<td colspan="2">H</td>+</tr>+<tr>+<td colspan="2">D</td>+<td colspan="2">E</td>+<td>G</td>+</tr>+</table>+^D++---+---+---+---+---++| A | F |++---+-------+-------++| C | B | H |++---+---+---+---+---++| D | E | G |++-------+-------+---++```++```+% pandoc -f html -t markdown+<table>+<tr>+<td colspan="2">A</td>+<td colspan="2">J</td>+<td rowspan="3">F</td>+</tr>+<tr>+<td rowspan="3">C</td>+<td>B</td>+<td rowspan="2" colspan="2">H</td>+</tr>+<tr>+<td>D</td>+</tr>+<tr>+<td colspan="4">K</td>+</tr>+</table>+^D++---+---+-------+---++| A | J | F |++---+---+-------+ |+| C | B | H | |+| +---+ | |+| | D | | |+| +---+-------+---++| | K |++---+---------------++```++```+% pandoc -f html -t markdown-simple_tables-multiline_tables-pipe_tables+<table>+ <tbody>+ <tr>+ <td>a</td>+ <td></td>+ </tr>+ <tr>+ <td></td>+ <td></td>+ </tr>+ </tbody>+</table>+^D++---+---++| a | |++---+---++| | |++---+---++```+
@@ -0,0 +1,71 @@+```+% pandoc -t markdown++----------+----++| h1 | h2 |++:===:+===:+:===++| A | B |++-----+----+----++| C | D | E |++-----+----+----++^D++-------------+----++| h1 | h2 |++:====:+=====:+:===++| A | B |++------+------+----++| C | D | E |++------+------+----+++```++```+% pandoc -t markdown++-----+----+----++| h1 | h2 | h3 |++:===:+===:+:===++| A | B |++-----+----+----++| C | D | E |++-----+----+----++^D++------+------+----++| h1 | h2 | h3 |++:====:+=====:+:===++| A | B |++------+------+----++| C | D | E |++------+------+----+++```++```+% pandoc -t markdown++:------:+:-----------:++| hello |  |++--------+-------------++| hello |  |++--------+-------------++^D++:------:+:-----------:++| hello |  |++--------+-------------++| hello |  |++--------+-------------+++```++```+% pandoc -t markdown++:------:+:-----------:++| hello |  |++--------+-------------++| hello |  |++--------+-------------++^D++:------:+:-----------:++| hello |  |++--------+-------------++| hello |  |++--------+-------------+++```
@@ -0,0 +1,6 @@+```+% pandoc --embed-resources+<script></script>+^D+<script></script>+```
@@ -0,0 +1,26 @@+```+% pandoc -f native -t markdown-raw_html+[ Figure+ ( "fig:foo" , [] , [ ( "label" , "1.1" ) ] )+ (Caption+ Nothing+ [ Plain+ [ Str "Figure" , Space , Str "1.1:" , Space , Str "Figure" ]+ ])+ [ Plain+ [ Image+ ( "" , [] , [] )+ [ Str "Figure" , Space , Str "1.1:" , Space , Str "Figure" ]+ ( "./image.png" , "" )+ ]+ ]+]+^D+:::: {#fig:foo .figure label="1.1"}+++::: caption+Figure 1.1: Figure+:::+::::+```
@@ -0,0 +1,17 @@+```+% pandoc -f markdown -t markdown+ header1 header2+ --------- ---------+ r1c1 r1c2+ r2c1 r2c2++ : mycaption {#myid .myclass key="value"}+^D+ header1 header2+ --------- ---------+ r1c1 r1c2+ r2c1 r2c2++ : mycaption {#myid .myclass key="value"}++```
@@ -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,97 @@+Ungrouped field instruction:+```+% pandoc -f rtf -t native+{\rtf1\ansi\deff0+{\fonttbl{\f0\froman Times New Roman;}}+{\colortbl;\red0\green0\blue0;}+\deftab720++\trowd\trleft0\cellx2000\cellx4000+\pard\intbl+{{\field{\*\fldinst HYPERLINK "https://example.com" }{\fldrslt {\hich\af0\loch\hich\af0\loch\cf0\f0\cf0\f0\loch+{\*\bkmkstart _dx_frag_StartFragment}{\*\bkmkend _dx_frag_StartFragment}Problem Text}}}}\cell+\pard\intbl Normal Text\cell+\row++\trowd\trleft0\cellx2000\cellx4000+\pard\intbl Simple Text\cell+\pard\intbl More Text\cell+\row+}+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "Problem" , Space , Str "Text" ]+ ( "https://example.com" , "" )+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Normal" , Space , Str "Text" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Simple" , Space , Str "Text" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "More" , Space , Str "Text" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+```++Additionally, ungrouped field result:+```+% pandoc -f rtf -t native+{\rtf1\ansi\ansicpg1252\cocoartf2867+\cocoatextscaling0\cocoaplatform1{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}+{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;}+\paperw11905\paperh16837\margl1133\margr1133\margb1133\margt1133+\deftab720+\pard\pardeftab720\partightenfactor0+{\field{\*\fldinst{HYPERLINK "https://example.com"}}{\fldrslt +\f0\fs22 \cf2 \up0 \nosupersub \ul \ulc2 link}}}+^D+[ Para+ [ Underline+ [ Link+ ( "" , [] , [] )+ [ Str "link" ]+ ( "https://example.com" , "" )+ ]+ ]+]+```
@@ -0,0 +1,50 @@+```+% pandoc -f markdown -t typst+::: {lang="en"}+This text should be in English.+:::+^D+#block[+#set text(lang: "en");+This text should be in English.++]+```++```+% pandoc -f markdown -t typst+::: {lang="fr"}+Ce texte devrait être en français.+:::+^D+#block[+#set text(lang: "fr");+Ce texte devrait être en français.++]+```++```+% pandoc -f markdown -t typst+::: {lang="de-DE"}+Dieser Text sollte auf Deutsch sein.+:::+^D+#block[+#set text(lang: "de");+Dieser Text sollte auf Deutsch sein.++]+```++```+% pandoc -f markdown -t typst+::: {lang=""}+This should not have lang set.+:::+^D+#block[+This should not have lang set.++]+```
@@ -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.]+)
@@ -0,0 +1,15 @@+```+% pandoc -f typst -t native+First paragraph.++#pagebreak()++Second paragraph.+^D+[ Para [ Str "First" , Space , Str "paragraph." ]+, Div+ ( "" , [ "page-break" ] , [ ( "wrapper" , "1" ) ] )+ [ HorizontalRule ]+, Para [ Str "Second" , Space , Str "paragraph." ]+]+```
binary file changed (absent → 14206 bytes)
@@ -0,0 +1,7 @@+```+% pandoc command/11113.docx -t plain+^D+Colored:❤️😏📖👌😒🤍++BW: 😊︎+```
@@ -0,0 +1,10 @@+The heading is "unlinked" before adding it to the TOC.++```+% pandoc --to=latex+<http://example.com/> {-}+=========================+^D+\section*{\texorpdfstring{\url{http://example.com/}}{http://example.com/}}\label{httpexample.com}+\addcontentsline{toc}{section}{{http://example.com/}}+```
@@ -0,0 +1,23 @@+```+% pandoc -f html -t markdown_strict+pipe_tables-raw_html+<table>+<tr>+<th class="" colspan="2" rowspan="1"><b>Subject</b></th>+<th class=""><b>Grade</b></th>+</tr>+<tr>+<td class="" colspan="1" rowspan="2">Physics</td>+<td class="">Practical</td>+<td class="">A</td>+</tr>+<tr>+<td class="">Theory</td>+<td class="">B+</td>+</tr>+</table>+^D+| **Subject** | | **Grade** |+|-------------|-----------|-----------|+| Physics | Practical | A |+| | Theory | B+ |+```
@@ -0,0 +1,71 @@+```+% pandoc -f rst -t native+.. figure:: image.png+ :alt: my alt++ Caption+^D+[ Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "Caption" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] )+ [ Str "my" , Space , Str "alt" ]+ ( "image.png" , "" )+ ]+ ]+]+```++```+% pandoc -f rst -t native+.. figure:: image.png++ Caption+^D+[ Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "Caption" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] ) [ Str "Caption" ] ( "image.png" , "" )+ ]+ ]+]+```++```+% pandoc -f native -t markdown+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing [ Plain [ Str "Caption" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [ Str "my", Space, Str "alt" ] ( "image.png" , "" )+ ]+ ]+]+^D+{alt="my alt"}+```++Ignore `\pandocbounded`:+```+% pandoc -f latex -t native+\begin{figure}+\centering+\pandocbounded{\includegraphics[keepaspectratio,alt={Caption}]{image.png}}+\caption{Caption}+\end{figure}+^D+[ Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "Caption" ] ])+ [ Para+ [ Image+ ( "" , [] , [] ) [ Str "Caption" ] ( "image.png" , "" )+ ]+ ]+]+```
@@ -0,0 +1,29 @@+```+% pandoc -f rst+=== =====+int float+=== =====+10 9.90+-10 9.90+=== =====+^D+<table>+<thead>+<tr>+<th>int</th>+<th>float</th>+</tr>+</thead>+<tbody>+<tr>+<td>10</td>+<td>9.90</td>+</tr>+<tr>+<td>-10</td>+<td>9.90</td>+</tr>+</tbody>+</table>++```
@@ -0,0 +1,19 @@+```+% pandoc -f native -t rst+[ BulletList+ [ [ Plain [ Str "list" ]+ , CodeBlock ( "" , [ "ruby" ] , [] ) "code = 7 # comment"+ ]+ , [ Plain [ Str "second" , Space , Str "item" ] ]+ ]+]+^D+- list++ .. code:: ruby++ code = 7 # comment++- second item++```
@@ -0,0 +1,80 @@+Parsing PARAMETERS of Org-mode blocks++```+% pandoc -f org --to=native+#+attr_html: :width 10px+#+BEGIN_myex :this that+huhu+#+END_myex+^D+[ Div+ ( ""+ , [ "myex" ]+ , [ ( "width" , "10px" ) , ( "this" , "that" ) ]+ )+ [ Para [ Str "huhu" ] ]+]+```++Python-style parameters are accepted, too.++```+% pandoc -f org --to=native+#+BEGIN_myblock width=10px+[[image.svg][logo]]+#+END_myblock+^D+[ Div+ ( "" , [ "myblock" ] , [ ( "width" , "10px" ) ] )+ [ Para+ [ Span+ ( ""+ , [ "spurious-link" ]+ , [ ( "target" , "image.svg" ) ]+ )+ [ Emph [ Str "logo" ] ]+ ]+ ]+]+```++The fallback is to put the remainder of the line into a `parameters`+attribute.++```+% pandoc -f org --to=native+#+BEGIN_myblock these are parameters in an unsupported format+/OK/+#+END_myblock+^D+[ Div+ ( ""+ , [ "myblock" ]+ , [ ( "parameters"+ , "these are parameters in an unsupported format"+ )+ ]+ )+ [ Para [ Emph [ Str "OK" ] ] ]+]+```++Also works on dynamic blocks.++```+% pandoc -f org --to=markdown+#+BEGIN: clocktable :scope subtree :maxlevel 3+#+CAPTION: Clock summary at [2025-10-18 Sat 17:23]+| Headline | Time |+|--------------+--------|+| *Total time* | *0:00* |+#+END:+^D+::: {.clocktable scope="subtree" maxlevel="3"}+ Headline Time+ ---------------- ----------+ **Total time** **0:00**++ : Clock summary at \[2025-10-18 Sat 17:23\]+:::+```
@@ -0,0 +1,13 @@+```+% pandoc -t typst -f man+.PP+.IR login (1)+.PP+and a regular (paren) that should not be escaped.+^D+#emph[login]\(1)++and a regular (paren) that should not be escaped.++```+
@@ -0,0 +1,16 @@+```+% pandoc -f rtf -t native+{\field{\*\fldinst{\rtlch\ab0\ai0\af2\alang1025\afs22\ltrch\b0\i0\fs22\lang1033\langnp1033\langfe1033\langfenp1033+\loch\af2\dbch\af2\hich\f2\insrsid10976062\strike0\ulnone\cf1 HYPERLINK "https://example.com"}{\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b28000000680074007400700073003a002f002f006500780061006d0070006c0065002e0063006f006d000000}}+{\fldrslt{\rtlch\ab0\ai0\af2\alang1025\afs22\ltrch\b0\i0\fs22\lang1033\langnp1033\langfe1033\langfenp1033\loch\af2\dbch\af2\hich\f2\strike0\ul\cf2 link}}}+^D+[ Para+ [ Underline+ [ Link+ ( "" , [] , [] )+ [ Str "link" ]+ ( "https://example.com" , "" )+ ]+ ]+]+```
@@ -0,0 +1,27 @@+```+% pandoc -f markdown -t native+\ifstrequal{hello}{hello}{TRUE}{FALSE}+\ifstrequal{hello}{world}{TRUE}{FALSE}+^D+[ Para+ [ RawInline (Format "tex") "TRUE"+ , SoftBreak+ , RawInline (Format "tex") "FALSE"+ ]+]+```++```+% pandoc -f markdown-latex_macros -t native+\ifstrequal{hello}{hello}{TRUE}{FALSE}+\ifstrequal{hello}{world}{TRUE}{FALSE}+^D+[ Para+ [ RawInline+ (Format "tex") "\\ifstrequal{hello}{hello}{TRUE}{FALSE}"+ , SoftBreak+ , RawInline+ (Format "tex") "\\ifstrequal{hello}{world}{TRUE}{FALSE}"+ ]+]+```
@@ -0,0 +1,19 @@+```+% pandoc -t latex+$$+\begin{eqnarray}+S &\rightarrow& a A \nonumber \\+A &\rightarrow& d B \ | \ b A \ | \ c A \nonumber \\+B &\rightarrow& a c \ | \ b C \ | \ c A \nonumber \\+C &\rightarrow& \epsilon \nonumber+\end{eqnarray}+$$+^D++\begin{eqnarray}+S &\rightarrow& a A \nonumber \\+A &\rightarrow& d B \ | \ b A \ | \ c A \nonumber \\+B &\rightarrow& a c \ | \ b C \ | \ c A \nonumber \\+C &\rightarrow& \epsilon \nonumber+\end{eqnarray}+```
@@ -0,0 +1,25 @@+```+% pandoc -f markdown -t native -s+---+header-includes: |+ \makeatletter+ \beamer@ignorenonframefalse+ \makeatother+...++^D+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "header-includes"+ , MetaBlocks+ [ RawBlock+ (Format "tex")+ "\\makeatletter\n\\beamer@ignorenonframefalse\n\\makeatother"+ ]+ )+ ]+ }+ []+```
@@ -0,0 +1,28 @@+```+% pandoc -f mediawiki -t native+<foo>++<samp>x</samp>++<kbd>x</kbd>++<var>x</var>++<mark>This is ''highlighted''</mark>+^D+[ Para [ Str "<foo>" ]+, Para [ Code ( "" , [ "sample" ] , [] ) "x" ]+, Para [ Span ( "" , [ "kbd" ] , [] ) [ Str "x" ] ]+, Para [ Code ( "" , [ "variable" ] , [] ) "x" ]+, Para+ [ Span+ ( "" , [ "mark" ] , [] )+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Emph [ Str "highlighted" ]+ ]+ ]+]+```
@@ -0,0 +1,67 @@+```+% pandoc -f docbook -t native -s+<?xml version="1.0"?>+<book xmlns="http://docbook.org/ns/docbook" version="5.0" dir="ltr">+ <info>+ <title>Book title</title>+ <subtitle>Book subtitle</subtitle>+ </info>+ <chapter>+ <info>+ <title>Chapter title</title>+ </info>+ <para>My sentence</para>+ </chapter>+</book>+^D+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "subtitle"+ , MetaInlines [ Str "Book" , Space , Str "subtitle" ]+ )+ , ( "title"+ , MetaInlines [ Str "Book" , Space , Str "title" ]+ )+ ]+ }+ [ Header+ 1 ( "" , [] , [] ) [ Str "Chapter" , Space , Str "title" ]+ , Para [ Str "My" , Space , Str "sentence" ]+ ]+```++```+% pandoc -f docbook -t native -s+<?xml version="1.0"?>+<book xmlns="http://docbook.org/ns/docbook" version="5.0" dir="ltr">+ <chapter>+ <info>+ <title>Chapter title</title>+ </info>+ <para>My sentence</para>+ </chapter>+ <info>+ <title>Book title</title>+ <subtitle>Book subtitle</subtitle>+ </info>+</book>+^D+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "subtitle"+ , MetaInlines [ Str "Book" , Space , Str "subtitle" ]+ )+ , ( "title"+ , MetaInlines [ Str "Book" , Space , Str "title" ]+ )+ ]+ }+ [ Header+ 1 ( "" , [] , [] ) [ Str "Chapter" , Space , Str "title" ]+ , Para [ Str "My" , Space , Str "sentence" ]+ ]+```
@@ -0,0 +1,6 @@+```+% pandoc -f rst -t native+Cho\ **co**\ late+^D+[ Para [ Str "Cho" , Strong [ Str "co" ] , Str "late" ] ]+```
@@ -0,0 +1,21 @@+```+% pandoc -f mediawiki -t texinfo+foofoo++ bar+ baz++foofoo+^D+@node Top+@top Top++foofoo++@example+bar+baz+@end example++foofoo+```
@@ -0,0 +1,12 @@+```+% pandoc -f rst+foo-+ bar+^D+<dl>+<dt>foo-</dt>+<dd>+<p>bar</p>+</dd>+</dl>+```
@@ -0,0 +1,9 @@+```+% pandoc -t commonmark -f html+<h1>The Hobbit<br>or<br>There and Back Again</h1>+^D+The Hobbit\+or\+There and Back Again+====================+```
@@ -0,0 +1,33 @@+Subfigures should be converted to *fig-group* elements.++```+% pandoc -f latex -t jats+\begin{figure}[H]+ \begin{subfigure}+ \centering+ \includegraphics[height=1.5in]{assets/A.png}+ \caption{Graph for function *A*.}+ \label{fig:A}+ \end{subfigure}+ \begin{subfigure}+ \centering+ \includegraphics[height=1.5in]{assets/B.png}+ \caption{Graph for function *B*.}+ \label{fig:B}+ \end{subfigure}+ \label{fig:graphs}+ \caption{Function graphs.}+\end{figure}+^D+<fig-group id="figU003Agraphs">+ <caption><p>Function graphs.</p></caption>+ <fig id="figU003AA">+ <caption><p>Graph for function *A*.</p></caption>+ <graphic mimetype="image" mime-subtype="png" xlink:href="assets/A.png" />+ </fig>+ <fig id="figU003AB">+ <caption><p>Graph for function *B*.</p></caption>+ <graphic mimetype="image" mime-subtype="png" xlink:href="assets/B.png" />+ </fig>+</fig-group>+```
@@ -0,0 +1,61 @@+```+% pandoc -f markdown -t native+$ invalid opening inline math$++$+invalid opening inline math$++$invalid closing inline math $++$invalid closing inline math+$++$valid inline math$+^D+[ Para+ [ Str "$"+ , Space+ , Str "invalid"+ , Space+ , Str "opening"+ , Space+ , Str "inline"+ , Space+ , Str "math$"+ ]+, Para+ [ Str "$"+ , SoftBreak+ , Str "invalid"+ , Space+ , Str "opening"+ , Space+ , Str "inline"+ , Space+ , Str "math$"+ ]+, Para+ [ Str "$invalid"+ , Space+ , Str "closing"+ , Space+ , Str "inline"+ , Space+ , Str "math"+ , Space+ , Str "$"+ ]+, Para+ [ Str "$invalid"+ , Space+ , Str "closing"+ , Space+ , Str "inline"+ , Space+ , Str "math"+ , SoftBreak+ , Str "$"+ ]+, Para [ Math InlineMath "valid inline math" ]+]+```
@@ -0,0 +1,17 @@+```+% pandoc -f markdown -t asciidoc+This is a _test_[^1].++And yet another **one**[^1].++We can also try to write #hashtags [this]{.test}.++[^1]: Test footnote.+^D+This is a __test__footnote:[Test footnote.].++And yet another **one**footnote:[Test footnote.].++We can also try to write ++#++hashtags [.test]#this#.++```
@@ -0,0 +1,75 @@+```+% pandoc -f rtf -t native+{\rtf1\ansi\deff3\adeflang1025+{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\fnil\fprq0\fcharset2 OpenSymbol{\*\falt Arial Unicode MS};}{\f5\fswiss\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f6\fnil\fprq2\fcharset0 Noto Sans CJK SC;}{\f7\fnil\fprq2\fcharset0 Matangi Light;}{\f8\fnil\fprq0\fcharset128 Matangi Light;}{\f9\fnil\fprq0\fcharset128 OpenSymbol{\*\falt Arial Unicode MS};}}+{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}+{\stylesheet{\s0\snext0\widctlpar\hyphpar0\ltrpar\kerning1\cf0\rtlch\af7\afs24\alang1081\ltrch\hich\af3\afs24\alang1033\dbch\af10\langfe2052\loch\f3\fs24\lang1033 Normal;}+{\*\cs15\snext15\rtlch\af4\ltrch\hich\af4\dbch\af4\loch\f4 Bullets;}+{\s16\sbasedon0\snext17\sb240\sa120\keepn\rtlch\af7\afs28\ltrch\hich\af5\afs28\dbch\af6\loch\f5\fs28 Heading;}+{\s17\sbasedon0\snext17\sl276\slmult1\sb0\sa140 Body Text;}+{\s18\sbasedon17\snext18\rtlch\af8\ltrch List;}+{\s19\sbasedon0\snext19\sb120\sa120\noline\rtlch\af8\afs24\ai\ltrch\fs24\i caption;}+{\s20\sbasedon0\snext20\noline\rtlch\af8\ltrch Index;}+{\s21\sbasedon0\snext21\nowidctlpar\noline Table Contents;}+}{\*\listtable{\list\listtemplateid1+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li720}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9702 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li1080}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9642 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li1440}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li1800}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9702 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li2160}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9642 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li2520}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li2880}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9702 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li3240}+{\listlevel\levelnfc23\leveljc0\levelstartat1\levelfollow0{\leveltext \'01\u9642 ?;}{\levelnumbers;}\f9\rtlch\af4\ltrch\fi-360\li3600}\listid1}+{\list\listtemplateid2+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}+{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}\listid2}+}{\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}}{\*\generator LibreOffice/25.8.4.2$Linux_X86_64 LibreOffice_project/580$Build-2}{\info{\creatim\yr2025\mo12\dy28\hr10\min51}{\revtim\yr2025\mo12\dy28\hr10\min53}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab709+\hyphauto1\viewscale140\formshade\nobrkwrptbl\paperh15840\paperw12240\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\sftnnar\saftnnrlc\sectunlocked1\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\fet\aftnrstcont\aftnstart1\aftnnrlc+{\*\ftnsep\chftnsep}\pgndec\pard\plain \s0\widctlpar\hyphpar0\ltrpar\kerning1\cf0\rtlch\af7\afs24\alang1081\ltrch\hich\af3\afs24\alang1033\dbch\af10\langfe2052\loch\f3\fs24\lang1033{\listtext\pard\plain \rtlch\af4\ltrch\hich\af4\dbch\af4\loch\f4 \u8226\'95\tab}\ilvl0\ls1 \fi-360\li720\lin720\ql\ltrpar{+List item}+\par \trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf1\clpadfl3\clpadl55\clbrdrl\brdrs\brdrw10\brdrcf1\clpadft3\clpadt55\clbrdrb\brdrs\brdrw10\brdrcf1\clpadfb3\clpadb55\clpadfr3\clpadr55\cellx4986\clbrdrt\brdrs\brdrw10\brdrcf1\clpadfl3\clpadl55\clbrdrl\brdrs\brdrw10\brdrcf1\clpadft3\clpadt55\clbrdrb\brdrs\brdrw10\brdrcf1\clpadfb3\clpadb55\clbrdrr\brdrs\brdrw10\brdrcf1\clpadfr3\clpadr55\cellx9972\pard\plain \s21\nowidctlpar\noline\intbl\ql\ltrpar{+A}\cell\pard\plain \s21\nowidctlpar\noline\intbl\ql\ltrpar{+B}\cell\row\pard \pard\plain \s0\widctlpar\hyphpar0\ltrpar\kerning1\cf0\rtlch\af7\afs24\alang1081\ltrch\hich\af3\afs24\alang1033\dbch\af10\langfe2052\loch\f3\fs24\lang1033\ql\ltrpar+\par }+^D+[ BulletList+ [ [ Para [ Str "List" , Space , Str "item" ] ] ]+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "A" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "B" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+```
@@ -0,0 +1,6 @@+```+% pandoc -f native -t asciidoc+[ Para [ SmallCaps [ Str "foo" ] ] ]+^D+[smallcaps]#foo#+```
@@ -0,0 +1,17 @@+```+% pandoc -t markdown -f native+[ Para [ Math DisplayMath "\ne = mc^2\n" ] ]+^D+$$+e = mc^2+$$+```++But we need to collapse spaces around inline math:++```+% pandoc -t markdown -f native+[ Para [ Math InlineMath "\ne=mc\n" ]]+^D+$e=mc$+```
@@ -0,0 +1,11 @@+```+% pandoc -t native+text^[sup]{.class}^+^D+[ Para+ [ Str "text"+ , Superscript+ [ Span ( "" , [ "class" ] , [] ) [ Str "sup" ] ]+ ]+]+```
@@ -0,0 +1,15 @@+````+% pandoc -t revealjs --syntax-highlighting=idiomatic+# Slide++```python+def hello():+ print("Hello")+```+^D+<section id="slide" class="slide level1">+<h1>Slide</h1>+<pre><code class="language-python">def hello():+ print("Hello")</code></pre>+</section>+````
@@ -0,0 +1,12 @@+```+% pandoc -f docbook -t markdown+<example>+ <para>+ Example without a title.+ </para>+</example>+^D+::: example+Example without a title.+:::+```
@@ -0,0 +1,62 @@+Test for \footnotemark and \footnotetext (issue #11450)++```+% pandoc -f latex -t native+Text\footnotemark{}.+\footnotetext{The footnote content.}+^D+[ Para+ [ Str "Text"+ , Note+ [ Para+ [ Str "The"+ , Space+ , Str "footnote"+ , Space+ , Str "content."+ ]+ ]+ , Str "."+ ]+]+```++With explicit footnote numbers:++```+% pandoc -f latex -t native+First\footnotemark[1] and second\footnotemark[2].+\footnotetext[1]{First note.}+\footnotetext[2]{Second note.}+^D+[ Para+ [ Str "First"+ , Note [ Para [ Str "First" , Space , Str "note." ] ]+ , Space+ , Str "and"+ , Space+ , Str "second"+ , Note [ Para [ Str "Second" , Space , Str "note." ] ]+ , Str "."+ ]+]+```++Mixed with regular footnotes:++```+% pandoc -f latex -t native+Text\footnotemark[1] and more\footnote{Regular footnote.}+\footnotetext[1]{Marked footnote.}+^D+[ Para+ [ Str "Text"+ , Note [ Para [ Str "Marked" , Space , Str "footnote." ] ]+ , Space+ , Str "and"+ , Space+ , Str "more"+ , Note [ Para [ Str "Regular" , Space , Str "footnote." ] ]+ ]+]+```
@@ -0,0 +1,26 @@+```+% pandoc -f textile -t html+| foo | bar |+| table+* item 1+* item 2+* item 3 | xxx |+^D+<table>+<tbody>+<tr>+<td>foo</td>+<td>bar</td>+</tr>+<tr>+<td><p>table</p>+<ul>+<li>item 1</li>+<li>item 2</li>+<li>item 3</li>+</ul></td>+<td>xxx</td>+</tr>+</tbody>+</table>+```
@@ -0,0 +1,13 @@+```+% pandoc -t typst+'hi' and \'+^D+'hi' and \'+```++```+% pandoc -f markdown -t typst | pandoc -f typst -t markdown+"hi" \" 'hi' and \'+^D+"hi" \" 'hi' and \'+```
@@ -0,0 +1,31 @@+```+% pandoc -f docbook -t gfm+<important>+<itemizedlist>+<listitem>+<simpara>Test.</simpara>+</listitem>+<listitem>+<simpara>Test 2.</simpara>+</listitem>+</itemizedlist>+</important>+^D+> [!IMPORTANT]+> - Test.+>+> - Test 2.+```++```+% pandoc -f gfm -t gfm+> [!IMPORTANT]+> - Test.+>+> - Test 2.+^D+> [!IMPORTANT]+> - Test.+>+> - Test 2.+```
@@ -0,0 +1,82 @@+```+% pandoc -t revealjs --template=command/11486/scroll.revealjs+---+view: scroll+---+^D+ scrollActivationWidth: 0,+ scrollSnap: 'mandatory',+ scrollProgress: 'auto',+```++```+% pandoc -t revealjs --template=command/11486/scroll.revealjs+---+view: scroll+scrollSnap: false+---+^D+ scrollActivationWidth: 0,+ scrollSnap: false,+ scrollProgress: 'auto',+```++```+% pandoc -t revealjs --template=command/11486/scroll.revealjs+---+view: scroll+scrollSnap: proximity+---+^D+ scrollActivationWidth: 0,+ scrollSnap: 'proximity',+ scrollProgress: 'auto',+```++```+% pandoc -t revealjs --template=command/11486/scroll.revealjs+---+view: scroll+scrollActivationWidth: 500+---+^D+ scrollActivationWidth: 500,+ scrollSnap: 'mandatory',+ scrollProgress: 'auto',+```++```+% pandoc -t revealjs --template=command/11486/scroll.revealjs+---+view: scroll+scrollProgress: true+---+^D+ scrollActivationWidth: 0,+ scrollSnap: 'mandatory',+ scrollProgress: true,+```++```+% pandoc -t revealjs --template=command/11486/scroll.revealjs+---+view: scroll+scrollProgress: false+---+^D+ scrollActivationWidth: 0,+ scrollSnap: 'mandatory',+ scrollProgress: false,+```++```+% pandoc -t revealjs --template=command/11486/scroll.revealjs+---+view: scroll+scrollProgress: auto+---+^D+ scrollActivationWidth: 0,+ scrollSnap: 'mandatory',+ scrollProgress: 'auto',+```
@@ -0,0 +1,15 @@+$if(view)$+ scrollActivationWidth: $scrollActivationWidth$,+$if(scrollSnap)$+ scrollSnap: '$scrollSnap/nowrap$',+$else$+ scrollSnap: false,+$endif$+$if(scrollProgressAuto)$+ scrollProgress: 'auto',+$elseif(scrollProgress)$+ scrollProgress: $scrollProgress$,+$else$+ scrollProgress: false,+$endif$+$endif$
@@ -0,0 +1,13 @@+```+% pandoc -t markdown+<&lt;+^D+\<\<+```++```+% pandoc -t markdown+&#xa0;+^D+\ +```
@@ -0,0 +1,73 @@+External images should not use [[File:...]] syntax.++Inline external image:+```+% pandoc -f native -t mediawiki+[Para [Image ("",[],[]) [] ("https://example.org/image.png", "")]]+^D+<nowiki></nowiki>https://example.org/image.png<nowiki></nowiki>+```++Inline local image (should still use [[File:]]):+```+% pandoc -f native -t mediawiki+[Para [Image ("",[],[]) [] ("local.png", "")]]+^D+[[File:local.png]]+```++Figure with external image (from markdown):+```+% pandoc -f markdown -t mediawiki++^D+<nowiki></nowiki>https://example.org/figure.png<nowiki></nowiki>+```++Local image (from markdown, no caption):+```+% pandoc -f markdown -t mediawiki++^D+[[File:local.png]]+```++Figure with caption and external image:+```+% pandoc -f markdown -t mediawiki++^D+<div class="figure">+<nowiki></nowiki>https://example.org/figure.png<nowiki></nowiki>+</div>+```++Figure with caption and local image:+```+% pandoc -f markdown -t mediawiki++^D+<div class="figure">+[[File:local.png|Caption]]+</div>+```++SimpleFigure with external image (native format with fig: title):+```+% pandoc -f native -t mediawiki+[Figure ("",[],[]) (Caption Nothing []) [Para [Image ("",[],[]) [Str "caption"] ("https://example.org/figure.png", "fig:")]]]+^D+<div class="figure">+<nowiki></nowiki>https://example.org/figure.png<nowiki></nowiki>+</div>+```++SimpleFigure with local image (native format with fig: title):+```+% pandoc -f native -t mediawiki+[Figure ("",[],[]) (Caption Nothing []) [Para [Image ("",[],[]) [Str "caption"] ("local.png", "fig:")]]]+^D+<div class="figure">+[[File:local.png|thumb|none|alt=caption|caption]]+</div>+```
@@ -0,0 +1,121 @@+```+% pandoc -f markdown -t icml+{object-style="myStyle"}+^D+<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/Paragraph">+ <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle">+ <Rectangle Self="uec" StrokeWeight="0" ItemTransform="1 0 0 1 32 -32" AppliedObjectStyle="ObjectStyle/myStyle">+ <Properties>+ <PathGeometry>+ <GeometryPathType PathOpen="false">+ <PathPointArray>+ <PathPointType Anchor="-32 -32" LeftDirection="-32 -32" RightDirection="-32 -32" />+ <PathPointType Anchor="-32 32" LeftDirection="-32 32" RightDirection="-32 32" />+ <PathPointType Anchor="32 32" LeftDirection="32 32" RightDirection="32 32" />+ <PathPointType Anchor="32 -32" LeftDirection="32 -32" RightDirection="32 -32" />+ </PathPointArray>+ </GeometryPathType>+ </PathGeometry>+ </Properties>+ <Image Self="ue6" ItemTransform="1 0 0 1 -32 -32">+ <Properties>+ <Profile type="string">+ $ID/Embedded+ </Profile>+ <GraphicBounds Left="0" Top="0" Right="64" Bottom="64" />+ </Properties>+ <Link Self="ueb" LinkResourceURI="file:command/11498.png" />+ </Image>+ </Rectangle>+ </CharacterStyleRange>+</ParagraphStyleRange>+```+```+% pandoc -s -f markdown -t icml+{object-style="myStyle"}+^D+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>+<?aid style="50" type="snippet" readerVersion="6.0" featureSet="513" product="8.0(370)" ?>+<?aid SnippetType="InCopyInterchange"?>+<Document DOMVersion="8.0" Self="pandoc_doc">+ <RootCharacterStyleGroup Self="pandoc_character_styles">+ <CharacterStyle Self="$ID/NormalCharacterStyle" Name="Default" />+ <CharacterStyle Self="CharacterStyle/" Name="">+ <Properties>+ <BasedOn type="object">$ID/NormalCharacterStyle</BasedOn>+ </Properties>+ </CharacterStyle>+ </RootCharacterStyleGroup>+ <RootParagraphStyleGroup Self="pandoc_paragraph_styles">+ <ParagraphStyle Self="$ID/NormalParagraphStyle" Name="$ID/NormalParagraphStyle"+ SpaceBefore="6" SpaceAfter="6"> <!-- paragraph spacing -->+ <Properties>+ <TabList type="list">+ <ListItem type="record">+ <Alignment type="enumeration">LeftAlign</Alignment>+ <AlignmentCharacter type="string">.</AlignmentCharacter>+ <Leader type="string"></Leader>+ <Position type="unit">10</Position> <!-- first tab stop -->+ </ListItem>+ </TabList>+ </Properties>+ </ParagraphStyle>+ <ParagraphStyle Self="ParagraphStyle/Paragraph" Name="Paragraph" LeftIndent="0">+ <Properties>+ <BasedOn type="object">$ID/NormalParagraphStyle</BasedOn>+ </Properties>+ </ParagraphStyle>+ </RootParagraphStyleGroup>+ <RootTableStyleGroup Self="pandoc_table_styles">+ <TableStyle Self="TableStyle/Table" Name="Table" />+ </RootTableStyleGroup>+ <RootCellStyleGroup Self="pandoc_cell_styles">+ <CellStyle Self="CellStyle/Cell" AppliedParagraphStyle="ParagraphStyle/$ID/[No paragraph style]" Name="Cell" />+ </RootCellStyleGroup>+ <RootObjectStyleGroup Self="pandoc_object_styles">+ <ObjectStyle Self="ObjectStyle/myStyle" Name="myStyle">+ <Properties>+ <BasedOn type="string">$ID/None</BasedOn>+ </Properties>+ </ObjectStyle>+ </RootObjectStyleGroup>+ <Story Self="pandoc_story"+ TrackChanges="false"+ StoryTitle=""+ AppliedTOCStyle="n"+ AppliedNamedGrid="n" >+ <StoryPreference OpticalMarginAlignment="true" OpticalMarginSize="12" />++<!-- body needs to be non-indented, otherwise code blocks are indented too far -->+<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/Paragraph">+ <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle">+ <Rectangle Self="uec" StrokeWeight="0" ItemTransform="1 0 0 1 32 -32" AppliedObjectStyle="ObjectStyle/myStyle">+ <Properties>+ <PathGeometry>+ <GeometryPathType PathOpen="false">+ <PathPointArray>+ <PathPointType Anchor="-32 -32" LeftDirection="-32 -32" RightDirection="-32 -32" />+ <PathPointType Anchor="-32 32" LeftDirection="-32 32" RightDirection="-32 32" />+ <PathPointType Anchor="32 32" LeftDirection="32 32" RightDirection="32 32" />+ <PathPointType Anchor="32 -32" LeftDirection="32 -32" RightDirection="32 -32" />+ </PathPointArray>+ </GeometryPathType>+ </PathGeometry>+ </Properties>+ <Image Self="ue6" ItemTransform="1 0 0 1 -32 -32">+ <Properties>+ <Profile type="string">+ $ID/Embedded+ </Profile>+ <GraphicBounds Left="0" Top="0" Right="64" Bottom="64" />+ </Properties>+ <Link Self="ueb" LinkResourceURI="file:command/11498.png" />+ </Image>+ </Rectangle>+ </CharacterStyleRange>+</ParagraphStyleRange>++ </Story>+ +</Document>+```
binary file changed (absent → 1306 bytes)
@@ -0,0 +1,6 @@+```+% pandoc -f html -t typst+<p><a href="http://torch.utils.data" rel="noopener noreferrer nofollow" target="_blank">torch.utils.data</a>.Dataset</p>+^D+#link("http://torch.utils.data")[torch.utils.data]\.Dataset+```
@@ -0,0 +1,42 @@+```+% pandoc -f markdown+lists_without_preceding_blankline+alerts -t native+:::: caution+::: title+Caution+:::++Foo bar, wuppie fluppie!+::::+^D+[ Div+ ( "" , [ "caution" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Caution" ] ]+ , Para+ [ Str "Foo"+ , Space+ , Str "bar,"+ , Space+ , Str "wuppie"+ , Space+ , Str "fluppie!"+ ]+ ]+]+```++```+% pandoc -f markdown+lists_without_preceding_blankline -t native+hello+- a+- b+c+^D+[ Para [ Str "hello" ]+, BulletList+ [ [ Plain [ Str "a" ] ]+ , [ Plain [ Str "b" , SoftBreak , Str "c" ] ]+ ]+]++```+
@@ -0,0 +1,47 @@+```+% pandoc -f native -t markdown+[ DefinitionList+ [ ( [ Str "Input" ]+ , [ [ CodeBlock ( "" , [] , [] ) "Term\n\n : Def" ] ]+ )+ ]+]+^D+Input++: Term++ : Def+```++```+% pandoc -f markdown -t native+Input++: Term++ : Def+^D+[ DefinitionList+ [ ( [ Str "Input" ]+ , [ [ CodeBlock ( "" , [] , [] ) "Term\n\n : Def" ] ]+ )+ ]+]+```++```+% pandoc -f native -t markdown+four_space_rule+[ DefinitionList+ [ ( [ Str "Input" ]+ , [ [ CodeBlock ( "" , [] , [] ) "Term\n\n : Def" ] ]+ )+ ]+]+^D+Input++: Term++ : Def+```
@@ -0,0 +1,10 @@+```+% pandoc -t mediawiki+[example](https://example.com/#/#room)++[example](https://example.com/##)+^D+[https://example.com/#/#room example]++[https://example.com/## example]+```
@@ -0,0 +1,18 @@+```+% pandoc -t markdown+:::+A+:::+^D+\::: A \:::+```++```+% pandoc -t commonmark+fenced_divs+:::+A+:::+^D+\::: A \:::+```+
@@ -0,0 +1,16 @@+```+% pandoc -t typst+::: {lang=en}+1. item+2. item+3. item+:::+^D+#block[+#set text(lang: "en");++ item++ item++ item++]+```
@@ -0,0 +1,10 @@+```+% pandoc --typst-input foo=FOO --typst-input bar="bar bim" -f typst -t plain+#sys.inputs.at("foo");++#sys.inputs.at("bar");+^D+FOO++bar bim+```
@@ -0,0 +1,20 @@+```+% pandoc -f markdown -t native+t^[a]{.cb}\ b^+t^[a]{fg=yellow bg=blue}\ b^+^D+[ Para+ [ Str "t"+ , Superscript+ [ Span ( "" , [ "cb" ] , [] ) [ Str "a" ] , Str "\160b" ]+ , SoftBreak+ , Str "t"+ , Superscript+ [ Span+ ( "" , [] , [ ( "fg" , "yellow" ) , ( "bg" , "blue" ) ] )+ [ Str "a" ]+ , Str "\160b"+ ]+ ]+]+```
@@ -0,0 +1,16 @@+```+% pandoc -f typst --wrap=none+#rotate(90deg, figure(+ [body text here inside rotate],+ caption: "Figure 1: How a caption gets lost when rotating",+ supplement: none,+))+^D+<div class="rotate" data-angle="90.0">+<figure>+<p>body text here inside rotate</p>+<figcaption><p>Figure 1: How a caption gets lost when rotating</p></figcaption>+</figure>+</div>++```
@@ -0,0 +1,22 @@+```+% pandoc -f latex -t typst+\begin{table}+ \caption{Caption}\label{tab}+ \begin{tabular}{cc}+ a & b \\ c & d+ \end{tabular}+\end{table}+^D+#figure(+ align(center)[#table(+ columns: 2,+ align: (center,center,),+ [a], [b],+ [c], [d],+ )]+ , caption: [Caption]+ , kind: table+ )+<tab>++```
@@ -0,0 +1,54 @@+```+% pandoc -f latex -t plain+\documentclass[english]{article}+\usepackage[T1]{fontenc}+\usepackage[utf8]{inputenc}+\usepackage{amsthm}+\theoremstyle{plain}+\newtheorem{thm}{\protect\theoremname}+\newtheorem{prop}[thm]{\protect\propositionname}+\usepackage{babel}+\providecommand{\propositionname}{Proposition}+\providecommand{\theoremname}{Theorem}++\begin{document}+\begin{thm}+first theorem+\end{thm}+\begin{prop}+first proposition+\end{prop}++\end{document}+<div class="thm">+<p><strong>Theorem 1</strong>. <em>first theorem</em></p>+</div>+<div class="prop">+<p><strong>Proposition 2</strong>. <em>first proposition</em></p>+</div>+jgm@Johns-MacBook-Air:~/src/pandoc % `make binpath` -f latex -t plain+\documentclass[english]{article}+\usepackage[T1]{fontenc}+\usepackage[utf8]{inputenc}+\usepackage{amsthm}+\theoremstyle{plain}+\newtheorem{thm}{\protect\theoremname}+\newtheorem{prop}[thm]{\protect\propositionname}+\usepackage{babel}+\providecommand{\propositionname}{Proposition}+\providecommand{\theoremname}{Theorem}++\begin{document}+\begin{thm}+first theorem+\end{thm}+\begin{prop}+first proposition+\end{prop}++\end{document}+^D+Theorem 1. first theorem++Proposition 2. first proposition+```
@@ -0,0 +1,28 @@+```+% pandoc -f man -t html+.TH "TEST" "1" "2026-05-08" "test v1.0.0" "test manual"+.SH HEADING+.TS+tab(;);+l l.+this is a table element \+written in two lines;abcdefg+another \+one;123456+.TE+^D+<h1 id="heading">HEADING</h1>+<table>+<tbody>+<tr>+<td style="text-align: left;">this is a table element written in two+lines</td>+<td style="text-align: left;">abcdefg</td>+</tr>+<tr>+<td style="text-align: left;">another one</td>+<td style="text-align: left;">123456</td>+</tr>+</tbody>+</table>+```
@@ -17,28 +17,28 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>col 1</th> <th>col 2</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>1</td> <td>Second column of row 1.</td> </tr>-<tr class="even">-<td><p>2</p></td>-<td><p>Second column of row 2. Second line of paragraph.</p></td>+<tr>+<td>2</td>+<td>Second column of row 2. Second line of paragraph.</td> </tr>-<tr class="odd">-<td><p>3</p></td>+<tr>+<td>3</td> <td><ul> <li>Second column of row 3.</li> <li>Second item in bullet list (row 3, column 2).</li> </ul></td> </tr>-<tr class="even">+<tr> <td></td> <td>Row 4; column 1 will be empty.</td> </tr>
@@ -0,0 +1,35 @@+```+% pandoc -t markdown -f html+<table>+ <colgroup>+ <col width="1%"/>+ <col />+ </colgroup>+ <tbody>+ <tr>+ <td>+ <p>A</p><p>B</p>+ </td>+ <td>+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do+ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut+ enim ad minim veniam, quis nostrud exercitation ullamco laboris+ nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor+ in reprehenderit in voluptate velit esse cillum dolore eu fugiat+ nulla pariatur. Excepteur sint occaecat cupidatat non proident,+ sunt in culpa qui officia deserunt mollit anim id est laborum.+ </td>+ </tr>+ </tbody>+</table>+^D++---+------------------------------------------------------------------++| A | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do |+| | eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut |+| B | enim ad minim veniam, quis nostrud exercitation ullamco laboris |+| | nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor |+| | in reprehenderit in voluptate velit esse cillum dolore eu fugiat |+| | nulla pariatur. Excepteur sint occaecat cupidatat non proident, |+| | sunt in culpa qui officia deserunt mollit anim id est laborum. |++---+------------------------------------------------------------------++```
@@ -0,0 +1,42 @@+```+% pandoc -f man -t html+TH "TEST" "1" "2026-05-25" "test v1.0.0" "test manual"+.SH HEADING+.TP 4+This is the unindented tag.+This text, along with the table, should be indented.+.TS+tab(;);+l l.+aaa;bbb+ccc;ddd+.TE+This should still be indented, until some other macro is called to change it.+.PP+Like this.+^D+<p>TH "TEST" "1" "2026-05-25" "test v1.0.0" "test manual"</p>+<h1 id="heading">HEADING</h1>+<dl>+<dt>This is the unindented tag.</dt>+<dd>+<p>This text, along with the table, should be indented.</p>+<table>+<tbody>+<tr>+<td style="text-align: left;">aaa</td>+<td style="text-align: left;">bbb</td>+</tr>+<tr>+<td style="text-align: left;">ccc</td>+<td style="text-align: left;">ddd</td>+</tr>+</tbody>+</table>+<p>This should still be indented, until some other macro is called to+change it.</p>+</dd>+</dl>+<p>Like this.</p>++```
@@ -0,0 +1,81 @@+Cell paragraphs that use `\plain` after `\intbl`, together with a single+`\trowd` and `\row` row terminators, should produce a flat table rather+than deeply nested tables.++```+% pandoc -f rtf -t native+{\rtf1\ansi\deff0+{\fonttbl{\f0 Times;}{\f1 Times;}{\f2 Times;}}+\trowd\trgaph60\trleft0+\clvertalt\cellx3245+\clvertalt\cellx6490+\clvertalt\cellx9735+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 A\plain\f1\fs22\cell+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 B\plain\f1\fs22\cell+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 C\plain\f1\fs22\cell+\intbl\row+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 1\plain\f1\fs22\cell+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 2\plain\f1\fs22\cell+\pard\intbl\s0\ql\plain\f0\fs20\plain\f2\fs22 3\plain\f1\fs22\cell+\intbl\row+}+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "A" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "B" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "C" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+```
@@ -129,7 +129,7 @@ , Link ( "" , []- , [ ( "reference-type" , "ref" )+ , [ ( "reference-type" , "ref+label" ) , ( "reference" , "def:tri" ) ] )
@@ -1,5 +1,5 @@ ```-% pandoc -t latex --listings+% pandoc -t latex --syntax-highlighting=idiomatic bla bla `a % b` *bla bla `a % b`*
@@ -55,9 +55,9 @@ </div> ^D \begin{frame}{Slide one}-\protect\hypertarget{slide-one}{}+\protect\phantomsection\label{slide-one} \begin{columns}[T]-\begin{column}{0.4\textwidth}+\begin{column}{0.4\linewidth} \begin{itemize} \tightlist \item@@ -67,7 +67,7 @@ \end{itemize} \end{column} -\begin{column}{0.4\textwidth}+\begin{column}{0.4\linewidth} \begin{itemize} \tightlist \item@@ -77,7 +77,7 @@ \end{itemize} \end{column} -\begin{column}{0.1\textwidth}+\begin{column}{0.1\linewidth} ok \end{column} \end{columns}
@@ -6,13 +6,10 @@ # Three {.unlisted .unnumbered} ^D-\hypertarget{one}{%-\section{One}\label{one}}+\section{One}\label{one} -\hypertarget{two}{%-\section*{Two}\label{two}}+\section*{Two}\label{two} \addcontentsline{toc}{section}{Two} -\hypertarget{three}{%-\section*{Three}\label{three}}+\section*{Three}\label{three} ```
@@ -3,7 +3,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -11,7 +11,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td>@@ -44,7 +44,7 @@ (TableHead ( "" , [] , [] ) [ Row- ( "" , [ "header" ] , [] )+ ( "" , [] , [] ) [ Cell ( "" , [] , [] ) AlignRight@@ -76,7 +76,7 @@ (RowHeadColumns 0) [] [ Row- ( "" , [ "odd" ] , [] )+ ( "" , [] , [] ) [ Cell ( "" , [] , [] ) AlignRight@@ -111,7 +111,7 @@ ``` % pandoc -f html -t native <table>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align:left;">12</td> <td style="text-align: center">12</td>@@ -133,7 +133,7 @@ (RowHeadColumns 0) [] [ Row- ( "" , [ "odd" ] , [] )+ ( "" , [] , [] ) [ Cell ( "" , [] , [] ) AlignRight
@@ -7,11 +7,16 @@ \label{fig:setminus} \end{figure} ^D-[ Para- [ Image- ( "fig:setminus" , [] , [ ( "width" , "80%" ) ] )- [ Str "Set" , Space , Str "subtraction" ]- ( "setminus.png" , "fig:" )+[ Figure+ ( "fig:setminus" , [] , [ ( "latex-placement" , "ht" ) ] )+ (Caption+ Nothing [ Plain [ Str "Set" , Space , Str "subtraction" ] ])+ [ Plain+ [ Image+ ( "" , [] , [ ( "width" , "80%" ) ] )+ []+ ( "setminus.png" , "" )+ ] ] ] ```
@@ -0,0 +1,6 @@+```+% pandoc -t asciidoc -f html+<a href="http://example.com">][</a>+^D+http://example.com[++][++]+```
@@ -13,15 +13,16 @@ ^D \begin{longtable}[]{@{}ll@{}} \caption{a table}\tabularnewline-\toprule()+\toprule\noalign{} x & y\footnote{a footnote} \\-\midrule()+\midrule\noalign{} \endfirsthead-\toprule()+\toprule\noalign{} x & y{} \\-\midrule()+\midrule\noalign{} \endhead+\bottomrule\noalign{}+\endlastfoot 1 & 2 \\-\bottomrule() \end{longtable} ```
@@ -6,23 +6,23 @@ 2. beta * gamma ^D-<text:list text:style-name="L1">+<text:list text:style-name="Numbering_20_1"> <text:list-item>- <text:p text:style-name="P1">a</text:p>+ <text:p text:style-name="List_20_Number_20_Tight">a</text:p> </text:list-item> <text:list-item>- <text:p text:style-name="P1">b</text:p>- <text:list>+ <text:p text:style-name="List_20_Number_20_Tight">b</text:p>+ <text:list text:style-name="Numbering_20_1"> <text:list-item>- <text:p text:style-name="P1">alpha</text:p>+ <text:p text:style-name="List_20_Number_20_Tight">alpha</text:p> </text:list-item> <text:list-item>- <text:p text:style-name="P1">beta</text:p>+ <text:p text:style-name="List_20_Number_20_Tight">beta</text:p> </text:list-item> </text:list>- <text:list text:style-name="L2">+ <text:list text:style-name="List_20_1"> <text:list-item>- <text:p text:style-name="P2">gamma</text:p>+ <text:p text:style-name="List_20_Bullet_20_Tight">gamma</text:p> </text:list-item> </text:list> </text:list-item>@@ -40,20 +40,23 @@ more text -- this line is missing in the odt output ^D-<text:list text:style-name="L1">+<text:list text:style-name="Pandoc_5f_Numbering_5f_1"> <text:list-item>- <text:p text:style-name="P1">text</text:p>- <text:p text:style-name="P1">some text</text:p>- <text:list>+ <text:p text:style-name="List_20_Number">text</text:p>+ <text:p text:style-name="List_20_Number">some text</text:p>+ <text:list text:style-name="Pandoc_5f_Numbering_5f_2"> <text:list-item>- <text:p text:style-name="P1">sub item 1</text:p>+ <text:p text:style-name="List_20_Number_20_Tight">sub item+ 1</text:p> </text:list-item> <text:list-item>- <text:p text:style-name="P1">sub item 2</text:p>+ <text:p text:style-name="List_20_Number_20_Tight">sub item+ 2</text:p> </text:list-item> </text:list>- <text:p text:style-name="P1">more text – this line is missing in the- odt output</text:p>+ <text:p text:style-name="List_20_Number">more text – this line is+ missing in the odt output</text:p> </text:list-item> </text:list> ```+
@@ -0,0 +1,59 @@+```+% pandoc -f textile -t native+This list starts:++# one+# two++This list should continue at 3:++#3 three+# four++This list should restart at 1:++# one again+# two again+^D+[ Para+ [ Str "This" , Space , Str "list" , Space , Str "starts:" ]+, OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "one" ] ] , [ Plain [ Str "two" ] ] ]+, Para+ [ Str "This"+ , Space+ , Str "list"+ , Space+ , Str "should"+ , Space+ , Str "continue"+ , Space+ , Str "at"+ , Space+ , Str "3:"+ ]+, OrderedList+ ( 3 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "three" ] ] , [ Plain [ Str "four" ] ] ]+, Para+ [ Str "This"+ , Space+ , Str "list"+ , Space+ , Str "should"+ , Space+ , Str "restart"+ , Space+ , Str "at"+ , Space+ , Str "1:"+ ]+, OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "one" , Space , Str "again" ] ]+ , [ Plain [ Str "two" , Space , Str "again" ] ]+ ]+]+```+
@@ -6,7 +6,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><p>* hello</p></td> </tr> </tbody>@@ -22,7 +22,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><ul> <li>hello</li> </ul></td>@@ -40,7 +40,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><p><code>* hello</code></p></td> </tr> </tbody>
@@ -7,7 +7,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> </tr> </tbody> </table>@@ -17,7 +17,7 @@ % pandoc -f mediawiki -t html5 {| border="4" cellspacing="2" cellpadding="0" WIDTH="100%" |------| peildatum Simbase || november 2005 || '''uitslagen Flohrgambiet''' ||+| peildatum Simbase || november 2005 || colspan=2 | '''uitslagen Flohrgambiet''' |----- | totaal aantal partijen Simbase || 7.316.773 | wit wint || 53%@@ -31,25 +31,24 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><p>peildatum Simbase</p></td> <td><p>november 2005</p></td>-<td><p><strong>uitslagen Flohrgambiet</strong></p></td>-<td></td>+<td colspan="2"><p><strong>uitslagen Flohrgambiet</strong></p></td> </tr>-<tr class="even">+<tr> <td><p>totaal aantal partijen Simbase</p></td> <td><p>7.316.773</p></td> <td><p>wit wint</p></td> <td><p>53%</p></td> </tr>-<tr class="odd">+<tr> <td><p>percentage (en partijen) Flohrgambiet</p></td> <td><p>0.023 % (1.699)</p></td> <td><p>zwart wint</p></td> <td><p>27%</p></td> </tr>-<tr class="even">+<tr> <td><p>percentage Flohrgambiet in aug 2003</p></td> <td><p>0.035 %</p></td> <td><p>remise</p></td>@@ -81,29 +80,30 @@ ^D <table> <thead>-<tr class="header">+<tr> <th><p>Plaats</p></th> <th><p>Rijder</p></th> <th><p>Aantal</p></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td><p>1</p></td>-<td><p><a href="Sébastien_Loeb" title="wikilink">Sébastien-Loeb</a></p></td>+<td style="text-align: left;"><p><a href="Sébastien_Loeb"+class="wikilink" title="Sébastien Loeb">Sébastien Loeb</a></p></td> <td><p>78</p></td> </tr>-<tr class="even">+<tr> <td><p>2</p></td>-<td><p><strong><a href="Sébastien_Ogier" title="wikilink">Sébastien+<td style="text-align: left;"><p><strong><a href="Sébastien_Ogier"+class="wikilink" title="Sébastien Ogier">Sébastien Ogier</a></strong></p></td> <td><p>38</p></td> </tr>-<tr class="odd">+<tr> <td><p>10</p></td>-<td><p><a href="Hannu_Mikkola" title="wikilink">Hannu-Mikkola</a></p></td>+<td style="text-align: left;"><p><a href="Hannu_Mikkola"+class="wikilink" title="Hannu Mikkola">Hannu Mikkola</a></p></td> <td><p>18</p></td> </tr> </tbody>
@@ -19,11 +19,11 @@ </tr> </table> ^D-+-----------------------------------------------------------------------+-| +------------------------------------------------------------------+ |-| | ----------- | |-| | some text | |-| | ----------- | |-| +------------------------------------------------------------------+ |-+-----------------------------------------------------------------------+++---------------------------------------------------------------------------++| +-----------------------------------------------------------------------+ |+| | ----------- | |+| | some text | |+| | ----------- | |+| +-----------------------------------------------------------------------+ |++---------------------------------------------------------------------------+ ```
@@ -10,5 +10,5 @@ % pandoc -f html -t latex <a name="foo"></a><br/> ^D-\protect\hypertarget{foo}{}{}\strut \\+\protect\phantomsection\label{foo}{}\strut \\ ```
@@ -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}" ] ] ```
@@ -18,12 +18,12 @@ <col style="width: 15%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td>First</td> <td>12.0</td> <td>Example row spanning lines</td> </tr>-<tr class="even">+<tr> <td>Second</td> <td>5.0</td> <td>Another</td>
@@ -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[]);!}
@@ -28,24 +28,24 @@ <col style="width: 54%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -79,24 +79,24 @@ <table> <caption>Frozen Delights!</caption> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -130,24 +130,24 @@ <table> <caption>Frozen Delights!</caption> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -176,17 +176,17 @@ <table> <caption>Frozen Delights!</caption> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td>On a stick!</td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -219,24 +219,24 @@ <table> <caption>Frozen Delights!</caption> <thead>-<tr class="header">+<tr> <th>Treat</th> <th>Quantity</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td></td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td></td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>@@ -266,7 +266,7 @@ <table> <caption>Frozen Delights!</caption> <tbody>-<tr class="odd">+<tr> <td>Albatross</td> <td>2.99</td> <td><ul>@@ -274,12 +274,12 @@ <li>In a cup!</li> </ul></td> </tr>-<tr class="even">+<tr> <td>Crunchy Frog</td> <td>1.49</td> <td>If we took the bones out, it wouldn't be crunchy, now would it?</td> </tr>-<tr class="odd">+<tr> <td>Gannet Ripple</td> <td>1.99</td> <td>On a stick!</td>
@@ -8,5 +8,5 @@ % pandoc -fmarkdown-implicit_figures -t latex {height=2em} ^D-\includegraphics[width=\textwidth,height=2em]{lalune.jpg}+\includegraphics[width=\linewidth,height=2em,keepaspectratio,alt={image}]{lalune.jpg} ```
@@ -7,5 +7,5 @@ ^D Some text -- element+- element ```
@@ -14,22 +14,22 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;"><span><strong>ﺍ</strong></span></td> <td style="text-align: left;"></td> <td style="text-align: left;"></td> </tr>-<tr class="even">+<tr> <td style="text-align: right;"><strong>ﺄﺤﺴﻨﺘـ(ﻭﺍ) IV</strong></td> <td style="text-align: left;"><em><span>ʾaḥsant(ū)</span></em></td> <td style="text-align: left;">thank you</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;"><em>blah</em></td> <td style="text-align: left;"><em>blah</em></td> <td style="text-align: left;"><em>blah</em></td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">blah</td> <td style="text-align: left;">blah</td> <td style="text-align: left;">blah</td>
@@ -9,7 +9,7 @@ <li>|something|</li> <li><table> <tbody>-<tr class="odd">+<tr> <td>else</td> </tr> </tbody>
@@ -91,6 +91,8 @@ [])] ^D +---+---++| | |++===+===+ | 1 | 2 | +---+---+ | | |
@@ -10,7 +10,7 @@ normal \f[I]italic \f[BI]bold in the middle\f[I] only italic\f[R] normal. .PP-normal \f[B]bold \f[VB]code\f[B] more bold\f[R] normal.+normal \f[B]bold \f[CB]code\f[B] more bold\f[R] normal. .PP-normal \f[V]code\f[R] normal.+normal \f[CR]code\f[R] normal. ```
@@ -15,14 +15,17 @@ \caption{Subfigure with Subfloat} \end{figure} ^D+<figure data-latex-placement="ht"> <figure>-<img src="img1.jpg" alt="Caption 1" />-<figcaption aria-hidden="true">Caption 1</figcaption>+<img src="img1.jpg" />+<figcaption>Caption 1</figcaption> </figure> <figure>-<img src="img2.jpg" alt="Caption 2" />-<figcaption aria-hidden="true">Caption 2</figcaption>+<img src="img2.jpg" />+<figcaption>Caption 2</figcaption> </figure>+<figcaption>Subfigure with Subfloat</figcaption>+</figure> ``` ``` % pandoc -f latex -t html5@@ -31,8 +34,8 @@ \caption{Caption 3} \end{figure} ^D-<figure>-<img src="img1.jpg" alt="Caption 3" />-<figcaption aria-hidden="true">Caption 3</figcaption>+<figure data-latex-placement="ht">+<img src="img1.jpg" />+<figcaption>Caption 3</figcaption> </figure> ```
@@ -6,9 +6,9 @@ <li>baz</li> </ul> ^D-- foo-- bar-- baz+- foo+- bar+- baz ``` ```@@ -19,10 +19,10 @@ <li>baz</li> </ul> ^D-- foo-- bar- - subbar-- baz+- foo+- bar+ - subbar+- baz ``` @@ -34,9 +34,9 @@ <li>baz</li> </ul> ^D-- foo-- [bar]{#id}-- baz+- foo+- [bar]{#id}+- baz ``` @@ -48,12 +48,12 @@ <li><p>baz</p></li> </ul> ^D-- foo+- foo -- ::: {#id}- bar- :::+- ::: {#id}+ bar+ ::: -- baz+- baz ```
@@ -4,7 +4,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td><a href="http://example.com/">link text</a></td> </tr> </tbody>
@@ -4,9 +4,9 @@ |--------------|-------|--------------------------------------------------------------------------| | aaaaaaaaaaaa | | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ^D-| aaaaaaaaaaaa | bbbbb | ccccccccccc |+| aaaaaaaaaaaa | bbbbb | ccccccccccc | |------------|-------|------------------------------------------------------|-| aaaaaaaaaaaa | | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |+| aaaaaaaaaaaa | | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ``` ```@@ -15,9 +15,9 @@ |--------------|-------|--------------------------------------------------------------------------| | aaaaaaaaaaaa | | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ^D-| aaaaaaaaaaaa | bbbbb | ccccccccccc |+| aaaaaaaaaaaa | bbbbb | ccccccccccc | |------------|-------|------------------------------------------------------|-| aaaaaaaaaaaa | | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |+| aaaaaaaaaaaa | | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ``` ```@@ -26,7 +26,7 @@ |--------------|-------|--------------------------------------------------------------------------| | aaaaaaaaaaaa | | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ^D-| aaaaaaaaaaaa | bbbbb | ccccccccccc |-|--------------|-------|--------------------------------------------------------------------------|-| aaaaaaaaaaaa | | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |+| aaaaaaaaaaaa | bbbbb | ccccccccccc |+|----|----|----|+| aaaaaaaaaaaa | | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc | ```
@@ -9,7 +9,7 @@ % pandoc -f latex -t native \texttt{``hi''} ^D-[ Para [ Code ( "" , [] , [] ) "\8220hi\8221" ] ]+[ Para [ Code ( "" , [] , [] ) "\8216\8216hi\8217\8217" ] ] ``` ```
@@ -14,11 +14,11 @@ </div> ^D \begin{frame}{Level 2 blocks}-\protect\hypertarget{level-2-blocks}{}+\protect\phantomsection\label{level-2-blocks} \begin{columns}[T]-\begin{column}{0.4\textwidth}+\begin{column}{0.4\linewidth} \begin{block}{Block one}-\protect\hypertarget{block-one}{}+\protect\phantomsection\label{block-one} \begin{itemize} \tightlist \item@@ -27,9 +27,9 @@ \end{block} \end{column} -\begin{column}{0.6\textwidth}+\begin{column}{0.6\linewidth} \begin{block}{Block two}-\protect\hypertarget{block-two}{}+\protect\phantomsection\label{block-two} \begin{itemize} \tightlist \item
@@ -8,11 +8,9 @@ Here is inline html: -<div>-+::: {} `<balise>`{=html} bla bla--</div>+::: ```
@@ -4,7 +4,13 @@ <img src="foo" alt="bar"> </figure> ^D-[ Para [ Image ( "" , [] , [] ) [] ( "foo" , "fig:" ) ] ]+[ Figure+ ( "" , [] , [] )+ (Caption Nothing [])+ [ Plain+ [ Image ( "" , [] , [] ) [ Str "bar" ] ( "foo" , "" ) ]+ ]+] ``` ```@@ -18,8 +24,13 @@ </figcaption> </figure> ^D-[ Para- [ Image ( "" , [] , [] ) [ Str "baz" ] ( "foo" , "fig:" ) ]+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing [ Div ( "" , [] , [] ) [ Plain [ Str "baz" ] ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [ Str "bar" ] ( "foo" , "" ) ]+ ] ] ``` @@ -30,9 +41,9 @@ <figcaption><p><em>baz</em></p></figcaption> </figure> ^D-[ Para- [ Image- ( "" , [] , [] ) [ Emph [ Str "baz" ] ] ( "foo" , "fig:" )- ]+[ Figure+ ( "" , [] , [] )+ (Caption Nothing [ Para [ Emph [ Str "baz" ] ] ])+ [ Plain [ Image ( "" , [] , [] ) [] ( "foo" , "" ) ] ] ] ```
@@ -5,7 +5,7 @@ #+end_example ^D [ CodeBlock- ( "" , [ "example" ] , [] )+ ( "" , [] , [] ) " This should retain the four leading spaces\n" ] ```@@ -40,13 +40,13 @@ ^D <ul> <li><p>depth 1</p>-<pre id="bob" class="example"><code> Vertical alignment is four spaces beyond the appearance of the word "depth".+<pre id="bob"><code> Vertical alignment is four spaces beyond the appearance of the word "depth". </code></pre> <ul> <li><p>depth 2</p>-<pre class="example"><code>Vertically aligned with the second appearance of the word "depth".+<pre><code>Vertically aligned with the second appearance of the word "depth". </code></pre>-<pre class="example"><code> Vertical alignment is four spaces beyond the second+<pre><code> Vertical alignment is four spaces beyond the second appearance of the word "depth". The "begin" portion is a component of this deeper list element, so that guarantees@@ -55,7 +55,7 @@ </code></pre> <p>Still inside the inner list element</p></li> </ul>-<pre id="carrie" class="example"><code>This belongs to the outer list element, and is aligned accordingly, since the NAME attribute is not indented deeply enough. It is not enough for the BEGIN alone to be aligned deeply if the block is meant to have a NAME.+<pre id="carrie"><code>This belongs to the outer list element, and is aligned accordingly, since the NAME attribute is not indented deeply enough. It is not enough for the BEGIN alone to be aligned deeply if the block is meant to have a NAME. </code></pre> <p>Still in the shallower list element since the preceding example block forced the deeper list element to terminate.</p></li>
@@ -4,7 +4,7 @@ ^D <p>This.<a href="#foofn1" class="footnote-ref" id="foofnref1" role="doc-noteref"><sup>1</sup></a></p>-<section id="footnotes" class="footnotes footnotes-end-of-document"+<section id="foofootnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes"> <hr /> <ol>
@@ -2,10 +2,8 @@ % pandoc -f native -t rst [Para [Image ("",["align-right"],[("width","100px")]) [Str "image"] ("foo.png","fig:test")]] ^D-.. figure:: foo.png- :alt: test- :align: right- :width: 100px+|image| - image+.. |image| image:: foo.png+ :width: 100px ```
@@ -0,0 +1,27 @@+```+% pandoc -r latex -w plain+\newcommand{\foo}{123}\renewcommand\foo{456}\foo+^D+456+```++```+% pandoc -r latex -w plain+\newcommand\foo{123}\renewcommand\foo{456}\foo+^D+456+```++```+% pandoc -r latex -w plain+\newcommand{\foo}{123}\renewcommand{\foo}{456}\foo+^D+456+```++```+% pandoc -r latex -w plain+\newcommand\foo{123}\renewcommand{\foo}{456}\foo+^D+456+```
@@ -8,7 +8,7 @@ ^D Test 1 -{empty}[my text]+++[++my text++]++ Test 2 ```
@@ -3,5 +3,5 @@ A ‘simple’ example ^D .LP-A \[oq]simple\[cq] example+A \(oqsimple\(cq example ```
@@ -0,0 +1,58 @@+```+% pandoc -f native -t rst --list-tables+[Table ("",[],[]) (Caption Nothing+ [Plain [Str "Here",Space,Str "is",Space,Str "a",Space,Str "caption."]])+ [(AlignDefault,ColWidth 0.1527777777777778)+ ,(AlignDefault,ColWidth 0.1388888888888889)+ ,(AlignDefault,ColWidth 0.16666666666666666)+ ,(AlignDefault,ColWidth 0.375)]+ (TableHead ("",[],[])+ [Row ("",[],[])+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "Centered",SoftBreak,Str "Header"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "Left",SoftBreak,Str "Aligned"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "Right",SoftBreak,Str "Aligned"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "Default",Space,Str "aligned"]]]])+ [(TableBody ("",[],[]) (RowHeadColumns 0)+ []+ [Row ("",[],[])+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "First"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain []]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "12.0"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",SoftBreak,Str "spans",Space,Str "multiple",Space,Str "lines."]]]+ ,Row ("",[],[])+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "Second"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "row"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "5.0"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "Here\8217s",Space,Str "another",Space,Str "one.",Space,Str "Note",SoftBreak,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",SoftBreak,Str "rows."]]]])]+ (TableFoot ("",[],[])+ [])]+^D+.. list-table:: Here is a caption.+ :widths: 11 10 12 27+ :header-rows: 1++ * - Centered Header+ - Left Aligned+ - Right Aligned+ - Default aligned+ * - First+ - + - 12.0+ - Example of a row that spans multiple lines.+ * - Second+ - row+ - 5.0+ - Here’s another one. Note the blank line between rows.+```
@@ -2,8 +2,8 @@ % pandoc --to "markdown-bracketed_spans-fenced_divs-link_attributes-simple_tables-multiline_tables-grid_tables-pipe_tables-fenced_code_attributes-markdown_in_html_blocks-table_captions-smart" {#img:1} ^D-<figure>-<img src="img.png" id="img:1" alt="Caption" />+<figure id="img:1">+<img src="img.png" alt="Caption" /> <figcaption aria-hidden="true">Caption</figcaption> </figure> ```
@@ -12,13 +12,13 @@ :::: ^D \begin{frame}{title}-\protect\hypertarget{title}{}+\protect\phantomsection\label{title} \begin{columns}[T]-\begin{column}{0.08\textwidth}+\begin{column}{0.08\linewidth} content \end{column} -\begin{column}{0.84\textwidth}+\begin{column}{0.84\linewidth} content2 \end{column} \end{columns}
@@ -7,7 +7,7 @@ ^D [ Header 1- ( "non-ascii--raksmorgas" , [] , [] )+ ( "non-ascii-warning-raksmorgas" , [] , [] ) [ Str "non" , Space , Str "ascii"@@ -29,7 +29,7 @@ ^D [ Header 1- ( "non-ascii-\65039-r\228ksm\246rg\229s" , [] , [] )+ ( "non-ascii-warning-r\228ksm\246rg\229s" , [] , [] ) [ Str "non" , Space , Str "ascii"@@ -49,7 +49,7 @@ ^D [ Header 1- ( "non-ascii-\65039-r\228ksm\246rg\229s" , [] , [] )+ ( "non-ascii-warning-r\228ksm\246rg\229s" , [] , [] ) [ Str "non" , Space , Str "ascii"
@@ -0,0 +1,56 @@+```+% pandoc -f latex -t native+\begin{tabular}{c c}+ \begin{tabular}{c} a \\ \end{tabular}+ &+ \\+\end{tabular}+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignCenter , ColWidthDefault )+ , ( AlignCenter , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignCenter , ColWidthDefault ) ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "a" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+```
@@ -4,7 +4,8 @@ | ------- | ------- | ------- | | text | | text | ^D-{|+{| class="wikitable"+|- ! Column1 ! Column2 ! Column3
@@ -19,18 +19,18 @@ ^D \begin{frame} \begin{columns}[T]-\begin{column}[c]{0.48\textwidth}+\begin{column}[c]{0.48\linewidth} \end{column} -\begin{column}[b]{0.48\textwidth}+\begin{column}[b]{0.48\linewidth} \end{column} \end{columns} \begin{columns}[b,onlytextwidth]-\begin{column}[T]{0.48\textwidth}+\begin{column}[T]{0.48\linewidth} \end{column} -\begin{column}[t]{0.48\textwidth}+\begin{column}[t]{0.48\linewidth} \end{column} \end{columns}
@@ -0,0 +1,68 @@+```+% pandoc -f markdown -t html --number-sections+## First section++### Subhead++##### Subhead with gap++## Second section+^D+<h2 data-number="1" id="first-section"><span+class="header-section-number">1</span> First section</h2>+<h3 data-number="1.1" id="subhead"><span+class="header-section-number">1.1</span> Subhead</h3>+<h5 data-number="1.1.0.1" id="subhead-with-gap"><span+class="header-section-number">1.1.0.1</span> Subhead with gap</h5>+<h2 data-number="2" id="second-section"><span+class="header-section-number">2</span> Second section</h2>++```++```+% pandoc -f markdown -t html --number-sections+## First section++### Subhead++# Higher-level section++## Sub+^D+<h2 data-number="0.1" id="first-section"><span+class="header-section-number">0.1</span> First section</h2>+<h3 data-number="0.1.1" id="subhead"><span+class="header-section-number">0.1.1</span> Subhead</h3>+<h1 data-number="1" id="higher-level-section"><span+class="header-section-number">1</span> Higher-level section</h1>+<h2 data-number="1.1" id="sub"><span+class="header-section-number">1.1</span> Sub</h2>+```++For backwards compatibility, we want it to work the old way,+giving numbers like 0.1, when `--number-offset` is used:+```+% pandoc -f markdown -t html --number-sections --number-offset=2,2,2+## First section++### Subhead+^D+<h2 data-number="2.3" id="first-section"><span+class="header-section-number">2.3</span> First section</h2>+<h3 data-number="2.3.1" id="subhead"><span+class="header-section-number">2.3.1</span> Subhead</h3>++```++```+% pandoc -f markdown -t html --number-sections --number-offset=0,2,2+## First section++### Subhead+^D+<h2 data-number="0.3" id="first-section"><span+class="header-section-number">0.3</span> First section</h2>+<h3 data-number="0.3.1" id="subhead"><span+class="header-section-number">0.3.1</span> Subhead</h3>++```
@@ -0,0 +1,8 @@+```+% pandoc -f rst+Go to `g`_ `g <www.example.com>`_.+^D+<p>Go to <a href="www.example.com">g</a> <a+href="www.example.com">g</a>.</p>++```
@@ -0,0 +1,107 @@+```+% pandoc -t latex+++ Right Left Center Default+------- ------ ---------- -------+ 12 12 12 12+ 123 123 123 123+ 1 1 1 1++ : Demonstration of simple table syntax.+^D+\begin{figure}+\centering+\pandocbounded{\includegraphics[keepaspectratio,alt={This is a figure.}]{img.jpg}}+\caption{This is a figure.}+\end{figure}++\begin{longtable}[]{@{}rlcl@{}}+\caption{Demonstration of simple table syntax.}\tabularnewline+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endfirsthead+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endhead+\bottomrule\noalign{}+\endlastfoot+12 & 12 & 12 & 12 \\+123 & 123 & 123 & 123 \\+1 & 1 & 1 & 1 \\+\end{longtable}++```++```+% pandoc -t latex --figure-caption-position=above --table-caption-position=above+++ Right Left Center Default+------- ------ ---------- -------+ 12 12 12 12+ 123 123 123 123+ 1 1 1 1++ : Demonstration of simple table syntax.+^D+\begin{figure}+\centering+\caption{This is a figure.}+\pandocbounded{\includegraphics[keepaspectratio,alt={This is a figure.}]{img.jpg}}+\end{figure}++\begin{longtable}[]{@{}rlcl@{}}+\caption{Demonstration of simple table syntax.}\tabularnewline+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endfirsthead+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endhead+\bottomrule\noalign{}+\endlastfoot+12 & 12 & 12 & 12 \\+123 & 123 & 123 & 123 \\+1 & 1 & 1 & 1 \\+\end{longtable}++```++```+% pandoc -t latex --figure-caption-position=below --table-caption-position=below+++ Right Left Center Default+------- ------ ---------- -------+ 12 12 12 12+ 123 123 123 123+ 1 1 1 1++ : Demonstration of simple table syntax.+^D+\begin{figure}+\centering+\pandocbounded{\includegraphics[keepaspectratio,alt={This is a figure.}]{img.jpg}}+\caption{This is a figure.}+\end{figure}++\begin{longtable}[]{@{}rlcl@{}}+\toprule\noalign{}+Right & Left & Center & Default \\+\midrule\noalign{}+\endhead+\bottomrule\noalign{}+\tabularnewline+\caption{Demonstration of simple table syntax.}+\endlastfoot+12 & 12 & 12 & 12 \\+123 & 123 & 123 & 123 \\+1 & 1 & 1 & 1 \\+\end{longtable}++```
@@ -37,7 +37,7 @@ __ link1_ ^D-2> [WARNING] Circular reference 'link1' at line 1 column 15+2> [WARNING] Circular reference 'link1' at line 8 column 1 <p><a href="">click here</a></p> ```
@@ -7,20 +7,20 @@ | =^= | Centered , the same amount of characters is added to the left and the right. | | === | Padding. If a numeric value is printed with a sign, then additional characters are added after the sign. Otherwise it behaves like "=>=". This option is only available for numbers (default for numbers). | ^D-+--------+------------------------------------------------------------------+-| Option | Meaning |-+========+==================================================================+-| ``<`` | Left alignment, additional characters are added to the right |-| | (default for string). |-+--------+------------------------------------------------------------------+-| ``>`` | Right alignment, additional characters are added to the left. |-+--------+------------------------------------------------------------------+-| ``^`` | Centered , the same amount of characters is added to the left |-| | and the right. |-+--------+------------------------------------------------------------------+-| ``=`` | Padding. If a numeric value is printed with a sign, then |-| | additional characters are added after the sign. Otherwise it |-| | behaves like "``>``". This option is only available for numbers |-| | (default for numbers). |-+--------+------------------------------------------------------------------+++--------+-------------------------------------------------------------------++| Option | Meaning |++========+===================================================================++| ``<`` | Left alignment, additional characters are added to the right |+| | (default for string). |++--------+-------------------------------------------------------------------++| ``>`` | Right alignment, additional characters are added to the left. |++--------+-------------------------------------------------------------------++| ``^`` | Centered , the same amount of characters is added to the left and |+| | the right. |++--------+-------------------------------------------------------------------++| ``=`` | Padding. If a numeric value is printed with a sign, then |+| | additional characters are added after the sign. Otherwise it |+| | behaves like "``>``". This option is only available for numbers |+| | (default for numbers). |++--------+-------------------------------------------------------------------+ ```
@@ -4,12 +4,16 @@ <caption> <p>bar</p> </caption>- <graphic xlink:href="foo.png" xlink:alt-text="baz" />+ <graphic xlink:href="foo.png">+ <alt-text>baz</alt-text>+ </graphic> </fig> ^D-[ Para- [ Image- ( "fig-1" , [] , [] ) [ Str "bar" ] ( "foo.png" , "fig:" )+[ Figure+ ( "fig-1" , [] , [] )+ (Caption Nothing [ Plain [ Str "bar" ] ])+ [ Para+ [ Image ( "" , [] , [] ) [ Str "baz" ] ( "foo.png" , "" ) ] ] ] ```@@ -21,14 +25,17 @@ <title>foo</title> <p>bar</p> </caption>- <graphic xlink:href="foo.png" xlink:alt-text="baz" />+ <graphic xlink:href="foo.png">+ <alt-text>baz</alt-text>+ </graphic> </fig> ^D-[ Para- [ Image- ( "fig-1" , [] , [] )- [ Str "foo" , LineBreak , Str "bar" ]- ( "foo.png" , "fig:" )+[ Figure+ ( "fig-1" , [] , [] )+ (Caption+ Nothing [ Plain [ Str "foo" , LineBreak , Str "bar" ] ])+ [ Para+ [ Image ( "" , [] , [] ) [ Str "baz" ] ( "foo.png" , "" ) ] ] ] ```
@@ -21,22 +21,23 @@ hello\footnote{doc footnote} \begin{longtable}[]{@{}- >{\centering\arraybackslash}p{(\columnwidth - 0\tabcolsep) * \real{0.1667}}@{}}+ >{\centering\arraybackslash}p{(\linewidth - 0\tabcolsep) * \real{0.1667}}@{}} \caption[Sample table.]{Sample table.\footnote{caption footnote}}\tabularnewline-\toprule()+\toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering Fruit\footnote{header footnote} \end{minipage} \\-\midrule()+\midrule\noalign{} \endfirsthead-\toprule()+\toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering Fruit{} \end{minipage} \\-\midrule()+\midrule\noalign{} \endhead+\bottomrule\noalign{}+\endlastfoot Bans\footnote{table cell footnote} \\-\bottomrule() \end{longtable} dolly\footnote{doc footnote}
@@ -15,21 +15,32 @@ [ OrderedList ( 1 , Decimal , Period ) [ [ Para [ Str "foo" ]- , Para- [ Image- ( "" , [] , [] ) [ Str "bar" ] ( "bar.png" , "fig:" )+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "bar" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [ Str "bar" ] ( "bar.png" , "" )+ ] ] ] , [ Para [ Str "foo2" ]- , Para- [ Image- ( "" , [] , [] ) [ Str "bar2" ] ( "bar2.png" , "fig:" )+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "bar2" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] ) [ Str "bar2" ] ( "bar2.png" , "" )+ ] ] ] , [ Para [ Str "foo3" ]- , Para- [ Image- ( "" , [] , [] ) [ Str "foo3" ] ( "foo3.png" , "fig:" )+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "foo3" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] ) [ Str "foo3" ] ( "foo3.png" , "" )+ ] ] ] ]
@@ -6,9 +6,9 @@ hi there!‘ hi there! ^D-hi there?{}``-hi there!{}``-hi there?{}`-hi there!{}`+hi there?{\kern0pt}``+hi there!{\kern0pt}``+hi there?{\kern0pt}`+hi there!{\kern0pt}` hi there! ```
@@ -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;!}
@@ -4,7 +4,7 @@ ^D \begin{figure} \centering-\includegraphics{test/lalune.jpg}+\pandocbounded{\includegraphics[keepaspectratio,alt={moon}]{test/lalune.jpg}} \caption[moon]{moon\footnotemark{}} \end{figure} \footnotetext{the moon}
@@ -4,7 +4,7 @@ ~~_`hello world`_~~ ^D-\sout{\mbox{\texttt{hello\ world}}}+\st{\mbox{\texttt{hello\ world}}} -\sout{\emph{\mbox{\texttt{hello\ world}}}}+\st{\emph{\mbox{\texttt{hello\ world}}}} ```
@@ -4,5 +4,5 @@ : description ^D 1\. item-: description+: description ```
@@ -3,6 +3,5 @@ % pandoc -t latex # `foo`{.cpp} ^D-\hypertarget{foo}{%-\section{\texorpdfstring{\texttt{foo}}{foo}}\label{foo}}+\section{\texorpdfstring{\texttt{foo}}{foo}}\label{foo} ```
@@ -6,32 +6,61 @@ The caption. Here's what piggybacking on caption would look like {#fig:1} ^D-[ Para- [ Image- ( "test" , [] , [ ( "width" , "1in" ) ] )- [ Str "The"- , Space- , Str "caption."- , Space- , Str "Here's"- , Space- , Str "what"- , Space- , Str "piggybacking"- , Space- , Str "on"- , Space- , Str "caption"- , Space- , Str "would"- , Space- , Str "look"- , Space- , Str "like"- , Space- , Str "{#fig:1}"+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "The"+ , Space+ , Str "caption."+ , Space+ , Str "Here's"+ , Space+ , Str "what"+ , Space+ , Str "piggybacking"+ , Space+ , Str "on"+ , Space+ , Str "caption"+ , Space+ , Str "would"+ , Space+ , Str "look"+ , Space+ , Str "like"+ , Space+ , Str "{#fig:1}"+ ]+ ])+ [ Plain+ [ Image+ ( "test" , [] , [ ( "width" , "1in" ) ] )+ [ Str "The"+ , Space+ , Str "caption."+ , Space+ , Str "Here's"+ , Space+ , Str "what"+ , Space+ , Str "piggybacking"+ , Space+ , Str "on"+ , Space+ , Str "caption"+ , Space+ , Str "would"+ , Space+ , Str "look"+ , Space+ , Str "like"+ , Space+ , Str "{#fig:1}"+ ]+ ( "img1.jpg" , "" ) ]- ( "img1.jpg" , "fig:" ) ] ] ```
@@ -4,6 +4,6 @@ : Write output to *OUTFILE* instead of `stdout`(3) ^D .TP-\f[V]-o\f[R], \f[V]--output=\f[R]\f[I]OUTFILE\f[R]-Write output to \f[I]OUTFILE\f[R] instead of \f[V]stdout\f[R](3)+\f[CR]\-o\f[R], \f[CR]\-\-output=\f[R]\f[I]OUTFILE\f[R]+Write output to \f[I]OUTFILE\f[R] instead of \f[CR]stdout\f[R](3) ```
@@ -6,6 +6,6 @@ [[Plain [Str "Blah"]]]]]] ^D VIII. Blah- - Blah+ - Blah ```
@@ -0,0 +1,13 @@+```+% pandoc -f html -t djot+You can use <abbr title="Cascading Style Sheets">CSS</abbr>+^D+You can use [CSS]{.abbr title="Cascading Style Sheets"}+```++```+% pandoc -f djot -t html+You can use [CSS]{.abbr title="Cascading Style Sheets"}+^D+<p>You can use <abbr title="Cascading Style Sheets">CSS</abbr></p>+```
@@ -5,7 +5,7 @@ ,[] ,[Plain [Str "b"]]]] ^D-- a-- -- b+- a+- +- b ```
@@ -48,13 +48,13 @@ % pandoc -s -t native --data-dir=command/5876 --metadata-file=does-not-exist.yaml Hello ^D-2> Could not find metadata file does-not-exist.yaml+2> Could not find metadata file 'does-not-exist.yaml' => 98 ``` ``` % pandoc -s -t native --metadata-file=does-not-exist.yaml Hello ^D-2> Could not find metadata file does-not-exist.yaml+2> Could not find metadata file 'does-not-exist.yaml' => 98 ```
@@ -24,13 +24,13 @@ </body> </html> ^D-- A list of stuff with a table inside+- A list of stuff with a table inside - ===== ====== =====- First Second Third- ===== ====== =====- First Second Third- ===== ====== =====+ ===== ====== =====+ First Second Third+ ===== ====== =====+ First Second Third+ ===== ====== ===== -- Another list item+- Another list item ```
@@ -35,17 +35,17 @@ </body> </html> ^D-- A list of stuff with a table inside+- A list of stuff with a table inside - +-------+----------------------------------------------------+-------+- | First | Second | Third |- +=======+====================================================+=======+- | First | The big long table cell. The big long table cell. | Third |- | | The big long table cell. The big long table cell. | |- | | The big long table cell. The big long table cell. | |- | | The big long table cell. The big long table cell. | |- | | The big long table cell. The big long table cell. | |- +-------+----------------------------------------------------+-------++ +-------+------------------------------------------------------+-------++ | First | Second | Third |+ +=======+======================================================+=======++ | First | The big long table cell. The big long table cell. | Third |+ | | The big long table cell. The big long table cell. | |+ | | The big long table cell. The big long table cell. | |+ | | The big long table cell. The big long table cell. | |+ | | The big long table cell. The big long table cell. | |+ +-------+------------------------------------------------------+-------+ -- Another list item+- Another list item ```
@@ -4,8 +4,8 @@ ## Two #### Four ^D-- One- - Two+- One+ - Two One
@@ -8,11 +8,11 @@ <ol> <li><a href="text/title_page.xhtml" class="titlepage">Title Page</a></li>-<li><a href="#nav.xhtml#toc" class="toc">Table of Contents</a></li>+<li><a href="#nav.xhtml_toc" class="toc">Table of Contents</a></li> </ol> </nav> <p><span id="ch001.xhtml"></span></p>-<section id="ch001.xhtml#hi" class="level1" data-number="1">+<section id="ch001.xhtml_hi" class="level1" data-number="1"> <h1 data-number="1"><span class="header-section-number">1</span> Hi</h1> </section> ```
@@ -0,0 +1,54 @@+```+% pandoc -t native+Oxide 石英+------- ------+SiO2 100+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignRight , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Oxide" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "\30707\33521" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "SiO2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "100" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+```
@@ -70,26 +70,24 @@ Four ^D-\hypertarget{one}{%-\section{One}\label{one}}+\section{One}\label{one} \begin{frame}{One} One \end{frame} -\hypertarget{two}{%-\subsection{Two}\label{two}}+\subsection{Two}\label{two} \begin{frame}{Two} Two \end{frame} \begin{frame}{Three}-\protect\hypertarget{three}{}+\protect\phantomsection\label{three} Three \begin{block}{Four}-\protect\hypertarget{four}{}+\protect\phantomsection\label{four} Four \end{block} \end{frame}
@@ -32,15 +32,13 @@ - More text. ^D-\hypertarget{one}{%-\section{One}\label{one}}+\section{One}\label{one} -\hypertarget{one-a}{%-\subsection{One-A}\label{one-a}}+\subsection{One-A}\label{one-a} \begin{frame}{One-A} \begin{columns}[T]-\begin{column}{0.48\textwidth}+\begin{column}{0.48\linewidth} \begin{itemize} \tightlist \item@@ -48,7 +46,7 @@ \end{itemize} \end{column} -\begin{column}{0.48\textwidth}+\begin{column}{0.48\linewidth} \begin{itemize} \tightlist \item@@ -64,8 +62,7 @@ \end{itemize} \end{frame} -\hypertarget{one-b}{%-\subsection{One-B}\label{one-b}}+\subsection{One-B}\label{one-b} \begin{frame}{One-B} \begin{itemize}@@ -75,11 +72,9 @@ \end{itemize} \end{frame} -\hypertarget{two}{%-\section{Two}\label{two}}+\section{Two}\label{two} -\hypertarget{two-a}{%-\subsection{Two-A}\label{two-a}}+\subsection{Two-A}\label{two-a} \begin{frame}{Two-A} \begin{itemize}
@@ -7,8 +7,13 @@ \end{overpic} \end{figure*} ^D-[ RawBlock- (Format "latex")- "\\begin{figure*}\n \\centering\n \\begin{overpic}{test_pic}\n \\put (70,80) {Caption}\n \\end{overpic}\n\\end{figure*}"+[ Figure+ ( "" , [] , [] )+ (Caption Nothing [])+ [ RawBlock (Format "latex") "\\centering"+ , RawBlock+ (Format "latex")+ "\\begin{overpic}{test_pic}\n \\put (70,80) {Caption}\n \\end{overpic}"+ ] ] ```
@@ -13,15 +13,14 @@ ## Epilogue {.standout} ^D-\hypertarget{a-circus}{%-\section{A circus!}\label{a-circus}}+\section{A circus!}\label{a-circus} \begin{frame}{Another silly title}-\protect\hypertarget{another-silly-title}{}+\protect\phantomsection\label{another-silly-title} Not much to do about nothing. \end{frame} \begin{frame}[standout]{Epilogue}-\protect\hypertarget{epilogue}{}+\protect\phantomsection\label{epilogue} \end{frame} ```
@@ -38,79 +38,76 @@ , Space , Str "work." ]-, Div+, Table ( "tbl:label" , [] , [] )- [ Table+ (Caption+ Nothing+ [ Plain+ [ Str "This"+ , Space+ , Str "caption"+ , Space+ , Str "has"+ , Space+ , Str "no"+ , Space+ , Str "number."+ ]+ ])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignCenter , ColWidthDefault )+ , ( AlignRight , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody ( "" , [] , [] )- (Caption- Nothing- [ Plain- [ Str "This"- , Space- , Str "caption"- , Space- , Str "has"- , Space- , Str "no"- , Space- , Str "number."- ]- ])- [ ( AlignLeft , ColWidthDefault )- , ( AlignCenter , ColWidthDefault )- , ( AlignRight , ColWidthDefault )- ]- (TableHead ( "" , [] , [] ) [])- [ TableBody+ (RowHeadColumns 0)+ []+ [ Row ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row+ [ Cell ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Plain [ Str "\8212\8212\8211" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Plain [ Str "\8212\8212\8211" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Plain [ Str "\8212\8212\8211" ] ]- ]- , Row+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "\8212\8212\8211" ] ]+ , Cell ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Plain [ Str "\8212\8212\8211" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Plain [ Str "\8212\8212\8211" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Plain [ Str "\8212\8212\8211" ] ]- ]+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "\8212\8212\8211" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "\8212\8212\8211" ] ] ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "\8212\8212\8211" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "\8212\8212\8211" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "\8212\8212\8211" ] ]+ ] ]- (TableFoot ( "" , [] , [] ) []) ]+ (TableFoot ( "" , [] , [] ) []) , Para [ Str "This" , Space@@ -134,24 +131,32 @@ , Space , Str "fine." ]-, Para- [ Image- ( "fig:label" , [] , [ ( "width" , "\\textwidth" ) ] )- [ Str "A"- , Space- , Str "numbered"- , Space- , Str "caption,"- , Space- , Str "if"- , Space- , Str "I"- , Space- , Str "use"- , Space- , Str "pandoc-crossref."+, Figure+ ( "fig:label" , [] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "A"+ , Space+ , Str "numbered"+ , Space+ , Str "caption,"+ , Space+ , Str "if"+ , Space+ , Str "I"+ , Space+ , Str "use"+ , Space+ , Str "pandoc-crossref."+ ]+ ])+ [ Plain+ [ Image+ ( "" , [] , [ ( "width" , "\\textwidth" ) ] )+ []+ ( "example.png" , "" ) ]- ( "example.png" , "fig:" ) ] ] ```
@@ -0,0 +1,6 @@+```+% pandoc -t docx -f native -o - | pandoc -f docx -t native+[ HorizontalRule ]+^D+[ HorizontalRule ]+```
@@ -4,7 +4,5 @@ <label>I</label><title>Introduction</title> </sec> ^D-[ Header- 1 ( "" , [] , [] ) [ Str "I." , Space , Str "Introduction" ]-]+[ Header 1 ( "" , [] , [] ) [ Str "Introduction" ] ] ```
@@ -0,0 +1,29 @@+```+% pandoc -f commonmark+implicit_figures -t native+{#ident width="100%"}+^D+[ Para+ [ Image+ ( "" , [] , [] ) [ Str "caption" ] ( "image.jpg" , "" )+ , Str "{#ident"+ , Space+ , Str "width=\"100%\"}"+ ]+]++```++```+% pandoc -f commonmark -t native+{#ident width="100%"}+^D+[ Para+ [ Image+ ( "" , [] , [] ) [ Str "caption" ] ( "image.jpg" , "" )+ , Str "{#ident"+ , Space+ , Str "width=\"100%\"}"+ ]+]++```
@@ -2,5 +2,5 @@ % pandoc -f native -t latex --wrap=none [Link ("test2",[],[]) [Str "link",Space,Str "to",Space,Str "text",Space,Str "test1"] ("#test1","")] ^D-\protect\hypertarget{test2}{\protect\hyperlink{test1}{link to text test1}}+\protect\phantomsection\label{test2}\hyperref[test1]{link to text test1} ```
@@ -0,0 +1,12 @@+```+% pandoc --wrap=preserve --file-scope command/file1.txt command/file2.txt+^D+<h1 id="command__file1.txt__zed">Zed</h1>+<p><a href="bar">foo</a>+and <a href="#command__file1.txt__zed">Zed</a>+and <a href="#command__file2.txt__zed">other Zed</a>+and <a href="#command__file2.txt">other file</a>+and <a href="c.md#zed">foreign Zed</a></p>+<h2 id="command__file2.txt__zed">Zed</h2>+<p><a href="baz">foo</a></p>+```
@@ -0,0 +1,6 @@+```+% pandoc -t asciidoc+test^[this is a note\]. and more]+^D+testfootnote:[this is a note++]++. and more]+```
@@ -7,13 +7,13 @@ ^D <table class="table-dark"> <thead>-<tr class="header">+<tr> <th>h1</th> <th>h2</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>c1</td> <td>c2</td> </tr>
@@ -18,7 +18,7 @@ <col style="width: 69%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Col 1</th> <th style="text-align: center;">Col 2</th> <th style="text-align: center;">Col 3</th>@@ -26,7 +26,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">High</td> <td style="text-align: center;">Med</td> <td style="text-align: center;">Med</td>
@@ -8,13 +8,13 @@ <table> <caption>Test table</caption> <thead>-<tr class="header">+<tr> <th>Column1</th> <th>Column2</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Data1</td> <td><ul> <li>data1</li>
@@ -0,0 +1,10 @@+```+% pandoc -f rst+I recommend you try |Python|_.++.. |Python| replace:: Python, *the* best language around+.. _Python: http://www.python.org/+^D+<p>I recommend you try <a href="http://www.python.org/"><span>Python,+<em>the</em> best language around</span></a>.</p>+```
@@ -4,7 +4,7 @@ <emphasis>emphasized </emphasis>text </para> ^D-[ Para [ Emph [ Str "emphasized" ] , Space , Str "text" ] ]+[ Para [ Emph [ Str "emphasized" , Space ] , Str "text" ] ] ``` ```@@ -13,6 +13,6 @@ <italic> hi </italic>there </p> ^D-[ Para [ Emph [ Str "hi" ] , Space , Str "there" ] ]+[ Para [ Emph [ Space , Str "hi" , Space ] , Str "there" ] ] ```
@@ -22,11 +22,11 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-doe .csl-entry} Doe, John. "An Article," 2020. <https://doi.org/10.1109/5.771073>. :::-:::+:::: [^1]: John Doe, "An Article," 2020, <https://doi.org/10.1109/5.771073>. ```
@@ -13,7 +13,7 @@ % pandoc -f native -t opendocument+xrefs_name --quiet [Header 1 ("chapter1",[],[]) [Str "The",Space,Str "Chapter"] ,Para [Str "Chapter",Space,Str "1",Space,Str "references",Space,Link ("",[],[]) [Str "The",Space,Str "Chapter"] ("#chapter1","")]-,Para [Image ("lalune",[],[]) [Str "lalune"] ("lalune.jpg","fig:Voyage dans la Lune")]+,Figure ("lalune",[],[]) (Caption Nothing [Para [Str "Voyage dans la Lune"]]) [Plain [Image ("",[],[]) [Str "lalune"] ("lalune.jpg","")]] ,Para [Str "Image",Space,Str "1",Space,Str "references",Space,Link ("",[],[]) [Str "La",Space,Str "Lune"] ("#lalune","")]] ^D <text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="chapter1" />The@@ -22,7 +22,7 @@ <text:bookmark-ref text:reference-format="text" text:ref-name="chapter1">The Chapter</text:bookmark-ref></text:p> <text:p text:style-name="FigureWithCaption"><draw:frame draw:name="img1"><draw:image xlink:href="lalune.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame></text:p>-<text:p text:style-name="FigureCaption">lalune</text:p>+<text:p text:style-name="FigureCaption">Voyage dans la Lune</text:p> <text:p text:style-name="Text_20_body">Image 1 references <text:sequence-ref text:reference-format="caption" text:ref-name="lalune">La Lune</text:sequence-ref></text:p>@@ -31,7 +31,7 @@ % pandoc -f native -t opendocument+xrefs_number --quiet [Header 1 ("chapter1",[],[]) [Str "The",Space,Str "Chapter"] ,Para [Str "Chapter",Space,Str "1",Space,Str "references",Space,Link ("",[],[]) [Str "The",Space,Str "Chapter"] ("#chapter1","")]-,Para [Image ("lalune",[],[]) [Str "lalune"] ("lalune.jpg","fig:Voyage dans la Lune")]+,Figure ("lalune",[],[]) (Caption Nothing [Para [Str "lalune"]]) [Plain [Image ("",[],[]) [Str "lalune"] ("lalune.jpg","Voyage dans la Lune")]] ,Para [Str "Image",Space,Str "1",Space,Str "references",Space,Link ("",[],[]) [Str "La",Space,Str "Lune"] ("#lalune","")]] ^D <text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="chapter1" />The@@ -47,7 +47,7 @@ % pandoc -f native -t opendocument+xrefs_number+xrefs_name --quiet [Header 1 ("chapter1",[],[]) [Str "The",Space,Str "Chapter"] ,Para [Str "Chapter",Space,Str "1",Space,Str "references",Space,Link ("",[],[]) [Str "The",Space,Str "Chapter"] ("#chapter1","")]-,Para [Image ("lalune",[],[]) [Str "lalune"] ("lalune.jpg","fig:Voyage dans la Lune")]+,Figure ("lalune",[],[]) (Caption Nothing [Para [Str "Voyage dans la Lune"]]) [Plain [Image ("",[],[]) [Str "lalune"] ("lalune.jpg","")]] ,Para [Str "Image",Space,Str "1",Space,Str "references",Space,Link ("",[],[]) [Str "La",Space,Str "Lune"] ("#lalune","")]] ^D <text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="chapter1" />The@@ -56,7 +56,7 @@ <text:bookmark-ref text:reference-format="number" text:ref-name="chapter1"></text:bookmark-ref><text:s /><text:bookmark-ref text:reference-format="text" text:ref-name="chapter1">The Chapter</text:bookmark-ref></text:p> <text:p text:style-name="FigureWithCaption"><draw:frame draw:name="img1"><draw:image xlink:href="lalune.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame></text:p>-<text:p text:style-name="FigureCaption">lalune</text:p>+<text:p text:style-name="FigureCaption">Voyage dans la Lune</text:p> <text:p text:style-name="Text_20_body">Image 1 references <text:sequence-ref text:reference-format="value" text:ref-name="lalune"></text:sequence-ref><text:s /><text:sequence-ref text:reference-format="caption" text:ref-name="lalune">La Lune</text:sequence-ref></text:p>
@@ -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. ```
@@ -17,7 +17,7 @@ [])] ^D <?xml version="1.0" encoding="utf-8" ?>-<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.2">+<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.3"> <office:font-face-decls> <style:font-face style:name="Courier New" style:font-family-generic="modern" style:font-pitch="fixed" svg:font-family="'Courier New'" /> </office:font-face-decls>
@@ -0,0 +1,80 @@+```+% pandoc -f native -t latex+[ Para [ Code ( "" , [ "python" ] , [] ) "x = 5" ]+, Figure+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "test"+ , Space+ , Code ( "" , [ "python" ] , [] ) "x = 5"+ ]+ ])+ [ Plain+ [ Image+ ( "" , [] , [] )+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "test"+ , Space+ , Code ( "" , [ "python" ] , [] ) "x = 5"+ ]+ ( "test.png" , "" )+ ]+ ]+, Table+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Plain [ Code ( "" , [ "cpp" ] , [] ) "caption" ] ])+ [ ( AlignDefault , ColWidthDefault ) ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "A" ] ]+ ]+ ])+, Para [ Code ( "" , [ "cpp" ] , [] ) "caption" ]+]+^D+\VERB|\NormalTok{x }\OperatorTok{=} \DecValTok{5}|++\begin{figure}+\centering+\pandocbounded{\includegraphics[keepaspectratio,alt={This is a test x = 5}]{test.png}}+\caption{This is a test+\protect\VERB|\NormalTok{x }\OperatorTok{=} \DecValTok{5}|}+\end{figure}++\begin{longtable}[]{@{}l@{}}+\caption{\protect\VERB|\NormalTok{caption}|}\tabularnewline+\toprule\noalign{}+\endfirsthead+\endhead+\midrule\noalign{}+A \\+\bottomrule\noalign{}+\endlastfoot+\end{longtable}++\VERB|\NormalTok{caption}|+```
@@ -27,13 +27,13 @@ \*FvwmAnimate: Color color -: Tells **FvwmAnimate** what color to draw with. The color is- \"XOR\'ed\" (exclusive ORed) onto the background.+: Tells **FvwmAnimate** what color to draw with. The color is+ \"XOR\'ed\" (exclusive ORed) onto the background. \*FvwmAnimate: Pixmap pixmap -: Tells **FvwmAnimate** to use **pixmap** to draw with. This can be- useful if **\*FvwmAnimate: Color** gives poor results.+: Tells **FvwmAnimate** to use **pixmap** to draw with. This can be+ useful if **\*FvwmAnimate: Color** gives poor results. ``` ```@@ -46,7 +46,7 @@ there ^D-- hi+- hi -- there+- there ```
@@ -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)" ]@@ -126,10 +122,6 @@ , Str "3rd" , Space , Str "ed."- , Space- , Str "Wiesbaden,"- , Space- , Str "Germany:" , Space , Str "Springer" , Space
@@ -23,12 +23,12 @@ ::: thm **Theorem 1**. *a* -+ ::: ::: thm2 **Theorem 1**. a -+ ::: ```
@@ -4,9 +4,9 @@ % pandoc -f native -t rst [Para [Image ("",["align-center"],[]) [Str "https://pandoc.org/diagram.jpg"] ("https://pandoc.org/diagram.jpg","")]] ^D-.. image:: https://pandoc.org/diagram.jpg- :alt: https://pandoc.org/diagram.jpg- :align: center+|https://pandoc.org/diagram.jpg|++.. |https://pandoc.org/diagram.jpg| image:: https://pandoc.org/diagram.jpg ``` Here we just omit the center attribute as it's not valid:
@@ -14,5 +14,5 @@ Crazy. n.d. -Doe, John. 2005. First Book. Cambridge: Cambridge University Press.+Doe, John. 2005. First Book. Cambridge University Press. ```
@@ -0,0 +1,12 @@+```+% pandoc -t docx -o - | pandoc -f docx -t markdown --track-changes=all+[This is the comment]{.comment-start id="1" author="Mike"+date="2020-12-17T16:53:00Z"} [Here is my reply]{.comment-start id="2"+author="Mike" date="2020-12-17T17:39:00Z"} This is the content being+commented on [[]{.comment-end id="2"}]{.comment-end id="1"}+^D+[This is the comment]{.comment-start id="1" author="Mike"+date="2020-12-17T16:53:00Z"} [Here is my reply]{.comment-start id="2"+author="Mike" date="2020-12-17T17:39:00Z"} This is the content being+commented on [[]{.comment-end id="2"}]{.comment-end id="1"}+```
@@ -0,0 +1,76 @@+```+% pandoc -f mediawiki -t native+{| class="wikitable"+!colspan=4 | template request+|-+| mode || No || String || MUST be "template" or omitted+|}+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 4)+ [ Para [ Str "template" , Space , Str "request" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "mode" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "No" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "String" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "MUST"+ , Space+ , Str "be"+ , Space+ , Str "\"template\""+ , Space+ , Str "or"+ , Space+ , Str "omitted"+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]++```
@@ -39,6 +39,7 @@ </body> <back> <ref-list>+ <title></title> <ref id="ref-doe"> <mixed-citation>Doe, J. (2021). Another article. <italic>Proceedings of the Academy of Test Inputs</italic>.
@@ -81,6 +81,7 @@ </body> <back> <ref-list>+ <title></title> <ref id="ref-year-month"> <element-citation publication-type="article-journal"> <person-group person-group-type="author">
@@ -15,14 +15,14 @@ <col style="width: 70%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>Version</th> <th>Date</th> <th>Description</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>0.1.0</td> <td>18/02/2013</td> <td>Initial Release</td>
@@ -6,7 +6,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td>setting</td> <td><code>echo PATH="path"</code></td> </tr>
@@ -0,0 +1,17 @@+```+% pandoc -t markdown+- one+ - two+^D+- one+ - two+```++```+% pandoc -t markdown+four_space_rule+- one+ - two+^D+- one+ - two+```
@@ -4,7 +4,7 @@ ^D \begin{figure} \centering-\includegraphics[page=13,trim=1cm,clip,width=4cm]{slides.pdf}+\pandocbounded{\includegraphics[keepaspectratio,page=13,trim=1cm,clip,width=4cm,alt={Global frog population.}]{slides.pdf}} \caption{Global frog population.} \end{figure}
@@ -0,0 +1,47 @@+```+% pandoc -t revealjs --slide-level=1+# Overview++:::::::::::::: {.columns}+::: {.column width="40%"}++Left column++:::+::: {.column width="60%"}++* First list+ * subitem++. . .++* Second list+ * subitem+:::+::::::::::::::+^D+<section id="overview" class="slide level1">+<h1>Overview</h1>+<div class="columns">+<div class="column" style="width:40%;">+<p>Left column</p>+</div><div class="column" style="width:60%;">+<ul>+<li>First list+<ul>+<li>subitem</li>+</ul></li>+</ul>+<div class="fragment">+<ul>+<li>Second list+<ul>+<li>subitem</li>+</ul></li>+</ul>+</div>+</div>+</div>+</section>++```
@@ -13,12 +13,12 @@ <col style="width: 26%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td>日本語</td> <td>の文字列</td> <td>words in english</td> </tr>-<tr class="even">+<tr> <td>abc defghij</td> <td>def</td> <td>xyz</td>
@@ -0,0 +1,25 @@+```+% pandoc --citeproc -t plain+---+references:+- author:+ - family: Reese+ given: Trevor R.+ collection-title: 3rd series+ container-title: William and Mary Quarterly+ id: reese+ issued: 1958+ language: en-US+ page: 168-190+ title: Georgia in Anglo-Spanish diplomacy, 1736-1739+ type: article-journal+ volume: 15+...+and also in -@reese+^D+and also in (1958)++Reese, Trevor R. 1958. “Georgia in Anglo-Spanish Diplomacy, 1736-1739.”+William and Mary Quarterly, 3rd series, vol. 15: 168–90.++```
@@ -14,14 +14,17 @@ </tbody> </table> ^D+{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}- >{\raggedright\arraybackslash}p{(\columnwidth - 0\tabcolsep) * \real{1.0000}}@{}}-\toprule()+ >{\raggedright\arraybackslash}p{(\linewidth - 0\tabcolsep) * \real{1.0000}}@{}}+\toprule\noalign{} \endhead+\bottomrule\noalign{}+\endlastfoot \begin{minipage}[t]{\linewidth}\raggedright { text\\ text2 }\strut \end{minipage} \\-\bottomrule() \end{longtable}+} ```
@@ -17,21 +17,21 @@ text in block ^D \begin{frame}{Slide}-\protect\hypertarget{slide}{}+\protect\phantomsection\label{slide} Some blocks: \begin{exampleblock}{example block title}-\protect\hypertarget{example-block-title}{}+\protect\phantomsection\label{example-block-title} text in block \end{exampleblock} \begin{alertblock}{alert block title}-\protect\hypertarget{alert-block-title}{}+\protect\phantomsection\label{alert-block-title} text in block \end{alertblock} \begin{block}{block title}-\protect\hypertarget{block-title}{}+\protect\phantomsection\label{block-title} text in block \end{block} \end{frame}
@@ -0,0 +1,1227 @@+Table with row and column spans+```+% pandoc -f html -t asciidoc+<table>+ <colgroup>+ <col style="width: 17%" />+ <col style="width: 16%" />+ <col style="width: 15%" />+ <col style="width: 52%" />+ </colgroup>+ <thead>+ <tr>+ <th>Header 1</th>+ <th>Header 2</th>+ <th>Header 3</th>+ <th>Header 4</th>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td>body row 1</td>+ <td>column 2</td>+ <td>column 3</td>+ <td>column 4</td>+ </tr>+ <tr>+ <td>body row 2</td>+ <td colspan="2">Cells may span columns.</td>+ <td>fff</td>+ </tr>+ <tr>+ <td>body row 3</td>+ <td rowspan="2">Cells may span rows.</td>+ <td rowspan="2">+ <ul>+ <li>Cells</li>+ <li>can</li>+ <li>contain</li>+ <li>blocks.</li>+ </ul>+ </td>+ <td rowspan="2">+ <ul>+ <li>This is a very long line of text</li>+ <li><a href="http://www.python.org/">Python</a></li>+ <li>b</li>+ <li>c</li>+ </ul>+ </td>+ </tr>+ <tr>+ <td>body row 4</td>+ </tr>+ </tbody>+</table>+^D+[width="100%",cols="17%,16%,15%,52%",options="header",]+|===+|Header 1 |Header 2 |Header 3 |Header 4+|body row 1 |column 2 |column 3 |column 4+|body row 2 2+|Cells may span columns. |fff+|body row 3 .2+|Cells may span rows. .2+a|+* Cells+* can+* contain+* blocks.++.2+a|+* This is a very long line of text+* http://www.python.org/[Python]+* b+* c++|body row 4+|===+```++Header and footer.+AsciiDoc only supports 1 header and 1 footer row.+So for multiple header and/or footer rows all the extra rows become part of the table body.+```+% pandoc -f html -t asciidoc+<table>+ <thead>+ <tr>+ <th colspan="2">Inputs</th>+ <th>Output</th>+ </tr>+ <tr>+ <th>A</th>+ <th>B</th>+ <th>A or B</th>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td>False</td>+ <td>False</td>+ <td>False</td>+ </tr>+ <tr>+ <td>True</td>+ <td>False</td>+ <td>True</td>+ </tr>+ <tr>+ <td>False</td>+ <td>True</td>+ <td>True</td>+ </tr>+ <tr>+ <td>True</td>+ <td>True</td>+ <td>True</td>+ </tr>+ </tbody>+ <tfoot>+ <tr>+ <td>A</td>+ <td>B</td>+ <td>A or B</td>+ </tr>+ <tr>+ <td colspan="2">Inputs</td>+ <td>Output</td>+ </tr>+ </tfoot>+</table>+<table>+ <thead>+ <tr>+ <th colspan="2">Header</th>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td>Body 1-1</td>+ <td>Body 2-1</td>+ </tr>+ </tbody>+ <tfoot>+ <tr>+ <td colspan="2">Footer</td>+ </tr>+ </tfoot>+</table>+^D+[cols=",,",options="header,footer",]+|===+2+|Inputs |Output+|A |B |A or B+|False |False |False+|True |False |True+|False |True |True+|True |True |True+|A |B |A or B+2+|Inputs |Output+|===++[cols=",",options="header,footer",]+|===+2+|Header+|Body 1-1 |Body 2-1+2+|Footer+|===+```++Table without header but with footer rows+```+% pandoc -f html -t asciidoc+<table>+ <colgroup>+ <col style="width: 37%" />+ <col style="width: 37%" />+ <col style="width: 26%" />+ </colgroup>+ <tbody>+ <tr>+ <td>False</td>+ <td>False</td>+ <td>False</td>+ </tr>+ <tr>+ <td>True</td>+ <td>False</td>+ <td>True</td>+ </tr>+ <tr>+ <td>False</td>+ <td>True</td>+ <td>True</td>+ </tr>+ <tr>+ <td>True</td>+ <td>True</td>+ <td>True</td>+ </tr>+ </tbody>+ <tfoot>+ <tr>+ <td>A</td>+ <td>B</td>+ <td>A or B</td>+ </tr>+ <tr>+ <td colspan="2">Inputs</td>+ <td>Output</td>+ </tr>+ </tfoot>+</table>+^D+[width="100%",cols="37%,37%,26%",options="footer",]+|===+|False |False |False+|True |False |True+|False |True |True+|True |True |True+|A |B |A or B+2+|Inputs |Output+|===+```++Adjust row span for multiple header rows+```+% pandoc -f html -t asciidoc+<table style="width: 63%">+ <colgroup>+ <col style="width: 30%" />+ <col style="width: 11%" />+ <col style="width: 11%" />+ <col style="width: 11%" />+ </colgroup>+ <thead>+ <tr>+ <th rowspan="2">Location</th>+ <th colspan="3">Temperature 1961-1990 in degree Celsius</th>+ </tr>+ <tr>+ <th>min</th>+ <th>mean</th>+ <th>max</th>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td>Antarctica</td>+ <td>-89.2</td>+ <td>N/A</td>+ <td>19.8</td>+ </tr>+ <tr>+ <td>Earth</td>+ <td>-89.2</td>+ <td>14</td>+ <td>56.7</td>+ </tr>+ </tbody>+</table>+<table style="width: 63%">+ <colgroup>+ <col style="width: 11%" />+ <col style="width: 11%" />+ <col style="width: 11%" />+ <col style="width: 30%" />+ </colgroup>+ <thead>+ <tr>+ <th colspan="3">Temperature 1961-1990 in degree Celsius</th>+ <th rowspan="2">Location</th>+ </tr>+ <tr>+ <th>min</th>+ <th>mean</th>+ <th>max</th>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td>-89.2</td>+ <td>N/A</td>+ <td>19.8</td>+ <td>Antarctica</td>+ </tr>+ <tr>+ <td>-89.2</td>+ <td>14</td>+ <td>56.7</td>+ <td>Earth</td>+ </tr>+ </tbody>+</table>+<table style="width: 65%">+ <colgroup>+ <col style="width: 11%" />+ <col style="width: 11%" />+ <col style="width: 11%" />+ <col style="width: 18%" />+ <col style="width: 14%" />+ </colgroup>+ <thead>+ <tr>+ <th colspan="3">Temperature 1961-1990 in degree Celsius</th>+ <th rowspan="2">Location</th>+ <th>Extra</th>+ </tr>+ <tr>+ <th>min</th>+ <th>mean</th>+ <th>max</th>+ <th>Extra 2</th>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td>-89.2</td>+ <td>N/A</td>+ <td>19.8</td>+ <td>Antarctica</td>+ <td>Extra 3</td>+ </tr>+ <tr>+ <td>-89.2</td>+ <td>14</td>+ <td>56.7</td>+ <td>Earth</td>+ <td>Extra 4</td>+ </tr>+ </tbody>+</table>+<table>+ <thead>+ <tr>+ <th>Header 1-1</th>+ <th colspan="2" rowspan="2">Header 1-2</th>+ </tr>+ <tr>+ <th>Header 2-1</th>+ </tr>+ <tr>+ <th>Header 3-1</th>+ <th>Header 3-2</th>+ <th>Header 3-3</th>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td rowspan="2">Body 1-1</td>+ <td colspan="2">Body 1-2</td>+ </tr>+ <tr>+ <td>Body 2-1</td>+ <td>Body 2-2</td>+ </tr>+ </tbody>+</table>+<table>+ <thead>+ <tr>+ <th rowspan="2">Header 1-1</th>+ <th>Header 1-2</th>+ <th rowspan="2">Header 1-3</th>+ </tr>+ <tr>+ <th>Header 2-1</th>+ </tr>+ <tr>+ <th>Header 3-1</th>+ <th>Header 3-2</th>+ <th>Header 3-3</th>+ </tr>+ </thead>+ <tbody></tbody>+</table>+^D+[width="63%",cols="49%,17%,17%,17%",options="header",]+|===+|Location 3+|Temperature 1961-1990 in degree Celsius+| |min |mean |max+|Antarctica |-89.2 |N/A |19.8+|Earth |-89.2 |14 |56.7+|===++[width="63%",cols="19%,17%,17%,47%",options="header",]+|===+3+|Temperature 1961-1990 in degree Celsius |Location+|min |mean |max |+|-89.2 |N/A |19.8 |Antarctica+|-89.2 |14 |56.7 |Earth+|===++[width="65%",cols="20%,16%,16%,27%,21%",options="header",]+|===+3+|Temperature 1961-1990 in degree Celsius |Location |Extra+|min |mean |max | |Extra 2+|-89.2 |N/A |19.8 |Antarctica |Extra 3+|-89.2 |14 |56.7 |Earth |Extra 4+|===++[cols=",,",options="header",]+|===+|Header 1-1 2+|Header 1-2+|Header 2-1 2+|+|Header 3-1 |Header 3-2 |Header 3-3+.2+|Body 1-1 2+|Body 1-2+|Body 2-1 |Body 2-2+|===++[cols=",,",options="header",]+|===+|Header 1-1 |Header 1-2 |Header 1-3+| |Header 2-1 |+|Header 3-1 |Header 3-2 |Header 3-3+|===+```++Adjust row span in multiple footer rows.+```+% pandoc -f html -t asciidoc+<table>+ <colgroup>+ <col style="width: 40%" />+ <col style="width: 40%" />+ <col style="width: 20%" />+ </colgroup>+ <tbody>+ <tr>+ <td>Body 1-1</td>+ <td>Body 1-2</td>+ <td>Body 1-3</td>+ </tr>+ </tbody>+ <tfoot>+ <tr>+ <td colspan="2">Footer 1-1/2</td>+ <td>Footer 1-3</td>+ </tr>+ <tr>+ <td>Footer 2-1</td>+ <td rowspan="3">Span 3</td>+ <td>Footer 2-3</td>+ </tr>+ <tr>+ <td rowspan="2">Span 2</td>+ <td>Footer 3-3</td>+ </tr>+ <tr>+ <td>Footer 4-3</td>+ </tr>+ </tfoot>+</table>+<table>+ <tbody>+ <tr>+ <td>Body 1-1</td>+ <td>Body 1-2</td>+ <td>Body 1-3</td>+ <td>Body 1-4</td>+ <td>Body 1-5</td>+ </tr>+ <tr>+ <td>Body 2-1</td>+ <td>Body 2-2</td>+ <td>Body 2-3</td>+ <td>Body 2-4</td>+ <td>Body 2-5</td>+ </tr>+ </tbody>+ <tfoot>+ <tr>+ <td colspan="3">Footer 1-1/2/3</td>+ <td>Footer 1-4</td>+ <td>Footer 1-5</td>+ </tr>+ <tr>+ <td>Footer 2-1</td>+ <td rowspan="3">Span 3</td>+ <td>Footer 2-3</td>+ <td colspan="2">Footer 2-4/5</td>+ </tr>+ <tr>+ <td rowspan="2">Span 2</td>+ <td colspan="2">Footer 3-3/4</td>+ <td rowspan="2">Span 2</td>+ </tr>+ <tr>+ <td rowspan="3">Span 3</td>+ <td>Footer 4-4</td>+ </tr>+ <tr>+ <td>Footer 5-1</td>+ <td>Footer 5-2</td>+ <td>Footer 5-4</td>+ <td rowspan="2">Span 2</td>+ </tr>+ <tr>+ <td colspan="2">Footer 6-1/2</td>+ <td>Footer 6-4</td>+ </tr>+ </tfoot>+</table>+<table>+ <tbody>+ <tr>+ <td>Body 1</td>+ <td>Body 2</td>+ <td>Body 3</td>+ <td>Body 4</td>+ </tr>+ </tbody>+ <tfoot>+ <tr>+ <td>Footer 1-1</td>+ <td colspan="2" rowspan="3">Span 3</td>+ <td rowspan="2">Span 2</td>+ </tr>+ <tr>+ <td>Footer 2-1</td>+ </tr>+ <tr>+ <td>Footer 3-1</td>+ <td>Footer 3-4</td>+ </tr>+ </tfoot>+</table>+<table>+ <tbody>+ <tr>+ <td>Body 1-1</td>+ <td>Body 1-2</td>+ <td>Body 1-3</td>+ <td>Body 1-4</td>+ </tr>+ </tbody>+ <tfoot>+ <tr>+ <td colspan="2">Footer 1-1/2</td>+ <td rowspan="6">Span 6</td>+ <td>Footer 1-4</td>+ </tr>+ <tr>+ <td rowspan="3">Span 3</td>+ <td>Footer 2-2</td>+ <td>Footer 2-4</td>+ </tr>+ <tr>+ <td>Footer 3-2</td>+ <td>Footer 3-4</td>+ </tr>+ <tr>+ <td>Footer 4-2</td>+ <td>Footer 4-4</td>+ </tr>+ <tr>+ <td>Footer 5-1</td>+ <td>Footer 5-2</td>+ <td rowspan="2">Span 2</td>+ </tr>+ <tr>+ <td colspan="2">Footer 6-1/2</td>+ </tr>+ </tfoot>+</table>+^D+[width="100%",cols="40%,40%,20%",options="footer",]+|===+|Body 1-1 |Body 1-2 |Body 1-3+2+|Footer 1-1/2 |Footer 1-3+|Footer 2-1 .2+|Span 3 |Footer 2-3+|Span 2 |Footer 3-3+| | |Footer 4-3+|===++[cols=",,,,",options="footer",]+|===+|Body 1-1 |Body 1-2 |Body 1-3 |Body 1-4 |Body 1-5+|Body 2-1 |Body 2-2 |Body 2-3 |Body 2-4 |Body 2-5+3+|Footer 1-1/2/3 |Footer 1-4 |Footer 1-5+|Footer 2-1 .3+|Span 3 |Footer 2-3 2+|Footer 2-4/5+.2+|Span 2 2+|Footer 3-3/4 .2+|Span 2+.2+|Span 3 |Footer 4-4+|Footer 5-1 |Footer 5-2 |Footer 5-4 |Span 2+2+|Footer 6-1/2 | |Footer 6-4 |+|===++[cols=",,,",options="footer",]+|===+|Body 1 |Body 2 |Body 3 |Body 4+|Footer 1-1 2.2+|Span 3 .2+|Span 2+|Footer 2-1+|Footer 3-1 2+| |Footer 3-4+|===++[cols=",,,",options="footer",]+|===+|Body 1-1 |Body 1-2 |Body 1-3 |Body 1-4+2+|Footer 1-1/2 .5+|Span 6 |Footer 1-4+.3+|Span 3 |Footer 2-2 |Footer 2-4+|Footer 3-2 |Footer 3-4+|Footer 4-2 |Footer 4-4+|Footer 5-1 |Footer 5-2 |Span 2+2+|Footer 6-1/2 | |+|===+```++Individual cell alignments+```+% pandoc -f native -t asciidoc+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Left" , Space , Str "Header" ] ]+ , Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 2)+ (ColSpan 2)+ [ Plain [ Str "Center" , Space , Str "Headers" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Right" , Space , Str "Header" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Center" , Space , Str "Header" ] ]+ , Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Right" , Space , Str "Header" ] ]+ , Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Left" , Space , Str "Header" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "Right" , Space , Str "Body" ] ]+ , Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "Left" , Space , Str "Body" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Center" , Space , Str "Body" ] ]+ , Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Right" , Space , Str "Body" ] ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 1)+ (ColSpan 3)+ [ Plain [ Str "Center" , Space , Str "Footer" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "Left" , Space , Str "Footer" ] ]+ , Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 3)+ (ColSpan 1)+ [ Plain [ Str "Center" , Space , Str "Footer" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "Right" , Space , Str "Footer" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "Center" , Space , Str "Footer" ] ]+ ]+ ])+]+^D+[cols=",,",options="header,footer",]+|===+<|Left Header 2+^|Center Headers+>|Right Header 2+|+^|Center Header >|Right Header <|Left Header+.2+>|Right Body 2+<|Left Body+^|Center Body >|Right Body+3+^|Center Footer+2+<|Left Footer .2+^|Center Footer+2+>|Right Footer+2+^|Center Footer |+|===+```++Adjust row span for empty rows and handle empty rows in general+```+% pandoc -f native -t asciidoc+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "Header" , Space , Str "1-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 3)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "Header" , Space , Str "1-3" ] ]+ ]+ , Row ( "" , [] , [] ) []+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header" , Space , Str "2-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header" , Space , Str "2-3" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 3)+ (ColSpan 2)+ [ Plain [ Str "Body" , Space , Str "1-1/2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 5)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "5" ] ]+ ]+ , Row ( "" , [] , [] ) []+ , Row ( "" , [] , [] ) []+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "2-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "2-2" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "3-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "3-2" ] ]+ ]+ , Row ( "" , [] , [] ) []+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 5)+ (ColSpan 1)+ [ Plain+ [ Str "Span" , Space , Str "5" ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "Footer" , Space , Str "1-2" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 2)+ [ Plain+ [ Str "Span" , Space , Str "2" ]+ ]+ ]+ , Row ( "" , [] , [] ) []+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "Footer" , Space , Str "3-2/3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "Footer" , Space , Str "4-2/3" ] ]+ ]+ ])+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "1-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "1-2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 3)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "4" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 5)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "2-2" ] ]+ ]+ , Row+ ( "" , [] , [] ) []+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "3-2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "3-3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "4-2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "4-3" ] ]+ ]+ , Row+ ( "" , [] , [] ) []+ , Row+ ( "" , [] , [] ) []+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "6-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "6-2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "6-3" ] ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Footer" , Space , Str "1-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 8)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "8" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Footer" , Space , Str "1-3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 3)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Footer" , Space , Str "2-3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "2" ] ]+ ]+ , Row ( "" , [] , [] ) []+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Footer" , Space , Str "4-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Footer" , Space , Str "4-3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Footer" , Space , Str "5-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 3)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "2" ] ]+ ]+ , Row ( "" , [] , [] ) []+ ])+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [ "rowspan-cell" ] , [] )+ AlignDefault+ (RowSpan 6)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "6" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "1-2" ] ]+ , Cell+ ( "" , [ "rowspan-cell" ] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "2" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [ "rowspan-cell" ] , [] )+ AlignDefault+ (RowSpan 3)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [ "rowspan-cell" ] , [] )+ AlignDefault+ (RowSpan 4)+ (ColSpan 1)+ [ Plain [ Str "Span" , Space , Str "4" ] ]+ ]+ , Row ( "" , [] , [] ) []+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "3-2" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "4-2" ] ]+ ]+ , Row ( "" , [] , [] ) []+ , Row ( "" , [] , [] ) []+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+^D+[cols=",,",options="header,footer",]+|===+|Header 1-1 |Span 3 |Header 1-3+|Header 2-1 | |Header 2-3+2+|Body 1-1/2 .3+|Span 5+|Body 2-1 |Body 2-2+|Body 3-1 |Body 3-2+| | |+.3+|Span 5 2+|Footer 1-2+2+|Span 2+2+|Footer 3-2/3+| 2+|Footer 4-2/3+|===++[cols=",,",options="footer",]+|===+|Body 1-1 |Body 1-2 .2+|Span 4+.3+|Span 5 |Body 2-2+|Body 3-2 |Body 3-3+|Body 4-2 |Body 4-3+| | |+|Body 6-1 |Body 6-2 |Span 6-3+|Footer 1-1 .5+|Span 8 |Footer 1-3+.2+|Span 3 |Footer 2-3+|Span 2+|Footer 4-1 |Footer 4-3+|Footer 5-1 |Span 3+|Span 2 | |+|===++[cols=",,",]+|===+.5+|Span 6 |Body 1-2 .2+|Span 2+.2+|Span 3+.3+|Span 4+|Body 3-2+|Body 4-2+| | |+| | |+|===+```
@@ -27,7 +27,12 @@ % pandoc -f markdown -t org -C --bibliography command/biblio.bib - [@item1] ^D-- [cite:@item1]+- (Doe 2005)++<<refs>>++<<ref-item1>>+Doe, John. 2005. /First Book/. Cambridge University Press. ``` @@ -40,7 +45,7 @@ <<refs>> <<ref-item1>>-Doe, John. 2005. /First Book/. Cambridge: Cambridge University Press.+Doe, John. 2005. /First Book/. Cambridge University Press. ``` ```@@ -55,13 +60,13 @@ - [cite:@item1; @item2] - [cite:see @item1; @item2] ^D-- @item1-- @item1 [p. 12]-- @item1 [p.12; see also @item2]-- [@item1]-- [-@item1]-- [see @item1 p. 12]-- [see @item1 p. 12 and *passim*]-- [@item1; @item2]-- [see @item1; @item2]+- @item1+- @item1 [p. 12]+- @item1 [p.12; see also @item2]+- [@item1]+- [-@item1]+- [see @item1 p. 12]+- [see @item1 p. 12 and *passim*]+- [@item1; @item2]+- [see @item1; @item2] ```
@@ -0,0 +1,39 @@+```+% pandoc -f rst -t native+.. figure:: example.png+ :figclass: foo bar+ :align: right+ :width: 1in++ This is a caption.+^D+[ Figure+ ( "" , [ "foo" , "bar" , "align-right" ] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "caption."+ ]+ ])+ [ Plain+ [ Image+ ( "" , [] , [ ( "width" , "1in" ) ] )+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "caption."+ ]+ ( "example.png" , "" )+ ]+ ]+]+```
@@ -0,0 +1,70 @@+```+% pandoc -t native -f latex+\begin{equation*}+[d,\delta]=0.+\end{equation*}+^D+[ Para+ [ Math+ DisplayMath+ "\\begin{equation*}\n[d,\\delta]=0.\n\\end{equation*}"+ ]+]+```++```+% pandoc -t native -f latex+\begin{table}[htb]+ \begin{tabular}{|c|c|}+ $W$ & rel. err. \\[0mm]+ [$\mu$m] & [\%]\\+ \end{tabular}+\end{table}+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignCenter , ColWidthDefault )+ , ( AlignCenter , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Math InlineMath "W" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "rel." , Space , Str "err." ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "[" , Math InlineMath "\\mu" , Str "m]" ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "[%]" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+```
@@ -5,7 +5,7 @@ - two ^D <ul>-<li>one </li>+<li>one</li> <li>two</li> </ul> ```
@@ -0,0 +1,28 @@+```+% pandoc -t revealjs+# Slide++::: columns+:::: column+Left column+::::++. . .++:::: column+Right column+::::+:::+^D+<section id="slide" class="slide level1">+<h1>Slide</h1>+<div class="columns">+<div class="column">+<p>Left column</p>+</div><div class="fragment"><div class="column">+<p>Right column</p>+</div></div>+</div>+</section>++```
@@ -0,0 +1,62 @@+```+% pandoc -f bibtex -t csljson+@misc{doe,+ author = "Jane Doe",+ title = "Work",+ year = "2021",+ url = "%20and%20"+}+^D+[+ {+ "URL": "%20and%20",+ "author": [+ {+ "family": "Doe",+ "given": "Jane"+ }+ ],+ "id": "doe",+ "issued": {+ "date-parts": [+ [+ 2021+ ]+ ]+ },+ "title": "Work",+ "type": ""+ }+]+```+```+% pandoc -f bibtex -t csljson+@misc{doe,+ author = "Jane Doe",+ title = "Work",+ year = "2021",+ doi = "%20and%20"+}+^D+[+ {+ "DOI": "%20and%20",+ "author": [+ {+ "family": "Doe",+ "given": "Jane"+ }+ ],+ "id": "doe",+ "issued": {+ "date-parts": [+ [+ 2021+ ]+ ]+ },+ "title": "Work",+ "type": ""+ }+]+```
binary file changed (absent → 11923 bytes)
@@ -0,0 +1,5 @@+```+% pandoc command/7691.docx+^D+<p>Some text</p>+```
@@ -11,14 +11,14 @@ <col style="width: 33%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>aaaaaaaaaaaa</th> <th>bbbbb</th> <th>ccccccccccc</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td></td> <td></td> <td>cccccccccc cccccccccc cccccccccc cccccccccc cccccccccc
@@ -0,0 +1,56 @@+```+% pandoc -f markdown+mark -t html+==Hi==+^D+<p><mark>Hi</mark></p>+```++```+% pandoc -f markdown+mark -t latex+==Hi==+^D+\hl{Hi}+```++```+% pandoc -f markdown+mark -t rst+==Hi==+^D+:mark:`Hi`+```++```+% pandoc -f html -t markdown+mark+<mark>Hi</mark>+^D+==Hi==+```++```+% pandoc -f html -t markdown+<mark>Hi</mark>+^D+[Hi]{.mark}+```++```+% pandoc -f rst -t markdown+mark+:mark:`Hi`+^D+==Hi==+```++```+% pandoc -f markdown+mark -t docx -o - | pandoc -f docx -t markdown+mark+==Hi==+^D+==Hi==+```++```+% pandoc -f latex -t markdown+mark+\hl{Hi}+^D+==Hi==+```+
@@ -0,0 +1,59 @@+Here the thing to remember is that block level structure indications+take precedence over inline level structure indications:++```+% pandoc+Term+: Def+<!--+: comment def+-->+^D+<dl>+<dt>Term</dt>+<dd>+Def <!–+</dd>+<dd>+comment def –>+</dd>+</dl>+```++```+% pandoc+Term+: Def+test <!--+: comment def+and -->+^D+<dl>+<dt>Term</dt>+<dd>+Def test <!–+</dd>+<dd>+comment def and –>+</dd>+</dl>+```++```+% pandoc+Term+: Def+`code+: comment def+more code`+^D+<dl>+<dt>Term</dt>+<dd>+Def `code+</dd>+<dd>+comment def more code`+</dd>+</dl>+```
@@ -7,14 +7,14 @@ <col style="width: 20%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>aaa</th> <th>bbb</th> <th>ccc</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi.</td> <td></td>@@ -23,9 +23,9 @@ </tbody> </table> ^D-| aaa | bbb | ccc |+| aaa | bbb | ccc | |---------------|------------------------------------------|---------------|-| Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. | | ccc |+| Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. | | ccc | ``` @@ -45,9 +45,9 @@ </tr> </table> ^D-| aaa | bbb | ccc |-|-------------------------------------------------------------------------------------------------------------|-----|-----|-| Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. | | ccc |+| aaa | bbb | ccc |+|----|----|----|+| Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. | | ccc | ``` @@ -60,14 +60,14 @@ <col style="width: 20%" /> </colgroup> <thead>-<tr class="header">+<tr> <th>aaa</th> <th>bbb</th> <th>ccc</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi.</td> <td>bbb</td>@@ -76,8 +76,8 @@ </tbody> </table> ^D-| aaa | bbb | ccc |-|-------------------------------------------------------------------------------------------------------------|-----|-----|+| aaa | bbb | ccc |+|----|----|----| | Consequat nisi sit amet nibh. Nunc mi tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. | bbb | ccc | ```
@@ -10,13 +10,12 @@ ok ^D-\hypertarget{section}{%-\section{section}\label{section}}+\section{section}\label{section} \note{my note} \begin{frame}{slide}-\protect\hypertarget{slide}{}+\protect\phantomsection\label{slide} ok \end{frame} ```
@@ -2,6 +2,6 @@ % pandoc -s -t native --data-dir=command/7861 --metadata-file=../../7861.yaml Hello ^D-2> Could not find metadata file ../../7861.yaml+2> Could not find metadata file '../../7861.yaml' => 98 ```
@@ -10,10 +10,17 @@ Text ^D [ Div- ( "" , [] , [ ( "data-pos" , "8:1-9:1" ) ] )+ ( ""+ , []+ , [ ( "wrapper" , "1" ) , ( "data-pos" , "8:1-9:1" ) ]+ ) [ Para [ Span- ( "" , [] , [ ( "data-pos" , "8:1-8:5" ) ] ) [ Str "Text" ]+ ( ""+ , []+ , [ ( "wrapper" , "1" ) , ( "data-pos" , "8:1-8:5" ) ]+ )+ [ Str "Text" ] ] ] ]
@@ -6,7 +6,7 @@ ^D <table> <tbody>-<tr class="odd">+<tr> <td style="text-align: right; padding-right: 4px;">a</td> </tr> </tbody>
@@ -22,7 +22,7 @@ ) [ Header 1- ( "chapter-1" , [] , [ ( "number" , "1" ) ] )+ ( "" , [] , [ ( "number" , "1" ) ] ) [ Str "Chapter" , Space , Str "1" ] , Para [ Str "Here"
@@ -7,15 +7,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>@@ -31,15 +31,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>@@ -66,15 +66,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>@@ -90,15 +90,15 @@ ^D <table> <thead>-<tr class="header">+<tr> <th>single column table</th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td>item 1</td> </tr>-<tr class="even">+<tr> <td>item 2</td> </tr> </tbody>
@@ -0,0 +1,10 @@+```+% pandoc -d command/8024a.yaml -t markdown+Hello, if this works the text should be wrapped.+^D+Hello, if this+works the text+should be+wrapped.++```
@@ -0,0 +1,2 @@+defaults: ${.}/8024b.yaml+
@@ -0,0 +1,3 @@+wrap: auto+columns: 15+
@@ -7,6 +7,7 @@ ^D https://docs.oracle.com/database/121/BRADV/rcmxplat.htm#BRADV724[12.1 manual, Database Backup and Recovery User’s Guide:-[.enumeration_chapter]#Chapter 28# Transporting Data Across Platforms,-Steps to Transport a Database to a Different Platform Using Backup Sets]+[.enumeration_chapter]#Chapter 28# Transporting Data Across+Platforms, Steps to Transport a Database to a Different Platform+Using Backup Sets] ```
@@ -18,19 +18,19 @@ ^D <table> <thead>-<tr class="header">+<tr> <th><p>Header text</p></th> <th><p>Header text</p></th> <th><p>Header text</p></th> </tr> </thead> <tbody>-<tr class="odd">+<tr> <td><p>Example</p></td> <td><p>Example</p></td> <td><p>Example</p></td> </tr>-<tr class="even">+<tr> <td><p>Example</p></td> <td><p>Example</p></td> <td><p>Example</p></td>
@@ -0,0 +1,41 @@+# TOC in gfm contains no HTML by default+```+% pandoc --to=gfm --toc --standalone+# Head++Content+^D+- [Head](#head)++# Head++Content+```++# Same in Markdown if link_attributes extension is disabled+```+% pandoc --to=markdown-link_attributes --toc --standalone+# Head++Content+^D+- [Head](#head)++# Head++Content+```++# IDs are added to TOC with the "attributes" CommonMark extension+```+% pandoc --to=commonmark+gfm_auto_identifiers+attributes --toc -s+# Nam a sapien++Lorem ipsum dolor sit amet, consectetuer adipiscing elit.+^D+- [Nam a sapien](#nam-a-sapien){#toc-nam-a-sapien}++# Nam a sapien++Lorem ipsum dolor sit amet, consectetuer adipiscing elit.+```
@@ -11,14 +11,11 @@ <li>L4</li> </ul> ^D-- L1--- L2--- - L3.1- - L3.2--- L4+- L1+- L2+ - L3.1+ - L3.2+- L4 ``` Nested ordered lists@@ -34,10 +31,8 @@ </ol> ^D 1. L1- 2. L2--3. 1. L3.1+ 1. L3.1 2. L3.2 ``` @@ -53,10 +48,8 @@ </ol> </ul> ^D-- L1--- L2--- 1. L3.1- 2. L3.2+- L1+- L2+ 1. L3.1+ 2. L3.2 ```
@@ -1,19 +0,0 @@-```-% pandoc -f native -t revealjs-[ Null-, Header- 2- ( "header-after-null" , [] , [] )- [ Str "Header"- , Space- , Str "after"- , Space- , Str "null"- ]-]-^D-<section id="header-after-null" class="title-slide slide level2">-<h2>Header after null</h2>--</section>-```
@@ -0,0 +1,44 @@+````+% pandoc -t native+```yaml {#id}+some: code+```+^D+[ CodeBlock ( "id" , [ "yaml" ] , [] ) "some: code" ]+````++````+% pandoc -t native+```yaml {.class #id}+some: code+```+^D+[ CodeBlock+ ( "id" , [ "yaml" , "class" ] , [] ) "some: code"+]+````++<!-- Inline code sections at the start of the line should not be mistaken for code blocks -->+````+% pandoc -t native+```ab```+^D+[ Para [ Code ( "" , [] , [] ) "ab" ] ]+````++````+% pandoc -t native+```ab```{.class}+^D+[ Para [ Code ( "" , [ "class" ] , [] ) "ab" ] ]+````++<!-- Illegal language identifiers should be treated as inline code for now -->+````+% pandoc -t native+``` foo}{.bar}+test+```+^D+[ Para [ Code ( "" , [] , [] ) "foo}{.bar} test" ] ]+````
@@ -37,3 +37,15 @@ Main text ```++Uppercase ABSTRACT environment is not moved to metadata.+```+% pandoc --from=org --to=markdown --standalone+#+BEGIN_ABSTRACT+Some text.+#+END_ABSTRACT+^D+::: ABSTRACT+Some text.+:::+```
@@ -18,15 +18,15 @@ <col style="width: 44%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td>Some text</td> <td><span class="class1 class2 class3">text</span></td> </tr>-<tr class="even">+<tr> <td>Some text</td> <td><span class="class1 class2 class3">text</span></td> </tr>-<tr class="odd">+<tr> <td>Some text</td> <td><span class="class1 class2 class3">text</span></td> </tr>
@@ -6,9 +6,11 @@ ^D \begin{longtable}[]{@{}ll@{}} \caption{}\label{test}\tabularnewline-\toprule()+\toprule\noalign{}+\endfirsthead \endhead+\bottomrule\noalign{}+\endlastfoot one & two \\-\bottomrule() \end{longtable} ```
@@ -0,0 +1,23 @@+```+% pandoc -f latex+\newenvironment{topics}{+\newcommand{\topic}[2]{ \item{##1 / ##2} }+Topics:+\begin{itemize}+}+{+\end{itemize}+}++\begin{topics}+\topic{Foo}{Bar}+\topic{Baz}{Bim}+\end{topics}+^D+<p>Topics:</p>+<ul>+<li><p><span>Foo / Bar</span></p></li>+<li><p><span>Baz / Bim</span></p></li>+</ul>+```+
@@ -0,0 +1,13 @@+```+% pandoc -f native -t html+Link ("",["", "", ""],[]) [Str "foo"] ("https://example.com","")+^D+<a href="https://example.com">foo</a>+```++```+% pandoc -f native -t markdown+Link ("",["", "", ""],[]) [Str "foo"] ("https://example.com","")+^D+[foo](https://example.com){}+```
@@ -0,0 +1,20 @@+```+% pandoc -t native+Wow![@legras_michel_2010]+^D+[ Para+ [ Str "Wow!"+ , Cite+ [ Citation+ { citationId = "legras_michel_2010"+ , citationPrefix = []+ , citationSuffix = []+ , citationMode = NormalCitation+ , citationNoteNum = 2+ , citationHash = 0+ }+ ]+ [ Str "[@legras_michel_2010]" ]+ ]+]+```
@@ -0,0 +1,33 @@+```+% pandoc -t opendocument -s++---+title: |+ This *is* \+ a test+author: Someone+---++Testing.+^D+<?xml version="1.0" encoding="utf-8" ?>+<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.3">+ <office:font-face-decls>+ <style:font-face style:name="Courier New" style:font-family-generic="modern" style:font-pitch="fixed" svg:font-family="'Courier New'" />+ </office:font-face-decls>+ <office:automatic-styles>+ <style:style style:name="fr2" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" style:wrap="none" /></style:style>+ <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" /></style:style>+ </office:automatic-styles>+<office:body>+<office:text>+<text:p text:style-name="Title">This+<text:span text:style-name="Emphasis">is</text:span><text:line-break />a+test</text:p>+<text:p text:style-name="Author">Someone</text:p>+<text:p text:style-name="Text_20_body">Testing.</text:p>+</office:text>+</office:body>+</office:document-content>+```+
@@ -0,0 +1,41 @@+```+% pandoc -f markdown -t html5++------+-------++| Item | Price |++======+=======++| Eggs | 5£ |++------+-------++| Spam | 3£ |++======+=======++| Sum | 8£ |++======+=======++^D+<table style="width:21%;">+<colgroup>+<col style="width: 9%" />+<col style="width: 11%" />+</colgroup>+<thead>+<tr>+<th>Item</th>+<th>Price</th>+</tr>+</thead>+<tbody>+<tr>+<td>Eggs</td>+<td>5£</td>+</tr>+<tr>+<td>Spam</td>+<td>3£</td>+</tr>+</tbody><tfoot>+<tr>+<td>Sum</td>+<td>8£</td>+</tr>+</tfoot>++</table>+```
@@ -0,0 +1,15 @@+```+% pandoc -t html+# Title++test++. . .++test+^D+<h1 id="title">Title</h1>+<p>test</p>+<p>. . .</p>+<p>test</p>+```
@@ -0,0 +1,6 @@+```+% pandoc -f org -t markdown+some text cite:&long-2004-tecton-evolut+^D+some text @long-2004-tecton-evolut+```
@@ -0,0 +1,49 @@+```+% pandoc -t commonmark -f html+<table>+<tbody>+<tr>+<td title="this+ ++breaks">hello</td>+</tr>+</tbody>+</table>+^D+<table>+<tbody>+<tr>+<td title="this+ +breaks">hello</td>+</tr>+</tbody>+</table>+```++````+% pandoc -t commonmark -f markdown+``` {=html}+<table>+<tbody>+<tr>+<td title="this+ ++breaks">hello</td>+</tr>+</tbody>+</table>+```+^D+<table>+<tbody>+<tr>+<td title="this+ +breaks">hello</td>+</tr>+</tbody>+</table>+````
@@ -0,0 +1,90 @@+```+% pandoc -t jats -s+---+title: |-+ My\+ document+...++# Section\+with line break++Paragraph\+with line break++--------+A B+--- ---+1\ 3+2 4++*1\ 5\+2* 6++ 7+--------++^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>My<break/>document</article-title>+</title-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>+<sec id="section">+ <title>Section<break/></title>+ <p>with line break</p>+ <p>Paragraph+ with line break</p>+ <table-wrap>+ <table>+ <colgroup>+ <col width="7%" />+ <col width="7%" />+ </colgroup>+ <thead>+ <tr>+ <th align="left">A</th>+ <th align="left">B</th>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td align="left">1<break/>2</td>+ <td align="left">3 4</td>+ </tr>+ <tr>+ <td align="left"><italic>1+ 2</italic></td>+ <td align="left">5<break/>6</td>+ </tr>+ <tr>+ <td align="left"></td>+ <td align="left">7</td>+ </tr>+ </tbody>+ </table>+ </table-wrap>+</sec>+</body>+<back>+</back>+</article>+```
@@ -0,0 +1,38 @@+```+% pandoc -f markdown -t html --citeproc+---+title: test+nocite: '[@*]'+references:+- author:+ - family: Fekete+ given: Jean-Daniel+ - family: Freire+ given: Juliana+ DOI: 10.1109/MCG.2020.3006412+ id: feketeExploringReproducibilityVisualization2020+ ISSN: 1558-1756+ issue: 5+ issued: 2020-09+ page: 108-119+ source: IEEE Xplore+ title: Exploring Reproducibility in Visualization+ container-title: IEEE Computer Graphics and Applications+ type: article-journal+ volume: 40+---++## References+^D+<h2 class="unnumbered" id="references">References</h2>+<div id="refs" class="references csl-bib-body hanging-indent"+role="list">+<div id="ref-feketeExploringReproducibilityVisualization2020"+class="csl-entry" role="listitem">+Fekete, Jean-Daniel, and Juliana Freire. 2020. <span>“Exploring+Reproducibility in Visualization.”</span> <em>IEEE Computer Graphics and+Applications</em> 40 (5): 108–19. <a+href="https://doi.org/10.1109/MCG.2020.3006412">https://doi.org/10.1109/MCG.2020.3006412</a>.+</div>+</div>+```
@@ -0,0 +1,54 @@+```+% pandoc --citeproc -t jats -s+---+reference-section-title: Bibliography+csl: command/apa.csl+references:+- author:+ - family: Doe+ given: John+ id: test+ issued:+ date-parts:+ - - 2006+ title: Test+ type: 'article-journal'+ volume: 81+---++@test+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<permissions>+</permissions>+</article-meta>+</front>+<body>+<p>Doe (2006)</p>+</body>+<back>+<ref-list>+ <title>Bibliography</title>+ <ref id="ref-test">+ <mixed-citation>Doe, J. (2006). Test,+ <italic>81</italic>.</mixed-citation>+ </ref>+</ref-list>+</back>+</article>++```
@@ -0,0 +1,50 @@+```+% pandoc -f jats -t native -s+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<permissions>+</permissions>+</article-meta>+</front>+<body>+<p>Doe (2006)</p>+</body>+<back>+<ref-list>+ <title>Bibliography</title>+ <ref id="ref-test">+ <mixed-citation>Doe, J. (2006). Test,+ <italic>81</italic>.</mixed-citation>+ </ref>+</ref-list>+</back>+</article>+^D+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "references"+ , MetaList+ [ MetaMap (fromList [ ( "id" , MetaString "test" ) ]) ]+ )+ ]+ }+ [ Para [ Str "Doe" , Space , Str "(2006)" ]+ , Header 1 ( "" , [] , [] ) [ Str "Bibliography" ]+ , Div ( "refs" , [] , [] ) []+ ]+```
@@ -0,0 +1,31 @@+```+% pandoc -f man -t rst+LC_*+^D+LC\_\*+```++These examples of things that don't require escaping are taken+from the RST documentation:++```+% pandoc -f native -t rst+[Para [Str "2*x a**b O(N**2) e**(x*y) f(x)*f(y) a|b"]+,Para [Str "a**b O(N**2) e**(x*y) f(x)*f(y)"]+]+^D+2*x a**b O(N**2) e**(x*y) f(x)*f(y) a|b++a**b O(N**2) e**(x*y) f(x)*f(y)+```++These examples of things that do require escaping are taken+from the RST documentation:++```+% pandoc -f native -t rst+Str "*4, class_, *args, **kwargs, `TeX-quoted', *ML, *.txt"+^D+\*4, class\_, \*args, \**kwargs, \`TeX-quoted', \*ML, \*.txt+```+
@@ -0,0 +1,52 @@+```+% pandoc --toc -s -t markdown+::: {.cell .markdown id="6u8qXoeFGdqt"}+# Summary+> Expand to see summary++## Overview and Explanation+:::++# Details++## inner 1+text++## inner 2++### inner inner 1++## inner 3+text+^D+- [Summary](#summary){#toc-summary}+ - [Overview and+ Explanation](#overview-and-explanation){#toc-overview-and-explanation}+- [Details](#details){#toc-details}+ - [inner 1](#inner-1){#toc-inner-1}+ - [inner 2](#inner-2){#toc-inner-2}+ - [inner inner 1](#inner-inner-1){#toc-inner-inner-1}+ - [inner 3](#inner-3){#toc-inner-3}++::: {#6u8qXoeFGdqt .cell .markdown}+# Summary++> Expand to see summary++## Overview and Explanation+:::++# Details++## inner 1++text++## inner 2++### inner inner 1++## inner 3++text+```
@@ -0,0 +1,44 @@+```+% pandoc -f markdown -t asciidoc+[](http://www.apache.org/licenses/LICENSE-2.0)+^D+http://www.apache.org/licenses/LICENSE-2.0[image:https://img.shields.io/badge/License-Apache%202.0-blue.svg[alt,title="title"]]+```++```+% pandoc -f markdown -t docbook+[](http://www.apache.org/licenses/LICENSE-2.0)+^D+<para>+ <link xlink:href="http://www.apache.org/licenses/LICENSE-2.0"><inlinemediaobject>+ <imageobject>+ <objectinfo>+ <title>title</title>+ </objectinfo>+ <imagedata fileref="https://img.shields.io/badge/License-Apache%202.0-blue.svg" />+ </imageobject>+ <textobject>+ <phrase>alt</phrase>+ </textobject>+ </inlinemediaobject></link>+</para>+```++```+% pandoc -f docbook -t markdown+<para>+ <link xlink:href="http://www.apache.org/licenses/LICENSE-2.0"><inlinemediaobject>+ <imageobject>+ <objectinfo>+ <title>title</title>+ </objectinfo>+ <imagedata fileref="https://img.shields.io/badge/License-Apache%202.0-blue.svg" />+ </imageobject>+ <textobject>+ <phrase>alt</phrase>+ </textobject>+ </inlinemediaobject></link>+</para>+^D+[](http://www.apache.org/licenses/LICENSE-2.0)+```
@@ -0,0 +1,55 @@+# Unnumbered and unlisted headings in ConTeXt++```+% pandoc --to=context+# Preface {.unlisted -}++Nullam rutrum.++# Introduction++Nullam eu ante vel est convallis dignissim.++# Methods++Sed diam. Nulla posuere. Praesent fermentum tempor tellus. Nam+vestibulum accumsan nisl. Nam vestibulum accumsan nisl.++# References {-}+^D+\startsubject[title={Preface},reference={preface},number=no,incrementnumber=no]++Nullam rutrum.++\stopsubject++\startsectionlevel[title={Introduction},reference={introduction}]++Nullam eu ante vel est convallis dignissim.++\stopsectionlevel++\startsectionlevel[title={Methods},reference={methods}]++Sed diam. Nulla posuere. Praesent fermentum tempor tellus. Nam+vestibulum accumsan nisl. Nam vestibulum accumsan nisl.++\stopsectionlevel++\startsectionlevel[title={References},reference={references},number=no,incrementnumber=no]++\stopsectionlevel+```++## Semantic Headings with `--top-level-division`+```+% pandoc --to=context --top-level-division=chapter+# Bibliography {-}+None+^D+\startchapter[title={Bibliography},reference={bibliography},number=no,incrementnumber=no]++None++\stopchapter+```
@@ -0,0 +1,14 @@+```+% pandoc -f textile -t native+p>.++p=. Links:+^D+[ Div+ ( "" , [] , [ ( "style" , "text-align:right;" ) ] )+ [ Para [] ]+, Div+ ( "" , [] , [ ( "style" , "text-align:center;" ) ] )+ [ Para [ Str "Links:" ] ]+]+```
@@ -0,0 +1,90 @@+```+% pandoc -f markdown -s -t biblatex+---+references:+- id: Larsson_2016+ author:+ - family: Larsson+ given: Johan+ citation-key: Larsson_2016+ issued:+ - year: 2016+ medium: Windows+ title: 'qualpalr: Automatic Generation of Qualitative Color Palettes'+ type: software+ URL: https://cran.r-project.org/package=qualpalr+ version: 0.3.1+...+^D+@software{Larsson_2016,+ author = {Larsson, Johan},+ title = {Qualpalr: {Automatic} {Generation} of {Qualitative} {Color}+ {Palettes}},+ version = {0.3.1},+ date = {2016},+ url = {https://cran.r-project.org/package=qualpalr}+}+```++```+% pandoc -f markdown -s -t bibtex+---+references:+- id: Larsson_2016+ author:+ - family: Larsson+ given: Johan+ citation-key: Larsson_2016+ issued:+ - year: 2016+ medium: Windows+ title: 'qualpalr: Automatic Generation of Qualitative Color Palettes'+ type: software+ URL: https://cran.r-project.org/package=qualpalr+ version: 0.3.1+...+^D+@misc{Larsson_2016,+ author = {Larsson, Johan},+ title = {Qualpalr: {Automatic} {Generation} of {Qualitative} {Color}+ {Palettes}},+ year = {2016},+ url = {https://cran.r-project.org/package=qualpalr}+}+```++```+% pandoc -f biblatex -s -t csljson+@software{Larsson_2016,+ author = {Larsson, Johan},+ title = {Qualpalr: {Automatic} {Generation} of {Qualitative} {Color}+ {Palettes}},+ version = {0.3.1},+ date = {2016},+ url = {https://cran.r-project.org/package=qualpalr}+}+^D+[+ {+ "URL": "https://cran.r-project.org/package=qualpalr",+ "author": [+ {+ "family": "Larsson",+ "given": "Johan"+ }+ ],+ "id": "Larsson_2016",+ "issued": {+ "date-parts": [+ [+ 2016+ ]+ ]+ },+ "title": "Qualpalr: Automatic Generation of Qualitative Color Palettes",+ "title-short": "Qualpalr",+ "type": "software",+ "version": "0.3.1"+ }+]+```
@@ -0,0 +1,20 @@+```+% pandoc -t man+SEE ALSO+========++* [Milk](https://en.wikipedia.org/wiki/Milk)+* [EBNF](https://en.wikipedia.org/wiki/Extended_Backus–Naur_form)+^D+.SH SEE ALSO+.IP \(bu 2+\c+.UR https://en.wikipedia.org/wiki/Milk+Milk+.UE \c+.IP \(bu 2+\c+.UR https://en.wikipedia.org/wiki/Extended_Backus–Naur_form+EBNF+.UE \c+```
@@ -0,0 +1,16 @@+# Conversion of icon-like sequences followed by alphanum char+## to Jira+```+% pandoc -t jira+:P :P_ :PA :Pa :P2+^D+\:P \:P\_ :PA :Pa :P2+```++## from jira+```+% pandoc -f jira -t markdown+\:PA+^D+\\:PA+```
@@ -0,0 +1,27 @@+# Round-tripping tags in org+```+% pandoc --from org --to org --columns=72+* Header with tag :tag:+^D+* Header with tag :tag:+:PROPERTIES:+:CUSTOM_ID: header-with-tag+:END:+```++Multiple tags+```+% pandoc --from org-auto_identifiers --to org --columns=78+* Header with two tags :first:second:+^D+* Header with two tags :first:second:+```++Check that long headings work with tags++```+% pandoc --from org-auto_identifiers --to org --columns=40+* Header with tag and more words which are not that interesting :tag:+^D+* Header with tag and more words which are not that interesting :tag:+```
@@ -0,0 +1,11 @@+```+% pandoc -f html -t texinfo+<html>+foo <code>bar <var>baz</var> bar</code> foo+</html>+^D+@node Top+@top Top++foo @code{bar }@code{@var{baz}}@code{ bar} foo+```
@@ -0,0 +1,7 @@+```+% pandoc -f latex -t plain+\newenvironment{myenv}[1]{Open#1}{Close}+\begin{myenv}{x}Hello\end{myenv}+^D+OpenxHelloClose+```
@@ -0,0 +1,34 @@+```+% pandoc -f markdown -s -t bibtex+---+nocite: "[@*]"+references:+- id: mcdowell:why+ title: |+ Why is Sellars's Essay Called "Empiricism and the Philosophy of Mind"?+ author:+ - family: McDowell+ given: John+ journal: Proceedings of the Aristotelian Society+ type: chapter+ container-title: 'Empiricism, Perceptual Knowledge, Normativity, and Realism: Essays on Wilfrid Sellars'+ editor:+ - family: deVries+ given: Willem A.+ issued: 2009+ publisher: Oxford University Press+ publisher-place: Oxford+...+^D+@incollection{mcdowell:why,+ author = {McDowell, John},+ editor = {deVries, Willem A.},+ publisher = {Oxford University Press},+ title = {Why Is {Sellars’s} {Essay} {Called} “{Empiricism} and the+ {Philosophy} of {Mind}”?},+ booktitle = {Empiricism, Perceptual Knowledge, Normativity, and+ Realism: Essays on Wilfrid Sellars},+ year = {2009},+ address = {Oxford}+}+```
@@ -0,0 +1,22 @@+# Beamer tables must not use longtable footer+```+% pandoc -t beamer+| fruit | price |+|---------|------:|+| apple | 2.05 |+| oranges | 4.25 |+^D+\begin{frame}+{\def\LTcaptype{none} % do not increment counter+\begin{longtable}[]{@{}lr@{}}+\toprule\noalign{}+fruit & price \\+\midrule\noalign{}+\endhead+apple & 2.05 \\+oranges & 4.25 \\+\bottomrule\noalign{}+\end{longtable}+}+\end{frame}+```
@@ -0,0 +1,28 @@+```+% pandoc -t native+My text^[My note]isnot^[Text]+^D+[ Para+ [ Str "My"+ , Space+ , Str "text"+ , Note [ Para [ Str "My" , Space , Str "note" ] ]+ , Str "isnot"+ , Note [ Para [ Str "Text" ] ]+ ]+]++```++```+% pandoc -t native+^[note1]test^[note2]+^D+[ Para+ [ Note [ Para [ Str "note1" ] ]+ , Str "test"+ , Note [ Para [ Str "note2" ] ]+ ]+]++```
@@ -0,0 +1,23 @@+```+% pandoc -f rst -t native+.. role:: py:class(emphasis)++:py:class:`foo`+^D+[ Para [ Emph [ Str "foo" ] ] ]+```++```+% pandoc -f rst -t native+:py:class:`foo`+^D+[ Para+ [ Code+ ( ""+ , [ "interpreted-text" ]+ , [ ( "role" , "py:class" ) ]+ )+ "foo"+ ]+]+```
@@ -0,0 +1,54 @@+# A single pipe is parsed as an empty table+```+% pandoc -f org -t html+|+^D+<table>+<tbody>+<tr>+</tr>+</tbody>+</table>+```+# Accepts an empty org table within a grid table cell++The misaligned pipe in the first row is treated as an empty table.++```+% pandoc -f org -t html++-----+-----+-----+-----------++| | | | |++:====+=====+====:+==========:++| a | b | c | d |++-----+-----+-----+-----------++^D+<table style="width:42%;">+<colgroup>+<col style="width: 8%" />+<col style="width: 8%" />+<col style="width: 8%" />+<col style="width: 16%" />+</colgroup>+<thead>+<tr>+<th style="text-align: left;"></th>+<th></th>+<th style="text-align: right;"></th>+<th style="text-align: right;"><table>+<tbody>+<tr>+</tr>+</tbody>+</table></th>+</tr>+</thead>+<tbody>+<tr>+<td style="text-align: left;">a</td>+<td>b</td>+<td style="text-align: right;">c</td>+<td style="text-align: right;">d</td>+</tr>+</tbody>+</table>+```
@@ -0,0 +1,9 @@+```+% pandoc -f tsv -t gfm+a b c+ 6+^D+| a | b | c |+|-----|-----|-----|+| | | 6 |+```
@@ -0,0 +1,29 @@+```+% pandoc -f docbook -t asciidoc+<informaltable frame="all" rowsep="1" colsep="1">+ <tgroup cols="1">+ <thead>+ <row>+ <entry align="left" valign="top">h1</entry>+ <entry align="left" valign="top">h2</entry>+ </row>+ </thead>+ <tbody>+ <row>+ <entry align="left" valign="top">+ <simpara>!@#$%^&*(){}|~?+-',."<>[]\`</simpara>+ </entry>+ <entry align="left" valign="top">+ <simpara>col 2</simpara>+ </entry>+ </row>+ </tbody>+ </tgroup>+</informaltable>+^D+[cols=",",options="header",]+|===+<|h1 <|h2+<|!@++#++$%^&++*++()++{++}{vbar}~?{plus}-',."++<>[]\`++ <|col 2+|===+```
@@ -0,0 +1,40 @@+```+% pandoc -f docbook -t native+<formalpara xml:id="my_code_id">+<title>Code title</title>+<para>+<programlisting language="bash" linenumbering="unnumbered">echo "hello world!"</programlisting>+</para>+</formalpara>+<example xml:id="my_example_id">+<title>Example title</title>+<simpara>example content</simpara>+</example>+<sidebar xml:id="my_sidebar_id">+<title>Sidebar title</title>+<simpara>sidebar content</simpara>+</sidebar>+^D+[ Div+ ( "my_code_id" , [ "formalpara" ] , [] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Plain [ Str "Code" , Space , Str "title" ] ]+ , CodeBlock ( "" , [ "bash" ] , [] ) "echo \"hello world!\""+ ]+, Div+ ( "my_example_id" , [ "example" ] , [] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Plain [ Str "Example" , Space , Str "title" ] ]+ , Para [ Str "example" , Space , Str "content" ]+ ]+, Div+ ( "my_sidebar_id" , [ "sidebar" ] , [] )+ [ Div+ ( "" , [ "title" ] , [] )+ [ Plain [ Str "Sidebar" , Space , Str "title" ] ]+ , Para [ Str "sidebar" , Space , Str "content" ]+ ]+]+```
@@ -0,0 +1,14 @@+# Include Jira panel title in resulting div+```+% pandoc -f jira -t html+{panel:title=This is the title|titleBGColor=#cccccc|bgColor=#eeeeee}+Panel content+{panel}+^D+<div class="panel" data-titleBGColor="#cccccc" data-bgColor="#eeeeee">+<div class="panelheader">+<strong>This is the title</strong>+</div>+<p>Panel content</p>+</div>+```
@@ -0,0 +1,12 @@+# Org figures should be rendered implicit figures++```+% pandoc -f org -t markdown+implicit_figures+#+label: fig:bsdd-graphql-voyager-orig-detail+#+caption: Original bSDD GraphQL Schema: Detail of Classification and ClassificationProperty+[[./Classification-ClassificationProperty.png]]+^D+{#fig:bsdd-graphql-voyager-orig-detail}++```
@@ -0,0 +1,118 @@+```+% pandoc -f html-native_spans -t native+<table>+<tr>+<td>+ <p><span class="foo">a</span> <span class="bar">b</span></p>+</td>+</tr>+</table>+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault ) ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "a" , Space , Str "b" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]++```++```+% pandoc -f html-native_spans+raw_html -t native+<table>+<tr>+<td>+ <p><span class="foo">a</span> <span class="bar">b</span></p>+</td>+</tr>+</table>+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault ) ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ RawInline (Format "html") "<span class=\"foo\">"+ , Str "a"+ , RawInline (Format "html") "</span>"+ , Space+ , RawInline (Format "html") "<span class=\"bar\">"+ , Str "b"+ , RawInline (Format "html") "</span>"+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]++```++```+% pandoc -f html -t native+<table>+<tr>+<td>+ <p><span class="foo">a</span> <span class="bar">b</span></p>+</td>+</tr>+</table>+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault ) ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span ( "" , [ "foo" ] , [] ) [ Str "a" ]+ , Space+ , Span ( "" , [ "bar" ] , [] ) [ Str "b" ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]++```
@@ -0,0 +1,6 @@+```+% pandoc -f native -t mediawiki+[Link ("",[],[]) [Link ("",[],[]) [Str "test"] ("https://bar.example.com",""),Str "Test"] ("https://foo.example.com","")]+^D+[https://foo.example.com <span>test</span>Test]+```
@@ -0,0 +1,52 @@+# Alt text on images++```+% pandoc -f latex -t native+\documentclass[12pt]{article}+\usepackage{graphicx}+\begin{document}+Sample text+\begin{figure}[ht]+ \includegraphics[alt={Upside down painting},width=0.5\textwidth]{New_York_City_I.jpg}+ \caption{New York City by Piet Mondrian (Wikipedia)}+ \label{fig:Mondrian}+\end{figure}+\includegraphics[alt={Face of a mandrill}]{mandrill.jpg}+\end{document}+^D+[ Para [ Str "Sample" , Space , Str "text" ]+, Figure+ ( "fig:Mondrian" , [] , [ ( "latex-placement" , "ht" ) ] )+ (Caption+ Nothing+ [ Plain+ [ Str "New"+ , Space+ , Str "York"+ , Space+ , Str "City"+ , Space+ , Str "by"+ , Space+ , Str "Piet"+ , Space+ , Str "Mondrian"+ , Space+ , Str "(Wikipedia)"+ ]+ ])+ [ Para+ [ Image+ ( "" , [] , [ ( "width" , "50%" ) ] )+ [ Str "Upside down painting" ]+ ( "New_York_City_I.jpg" , "" )+ ]+ ]+, Para+ [ Image+ ( "" , [] , [] )+ [ Str "Face of a mandrill" ]+ ( "mandrill.jpg" , "" )+ ]+]+```
@@ -0,0 +1,50 @@+```+% pandoc -f html -t opendocument+<table>+ <tbody>+ <tr>+ <th>Header</th>+ <td>Normal cell (column 2)</td>+ <td>Normal cell (column 3)</td>+ </tr>+ <tr>+ <td>Normal cell (column 1)</td>+ <td>Normal cell (column 2)</td>+ <td>Normal cell (column 3)</td>+ </tr>+ </tbody>+</table>+^D+<table:table table:name="Table1" table:style-name="Table1">+ <table:table-column table:style-name="Table1.A" />+ <table:table-column table:style-name="Table1.B" />+ <table:table-column table:style-name="Table1.C" />+ <table:table-row>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Header</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Normal cell (column+ 2)</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Normal cell (column+ 3)</text:p>+ </table:table-cell>+ </table:table-row>+ <table:table-row>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Normal cell (column+ 1)</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Normal cell (column+ 2)</text:p>+ </table:table-cell>+ <table:table-cell table:style-name="TableRowCell" office:value-type="string">+ <text:p text:style-name="Table_20_Contents">Normal cell (column+ 3)</text:p>+ </table:table-cell>+ </table:table-row>+</table:table>+```
@@ -0,0 +1,75 @@+```+% pandoc -t html5 --reference-location=block+# Section 1++hello[^1]++: Sample table.[^2]++-----------+ Fruit[^3]+-----------+ Bans[^4]+-----------++# Section 2++dolly[^5]++[^1]: doc footnote+[^2]: caption footnote+[^3]: header footnote+[^4]: table cell footnote+[^5]: doc footnote+^D+<h1 id="section-1">Section 1</h1>+<p>hello<a href="#fn1" class="footnote-ref" id="fnref1"+role="doc-noteref"><sup>1</sup></a></p>+<aside id="footnotes" class="footnotes footnotes-end-of-block"+role="doc-footnote">+<ol>+<li id="fn1"><p>doc footnote<a href="#fnref1" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+</ol>+</aside>+<table style="width:17%;">+<caption>Sample table.<a href="#fn2" class="footnote-ref" id="fnref2"+role="doc-noteref"><sup>2</sup></a></caption>+<colgroup>+<col style="width: 16%" />+</colgroup>+<thead>+<tr>+<th style="text-align: center;">Fruit<a href="#fn3" class="footnote-ref"+id="fnref3" role="doc-noteref"><sup>3</sup></a></th>+</tr>+</thead>+<tbody>+<tr>+<td style="text-align: center;">Bans<a href="#fn4" class="footnote-ref"+id="fnref4" role="doc-noteref"><sup>4</sup></a></td>+</tr>+</tbody>+</table>+<aside id="footnotes-2" class="footnotes footnotes-end-of-block"+role="doc-footnote">+<ol start="2">+<li id="fn2"><p>caption footnote<a href="#fnref2" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+<li id="fn3"><p>header footnote<a href="#fnref3" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+<li id="fn4"><p>table cell footnote<a href="#fnref4"+class="footnote-back" role="doc-backlink">↩︎</a></p></li>+</ol>+</aside>+<h1 id="section-2">Section 2</h1>+<p>dolly<a href="#fn5" class="footnote-ref" id="fnref5"+role="doc-noteref"><sup>5</sup></a></p>+<aside id="footnotes-3" class="footnotes footnotes-end-of-block"+role="doc-footnote">+<ol start="5">+<li id="fn5"><p>doc footnote<a href="#fnref5" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+</ol>+</aside>+```
@@ -0,0 +1,66 @@+```+% pandoc -t html5 --reference-location=document+# Section 1++hello[^1]++: Sample table.[^2]++-----------+ Fruit[^3]+-----------+ Bans[^4]+-----------++# Section 2++dolly[^5]++[^1]: doc footnote+[^2]: caption footnote+[^3]: header footnote+[^4]: table cell footnote+[^5]: doc footnote+^D+<h1 id="section-1">Section 1</h1>+<p>hello<a href="#fn1" class="footnote-ref" id="fnref1"+role="doc-noteref"><sup>1</sup></a></p>+<table style="width:17%;">+<caption>Sample table.<a href="#fn2" class="footnote-ref" id="fnref2"+role="doc-noteref"><sup>2</sup></a></caption>+<colgroup>+<col style="width: 16%" />+</colgroup>+<thead>+<tr>+<th style="text-align: center;">Fruit<a href="#fn3" class="footnote-ref"+id="fnref3" role="doc-noteref"><sup>3</sup></a></th>+</tr>+</thead>+<tbody>+<tr>+<td style="text-align: center;">Bans<a href="#fn4" class="footnote-ref"+id="fnref4" role="doc-noteref"><sup>4</sup></a></td>+</tr>+</tbody>+</table>+<h1 id="section-2">Section 2</h1>+<p>dolly<a href="#fn5" class="footnote-ref" id="fnref5"+role="doc-noteref"><sup>5</sup></a></p>+<section id="footnotes" class="footnotes footnotes-end-of-document"+role="doc-endnotes">+<hr />+<ol>+<li id="fn1"><p>doc footnote<a href="#fnref1" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+<li id="fn2"><p>caption footnote<a href="#fnref2" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+<li id="fn3"><p>header footnote<a href="#fnref3" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+<li id="fn4"><p>table cell footnote<a href="#fnref4"+class="footnote-back" role="doc-backlink">↩︎</a></p></li>+<li id="fn5"><p>doc footnote<a href="#fnref5" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+</ol>+</section>+```
@@ -0,0 +1,72 @@+```+% pandoc -t html5 --reference-location=section+# Section 1++hello[^1]++: Sample table.[^2]++-----------+ Fruit[^3]+-----------+ Bans[^4]+-----------++# Section 2++dolly[^5]++[^1]: doc footnote+[^2]: caption footnote+[^3]: header footnote+[^4]: table cell footnote+[^5]: doc footnote+^D+<h1 id="section-1">Section 1</h1>+<p>hello<a href="#fn1" class="footnote-ref" id="fnref1"+role="doc-noteref"><sup>1</sup></a></p>+<table style="width:17%;">+<caption>Sample table.<a href="#fn2" class="footnote-ref" id="fnref2"+role="doc-noteref"><sup>2</sup></a></caption>+<colgroup>+<col style="width: 16%" />+</colgroup>+<thead>+<tr>+<th style="text-align: center;">Fruit<a href="#fn3" class="footnote-ref"+id="fnref3" role="doc-noteref"><sup>3</sup></a></th>+</tr>+</thead>+<tbody>+<tr>+<td style="text-align: center;">Bans<a href="#fn4" class="footnote-ref"+id="fnref4" role="doc-noteref"><sup>4</sup></a></td>+</tr>+</tbody>+</table>+<aside id="footnotes" class="footnotes footnotes-end-of-section"+role="doc-footnote">+<hr />+<ol>+<li id="fn1"><p>doc footnote<a href="#fnref1" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+<li id="fn2"><p>caption footnote<a href="#fnref2" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+<li id="fn3"><p>header footnote<a href="#fnref3" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+<li id="fn4"><p>table cell footnote<a href="#fnref4"+class="footnote-back" role="doc-backlink">↩︎</a></p></li>+</ol>+</aside>+<h1 id="section-2">Section 2</h1>+<p>dolly<a href="#fn5" class="footnote-ref" id="fnref5"+role="doc-noteref"><sup>5</sup></a></p>+<aside id="footnotes-2" class="footnotes footnotes-end-of-section"+role="doc-footnote">+<hr />+<ol start="5">+<li id="fn5"><p>doc footnote<a href="#fnref5" class="footnote-back"+role="doc-backlink">↩︎</a></p></li>+</ol>+</aside>+```
@@ -0,0 +1,8 @@+# Backslash escapes in markdown_strict++```+% pandoc --from=markdown_strict -t html+These are not escaped: \~ \"+^D+<p>These are not escaped: \~ \"</p>+```
@@ -0,0 +1,33 @@+```+% pandoc -f rtf -t native+{\rtf1\ansi\ansicpg1252\cocoartf2867+\cocoatextscaling0\cocoaplatform1{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}+{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;}+{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{decimal\}.}{\leveltext\leveltemplateid1\'02\'00.;}{\levelnumbers\'01;}\fi-360\li720\lin720 }{\listname ;}\listid1}+{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}}+{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}}+\paperw11905\paperh16837\margl1133\margr1133\margb1133\margt1133+\deftab720+\pard\pardeftab720\partightenfactor0++\f0\fs22 \cf2 \up0 \nosupersub \ulnone First paragraph\+\pard\tx20\tx360\pardeftab720\li360\fi-360\partightenfactor0+\ls1\ilvl0\cf2 \up0 \nosupersub \ulnone {\listtext 1. }\cf2 \up0 \nosupersub \ulnone Numbered item\+\pard\pardeftab720\partightenfactor0+\cf2 Second paragraph\+\pard\tx20\tx180\pardeftab720\li180\fi-180\partightenfactor0+\ls2\ilvl0\cf2 \up0 \nosupersub \ulnone {\listtext \uc0\u8226 }\cf2 \up0 \nosupersub \ulnone Bullet item\+\pard\pardeftab720\partightenfactor0+\cf2 New paragraph}+^D+[ Para [ Str "First" , Space , Str "paragraph" ]+, OrderedList+ ( 1 , Decimal , Period )+ [ [ Para [ Str "Numbered" , Space , Str "item" ] ] ]+, Para [ Str "Second" , Space , Str "paragraph" ]+, BulletList+ [ [ Para [ Str "Bullet" , Space , Str "item" ] ] ]+, Para [ Str "New" , Space , Str "paragraph" ]+]+```
@@ -0,0 +1,42 @@+# `\multicolumn` with column-type `p`++```+% pandoc --from=latex --to=html+\begin{tabular}{rrll}+ \toprule+ \textbf{First} & \textbf{Second} & \textbf{Third} & \textbf{Fourth} \\ \toprule+ 160 & 1 & test & test \\\midrule+ 160 & 2 & \multicolumn{2}{p{12cm}}{\textit{This is a test:}+ \begin{equation*}+ a^2+b^2 = c^2+ \end{equation*}+ }\\+\bottomrule+\end{tabular}+^D+<table>+<thead>+<tr>+<th style="text-align: right;"><strong>First</strong></th>+<th style="text-align: right;"><strong>Second</strong></th>+<th style="text-align: left;"><strong>Third</strong></th>+<th style="text-align: left;"><strong>Fourth</strong></th>+</tr>+</thead>+<tbody>+<tr>+<td style="text-align: right;">160</td>+<td style="text-align: right;">1</td>+<td style="text-align: left;">test</td>+<td style="text-align: left;">test</td>+</tr>+<tr>+<td style="text-align: right;">160</td>+<td style="text-align: right;">2</td>+<td colspan="2" style="text-align: left;"><em>This is a test:</em> <span+class="math display"><em>a</em><sup>2</sup> + <em>b</em><sup>2</sup> = <em>c</em><sup>2</sup></span></td>+</tr>+</tbody>+</table>++```
@@ -0,0 +1,43 @@+Github Formatted Markdown Identifiers+```+% pandoc -f man+gfm_auto_identifiers -t html+.TH "TEST" "1" "2026-05-08" "test v1.0.0" "test manual"+.SH 1st HEADING+.SH C++ & Rust+.SH HEADING+.SH HEADING+^D+<h1 id="1st-heading">1st HEADING</h1>+<h1 id="c--rust">C++ & Rust</h1>+<h1 id="heading">HEADING</h1>+<h1 id="heading-1">HEADING</h1>+```++Ascii Identifiers test+```+% pandoc -f man+ascii_identifiers -t html+.TH "TEST" "1" "2026-05-08" "test v1.0.0" "test manual"+.SH Über den Flüssen+^D+<h1 id="uber-den-flussen">Über den Flüssen</h1>+```++Headers without Auto Identifiers test+```+% pandoc -f man-auto_identifiers -t native+.TH "TEST" "1" "2026-05-08" "test v1.0.0" "test manual"+.SS Level 2+.SS different styles:+.SS Ordered+.SS Ordered+^D+[ Header+ 2 ( "" , [] , [] ) [ Str "Level" , Space , Str "2" ]+, Header+ 2+ ( "" , [] , [] )+ [ Str "different" , Space , Str "styles:" ]+, Header 2 ( "" , [] , [] ) [ Str "Ordered" ]+, Header 2 ( "" , [] , [] ) [ Str "Ordered" ]+]+```
@@ -0,0 +1,6 @@+```+% pandoc -f markdown+wikilinks_title_after_pipe --wrap=none+[[hi]] and ![[hi]]+^D+<p><a href="hi" class="wikilink">hi</a> and <img src="hi" class="wikilink" alt="hi" /></p>+```
@@ -0,0 +1,11 @@+```+% pandoc -f dokuwiki -t native+ * item 1+ * item 1.1+^D+[ BulletList+ [ [ Plain [ Str "item" , Space , Str "1" ] ]+ , [ Plain [ Str "item" , Space , Str "1.1" ] ]+ ]+]+```
@@ -0,0 +1,49 @@+```+% pandoc -f jats -t native -s+<article-meta>+ <title-group>+ <article-title></article-title>+ </title-group>+ <permissions>+ <copyright-statement>© 2023, Ellerman et al</copyright-statement>+ <copyright-year>2023</copyright-year>+ <copyright-holder>Ellerman et al</copyright-holder>+ <license license-type="open-access">+ <ali:license_ref xmlns:ali="http://www.niso.org/schemas/ali/1.0/">https://creativecommons.org/licenses/by/4.0/</ali:license_ref>+ <license-p>This document is distributed under a Creative Commons Attribution 4.0 International license.</license-p>+ </license>+ </permissions>+</article-meta>+^D+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "copyright"+ , MetaMap+ (fromList+ [ ( "holder" , MetaString "Ellerman et al" )+ , ( "statement"+ , MetaString "\169 2023, Ellerman et al"+ )+ , ( "year" , MetaString "2023" )+ ])+ )+ , ( "license"+ , MetaMap+ (fromList+ [ ( "link"+ , MetaString+ "https://creativecommons.org/licenses/by/4.0/"+ )+ , ( "text"+ , MetaString+ "This document is distributed under a Creative Commons Attribution 4.0 International license."+ )+ , ( "type" , MetaString "open-access" )+ ])+ )+ ]+ }+ []+```
@@ -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,45 @@++```+% pandoc -f latex -t native+\documentclass{amsart}+\newtheorem{theorem}{Theorem}+\begin{document}+\begin{theorem}\label{thm}+\begin{enumerate}+\item \label{item1}text1+\item \label{item2}text2+\item text3+\end{enumerate}+\end{theorem}+\end{document}+^D+[ Div+ ( "thm" , [ "theorem" ] , [] )+ [ Para+ [ Strong [ Str "Theorem" , Space , Str "1" ]+ , Str "."+ , Space+ , Space+ , Emph []+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para+ [ Emph+ [ Span ( "item1" , [] , [ ( "label" , "item1" ) ] ) []+ , Str "text1"+ ]+ ]+ ]+ , [ Para+ [ Emph+ [ Span ( "item2" , [] , [ ( "label" , "item2" ) ] ) []+ , Str "text2"+ ]+ ]+ ]+ , [ Para [ Emph [ Str "text3" ] ] ]+ ]+ ]+]+```
@@ -0,0 +1,42 @@+Raw EPUB attributes are rendered in EPUB output.++```+% pandoc -f native -t epub --metadata title=Raw -o - | pandoc -f epub -t html+[ RawBlock (Format "epub") "<p>ok</p>" ]+^D+<p><span id="title_page.xhtml"></span></p>+<p><span id="ch001.xhtml"></span></p>+<section id="ch001.xhtml_raw" class="unnumbered level1">+<h1 class="unnumbered">Raw</h1>+<p>ok</p>+</section>+```++Raw EPUB2 attributes are omitted from EPUB3 output.++```+% pandoc -f markdown -t epub3 --metadata title=Raw -o - | pandoc -f epub -t html+~~~ {=epub2}+<p>ok</p>+~~~+^D+<p><span id="title_page.xhtml"></span></p>+<p><span id="ch001.xhtml"></span></p>+<section id="ch001.xhtml_raw" class="unnumbered level1">+<h1 class="unnumbered">Raw</h1>+</section>+```++```+% pandoc -f markdown -t epub3 --metadata title=Raw -o - | pandoc -f epub -t html+~~~ {=epub3}+<p>ok</p>+~~~+^D+<p><span id="title_page.xhtml"></span></p>+<p><span id="ch001.xhtml"></span></p>+<section id="ch001.xhtml_raw" class="unnumbered level1">+<h1 class="unnumbered">Raw</h1>+<p>ok</p>+</section>+```
@@ -0,0 +1,31 @@+```+% pandoc --embed-resources+{.inline-svg}+{.inline-svg}+^D+<p><svg role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150"><use href="#svg_7868854ffb8f30209cd0" width="100%" height="100%" /></svg>+<svg id="svg_7868854ffb8f30209cd0" role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150">+ <path d="M 0 35.5 L 6.5 22.5 L 16 37 L 23 24 L 34.8 43.7 L 42.5 30 L 50.3 47 L 59.7 27.7 L 69 47 L 85 17.7 L 98.3 39 L 113 9.7 L 127.7 42.3 L 136.3 23.7 L 147 44.3 L 158.3 20.3 L 170.3 40.3 L 177.7 25.7 L 189.7 43 L 199.7 21 L 207.7 35 L 219 11 L 233 37 L 240.3 23.7 L 251 43 L 263 18.3 L 272.7 33.3 L 283 10 L 295 32.3 L 301.3 23 L 311.7 37 L 323.7 7.7 L 339.3 39 L 346.3 25.7 L 356.3 42.3 L 369.7 15 L 376.3 25.7 L 384 9 L 393 28.3 L 400.3 19 L 411.7 38.3 L 421 21 L 434.3 43 L 445 25 L 453 36.3 L 464.3 18.3 L 476.2 40.3 L 480 33.5 L 480 215 L 0 215 L 0 35.5 Z" fill="#175720" />+</svg></p>+```++```+% pandoc --embed-resources+{.inline-svg}+{#foo .inline-svg}+^D+<p><svg role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150"><use href="#foo" width="100%" height="100%" /></svg>+<svg id="foo" role="img" aria-label="minimal" alt="minimal" viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" xml:space="preserve" width="480" height="150">+ <path d="M 0 35.5 L 6.5 22.5 L 16 37 L 23 24 L 34.8 43.7 L 42.5 30 L 50.3 47 L 59.7 27.7 L 69 47 L 85 17.7 L 98.3 39 L 113 9.7 L 127.7 42.3 L 136.3 23.7 L 147 44.3 L 158.3 20.3 L 170.3 40.3 L 177.7 25.7 L 189.7 43 L 199.7 21 L 207.7 35 L 219 11 L 233 37 L 240.3 23.7 L 251 43 L 263 18.3 L 272.7 33.3 L 283 10 L 295 32.3 L 301.3 23 L 311.7 37 L 323.7 7.7 L 339.3 39 L 346.3 25.7 L 356.3 42.3 L 369.7 15 L 376.3 25.7 L 384 9 L 393 28.3 L 400.3 19 L 411.7 38.3 L 421 21 L 434.3 43 L 445 25 L 453 36.3 L 464.3 18.3 L 476.2 40.3 L 480 33.5 L 480 215 L 0 215 L 0 35.5 Z" fill="#175720" />+</svg></p>+```++```+% pandoc --embed-resources++^D+<figure>+<img role="img" aria-label="minimal" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PgoKPHN2ZyB2aWV3Qm94PSItLjMzMyAtLjMzMyA0ODAgMTUwIiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CiAgICA8cGF0aCBkPSJNIDAgMzUuNSBMIDYuNSAyMi41IEwgMTYgMzcgTCAyMyAyNCBMIDM0LjggNDMuNyBMIDQyLjUgMzAgTCA1MC4zIDQ3IEwgNTkuNyAyNy43IEwgNjkgNDcgTCA4NSAxNy43IEwgOTguMyAzOSBMIDExMyA5LjcgTCAxMjcuNyA0Mi4zIEwgMTM2LjMgMjMuNyBMIDE0NyA0NC4zIEwgMTU4LjMgMjAuMyBMIDE3MC4zIDQwLjMgTCAxNzcuNyAyNS43IEwgMTg5LjcgNDMgTCAxOTkuNyAyMSBMIDIwNy43IDM1IEwgMjE5IDExIEwgMjMzIDM3IEwgMjQwLjMgMjMuNyBMIDI1MSA0MyBMIDI2MyAxOC4zIEwgMjcyLjcgMzMuMyBMIDI4MyAxMCBMIDI5NSAzMi4zIEwgMzAxLjMgMjMgTCAzMTEuNyAzNyBMIDMyMy43IDcuNyBMIDMzOS4zIDM5IEwgMzQ2LjMgMjUuNyBMIDM1Ni4zIDQyLjMgTCAzNjkuNyAxNSBMIDM3Ni4zIDI1LjcgTCAzODQgOSBMIDM5MyAyOC4zIEwgNDAwLjMgMTkgTCA0MTEuNyAzOC4zIEwgNDIxIDIxIEwgNDM0LjMgNDMgTCA0NDUgMjUgTCA0NTMgMzYuMyBMIDQ2NC4zIDE4LjMgTCA0NzYuMiA0MC4zIEwgNDgwIDMzLjUgTCA0ODAgMjE1IEwgMCAyMTUgTCAwIDM1LjUgWiIgZmlsbD0iIzE3NTcyMCIvPgo8L3N2Zz4K" alt="minimal" />+<figcaption aria-hidden="true">minimal</figcaption>+</figure>+```
@@ -0,0 +1,48 @@+```+% pandoc -iNtslidy+# One++- one+- two+^D+<div id="one" class="slide section level1" number="1">+<h1><span class="header-section-number">1</span> One</h1>+<ul class="incremental">+<li>one</li>+<li>two</li>+</ul>+</div>+```++````+% pandoc -pstnative+```+ after tab+```+^D+Pandoc+ Meta { unMeta = fromList [] }+ [ CodeBlock ( "" , [] , [] ) "\tafter tab" ]+````++```+% pandoc -sfalse+hi+^D+<p>hi</p>+```++```+% pandoc --standalone=false+hi+^D+<p>hi</p>+```++```+% pandoc --standalone=FALSE+hi+^D+<p>hi</p>+```+
@@ -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,9 @@+```+% pandoc -t typst+**Samsonov T.E.** Shape-Adaptive Geometric Simplification of Heterogeneous Line Datasets / T. E. Samsonov, O. P. Yakimova // International Journal of Geographical Information Science. — 2017. — Vol. 31. — № 8. — pp. 1485-1520.+^D+#strong[Samsonov T.E.] Shape-Adaptive Geometric Simplification of+Heterogeneous Line Datasets / T. E. Samsonov, O. P. Yakimova /\/+International Journal of Geographical Information Science. --- 2017. ---+Vol. 31. --- № 8. --- pp.~1485-1520.+```
@@ -0,0 +1,6 @@+```+% pandoc --wrap=none+consectetur [^\[link\]^](#ref "Title")+^D+<p>consectetur <a href="#ref" title="Title"><sup>[link]</sup></a></p>+```
@@ -0,0 +1,122 @@+```+% pandoc -f html -t native+<table>+ <tr>+ <th colspan="2">a</th>+ <td>b</td>+ </tr>+ <tr>+ <th>c</th>+ <th>d</th>+ <td>e</td>+ </tr>+</table>+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 2)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ 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" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "e" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]++```++```+% pandoc -f html -t native+<table>+<tr>+<th rowspan="2">Heading</th>+<td>content</td>+</tr>+<tr>+<td>content2</td>+</tr>+</table>+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 1)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "Heading" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "content" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "content2" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]++```
@@ -0,0 +1,6 @@+```+% pandoc -t latex+[A theorem](https://en.wikipedia.org/wiki/Rice's_theorem).+^D+\href{https://en.wikipedia.org/wiki/Rice's_theorem}{A theorem}.+```
@@ -0,0 +1,77 @@+```+% pandoc -f org -t native+* has space after second colon+: aaa+: +: bbb+++* has no space after second colon+: aaa+:+: bbb+^D+[ Header+ 1+ ( "has-space-after-second-colon" , [] , [] )+ [ Str "has"+ , Space+ , Str "space"+ , Space+ , Str "after"+ , Space+ , Str "second"+ , Space+ , Str "colon"+ ]+, CodeBlock ( "" , [] , [] ) "aaa\n\nbbb\n"+, Header+ 1+ ( "has-no-space-after-second-colon" , [] , [] )+ [ Str "has"+ , Space+ , Str "no"+ , Space+ , Str "space"+ , Space+ , Str "after"+ , Space+ , Str "second"+ , Space+ , Str "colon"+ ]+, CodeBlock ( "" , [] , [] ) "aaa\n\nbbb\n"+]+```++```+% pandoc -f org -t native+* only the colon+:++* only the colon and a space+: +^D+[ Header+ 1+ ( "only-the-colon" , [] , [] )+ [ Str "only" , Space , Str "the" , Space , Str "colon" ]+, CodeBlock ( "" , [] , [] ) "\n"+, Header+ 1+ ( "only-the-colon-and-a-space" , [] , [] )+ [ Str "only"+ , Space+ , Str "the"+ , Space+ , Str "colon"+ , Space+ , Str "and"+ , Space+ , Str "a"+ , Space+ , Str "space"+ ]+, CodeBlock ( "" , [] , [] ) "\n"+]+```
@@ -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.++```+
binary file changed (absent → 12631 bytes)
@@ -0,0 +1,20 @@+```+% pandoc command/9002.docx -t html+^D+<table style="width:40%;">+<caption><p>This is my table!</p></caption>+<colgroup>+<col style="width: 20%" />+<col style="width: 20%" />+</colgroup>+<thead>+<tr>+<th>a</th>+<th>b</th>+</tr>+</thead>+<tbody>+</tbody>+</table>+<p>See <a href="#_Ref143272803">Table 1 This is my table!</a></p>+```
@@ -0,0 +1,54 @@+```+% pandoc -t jats --citeproc -s+---+references:+- author: DeGroot+ id: degroot_probability+ title: Probability+ issued: 2002+title: Doc example with single reference+---++# I like++[@degroot_probability].+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>Doc example with single reference</article-title>+</title-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>+<sec id="i-like">+ <title>I like</title>+ <p>(DeGroot 2002).</p>+</sec>+</body>+<back>+<ref-list>+ <title></title>+ <ref id="ref-degroot_probability">+ <mixed-citation>DeGroot. 2002.+ <italic>Probability</italic>.</mixed-citation>+ </ref>+</ref-list>+</back>+</article>+```
@@ -0,0 +1,61 @@+```+% pandoc -t jats+element_citations --citeproc -s+---+references:+- author: DeGroot+ id: degroot_probability+ title: Probability+ issued: 2002+title: Doc example with single reference+reference-section-title: Ref Title+---++# I like++[@degroot_probability].+^D+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN"+ "JATS-archivearticle1.dtd">+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<front>+<journal-meta>+<journal-id></journal-id>+<journal-title-group>+</journal-title-group>+<issn></issn>+<publisher>+<publisher-name></publisher-name>+</publisher>+</journal-meta>+<article-meta>+<title-group>+<article-title>Doc example with single reference</article-title>+</title-group>+<permissions>+</permissions>+</article-meta>+</front>+<body>+<sec id="i-like">+ <title>I like</title>+ <p>(DeGroot 2002).</p>+</sec>+</body>+<back>+<ref-list>+ <title>Ref Title</title>+ <ref id="ref-degroot_probability">+ <element-citation>+ <person-group person-group-type="author">+ <string-name>DeGroot</string-name>+ </person-group>+ <article-title>Probability</article-title>+ <year iso-8601-date="2002">2002</year>+ </element-citation>+ </ref>+</ref-list>+</back>+</article>++```
@@ -0,0 +1,6 @@+```+% pandoc -t native+![foo]+^D+[ Para [ Str "![foo]" ] ]+```
@@ -0,0 +1,30 @@+```+% pandoc -f org+#+TITLE: Testing++* Testing++p. lower case++P. Upper Case+^D+<h1 id="testing-1">Testing</h1>+<p>p. lower case</p>+<p>P. Upper Case</p>+```+```+% pandoc -f org+fancy_lists+#+TITLE: Testing++* Testing++p. lower case++P. Upper Case+^D+<h1 id="testing-1">Testing</h1>+<ol type="a">+<li><p>lower case</p></li>+<li><p>Upper Case</p></li>+</ol>+```
@@ -0,0 +1,13 @@+```+% pandoc -t latex+[**TreeTagger**](https://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/)+^D+\href{https://www.cis.uni-muenchen.de/~schmid/tools/TreeTagger/}{\textbf{TreeTagger}}+```++```+% pandoc -t latex+[**TreeTagger**](https://www.cis.uni-muenchen.de/%E7schmid/tools/TreeTagger/)+^D+\href{https://www.cis.uni-muenchen.de/\%E7schmid/tools/TreeTagger/}{\textbf{TreeTagger}}+```
@@ -0,0 +1,10 @@+```+% pandoc -t latex+{#foo}+^D+\begin{figure}+\centering+\pandocbounded{\includegraphics[keepaspectratio,alt={hi}]{there.jpg}}+\caption{hi}\label{foo}+\end{figure}+```
@@ -0,0 +1,47 @@+tests meant to test the fixes of bug [#9047](https://github.com/jgm/pandoc/issues/9047)++```+% pandoc -f html -t html+<ul class="task-list">+<li><label><input type="checkbox" />foo</label></li>+<li><label><input type="checkbox" checked="" />bar</label></li>+<li><label><input type="button" checked="" />foobar</label></li>+<li><input id="hello" type="checkbox" checked/><label for="hello">hello</label></li>+</ul>+^D+<ul>+<li><label><input type="checkbox" />foo</label></li>+<li><label><input type="checkbox" checked="" />bar</label></li>+<li>foobar</li>+<li><label><input type="checkbox" checked="" />hello</label></li>+</ul>+```++w/ rawHTML extension a checkbox by itself is kept+```+% pandoc -f html+raw_html -t html+raw_html+<input type="checkbox" checked="" />+^D+<input type="checkbox" checked>+</input>+```++w/ rawHTML extension, a checkbox in an `li` is handled properly+```+% pandoc -f html+raw_html -t html+raw_html+<ul>+<li><input type="checkbox" checked/>foo</li>+</ul>+^D+<ul class="task-list">+<li><label><input type="checkbox" checked="" />foo</label></li>+</ul>+```++w/o rawHTML extension, a checkbox outside of an `li` is properly ignored+```+% pandoc -f html -t html+<p><input type="checkbox" checked/>foo</p>+^D+foo+```
@@ -0,0 +1,10 @@+```+% pandoc -t latex+| 0 - A+| 1 - B+| 2 - C+^D+~~~0 - A\\+\strut ~~~1 - B\\+\strut ~~~2 - C+```
@@ -0,0 +1,15 @@+```+% pandoc -f html -t gfm+<table>+ <tr>+ <th>invalid head cell</td>+ </tr>+ <tr>+ <td>body cell</td>+ </tr>+</table>+^D+| invalid head cell |+|-------------------|+| body cell |+```
@@ -0,0 +1,17 @@+````+% pandoc -t gfm+a $$x=y$$ b+^D+a+``` math+x=y+```+b+````++````+% pandoc -t gfm+a $x=y$ b+^D+a $`x=y`$ b+````
@@ -0,0 +1,89 @@+Verify that the OpenDocument writer uses predefined list, paragraph, and+text styles instead of generating per-instance automatic styles.++```+% pandoc -t opendocument+- one+- two++1. ordered one+2. ordered two++Some *italic*, **bold**, ~~strike~~, and `code`.++> A block quote.++Final paragraph.+^D+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">one</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">two</text:p>+ </text:list-item>+</text:list>+<text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">ordered+ one</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">ordered+ two</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Some+<text:span text:style-name="Emphasis">italic</text:span>,+<text:span text:style-name="Strong_20_Emphasis">bold</text:span>,+<text:span text:style-name="Strikeout">strike</text:span>, and+<text:span text:style-name="Source_20_Text">code</text:span>.</text:p>+<text:p text:style-name="Quotations">A block quote.</text:p>+<text:p text:style-name="First_20_paragraph">Final paragraph.</text:p>+```++A non-default ordered list (start value other than 1, or non-decimal+format) generates a single named override style, not one per instance.++```+% pandoc -t opendocument+A) upper-alpha one+B) upper-alpha two++5. start at five+6. and continue+^D+<text:list text:style-name="Pandoc_5f_Numbering_5f_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">upper-alpha+ one</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">upper-alpha+ two</text:p>+ </text:list-item>+</text:list>+<text:list text:style-name="Numbering_20_1" text:start-value="5">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">start at+ five</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">and+ continue</text:p>+ </text:list-item>+</text:list>+```++A nested block quote uses the predefined `Quotations` style for the+outer paragraph, and inherits indent from it for the inner paragraph.++```+% pandoc -t opendocument+> First.+>+> > Nested.+^D+<text:p text:style-name="Quotations">First.</text:p>+<text:p text:style-name="P1">Nested.</text:p>+```
@@ -0,0 +1,51 @@+```+% pandoc -f latex -t native+\hfill {\Large \textbf{Theoretische Grundlagen der Informatik}}+^D+[ Para+ [ Span+ ( "" , [] , [] )+ [ Strong+ [ Str "Theoretische"+ , Space+ , Str "Grundlagen"+ , Space+ , Str "der"+ , Space+ , Str "Informatik"+ ]+ ]+ ]+]+```++```+% pandoc -f latex+raw_tex -t native+\hfill {\Large \textbf{Theoretische Grundlagen der Informatik}}+^D+[ Para+ [ RawInline (Format "latex") "\\hfill "+ , Span+ ( "" , [] , [] )+ [ RawInline (Format "latex") "\\Large "+ , Strong+ [ Str "Theoretische"+ , Space+ , Str "Grundlagen"+ , Space+ , Str "der"+ , Space+ , Str "Informatik"+ ]+ ]+ ]+]+```++```+% pandoc -f latex+raw_tex -t native+\hskip 2pt plus 1pt minus 1pt+^D+[ RawBlock (Format "latex") "\\hskip 2pt plus 1pt minus 1pt"+]+```
@@ -0,0 +1,15 @@+```+% pandoc -t org -f markdown+\* See Blah++\# not comment++\| not table \|+^D+* See Blah++# not comment++| not table |++```
@@ -0,0 +1,65 @@+```+% pandoc -f markdown -t native+[link][link contents]{target="_blank"}+[link2](https://example.com){target="_blank"}++[link contents]: https://example.com+^D+[ Para+ [ Link+ ( "" , [] , [ ( "target" , "_blank" ) ] )+ [ Str "link" ]+ ( "https://example.com" , "" )+ , SoftBreak+ , Link+ ( "" , [] , [ ( "target" , "_blank" ) ] )+ [ Str "link2" ]+ ( "https://example.com" , "" )+ ]+]++```++```+% pandoc -f markdown -t native+[link][link contents]{#id1 target="_blank"}+[link2](https://example.com){target="_blank"}++[link contents]: https://example.com {#id2 target="_nonblank"}+^D+[ Para+ [ Link+ ( "id1" , [] , [ ( "target" , "_blank" ) ] )+ [ Str "link" ]+ ( "https://example.com" , "" )+ , SoftBreak+ , Link+ ( "" , [] , [ ( "target" , "_blank" ) ] )+ [ Str "link2" ]+ ( "https://example.com" , "" )+ ]+]++```++```+% pandoc -f markdown -t native+[link][link contents]{target="_blank"}+[link2](https://example.com){target="_blank"}++[link contents]: https://example.com {.foo}+^D+[ Para+ [ Link+ ( "" , [ "foo" ] , [ ( "target" , "_blank" ) ] )+ [ Str "link" ]+ ( "https://example.com" , "" )+ , SoftBreak+ , Link+ ( "" , [] , [ ( "target" , "_blank" ) ] )+ [ Str "link2" ]+ ( "https://example.com" , "" )+ ]+]++```
@@ -0,0 +1,7 @@+```+% pandoc -t native+$a+%+b$+^D+[ Para [ Math InlineMath "a+%\nb" ] ]+```
@@ -0,0 +1,6 @@+```+% pandoc -f rst --wrap=none+Define _`my target`, then reference `my target`_.+^D+<p>Define <span id="my-target">my target</span>, then reference <a href="#my-target">my target</a>.</p>+```
@@ -0,0 +1,18 @@+```+% pandoc -f man -t markdown+.TH "EXAMPLE" "1"+.SH "OPTIONS"+.TP 8n+\fB\-\-help\fR+This is line one.+.sp+This is line two.+^D+# OPTIONS++**\--help**++: This is line one.++ This is line two.+```
@@ -0,0 +1,62 @@+```+% pandoc -f latex -t native+\begin{otherlanguage}{french}+Bonjour.+\end{otherlanguage}+^D+[ Div+ ( "" , [] , [ ( "lang" , "fr" ) ] )+ [ Para [ Str "Bonjour." ] ]+]+```++```+% pandoc -f latex -t native+\begin{otherlanguage*}{french}+Bonjour.+\end{otherlanguage*}+^D+[ Div+ ( "" , [ "otherlanguage*" ] , [] )+ [ Para+ [ Span ( "" , [] , [] ) [ Str "french" ]+ , SoftBreak+ , Str "Bonjour."+ ]+ ]+]+```++```+% pandoc -f latex -t native+\textfrench{Bonjour}+^D+[ Para+ [ Span ( "" , [] , [ ( "lang" , "fr" ) ] ) [ Str "Bonjour" ]+ ]+]+```++```+% pandoc -f latex -t native+\foreignlanguage{swissgerman}{Guten tag}+^D+[ Para+ [ Span+ ( "" , [] , [ ( "lang" , "de-CH-1901" ) ] )+ [ Str "Guten" , Space , Str "tag" ]+ ]+]+```++```+% pandoc -f latex -t native+\begin{french}+Bonjour.+\end{french}+^D+[ Div+ ( "" , [] , [ ( "lang" , "fr" ) ] )+ [ Para [ Str "Bonjour." ] ]+]+```
@@ -0,0 +1,6 @@+```+% pandoc -t latex+## [Section]{#Section3}+^D+\subsection{\texorpdfstring{\protect\hypertarget{Section3}{}{Section}}{Section}}\label{section}+```
@@ -0,0 +1,22 @@+# Escape special lines in Org-mode code blocks++````+% pandoc -f markdown -t org+``` org+** Click Application+*** Imports++#+begin_src py+from addict import Dict+#+end_src+```+^D+#+begin_src org+,** Click Application+,*** Imports++,#+begin_src py+from addict import Dict+,#+end_src+#+end_src+````
@@ -0,0 +1,34 @@+```+% pandoc -t typst+{width=3in}++{width=3in height=2in}++++And inline: {height=2in} and+.+^D+#figure(image("command/minimal.svg", width: 3in, alt: "minimal"),+ caption: [+ minimal+ ]+)++#figure(image("command/minimal.svg", height: 2in, width: 3in, alt: "minimal"),+ caption: [+ minimal+ ]+)++#figure(image("command/minimal.svg", alt: "minimal"),+ caption: [+ minimal+ ]+)++And inline:+#box(image("command/minimal.svg", height: 2in, alt: "minimal")) and+#box(image("command/minimal.svg", alt: "minimal")).++```
@@ -0,0 +1,18 @@+```+% pandoc -t latex --biblatex+[@scott2000, p. 33]+[@scott2000, pp. 33-34 and elsewhere; @scott2001, ch. 4]+^D+\autocite[33]{scott2000} \autocites[33-34 and+elsewhere]{scott2000}[ch.~4]{scott2001}++```++```+% pandoc -t latex --biblatex -Mlang=de+[@scott2000, p. 33]+[@scott2000, S. 33]+^D+\autocite[p.~33]{scott2000} \autocite[33]{scott2000}++```
@@ -0,0 +1,131 @@+```+% pandoc -f org -t native+#+LABEL: tbl:Cosasexample+#+CAPTION: Cosas++-------+-------++| cosas | cosas |+| cosas | cosas |++=======+=======++| cosas | cosas |+| cosas | cosas |++-------+-------++^D+[ Table+ ( "tbl:Cosasexample" , [] , [] )+ (Caption Nothing [ Plain [ Str "Cosas" ] ])+ [ ( AlignDefault , ColWidth 0.1111111111111111 )+ , ( AlignDefault , ColWidth 0.1111111111111111 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "cosas" , SoftBreak , Str "cosas" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "cosas" , SoftBreak , Str "cosas" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "cosas" , SoftBreak , Str "cosas" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "cosas" , SoftBreak , Str "cosas" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+```++```+% pandoc -f org -t markdown+#+LABEL: tbl:Cosasexample+#+CAPTION: Cosas++-------+-------++| cosas | cosas |+| cosas | cosas |++=======+=======++| cosas | cosas |+| cosas | cosas |++-------+-------++^D+ ---------------+ cosas cosas+ cosas cosas+ ------- -------+ cosas cosas+ cosas cosas++ ---------------++ : Cosas {#tbl:Cosasexample}++```++```+% pandoc -f org -t markdown+#+LABEL: tbl:Cosasexample++-------+-------++| cosas | cosas |+| cosas | cosas |++=======+=======++| cosas | cosas |+| cosas | cosas |++-------+-------++^D+ ---------------+ cosas cosas+ cosas cosas+ ------- -------+ cosas cosas+ cosas cosas++ ---------------++```++```+% pandoc -f org -t markdown+#+CAPTION: Cosas++-------+-------++| cosas | cosas |+| cosas | cosas |++=======+=======++| cosas | cosas |+| cosas | cosas |++-------+-------++^D+ ---------------+ cosas cosas+ cosas cosas+ ------- -------+ cosas cosas+ cosas cosas++ ---------------++ : Cosas++```
@@ -0,0 +1,29 @@+```+% pandoc -f mediawiki -t native+* Linearity in the first argument:+*:<math>\begin{align}+\langle a \mathbf u, \mathbf v\rangle &= a \langle \mathbf u, \mathbf v\rangle. \\+\langle \mathbf u + \mathbf v, \mathbf w\rangle &= \langle \mathbf u, \mathbf w\rangle+ \langle \mathbf v, \mathbf w\rangle.+\end{align}</math>+^D+[ BulletList+ [ [ Plain+ [ Str "Linearity"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "first"+ , Space+ , Str "argument:"+ ]+ , Para+ [ Math+ DisplayMath+ "\\begin{align}\n\\langle a \\mathbf u, \\mathbf v\\rangle &= a \\langle \\mathbf u, \\mathbf v\\rangle. \\\\\n\\langle \\mathbf u + \\mathbf v, \\mathbf w\\rangle &= \\langle \\mathbf u, \\mathbf w\\rangle+ \\langle \\mathbf v, \\mathbf w\\rangle.\n\\end{align}"+ ]+ ]+ ]+]+```
@@ -0,0 +1,8 @@+```+% pandoc -f markdown -t markdown_strict+pipe_tables+|V1 |V2 |V3 |V4 |V5 |V6 |V7 |V8 |V9 |V10 |V11 |V12 |V13 |V14 |V15 |V16 |V17 |V18 |V19 |V20 |V21 |V22 |V23 |V24 |V25 |V26 |V27 |V28 |V29 |V30 |V31 |V32 |V33 |V34 |V35 |V36 |V37 |V38 |V39 |V40 |V41 |V42 |V43 |V44 |V45 |V46 |V47 |V48 |V49 |V50 |V51 |V52 |V53 |V54 |V55 |V56 |V57 |V58 |V59 |V60 |V61 |V62 |V63 |V64 |V65 |V66 |V67 |V68 |V69 |V70 |V71 |V72 |+|:--|:--|:--|:--|:--|:--|:--|:--|:--|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|+^D+| V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 | V11 | V12 | V13 | V14 | V15 | V16 | V17 | V18 | V19 | V20 | V21 | V22 | V23 | V24 | V25 | V26 | V27 | V28 | V29 | V30 | V31 | V32 | V33 | V34 | V35 | V36 | V37 | V38 | V39 | V40 | V41 | V42 | V43 | V44 | V45 | V46 | V47 | V48 | V49 | V50 | V51 | V52 | V53 | V54 | V55 | V56 | V57 | V58 | V59 | V60 | V61 | V62 | V63 | V64 | V65 | V66 | V67 | V68 | V69 | V70 | V71 | V72 |+|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|+```
@@ -0,0 +1,14 @@+```+% pandoc -f html -t latex+<table><tbody><tr></tr></tbody></table>+^D+{\def\LTcaptype{none} % do not increment counter+\begin{longtable}[]{@{}l@{}}+\toprule\noalign{}+\endhead+\bottomrule\noalign{}+\endlastfoot+ \\+\end{longtable}+}+```
binary file changed (absent → 13439 bytes)
@@ -0,0 +1,45 @@+Caption belongs to the second table:+```+% pandoc -f docx -t html command/9358.docx+^D+<p>Lorem gipsum</p>+<table>+<colgroup>+<col style="width: 50%" />+<col style="width: 50%" />+</colgroup>+<thead>+<tr>+<th>A</th>+<th>B</th>+</tr>+</thead>+<tbody>+<tr>+<td>C</td>+<td>D</td>+</tr>+</tbody>+</table>+<p>Lorem ipsum</p>+<table>+<caption><p>Table 1 Numbers from 1 to 4</p></caption>+<colgroup>+<col style="width: 50%" />+<col style="width: 50%" />+</colgroup>+<thead>+<tr>+<th>1</th>+<th>2</th>+</tr>+</thead>+<tbody>+<tr>+<td>3</td>+<td>4</td>+</tr>+</tbody>+</table>+<p>Lorem yipsum</p>+```
@@ -0,0 +1,34 @@+```+% pandoc -f native -t latex+[ Para+ [ Strikeout+ [ Link+ ( "" , [] , [] )+ [ Str "Example" ]+ ( "https://example.com" , "" )+ ]+ ]+, Para+ [ Strikeout+ [ Link+ ( "" , [] , [] )+ [ Str "https://example.com" ]+ ( "https://example.com" , "" )+ ]+ ]+, Para+ [ Strikeout+ [ Link+ ( "" , [] , [] )+ [ Str "info@example.com" ]+ ( "mailto:info@example.com" , "" )+ ]+ ]+]+^D+\st{\mbox{\href{https://example.com}{Example}}}++\st{\mbox{\url{https://example.com}}}++\st{\mbox{\href{mailto:info@example.com}{\nolinkurl{info@example.com}}}}+```
@@ -0,0 +1,30 @@+```+% pandoc -t latex+"'In this case (A),++I get a kern to separate the quotes,' he said."++"'Also in this case (B), I get a kern,' he added."++"'But in this case (C), there is no kern,'++he continued."++"He concluded,++'Nor in this case (D) is there a kern.'"+^D+``\,'In this case (A),++I get a kern to separate the quotes,' he said.''++``\,`Also in this case (B), I get a kern,' he added.''++``\,`But in this case (C), there is no kern,'++he continued.''++``He concluded,++`Nor in this case (D) is there a kern.'\,''+```
@@ -0,0 +1,17 @@+```+% pandoc -t typst --wrap=preserve+A string of text that is long enough that after 73 chars that includes a+/ slash creates a newline+^D+A string of text that is long enough that after 73 chars that includes a+\/ slash creates a newline+```++```+% pandoc -t typst --wrap=preserve+A string of text that is long enough that after 73 chars that includes+a / slash creates a newline+^D+A string of text that is long enough that after 73 chars that includes+a / slash creates a newline+```
@@ -0,0 +1,23 @@+```+% pandoc -f html -t typst+<div id="my label">+<p>test</p>+</div>+<p>See <a href="#my label">my label</a>.</p>+^D+#block[+test++] #label("my label")+See #link(label("my label"))[my label].++```++```+% pandoc -f latex -t typst+\cite{10.1117/12.695309}+\cite{foo}+^D+#cite(label("10.1117/12.695309")) @foo++```
@@ -0,0 +1,21 @@+```+% pandoc -f latex -t native+\begin{figure}+\centering+\includegraphics[width=0.5\linewidth,height=0.5\textheight]{figures/placeholder}+\caption{Example figure}+\end{figure}+^D+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing [ Plain [ Str "Example" , Space , Str "figure" ] ])+ [ Plain+ [ Image+ ( "" , [] , [ ( "width" , "50%" ) , ( "height" , "50%" ) ] )+ []+ ( "figures/placeholder" , "" )+ ]+ ]+]+```
binary file changed (absent → 13701 bytes)
@@ -0,0 +1,9 @@+```+% pandoc command/9391.docx -t html+^D+<p>Lorem ipsum.</p>+<figure>+<img src="media/image1.png" style="width:1.09702in;height:1.09702in" />+<figcaption><p>Blue square.</p></figcaption>+</figure>+```
@@ -0,0 +1,13 @@+```+% pandoc --embed-resources+{.inline-svg}+^D+<p><svg id="svg_e1815ef374a63cf552e4" role="img" width="504pt" height="360pt" viewBox="0 0 504 360">+<defs>+<clipPath id="svg_e1815ef374a63cf552e4_clip1-c3ce354c">+ <path />+</clipPath>+</defs>+<g clip-path="url(#svg_e1815ef374a63cf552e4_clip1-c3ce354c)" clip-rule="nonzero"></g>+</svg></p>+```
@@ -0,0 +1,9 @@+<?xml version="1.0" encoding="UTF-8"?>+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="504pt" height="360pt" viewBox="0 0 504 360" version="1.1">+<defs>+<clipPath id="clip1-c3ce354c">+ <path/>+</clipPath>+</defs>+<g clip-path="url(#clip1-c3ce354c)" clip-rule="nonzero"></g>+</svg>
@@ -0,0 +1,6 @@+```+% pandoc -f man -t markdown+\fB--c \fI<file>+^D+**\--c** *\<file\>*+```
@@ -0,0 +1,19 @@+```+% pandoc -t typst+@something2024 says blah.++Here is a sentence [@something2024].++With supplement [@something2024, p. 3].++And just the year [-@something2024].+^D+#cite(<something2024>, form: "prose") says blah.++Here is a sentence @something2024.++With supplement @something2024[p.~3].++And just the year (#cite(<something2024>, form: "year")).++```
@@ -0,0 +1,7 @@+```+% pandoc --embed-resources++^D+<p><img role="img" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTkiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB2ZXJzaW9uPSIxLjEiIGlkPSJzdmcyIiB3aWR0aD0iMTkxLjU2MjY3IiBoZWlnaHQ9IjE1MS43MTIwMSIgdmlld0JveD0iMCAwIDE5MS41NjI2NyAxNTEuNzEyMDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGRlZnMgaWQ9ImRlZnM2Ij4KICAgIDxjbGlwUGF0aCBjbGlwUGF0aFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9ImNsaXBQYXRoMjQiPgogICAgICA8cGF0aCBkPSJNIDU2LjY5MzYyLDAgMTEzLjM4NzI0LDExMy4zODcyNCAxNzAuMDgwODYsMCBaIiBpZD0icGF0aDIyIiAvPgogICAgPC9jbGlwUGF0aD4KICAgIDxjbGlwUGF0aCBjbGlwUGF0aFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9ImNsaXBQYXRoMzgiPgogICAgICA8cGF0aCBkPSJNIDAsMCBIIDEwMCBWIDEwMCBIIDAgWiIgaWQ9InBhdGgzNiIgLz4KICAgIDwvY2xpcFBhdGg+CiAgICA8cmFkaWFsR3JhZGllbnQgZng9IjUwLjAwMDY0MSIgZnk9IjUwLjAwMDY0MSIgY3g9IjUwLjAwMDY0MSIgY3k9IjUwLjAwMDY0MSIgcj0iNTAuMDAwNjQxIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9InJhZGlhbEdyYWRpZW50NDYiPgogICAgICA8c3RvcCBzdHlsZT0ic3RvcC1vcGFjaXR5OjE7c3RvcC1jb2xvcjojZmZmZmZmIiBvZmZzZXQ9IjAiIGlkPSJzdG9wNDAiIC8+CiAgICAgIDxzdG9wIHN0eWxlPSJzdG9wLW9wYWNpdHk6MTtzdG9wLWNvbG9yOiM5OTk5ZmYiIG9mZnNldD0iMjUuMDAwMzIiIGlkPSJzdG9wNDIiIC8+CiAgICAgIDxzdG9wIHN0eWxlPSJzdG9wLW9wYWNpdHk6MTtzdG9wLWNvbG9yOiM5OTk5ZmYiIG9mZnNldD0iNTAuMDAwNjQiIGlkPSJzdG9wNDQiIC8+CiAgICA8L3JhZGlhbEdyYWRpZW50PgogIDwvZGVmcz4KICA8ZyBpZD0iZzgiIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDE1MS43MTIpIj4KICAgIDxnIGlkPSJnMTAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yNi42MDYsMC4xOTkpIj4KICAgICAgPGcgaWQ9ImcxMiI+CiAgICAgICAgPGcgaWQ9ImcxNCI+CiAgICAgICAgICA8ZyBpZD0iZzE2Ij4KICAgICAgICAgICAgPGcgaWQ9ImcxOCI+CiAgICAgICAgICAgICAgPGcgaWQ9ImcyMCIgY2xpcC1wYXRoPSJ1cmwoI2NsaXBQYXRoMjQpIj4KICAgICAgICAgICAgICAgIDxnIGlkPSJnMjYiIHRyYW5zZm9ybT0ibWF0cml4KDIuMjY4MDIsMCwwLDIuMjY4MDIsMTEzLjM4NzI0LDU2LjY5MzYyKSI+CiAgICAgICAgICAgICAgICAgIDxnIGlkPSJnMjgiPgogICAgICAgICAgICAgICAgICAgIDxnIGlkPSJnMzAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01MCwtNTApIj4KICAgICAgICAgICAgICAgICAgICAgIDxnIGlkPSJnMzIiPgogICAgICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iZzM0IiBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgzOCkiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0gMCwwIEggMTAwIFYgMTAwIEggMCBaIiBzdHlsZT0iZmlsbDp1cmwoI3JhZGlhbEdyYWRpZW50NDYpO3N0cm9rZTpub25lIiBpZD0icGF0aDQ4IiAvPgogICAgICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0gNTYuNjkzNjIsMCAxMTMuMzg3MjQsMTEzLjM4NzI0IDE3MC4wODA4NiwwIFoiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM5OTk5ZmY7c3Ryb2tlLXdpZHRoOjAuMzk4NTtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtZGFzaGFycmF5Om5vbmU7c3Ryb2tlLW9wYWNpdHk6MSIgaWQ9InBhdGg1MCIgLz4KICAgICAgICAgICAgPGcgaWQ9Imc1MiI+CiAgICAgICAgICAgICAgPGcgaWQ9Imc1NCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjMuMzM3LDUuNDU3KSI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iZzU2Ij4KICAgICAgICAgICAgICAgICAgPGcgaWQ9Imc1OCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTM2LjczMSwtNS42NTYpIj4KICAgICAgICAgICAgICAgICAgICA8dGV4dCB4bWw6c3BhY2U9InByZXNlcnZlIiB0cmFuc2Zvcm09Im1hdHJpeCgxLDAsMCwtMSwzNi43MzEsNS42NTYpIiBzdHlsZT0iZm9udC12YXJpYW50Om5vcm1hbDtmb250LXdlaWdodDpub3JtYWw7Zm9udC1zaXplOjkuOTYyNnB4O2ZvbnQtZmFtaWx5OkNNU1MxMDstaW5rc2NhcGUtZm9udC1zcGVjaWZpY2F0aW9uOkNNU1MxMDt3cml0aW5nLW1vZGU6bHItdGI7ZmlsbDojOTk5OWZmO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiBpZD0idGV4dDYyIj48dHNwYW4geD0iMCA0Ljk4MTI5OTkgOC4zODU1MiAxMy4xNzM1NDYgMTguMzIxMjIyIDIwLjcwMTI4NiAyNS4xMjg2NjYgMzAuMjc2MzQgMzcuMTkxMzgzIDQxLjAxMDA0OCA0Ni4xNTc3MjIgNTAuOTQ1NzQ3IDU2LjA5MzQyMiA2MC41MjA4MDIgNjguOTk1OTg3IDcyLjU5MzQ4MyA3NS45OTc3MDQgNzguMzc3NzY5IDgzLjE2NTc5NCA4OC4zMDM1MDUgOTMuMjg0ODA1IDk1LjY2NDg3MSIgeT0iMCIgaWQ9InRzcGFuNjAiPmdyYWRpZW50c2hhZGVkdHJpYW5nbGU8L3RzcGFuPjwvdGV4dD4KICAgICAgICAgICAgICAgICAgICA8ZyBpZD0iZzY0IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzNi43MzEsNS42NTYpIiAvPgogICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iZzY2IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNjMuMzM3LC01LjQ1NykiIC8+CiAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgICA8L2c+CiAgICAgICAgPC9nPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K" /></p>++```
@@ -0,0 +1,56 @@+<?xml version="1.0" encoding="UTF-9" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ version="1.1" id="svg2" width="191.56267" height="151.71201" viewBox="0 0 191.56267 151.71201" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">+ <defs id="defs6">+ <clipPath clipPathUnits="userSpaceOnUse" id="clipPath24">+ <path d="M 56.69362,0 113.38724,113.38724 170.08086,0 Z" id="path22" />+ </clipPath>+ <clipPath clipPathUnits="userSpaceOnUse" id="clipPath38">+ <path d="M 0,0 H 100 V 100 H 0 Z" id="path36" />+ </clipPath>+ <radialGradient fx="50.000641" fy="50.000641" cx="50.000641" cy="50.000641" r="50.000641" gradientUnits="userSpaceOnUse" id="radialGradient46">+ <stop style="stop-opacity:1;stop-color:#ffffff" offset="0" id="stop40" />+ <stop style="stop-opacity:1;stop-color:#9999ff" offset="25.00032" id="stop42" />+ <stop style="stop-opacity:1;stop-color:#9999ff" offset="50.00064" id="stop44" />+ </radialGradient>+ </defs>+ <g id="g8" transform="matrix(1.3333333,0,0,-1.3333333,0,151.712)">+ <g id="g10" transform="translate(-26.606,0.199)">+ <g id="g12">+ <g id="g14">+ <g id="g16">+ <g id="g18">+ <g id="g20" clip-path="url(#clipPath24)">+ <g id="g26" transform="matrix(2.26802,0,0,2.26802,113.38724,56.69362)">+ <g id="g28">+ <g id="g30" transform="translate(-50,-50)">+ <g id="g32">+ <g id="g34" clip-path="url(#clipPath38)">+ <path d="M 0,0 H 100 V 100 H 0 Z" style="fill:url(#radialGradient46);stroke:none" id="path48" />+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+ <path d="M 56.69362,0 113.38724,113.38724 170.08086,0 Z" style="fill:none;stroke:#9999ff;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" id="path50" />+ <g id="g52">+ <g id="g54" transform="translate(63.337,5.457)">+ <g id="g56">+ <g id="g58" transform="translate(-36.731,-5.656)">+ <text xml:space="preserve" transform="matrix(1,0,0,-1,36.731,5.656)" style="font-variant:normal;font-weight:normal;font-size:9.9626px;font-family:CMSS10;-inkscape-font-specification:CMSS10;writing-mode:lr-tb;fill:#9999ff;fill-opacity:1;fill-rule:nonzero;stroke:none" id="text62"><tspan x="0 4.9812999 8.38552 13.173546 18.321222 20.701286 25.128666 30.27634 37.191383 41.010048 46.157722 50.945747 56.093422 60.520802 68.995987 72.593483 75.997704 78.377769 83.165794 88.303505 93.284805 95.664871" y="0" id="tspan60">gradientshadedtriangle</tspan></text>+ <g id="g64" transform="translate(36.731,5.656)" />+ </g>+ </g>+ <g id="g66" transform="translate(-63.337,-5.457)" />+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+ </g>+</svg>
@@ -0,0 +1,85 @@+```+% pandoc -t latex -s+---+lang: de-DE+---++More text in English. ['Zitat auf Deutsch.']{lang=de}++[Bonjour]{lang=fr} [café]{lang="fr-FR"}+^D+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+ french,+ ngerman,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+ \usepackage[T1]{fontenc}+ \usepackage[utf8]{inputenc}+ \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+ \usepackage{unicode-math} % this also loads fontspec+ \defaultfontfeatures{Scale=MatchLowercase}+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+ % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+ \usepackage[]{microtype}+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+ \IfFileExists{parskip.sty}{%+ \usepackage{parskip}+ }{% else+ \setlength{\parindent}{0pt}+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+ \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+ \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+ pdflang={de-DE},+ hidelinks,+ pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++More text in English. \foreignlanguage{ngerman}{`Zitat auf Deutsch.'}++\foreignlanguage{french}{Bonjour} \foreignlanguage{french}{café}++\end{document}++```
@@ -0,0 +1,102 @@+```+% pandoc -f org -t native+#+begin_note+Useful note.+#+end_note++#+begin_warning+Be careful!+#+end_warning++#+begin_tip+Try this...+#+end_tip++#+begin_caution+Caution+#+end_caution++#+name: foo+#+begin_important+Important+#+end_important+^D+[ Div+ ( "" , [ "note" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Note" ] ]+ , Para [ Str "Useful" , Space , Str "note." ]+ ]+, Div+ ( "" , [ "warning" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Warning" ] ]+ , Para [ Str "Be" , Space , Str "careful!" ]+ ]+, Div+ ( "" , [ "tip" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Tip" ] ]+ , Para [ Str "Try" , Space , Str "this\8230" ]+ ]+, Div+ ( "" , [ "caution" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Caution" ] ]+ , Para [ Str "Caution" ]+ ]+, Div+ ( "foo" , [ "important" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Important" ] ]+ , Para [ Str "Important" ]+ ]+]++```++```+% pandoc -f native -t org+[ Div+ ( "" , [ "note" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Note" ] ]+ , Para [ Str "Useful" , Space , Str "note." ]+ ]+, Div+ ( "" , [ "warning" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Warning" ] ]+ , Para [ Str "Be" , Space , Str "careful!" ]+ ]+, Div+ ( "" , [ "tip" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Tip" ] ]+ , Para [ Str "Try" , Space , Str "this\8230" ]+ ]+, Div+ ( "" , [ "caution" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Caution" ] ]+ , Para [ Str "Caution" ]+ ]+, Div+ ( "foo" , [ "important" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Important" ] ]+ , Para [ Str "Important" ]+ ]+]+^D+#+begin_note+Useful note.+#+end_note++#+begin_warning+Be careful!+#+end_warning++#+begin_tip+Try this...+#+end_tip++#+begin_caution+Caution+#+end_caution++#+name: foo+#+begin_important+Important+#+end_important+```
@@ -0,0 +1,9 @@+```+% pandoc -t typst --wrap=preserve+**- a -+- b**+^D+#strong[\- a -+\- b]+```+
@@ -0,0 +1,7 @@+```+% pandoc -f markdown+wikilinks_title_after_pipe+[a](https://example.com)+^D+<p><a href="https://example.com">a</a></p>++```
@@ -0,0 +1,17 @@+```+% pandoc --number-sections+# One {-}++# Two++# Three {-}++# Four+^D+<h1 class="unnumbered" id="one">One</h1>+<h1 data-number="1" id="two"><span+class="header-section-number">1</span> Two</h1>+<h1 class="unnumbered" id="three">Three</h1>+<h1 data-number="2" id="four"><span+class="header-section-number">2</span> Four</h1>+```
@@ -0,0 +1,34 @@+```+% pandoc -f latex+raw_tex -t native+\begin{tabular}{l}+\begin{theorem}+Cats+\end{theorem}+\end{tabular}+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault ) ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ RawBlock+ (Format "latex")+ "\\begin{theorem}\nCats\n\\end{theorem}"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+```
@@ -0,0 +1,13 @@+```+% pandoc -t native -f latex+a\@ b\@c++\makeatletter+a\@ b\@c+\makeatother+a\@ b\@c+^D+[ Para [ Str "a" , Space , Str "bc" ]+, Para [ Str "ab" , SoftBreak , Str "a" , Space , Str "bc" ]+]+```
@@ -0,0 +1,19 @@+```+% pandoc -f docbook -t gfm+<note>+ <para>Some content</para>+</note>+<para>Spacer.</para>+<note>+ <title>A note with a title. Works, but the title is discarded.</title>+ <para>Some content</para>+</note>+^D+> [!NOTE]+> Some content++Spacer.++> [!NOTE]+> Some content+```
@@ -0,0 +1,23 @@+```+% pandoc -t native+::: {#something}+Text with a footnote.[^3]++[^3]: A footnote.+:::+^D+[ Div+ ( "something" , [] , [] )+ [ Para+ [ Str "Text"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "footnote."+ , Note [ Para [ Str "A" , Space , Str "footnote." ] ]+ ]+ ]+]+```
@@ -0,0 +1,46 @@+```+% pandoc -t native+\begin{tabular}{p{2in}}+\end{tabular}++# Test++\begin{tabular}{p{2\linewidth}}+\end{tabular}+^D+[ RawBlock+ (Format "tex") "\\begin{tabular}{p{2in}}\n\\end{tabular}"+, Header 1 ( "test" , [] , [] ) [ Str "Test" ]+, RawBlock+ (Format "tex")+ "\\begin{tabular}{p{2\\linewidth}}\n\\end{tabular}"+]+```++```+% pandoc -f latex -t native+\begin{tabular}{p{2in}}+\end{tabular}++Test++\begin{tabular}{p{2\linewidth}}+\end{tabular}+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault ) ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot ( "" , [] , [] ) [])+, Para [ Str "Test" ]+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidth 2.0 ) ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot ( "" , [] , [] ) [])+]+```
@@ -0,0 +1,11 @@+```+% pandoc -f native -t typst+[ Header 2 ( "" , [] , [] ) [ Str "One" ]+, Header 2 ( "" , [ "unnumbered", "unlisted" ] , [] ) [ Str "Two" ]+, Header 2 ( "" , [] , [] ) [ Str "Three" ]+]+^D+== One+#heading(level: 2, outlined: false, numbering: none)[Two]+== Three+```
@@ -0,0 +1,7 @@+```+% pandoc -t typst+**1. April 2024**+^D+#strong[\1. April 2024]++```
@@ -0,0 +1,6 @@+```+% pandoc -t latex+~~$T$~~+^D+\st{$T$}+```
binary file changed (absent → 13799 bytes)
@@ -0,0 +1,23 @@+```+% pandoc command/9603.docx -t html -f docx+styles+^D+<p>A table with a contemporary style:</p>+<table data-custom-style="TableContemporary">+<colgroup>+<col style="width: 50%" />+<col style="width: 50%" />+</colgroup>+<thead>+<tr>+<th>Test</th>+<th>Column</th>+</tr>+</thead>+<tbody>+<tr>+<td>1</td>+<td>2</td>+</tr>+</tbody>+</table>+```
@@ -0,0 +1,16 @@+```+% pandoc -f bibtex -t csljson -s+@MISC {3252037,+ TITLE = {Isomorphism between projective varieties $\mathbf{P}^{1}$ and a conic in $\mathbf{P}^{2}$},+ URL = {https://math.stackexchange.com/q/3252037}+}+^D+[+ {+ "URL": "https://math.stackexchange.com/q/3252037",+ "id": "3252037",+ "title": "Isomorphism between projective varieties $\\mathbf{P}^{1}$ and a conic in $\\mathbf{P}^{2}$",+ "type": ""+ }+]+```
@@ -0,0 +1,12 @@+```+% pandoc -f dokuwiki+ * [[https://example.com|https://example.com]]+ * [[https://example.com/start#monitoring|https://example.com/start#monitoring]]+^D+<ul>+<li><a href="https://example.com">https://example.com</a></li>+<li><a+href="https://example.com/start#monitoring">https://example.com/start#monitoring</a></li>+</ul>++```
@@ -0,0 +1,7 @@+```+% pandoc -f dokuwiki+[[.:supprimer-profil-windows|]]+^D+<p><a href="supprimer-profil-windows">supprimer-profil-windows</a></p>++```
@@ -0,0 +1,16 @@+```+% pandoc+> ::: {.fence}+> that is+> not closed++okay+^D+2> [WARNING] Div at _chunk line 1 column 1 unclosed at _chunk line 5 column 1, closing implicitly.+<blockquote>+<div class="fence">+<p>that is not closed</p>+</div>+</blockquote>+<p>okay</p>+```
@@ -0,0 +1,11 @@+```+% pandoc -f org -t native+#+title: repro++* heading-name+:PROPERTIES:+:ID: 123abc+:END:+^D+[ Header 1 ( "123abc" , [] , [] ) [ Str "heading-name" ] ]+```
@@ -0,0 +1,7 @@+```+% pandoc -t latex+[$T$]{.underline}+[$T$]{.mark}+^D+\ul{$T$} \hl{$T$}+```
@@ -0,0 +1,9 @@+````+% pandoc -f markdown -t html --embed-resources+```{=html}+<img class="something inline-svg" src="command/9652.svg" />+```+^D+<svg id="svg_b627f92299158b36552b" role="img" width="504.00pt" height="360.00pt" viewBox="0 0 504.00 360.00" class="something inline-svg please-do-not-delete-me">+</svg>+````
@@ -0,0 +1,3 @@+<?xml version='1.0' encoding='UTF-8' ?>+<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' class='please-do-not-delete-me' width='504.00pt' height='360.00pt' viewBox='0 0 504.00 360.00'>+</svg>
@@ -0,0 +1,7 @@+```+% pandoc -t opendocument+[Text here]{custom-style="Strikethrough"}+^D+<text:p text:style-name="Text_20_body"><text:span text:style-name="Strikethrough">Text+here</text:span></text:p>+```
@@ -0,0 +1,9 @@+```+% pandoc -f latex+\def\foo{BAR}+\foo+\ifstrequal{BAR}{BAR}{\def\foo{BAZ}}{}+\foo+^D+<p>BAR BAZ</p>+```
@@ -0,0 +1,14 @@+```+% pandoc -t mediawiki+This is a normal sentence with a manual text footnote\*++\* The footnote explains why it couldn't just be inside parentheses++\#foobar \#foobar+^D+This is a normal sentence with a manual text footnote*++<nowiki></nowiki>* The footnote explains why it couldn’t just be inside parentheses++<nowiki></nowiki>#foobar #foobar+```
@@ -0,0 +1,13 @@+```+% pandoc -f markdown+alerts -t native+> [!TIP]+> A suggestion.+^D+[ Div+ ( "" , [ "tip" ] , [] )+ [ Div ( "" , [ "title" ] , [] ) [ Para [ Str "Tip" ] ]+ , Para [ Str "A" , Space , Str "suggestion." ]+ ]+]++```
@@ -0,0 +1,62 @@+```+% pandoc -f native -t typst+[ Table+ ( "" , [] , [ ( "typst:figure:kind" , "figure" ) ] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "f" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "b" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+^D+#figure(+ align(center)[#table(+ columns: 2,+ align: (auto,auto,),+ table.header([f], [b],),+ table.hline(),+ [1], [2],+ )]+ , kind: figure+ )+```+
@@ -0,0 +1,58 @@+```+% pandoc -f native -t typst+[ Table+ ( "" , [ "typst:no-figure" ] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "f" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "b" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+^D+#table(+ columns: 2,+ align: (auto,auto,),+ table.header([f], [b],),+ table.hline(),+ [1], [2],+)+```
@@ -0,0 +1,21 @@+```+% pandoc -t gfm+- list item+ <details>++ - subitem+ </details>++ item _continue_ **with** formatting+- next list item+^D+- list item+ <details>++ - subitem++ </details>++ item *continue* **with** formatting+- next list item+```
@@ -0,0 +1,39 @@+```+% pandoc -t native -f csv+"one_line_break:+four_line_breaks:++++last_line"+^D+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault ) ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain+ [ Str "one_line_break:"+ , LineBreak+ , Str "four_line_breaks:"+ , LineBreak+ , LineBreak+ , LineBreak+ , LineBreak+ , Str "last_line"+ ]+ ]+ ]+ ])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot ( "" , [] , [] ) [])+]+```
@@ -0,0 +1,10 @@+```+% pandoc -f rst -t native+word.*word+------------+* abc+^D+[ Header 1 ( "word.word" , [] , [] ) [ Str "word.*word" ]+, BulletList [ [ Plain [ Str "abc" ] ] ]+]+```
@@ -0,0 +1,13 @@+```+% pandoc -f typst -t native+#let foo = [+ bar baz+]+*#foo*+^D+[ Para+ [ Strong+ [ SoftBreak , Str "bar" , Space , Str "baz" , SoftBreak ]+ ]+]+```
@@ -0,0 +1,14 @@+```+% pandoc -f html -t native+<ul>+ <li>Bullet point.</li>+ <p>Nested line.</p>+</ul>+^D+[ BulletList+ [ [ Para [ Str "Bullet" , Space , Str "point." ]+ , Para [ Str "Nested" , Space , Str "line." ]+ ]+ ]+]+```
@@ -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}"+ ]+] ```
@@ -0,0 +1,53 @@+````+% pandoc+- example 1+- ```+ one+ two+ ```+- list item three+^D+<ul>+<li>example 1</li>+<li><pre><code>one+two</code></pre></li>+<li>list item three</li>+</ul>+````++````+% pandoc+- example 3+- ```+one+two+```+- list item three+^D+<ul>+<li>example 3</li>+<li><pre><code>one+two</code></pre></li>+<li>list item three</li>+</ul>+````++Here is a case that we used to handle differently, but+#9865 aligns pandoc's markdown parser with commonmark in letting+block level structure take precedence over inline level structure.++````+% pandoc+- a <!--++- b++-->+- c+^D+<ul>+<li><p>a <!–</p></li>+<li><p>b</p></li>+</ul>+<p>–> - c</p>+````
@@ -0,0 +1,12 @@+```+% pandoc -f textile -t native+15% 50%+^D+[ Para [ Str "15%" , Space , Str "50%" ] ]+```+```+% pandoc -f textile -t native+15%. 70%+^D+[ Para [ Str "15%." , Space , Str "70%" ] ]+```
@@ -0,0 +1,6 @@+```+% pandoc -t native -f latex+raw_tex+\kern.1pt+^D+[ RawBlock (Format "latex") "\\kern.1pt" ]+```
@@ -0,0 +1,180 @@+```+% pandoc -f rst -t native --citeproc --bibliography command/biblio.bib+The axioms were introduced by :cite:t:`{see}item1`.+The axioms were introduced by :cite:t:`item1{p. 1166}`.+The axioms were introduced by :cite:t:`{see}item1{p. 1166}`.+Axioms were introduced :cite:`{see}item1`.+Axioms were introduced :cite:p:`item1{p. 1166}`.+Axioms were introduced :cite:p:`{see}item1{p. 1166}`.++.. bibliography::+^D+[ Para+ [ Str "The"+ , Space+ , Str "axioms"+ , Space+ , Str "were"+ , Space+ , Str "introduced"+ , Space+ , Str "by"+ , Space+ , Cite+ [ Citation+ { citationId = "item1"+ , citationPrefix = [ Str "see" ]+ , citationSuffix = []+ , citationMode = AuthorInText+ , citationNoteNum = 0+ , citationHash = 0+ }+ ]+ [ Str "(see" , Space , Str "Doe;" , Space , Str "2005)" ]+ , Str "."+ , SoftBreak+ , Str "The"+ , Space+ , Str "axioms"+ , Space+ , Str "were"+ , Space+ , Str "introduced"+ , Space+ , Str "by"+ , Space+ , Cite+ [ Citation+ { citationId = "item1"+ , citationPrefix = []+ , citationSuffix = [ Str "p." , Space , Str "1166" ]+ , citationMode = AuthorInText+ , citationNoteNum = 0+ , citationHash = 0+ }+ ]+ [ Str "Doe" , Space , Str "(2005," , Space , Str "1166)" ]+ , Str "."+ , SoftBreak+ , Str "The"+ , Space+ , Str "axioms"+ , Space+ , Str "were"+ , Space+ , Str "introduced"+ , Space+ , Str "by"+ , Space+ , Cite+ [ Citation+ { citationId = "item1"+ , citationPrefix = [ Str "see" ]+ , citationSuffix = [ Str "p." , Space , Str "1166" ]+ , citationMode = AuthorInText+ , citationNoteNum = 0+ , citationHash = 0+ }+ ]+ [ Str "(see"+ , Space+ , Str "Doe;"+ , Space+ , Str "2005,"+ , Space+ , Str "1166)"+ ]+ , Str "."+ , SoftBreak+ , Str "Axioms"+ , Space+ , Str "were"+ , Space+ , Str "introduced"+ , Space+ , Cite+ [ Citation+ { citationId = "item1"+ , citationPrefix = [ Str "see" ]+ , citationSuffix = []+ , citationMode = NormalCitation+ , citationNoteNum = 0+ , citationHash = 0+ }+ ]+ [ Str "(see" , Space , Str "Doe" , Space , Str "2005)" ]+ , Str "."+ , SoftBreak+ , Str "Axioms"+ , Space+ , Str "were"+ , Space+ , Str "introduced"+ , Space+ , Cite+ [ Citation+ { citationId = "item1"+ , citationPrefix = []+ , citationSuffix = [ Str "p." , Space , Str "1166" ]+ , citationMode = NormalCitation+ , citationNoteNum = 0+ , citationHash = 0+ }+ ]+ [ Str "(Doe" , Space , Str "2005," , Space , Str "1166)" ]+ , Str "."+ , SoftBreak+ , Str "Axioms"+ , Space+ , Str "were"+ , Space+ , Str "introduced"+ , Space+ , Cite+ [ Citation+ { citationId = "item1"+ , citationPrefix = [ Str "see" ]+ , citationSuffix = [ Str "p." , Space , Str "1166" ]+ , citationMode = NormalCitation+ , citationNoteNum = 0+ , citationHash = 0+ }+ ]+ [ Str "(see"+ , Space+ , Str "Doe"+ , Space+ , Str "2005,"+ , Space+ , Str "1166)"+ ]+ , Str "."+ ]+, Div+ ( "refs"+ , [ "references" , "csl-bib-body" , "hanging-indent" ]+ , []+ )+ [ Div+ ( "ref-item1" , [ "csl-entry" ] , [] )+ [ Para+ [ Str "Doe,"+ , Space+ , Str "John."+ , Space+ , Str "2005."+ , Space+ , Emph [ Str "First" , Space , Str "Book" ]+ , Str "."+ , Space+ , Str "Cambridge"+ , Space+ , Str "University"+ , Space+ , Str "Press."+ ]+ ]+ ]+]++```
@@ -0,0 +1,20 @@+```+% pandoc -t html5+# Section Ψ {#Ψ}++look at [Section Ψ](#Ψ).+^D+<h1 id="Ψ">Section Ψ</h1>+<p>look at <a href="#Ψ">Section Ψ</a>.</p>++```+```+% pandoc -t html4+# Section Ψ {#Ψ}++look at [Section Ψ](#Ψ).+^D+<h1 id="Ψ">Section Ψ</h1>+<p>look at <a href="#%CE%A8">Section Ψ</a>.</p>++```
@@ -0,0 +1,10 @@+```+% pandoc -f native -t markdown+[ BulletList+ [ [ BlockQuote [ Para [ Str "a" ] , Para [ Str "b" ] ] ] ]+]+^D+- > a+ >+ > b+```
@@ -0,0 +1,24 @@+```+% pandoc -t man -s -Vpandoc-version=X.Y+---+title: HELLO+section: 1+---+^D+.\" Automatically generated by Pandoc X.Y+.\"+.TH "HELLO" "1" "" ""+```++```+% pandoc -t man -s -Vpandoc-version=X.Y+---+title: HELLO+section: 1+header: Head+---+^D+.\" Automatically generated by Pandoc X.Y+.\"+.TH "HELLO" "1" "" "" "Head"+```
@@ -0,0 +1,28 @@+```+% pandoc -t typst --dpi 300+{width=300 height=300}+^D+#box(image("image.jpg", height: 1in, width: 1in))+```++```+% pandoc -t typst --dpi 600+{width=300px height=300px}+^D+#box(image("image.jpg", height: 0.5in, width: 0.5in))+```++```+% pandoc -t typst --dpi 600+{width=1in height=3cm}+^D+#box(image("image.jpg", height: 3cm, width: 1in))+```+++```+% pandoc -t typst --dpi 600+{.foo .bar baz=3}+^D+#box(image("image.jpg"))+```
@@ -0,0 +1,29 @@+```+% pandoc -f markdown -t native -s+---+header-includes: |+ \makeatletter+ \let\old@verbatim@font=\verbatim@font+ \def\verbatim@font{%+ \fontsize{10}{12}%+ \old@verbatim@font+ }+ \makeatother+...+^D+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "header-includes"+ , MetaBlocks+ [ RawBlock+ (Format "tex")+ "\\makeatletter\n\\let\\old@verbatim@font=\\verbatim@font\n\\def\\verbatim@font{%\n\\fontsize{10}{12}%\n\\old@verbatim@font\n}\n\\makeatother"+ ]+ )+ ]+ }+ []++```
@@ -0,0 +1,10 @@+```+% pandoc -f bibtex -t bibtex+@misc{agency,+ author = {{European Environment Agency}},+}+^D+@misc{agency,+ author = {{European Environment Agency}}+}+```
@@ -0,0 +1,55 @@+```+% pandoc -f rst -t gfm+.. note::+ This is my note.+^D+> [!NOTE]+> This is my note.+```++```+% pandoc -f gfm -t rst+> [!WARNING]+> Be careful!+^D+.. warning::++ Be careful!+```++```+% pandoc -f gfm -t asciidoc+> [!TIP]+> A tip.+^D+[TIP]+====+A tip.+====+```++```+% pandoc -f gfm -t docbook+> [!TIP]+> A tip.+^D+<tip>+ <title>Tip</title>+ <para>+ A tip.+ </para>+</tip>+```++```+% pandoc -f docbook -t gfm+<tip>+ <title>Tip</title>+ <para>+ A tip.+ </para>+</tip>+^D+> [!TIP]+> A tip.+```
@@ -17,7 +17,7 @@ äéıå ^D .PP-\[:a]\['e]\[.i]\[oa]+\(:a\('e\(.i\(oa ``` ```@@ -25,7 +25,7 @@ äéıå ^D .LP-\[:a]\['e]\[.i]\[oa]+\(:a\('e\(.i\(oa ``` ```
@@ -0,0 +1,19 @@+```+% pandoc --citeproc --csl command/chicago-fullnote-bibliography.csl -t plain+---+references:+- id: foo+ type: book+ author: John Doe+ title: A Book+...++See @foo [p. 21], as well.+^D+See John Doe,[1] as well.++John Doe. A Book, n.d.++[1] A Book, n.d., 21.+```+
@@ -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
@@ -53,7 +53,7 @@ publisher: Publisher publisher-place: Location title: Macbeth \[title field of bookinbook-1\]- type: chapter+ type: book volume: 3 volume-title: Tragedies \[title field of book-1\] - author:
@@ -0,0 +1,104 @@+```+% pandoc -f jats -t native -s+<book>+ <book-meta>+ <book-id book-id-type="publisher">handbook-648</book-id>+ <book-title-group>+ <book-title>The NCBI Handbook</book-title>+ </book-title-group>+ <contrib-group>+ <contrib contrib-type="author">+ <name><surname>McEntyre</surname>+ <given-names>Jo</given-names></name>+ <xref ref-type="aff" rid="bid.m.1"/>+ </contrib>+ <contrib contrib-type="editor">+ <name><surname>Ostell</surname>+ <given-names>Jim</given-names></name>+ <xref ref-type="aff" rid="bid.m.1"/>+ </contrib>+ </contrib-group>+ <aff id="bid.m.1">+ <institution>National Center for Biotechnology Information (NCBI), National Library of Medicine, National Institutes of Health</institution>, <addr-line>Bethesda, MD 20892-6510</addr-line>+ </aff>+ <pub-date iso-8601-date="2002-11">+ <month>11</month>+ <year>2002</year>+ </pub-date>+ <publisher>+ <publisher-name>National Center for Biotechnology Information (NCBI), National Library of Medicine, National Institutes of Health</publisher-name>+ <publisher-loc>Bethesda, MD</publisher-loc>+ </publisher>+ <edition>1</edition>+ <counts>+ <book-fig-count count="98"/>+ <book-table-count count="40"/>+ <book-equation-count count="0"/>+ <book-ref-count count="115"/>+ <book-page-count count="532"/>+ <book-word-count count="149852"/>+ </counts>+ </book-meta>+</book>+^D+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "author"+ , MetaList+ [ MetaInlines [ Str "Jo" , Space , Str "McEntyre" ] ]+ )+ , ( "date" , MetaInlines [ Str "2002-11" ] )+ , ( "institute"+ , MetaList+ [ MetaInlines+ [ Str "National"+ , Space+ , Str "Center"+ , Space+ , Str "for"+ , Space+ , Str "Biotechnology"+ , Space+ , Str "Information"+ , Space+ , Str "(NCBI),"+ , Space+ , Str "National"+ , Space+ , Str "Library"+ , Space+ , Str "of"+ , Space+ , Str "Medicine,"+ , Space+ , Str "National"+ , Space+ , Str "Institutes"+ , Space+ , Str "of"+ , Space+ , Str "Health,"+ , Space+ , Str "Bethesda,"+ , Space+ , Str "MD"+ , Space+ , Str "20892-6510"+ ]+ ]+ )+ , ( "title"+ , MetaInlines+ [ Str "The"+ , Space+ , Str "NCBI"+ , Space+ , Str "Handbook"+ ]+ )+ ]+ }+ []+```
@@ -0,0 +1,95 @@+```+% pandoc -f jats -t native -s+<book-part-wrapper + dtd-version="2.1"+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"+ xmlns:xi="http://www.w3.org/2001/XInclude"+ xmlns:mml="http://www.w3.org/1998/Math/MathML"+ xmlns:xlink="http://www.w3.org/1999/xlink">++ <collection-meta>+ <title-group>+ <title>Balisage Series on Markup Technologies</title>+ </title-group>+ + <abstract>+ <p>The <italic>Balisage Series on Markup Technologies</italic> + is an occasional series...</p>+ </abstract>+ </collection-meta>++ <book-meta>+ <book-title-group>+ <book-title>Proceedings of Balisage: The Markup Conference + 2013</book-title>+ </book-title-group>+ + <abstract>+ <p>Balisage is a peer-reviewed conference...</p></abstract>+ + </book-meta>+</book-part-wrapper>+^D+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "abstract"+ , MetaBlocks+ [ Para+ [ Str "Balisage"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "peer-reviewed"+ , Space+ , Str "conference..."+ ]+ ]+ )+ , ( "title"+ , MetaInlines+ [ Str "Proceedings"+ , Space+ , Str "of"+ , Space+ , Str "Balisage:"+ , Space+ , Str "The"+ , Space+ , Str "Markup"+ , Space+ , Str "Conference"+ , SoftBreak+ , Str "2013"+ ]+ )+ ]+ }+ [ Para+ [ Str "The"+ , Space+ , Emph+ [ Str "Balisage"+ , Space+ , Str "Series"+ , Space+ , Str "on"+ , Space+ , Str "Markup"+ , Space+ , Str "Technologies"+ ]+ , SoftBreak+ , Str "is"+ , Space+ , Str "an"+ , Space+ , Str "occasional"+ , Space+ , Str "series..."+ ]+ ]+```
@@ -0,0 +1,149 @@+```+% pandoc -f jats -t native+<book-part-wrapper + dtd-version="2.1"+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"+ xmlns:xi="http://www.w3.org/2001/XInclude"+ xmlns:mml="http://www.w3.org/1998/Math/MathML"+ xmlns:xlink="http://www.w3.org/1999/xlink">++ <collection-meta>+ <title-group>+ <title>Balisage Series on Markup Technologies</title>+ </title-group>+ + <abstract>+ <p>The <italic>Balisage Series on Markup Technologies</italic> + is an occasional series...</p>+ </abstract>+ </collection-meta>++ <book-meta>+ <book-title-group>+ <book-title>Proceedings of Balisage: The Markup Conference + 2013</book-title>+ </book-title-group>+ + <abstract>+ <p>Balisage is a peer-reviewed conference...</p></abstract>+ + </book-meta>++ <book-part id="bid.1" book-part-type="part">+ <book-part-meta>+ <title-group>+ <label>Part 1</label>+ <title>The Databases</title>+ </title-group>+ </book-part-meta>+ <body>+ <sec id="bid.3">+ <title>History</title>+ <p>Initially, GenBank was built and maintained at Los Alamos + National Laboratory.</p>+ </sec>+ </body>+ <back>+ <title>Back matter of book part</title>+ <ref-list>+ <title>References</title>+ <ref id="bid.41">+ <label>1</label>+ <element-citation>+ <person-group>+ <string-name>+ <surname>Olson</surname>+ <given-names>M</given-names>+ </string-name>+ <string-name>+ <surname>Hood</surname>+ <given-names>L</given-names>+ </string-name>+ <string-name>+ <surname>Cantor</surname>+ <given-names>C</given-names>+ </string-name>+ <string-name>+ <surname>Botstein</surname>+ <given-names>D</given-names>+ </string-name>+ </person-group>+ <article-title>A common language for physical mapping of the human genome</article-title>+ <source>Science</source>+ <year iso-8601-date="1989">1989</year>+ <volume>245</volume>+ <issue>4925</issue>+ <fpage>1434</fpage>+ <lpage>1435</lpage>+ <pub-id pub-id-type="pmid">2781285</pub-id>+ </element-citation>+ </ref>+ </ref-list>+ </back>+ </book-part>+</book-part-wrapper>+^D+[ Para+ [ Str "The"+ , Space+ , Emph+ [ Str "Balisage"+ , Space+ , Str "Series"+ , Space+ , Str "on"+ , Space+ , Str "Markup"+ , Space+ , Str "Technologies"+ ]+ , SoftBreak+ , Str "is"+ , Space+ , Str "an"+ , Space+ , Str "occasional"+ , Space+ , Str "series..."+ ]+, Header 2 ( "bid.3" , [] , [] ) [ Str "History" ]+, Para+ [ Str "Initially,"+ , Space+ , Str "GenBank"+ , Space+ , Str "was"+ , Space+ , Str "built"+ , Space+ , Str "and"+ , Space+ , Str "maintained"+ , Space+ , Str "at"+ , Space+ , Str "Los"+ , Space+ , Str "Alamos"+ , SoftBreak+ , Str "National"+ , Space+ , Str "Laboratory."+ ]+, Header+ 2+ ( "" , [] , [] )+ [ Str "Back"+ , Space+ , Str "matter"+ , Space+ , Str "of"+ , Space+ , Str "book"+ , Space+ , Str "part"+ ]+, Header 1 ( "" , [] , [] ) [ Str "References" ]+, Div ( "refs" , [] , [] ) []+]+```
@@ -0,0 +1,186 @@+```+% pandoc -f jats -t native+<book dtd-version="2.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:mml="http://www.w3.org/1998/Math/MathML">+ <front-matter>+ <front-matter-part>+ <book-part-meta>+ <title-group>+ <title>About this book</title>+ </title-group>+ </book-part-meta>+ <named-book-part-body>+ <sec sec-type="miscinfo">+ <title>The NCBI Handbook</title>+ <p>Bioinformatics consists of a computational approach+ to biomedical information management and analysis.</p>+ </sec>+ </named-book-part-body>+ </front-matter-part>+ </front-matter>+ <book-body>+ <book-part id="bid.1" book-part-type="part">+ <book-part-meta>+ <title-group>+ <label>Part 1</label>+ <title>The Databases</title>+ </title-group>+ </book-part-meta>+ <body>+ <sec id="bid.3">+ <title>History</title>+ <p>Initially, GenBank was built and maintained at Los Alamos + National Laboratory.</p>+ </sec>+ </body>+ <back>+ <title>Back matter of book part</title>+ <ref-list>+ <title>References</title>+ <ref id="bid.41">+ <label>1</label>+ <element-citation>+ <person-group>+ <string-name>+ <surname>Olson</surname>+ <given-names>M</given-names>+ </string-name>+ <string-name>+ <surname>Hood</surname>+ <given-names>L</given-names>+ </string-name>+ <string-name>+ <surname>Cantor</surname>+ <given-names>C</given-names>+ </string-name>+ <string-name>+ <surname>Botstein</surname>+ <given-names>D</given-names>+ </string-name>+ </person-group>+ <article-title>A common language for physical mapping of the human genome</article-title>+ <source>Science</source>+ <year iso-8601-date="1989">1989</year>+ <volume>245</volume>+ <issue>4925</issue>+ <fpage>1434</fpage>+ <lpage>1435</lpage>+ <pub-id pub-id-type="pmid">2781285</pub-id>+ </element-citation>+ </ref>+ </ref-list>+ </back>+ </book-part>+ </book-body>+ <book-back>+ <ack id="bid.394">+ <title>Acknowledgments</title>+ <p>We gratefully acknowledge the work of Vladimir Soussov,+ as well as the entire NCBI Entrez team...</p>+ </ack>+ </book-back>+</book>+^D+[ Header+ 2+ ( "" , [] , [] )+ [ Str "The" , Space , Str "NCBI" , Space , Str "Handbook" ]+, Para+ [ Str "Bioinformatics"+ , Space+ , Str "consists"+ , Space+ , Str "of"+ , Space+ , Str "a"+ , Space+ , Str "computational"+ , Space+ , Str "approach"+ , SoftBreak+ , Str "to"+ , Space+ , Str "biomedical"+ , Space+ , Str "information"+ , Space+ , Str "management"+ , Space+ , Str "and"+ , Space+ , Str "analysis."+ ]+, Header 2 ( "bid.3" , [] , [] ) [ Str "History" ]+, Para+ [ Str "Initially,"+ , Space+ , Str "GenBank"+ , Space+ , Str "was"+ , Space+ , Str "built"+ , Space+ , Str "and"+ , Space+ , Str "maintained"+ , Space+ , Str "at"+ , Space+ , Str "Los"+ , Space+ , Str "Alamos"+ , SoftBreak+ , Str "National"+ , Space+ , Str "Laboratory."+ ]+, Header+ 2+ ( "" , [] , [] )+ [ Str "Back"+ , Space+ , Str "matter"+ , Space+ , Str "of"+ , Space+ , Str "book"+ , Space+ , Str "part"+ ]+, Header 1 ( "" , [] , [] ) [ Str "References" ]+, Div ( "refs" , [] , [] ) []+, Header 2 ( "bid.394" , [] , [] ) [ Str "Acknowledgments" ]+, Para+ [ Str "We"+ , Space+ , Str "gratefully"+ , Space+ , Str "acknowledge"+ , Space+ , Str "the"+ , Space+ , Str "work"+ , Space+ , Str "of"+ , Space+ , Str "Vladimir"+ , Space+ , Str "Soussov,"+ , SoftBreak+ , Str "as"+ , Space+ , Str "well"+ , Space+ , Str "as"+ , Space+ , Str "the"+ , Space+ , Str "entire"+ , Space+ , Str "NCBI"+ , Space+ , Str "Entrez"+ , Space+ , Str "team..."+ ]+]+```
@@ -0,0 +1,83 @@+```+% pandoc -f jats -t native+<index-group>+ <index-title-group>+ <title>Index group</title>+ </index-title-group>+ <p>Content of index group</p>+ <index>+ <index-title-group>+ <title>Index</title>+ </index-title-group>+ <p>Content of index</p>+ <index-div>+ <index-title-group>+ <title>N</title>+ </index-title-group>+ <p>Content of index div</p>+ <index-entry>+ <term>Navy</term>+ <x>.</x>+ <see-entry>Armed forces</see-entry>+ <x>.</x>+ </index-entry>+ <index-entry>+ <term>Necessary and proper clause, congressional power</term>+ </index-entry>+ <index-entry>+ <term>Newsgathering as commerce</term>+ </index-entry>+ </index-div>+ </index>+</index-group>+^D+[ Header+ 1 ( "" , [] , [] ) [ Str "Index" , Space , Str "group" ]+, Para+ [ Str "Content"+ , Space+ , Str "of"+ , Space+ , Str "index"+ , Space+ , Str "group"+ ]+, Header 2 ( "" , [] , [] ) [ Str "Index" ]+, Para+ [ Str "Content" , Space , Str "of" , Space , Str "index" ]+, Header 3 ( "" , [] , [] ) [ Str "N" ]+, Para+ [ Str "Content"+ , Space+ , Str "of"+ , Space+ , Str "index"+ , Space+ , Str "div"+ ]+, Plain [ Str "Navy" ]+, Plain [ Str "." ]+, Plain [ Str "Armed" , Space , Str "forces" ]+, Plain [ Str "." ]+, Plain+ [ Str "Necessary"+ , Space+ , Str "and"+ , Space+ , Str "proper"+ , Space+ , Str "clause,"+ , Space+ , Str "congressional"+ , Space+ , Str "power"+ ]+, Plain+ [ Str "Newsgathering"+ , Space+ , Str "as"+ , Space+ , Str "commerce"+ ]+]+```
@@ -0,0 +1,45 @@+```+% pandoc -f jats -t native+<fig id="fig_A.1" orientation="portrait">+ <label>Figure A.1</label>+ <caption>+ <title>Field of Application</title>+ </caption>+ <legend>+ <title>Key</title>+ <def-list>+ <def-item>+ <term>I</term>+ <def><p>input</p></def>+ </def-item>+ <def-item>+ <term>O</term>+ <def><p>output</p></def>+ </def-item>+ ...+ </def-list>+ </legend>+ <graphic xlink:href="1234"/>+</fig>+^D+[ Figure+ ( "fig_A.1" , [] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "Field"+ , Space+ , Str "of"+ , Space+ , Str "Application"+ ]+ ])+ [ Header 1 ( "" , [] , [] ) [ Str "Key" ]+ , DefinitionList+ [ ( [ Str "I" ] , [ [ Para [ Str "input" ] ] ] )+ , ( [ Str "O" ] , [ [ Para [ Str "output" ] ] ] )+ ]+ , Para [ Image ( "" , [] , [] ) [] ( "1234" , "" ) ]+ ]+]+```
@@ -0,0 +1,68 @@+```+% pandoc -f jats -t native+<dedication>+ <named-book-part-body>+ <p>This is the dedication text.</p>+ </named-book-part-body>+</dedication>+^D+[ Header 1 ( "" , [] , [] ) [ Str "Dedication" ]+, Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "the"+ , Space+ , Str "dedication"+ , Space+ , Str "text."+ ]+]+```++```+% pandoc -f jats -t native+<foreword>+ <named-book-part-body>+ <p>This is the foreword text.</p>+ </named-book-part-body>+</foreword>+^D+[ Header 1 ( "" , [] , [] ) [ Str "Foreword" ]+, Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "the"+ , Space+ , Str "foreword"+ , Space+ , Str "text."+ ]+]+```++```+% pandoc -f jats -t native+<preface>+ <named-book-part-body>+ <p>This is the preface text.</p>+ </named-book-part-body>+</preface>+^D+[ Header 1 ( "" , [] , [] ) [ Str "Preface" ]+, Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "the"+ , Space+ , Str "preface"+ , Space+ , Str "text."+ ]+]+```
@@ -0,0 +1,175 @@+```+% pandoc -f jats -t native+<sec>+ <title>THE EUROPEAN UNION EXPLAINED</title>+</sec>+^D+[ Header+ 1+ ( "" , [] , [] )+ [ Str "THE"+ , Space+ , Str "EUROPEAN"+ , Space+ , Str "UNION"+ , Space+ , Str "EXPLAINED"+ ]+]+```++```+% pandoc -f jats -t native+<sec>+ <title display-as="3">THE EUROPEAN UNION EXPLAINED</title>+</sec>+^D+[ Header+ 3+ ( "" , [] , [] )+ [ Str "THE"+ , Space+ , Str "EUROPEAN"+ , Space+ , Str "UNION"+ , Space+ , Str "EXPLAINED"+ ]+]+```++```+% pandoc -f jats -t native+<body>+ <sec>+ <title>The European Parliament</title>+ <p>Members of the European Parliament (MEPs) are directly elected by EU citizens.</p>+ <sec>+ <title display-as="3">Composition of the European Parliament</title>+ <p>The seats in the European Parliament are allocated among the Member States.</p>+ </sec>+ <sec>+ <title>Composition of the European Parliament - II </title>+ <p>Most MEPs are associated with a national political party in their home country.</p>+ </sec>+ </sec>+</body>+^D+[ Header+ 1+ ( "" , [] , [] )+ [ Str "The"+ , Space+ , Str "European"+ , Space+ , Str "Parliament"+ ]+, Para+ [ Str "Members"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "European"+ , Space+ , Str "Parliament"+ , Space+ , Str "(MEPs)"+ , Space+ , Str "are"+ , Space+ , Str "directly"+ , Space+ , Str "elected"+ , Space+ , Str "by"+ , Space+ , Str "EU"+ , Space+ , Str "citizens."+ ]+, Header+ 3+ ( "" , [] , [] )+ [ Str "Composition"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "European"+ , Space+ , Str "Parliament"+ ]+, Para+ [ Str "The"+ , Space+ , Str "seats"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "European"+ , Space+ , Str "Parliament"+ , Space+ , Str "are"+ , Space+ , Str "allocated"+ , Space+ , Str "among"+ , Space+ , Str "the"+ , Space+ , Str "Member"+ , Space+ , Str "States."+ ]+, Header+ 2+ ( "" , [] , [] )+ [ Str "Composition"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "European"+ , Space+ , Str "Parliament"+ , Space+ , Str "-"+ , Space+ , Str "II"+ ]+, Para+ [ Str "Most"+ , Space+ , Str "MEPs"+ , Space+ , Str "are"+ , Space+ , Str "associated"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "national"+ , Space+ , Str "political"+ , Space+ , Str "party"+ , Space+ , Str "in"+ , Space+ , Str "their"+ , Space+ , Str "home"+ , Space+ , Str "country."+ ]+]+```
@@ -0,0 +1,122 @@+```+% pandoc -f jats -t native+<sec>+ <title>The European Parliament</title>+ <p>Members of the European Parliament (MEPs) are directly elected by EU citizens.</p>+</sec>+^D+[ Header+ 1+ ( "" , [] , [] )+ [ Str "The"+ , Space+ , Str "European"+ , Space+ , Str "Parliament"+ ]+, Para+ [ Str "Members"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "European"+ , Space+ , Str "Parliament"+ , Space+ , Str "(MEPs)"+ , Space+ , Str "are"+ , Space+ , Str "directly"+ , Space+ , Str "elected"+ , Space+ , Str "by"+ , Space+ , Str "EU"+ , Space+ , Str "citizens."+ ]+]+```++```+% pandoc -f jats -t native+<sec>+ <title suppress="no">The European Parliament</title>+ <p>Members of the European Parliament (MEPs) are directly elected by EU citizens.</p>+</sec>+^D+[ Header+ 1+ ( "" , [] , [] )+ [ Str "The"+ , Space+ , Str "European"+ , Space+ , Str "Parliament"+ ]+, Para+ [ Str "Members"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "European"+ , Space+ , Str "Parliament"+ , Space+ , Str "(MEPs)"+ , Space+ , Str "are"+ , Space+ , Str "directly"+ , Space+ , Str "elected"+ , Space+ , Str "by"+ , Space+ , Str "EU"+ , Space+ , Str "citizens."+ ]+]+```++```+% pandoc -f jats -t native+<sec>+ <title suppress="yes">The European Parliament</title>+ <p>Members of the European Parliament (MEPs) are directly elected by EU citizens.</p>+</sec>+^D+[ Para+ [ Str "Members"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "European"+ , Space+ , Str "Parliament"+ , Space+ , Str "(MEPs)"+ , Space+ , Str "are"+ , Space+ , Str "directly"+ , Space+ , Str "elected"+ , Space+ , Str "by"+ , Space+ , Str "EU"+ , Space+ , Str "citizens."+ ]+]+```
@@ -0,0 +1,69 @@+```+% pandoc -f jats -t native+<toc-group>+ <toc-title-group>+ <title>TOC group</title>+ </toc-title-group>+ <p>Content of toc group</p>+ <toc>+ <toc-title-group>+ <title>TOC</title>+ </toc-title-group>+ <p>Content of TOC</p>+ <toc-div content-type="sections">+ <toc-title-group>+ <title>Mental Health Services</title>+ </toc-title-group>+ <toc-entry>+ <label>Section 1</label>+ <title>Introduction</title>+ <nav-pointer rid="tc3"/>+ </toc-entry>+ <toc-entry>+ <label>Section 2</label>+ <title>Mental Health of the Population</title>+ <nav-pointer rid="tc4"/>+ </toc-entry>+ </toc-div>+ </toc>+</toc-group>+^D+[ Header+ 1 ( "" , [] , [] ) [ Str "TOC" , Space , Str "group" ]+, Para+ [ Str "Content"+ , Space+ , Str "of"+ , Space+ , Str "toc"+ , Space+ , Str "group"+ ]+, Header 2 ( "" , [] , [] ) [ Str "TOC" ]+, Para+ [ Str "Content" , Space , Str "of" , Space , Str "TOC" ]+, Header+ 3+ ( "" , [] , [] )+ [ Str "Mental"+ , Space+ , Str "Health"+ , Space+ , Str "Services"+ ]+, Header 4 ( "" , [] , [] ) [ Str "Introduction" ]+, Header+ 4+ ( "" , [] , [] )+ [ Str "Mental"+ , Space+ , Str "Health"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "Population"+ ]+]+```
@@ -26,11 +26,11 @@ Test.[^4] -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-test .csl-entry} Doe, John. "Test," n.d. :::-:::+:::: [^1]: John Doe, "Test," n.d., 12.
@@ -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. ```
@@ -0,0 +1,16 @@+```+% pandoc -f dokuwiki -t native+> <code>some+code+</code>+>> ok+> then+> more+^D+[ BlockQuote+ [ CodeBlock ( "" , [] , [] ) "some\ncode\n"+ , BlockQuote [ Plain [ Str "ok" ] ]+ , Plain [ Str "then" , LineBreak , Str "more" ]+ ]+]+```
@@ -0,0 +1,48 @@+# Figure with one image, caption and label++```+% pandoc -t context -f html+<figure>+ <img src="mandrill.jpg" />+ <figcaption><q>The Mandrill</q>, a photo used in+ image processing tests.</figcaption>+</figure>+^D+\startplacefigure[title={\quotation{The Mandrill}, a photo used in image+processing tests.}]+{\externalfigure[mandrill.jpg]}+\stopplacefigure+```++# Nested figures++```+% pandoc -t context -f html+<figure id="test-images">+ <figure id="mandrill">+ <img src="../testing/mandrill.jpg">+ <figcaption><q>The Mandrill</q> is a commonly used test image.</figcaption>+ </figure>+ <figure id="peppers">+ <img src="../testing/peppers.webp" >+ <figcaption>Another test image. This one is called <q>peppers</q>.</figcaption>+ </figure>+ <figcaption>Signal processing test images.</figcaption>+</figure>+^D+\startplacefigure[reference=test-images,title={Signal processing test+images.}]+\startfloatcombination+\startplacefigure[reference=mandrill,title={\quotation{The Mandrill} is+a commonly used test image.}]+{\externalfigure[../testing/mandrill.jpg]}+\stopplacefigure++\startplacefigure[reference=peppers,title={Another test image. This one+is called \quotation{peppers}.}]+{\externalfigure[../testing/peppers.webp]}+\stopplacefigure++\stopfloatcombination+\stopplacefigure+```
@@ -0,0 +1,8 @@+```+% pandoc -f native -t fb2+[Figure ("fig-id",[],[]) (Caption Nothing []) [Para [Str "content"]]]++^D+<?xml version="1.0" encoding="UTF-8"?>+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>unrecognised</genre></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><section><p>content</p></section></body></FictionBook>+```
@@ -0,0 +1,7 @@+```+% pandoc -f native -t haddock+[Figure ("fig-id",[],[]) (Caption Nothing []) [Para [Str "content"]]]++^D+content+```
@@ -0,0 +1,92 @@+# Writer++HTML5 figure with caption and content.++```+% pandoc -f native -t html5+[Figure ("fig-id",[],[]) (Caption Nothing [Plain [Str "caption"]]) [Para [Str "content"]]]++^D+<figure id="fig-id">+<p>content</p>+<figcaption>caption</figcaption>+</figure>+```++HTML5 figure with NO caption and content.++```+% pandoc -f native -t html5+[Figure ("fig-id",[],[]) (Caption Nothing []) [Para [Str "content"]]]++^D+<figure id="fig-id">+<p>content</p>+</figure>+```++HTML4 figure with caption and content.++```+% pandoc -f native -t html4+[Figure ("fig-id",[],[]) (Caption Nothing [Plain [Str "caption"]]) [Para [Str "content"]]]++^D+<div class="float" id="fig-id">+<p>content</p>+<div class="figcaption">caption</div>+</div>+```++HTML4 figure with NO caption and content.++```+% pandoc -f native -t html4+[Figure ("fig-id",[],[]) (Caption Nothing []) [Para [Str "content"]]]++^D+<div class="float" id="fig-id">+<p>content</p>+</div>+```++# Reader++Figure with caption and multiple elements.++```+% pandoc -f html -t native+<figure class="important">+ <img src="../media/rId25.jpg" />+ <ul> <li> ITEM </li> </ul>+ <figcaption> CAP2 </figcaption>+</figure>+^D+[ Figure+ ( "" , [ "important" ] , [] )+ (Caption Nothing [ Plain [ Str "CAP2" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "../media/rId25.jpg" , "" ) ]+ , BulletList [ [ Plain [ Str "ITEM" ] ] ]+ ]+]+```++Figure without caption.++```+% pandoc -f html -t native+<figure class="important">+ <img src="../media/rId25.jpg" />+ <ul> <li> ITEM </li> </ul>+</figure>+^D+[ Figure+ ( "" , [ "important" ] , [] )+ (Caption Nothing [])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "../media/rId25.jpg" , "" ) ]+ , BulletList [ [ Plain [ Str "ITEM" ] ] ]+ ]+]+```
@@ -0,0 +1,31 @@+Figure float with caption at the figure level.++```+% pandoc -f native -t jats+[Figure ("fig-id",[],[]) (Caption Nothing [Para [Str "Caption"]]) [Para [Str "Text"],+Para [Image ("fig-id-2",[],[]) [] ("foo.png", "fig:")]]]++^D+<fig id="fig-id">+ <caption><p>Caption</p></caption>+ <p>Text</p>+ <graphic id="fig-id-2" mimetype="image" mime-subtype="png" xlink:href="foo.png" xlink:title="fig:" />+</fig>+```++Figure float with caption and alt text.++```+% pandoc -f native -t jats+[Figure ("fig-id",[],[]) (Caption Nothing [Para [Str "Caption"]]) [Para [Str "Text"],+Para [Image ("fig-id-2",[],[]) [Str "alt"] ("foo.png", "fig:")]]]++^D+<fig id="fig-id">+ <caption><p>Caption</p></caption>+ <p>Text</p>+ <graphic id="fig-id-2" mimetype="image" mime-subtype="png" xlink:href="foo.png" xlink:title="fig:">+ <alt-text>alt</alt-text>+ </graphic>+</fig>+```
@@ -0,0 +1,9 @@+A figure with title+```+% pandoc -f native -t jira+[Figure ("fig-id",[],[("title","This is the title")]) (Caption Nothing []) []]+^D+{panel:title=This is the title}+{anchor:fig-id}+{panel}+```
@@ -0,0 +1,83 @@+# Figure with one image, caption and label++```+% pandoc -f latex -t native+\begin{document}+ \begin{figure}+ \includegraphics{../../media/rId25.jpg}+ \caption{CAP}+ \label{LAB}+ \end{figure}+\end{document}+^D+[ Figure+ ( "LAB" , [] , [] )+ (Caption Nothing [ Plain [ Str "CAP" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "../../media/rId25.jpg" , "" )+ ]+ ]+]+```++# Nested figures++```+% pandoc -f latex -t native+\begin{figure}+ \begin{subfigure}[b]{0.5\textwidth}+ \begin{subfigure}[b]{0.5\textwidth}+ \centering+ \includegraphics{test/media/rId25.jpg}+ \caption{CAP1.1}+ \end{subfigure}+ \begin{subfigure}[b]{0.5\textwidth}+ \centering+ \includegraphics{test/media/rId25.jpg}+ \caption{CAP1.2}+ \end{subfigure}+ \caption{CAP1}+ \label{fig:inner1}+ \end{subfigure}+ \begin{subfigure}[b]{0.5\textwidth}+ \includegraphics{test/media/rId25.jpg}+ \caption{CAP2}+ \label{fig:inner2}+ \end{subfigure}+ \caption{CAP}+ \label{fig:outer}+\end{figure}+^D+[ Figure+ ( "fig:outer" , [] , [] )+ (Caption Nothing [ Plain [ Str "CAP" ] ])+ [ Figure+ ( "fig:inner1" , [] , [] )+ (Caption Nothing [ Plain [ Str "CAP1" ] ])+ [ Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "CAP1.1" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] ) [] ( "test/media/rId25.jpg" , "" )+ ]+ ]+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "CAP1.2" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] ) [] ( "test/media/rId25.jpg" , "" )+ ]+ ]+ ]+ , Figure+ ( "fig:inner2" , [] , [] )+ (Caption Nothing [ Plain [ Str "CAP2" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "test/media/rId25.jpg" , "" )+ ]+ ]+ ]+]+```
@@ -0,0 +1,12 @@+Figure float with caption at the figure level.++```+% pandoc -f native -t markdown+[Figure ("fig-id",[],[]) (Caption Nothing [Para [Str "Caption"]]) [Para [Image ("",[],[]) [] ("foo.png", "fig:")]]]++^D+<figure id="fig-id">+<p><img src="foo.png" title="fig:" /></p>+<figcaption><p>Caption</p></figcaption>+</figure>+```
@@ -0,0 +1,11 @@+Figure float with caption at the figure level.++```+% pandoc -f native -t mediawiki+[Figure ("fig-id",[],[]) (Caption Nothing [Para [Str "Caption"]]) [Para [Image ("",[],[]) [] ("foo.png", "fig:")]]]++^D+<div id="fig-id" class="figure">+[[File:foo.png|thumb|none]]+</div>+```
@@ -0,0 +1,16 @@+```+% pandoc -f native -t org+[Figure ("fig-id",[],[]) (Caption Nothing []) [Para [Str "content"]]]++^D+<<fig-id>>+content+```++```+% pandoc -f native -t org+[Figure ("",[],[]) (Caption Nothing []) [Para [Str "content"]]]++^D+content+```
@@ -0,0 +1,13 @@+Figure float with caption at the figure level.++```+% pandoc -f native -t rst+[Figure ("fig-id",[],[]) (Caption Nothing [Para [Str "Caption"]]) [Para [Image ("",[],[]) [] ("foo.png", "fig:")]]]++^D+.. figure:: foo.png+ name: fig-id+ :alt: fig:++ Caption+```
@@ -0,0 +1,115 @@+Figure float with caption at the figure level.++```+% pandoc -f native -t texinfo+[Figure ("fig-id",[],[]) (Caption Nothing [Para [Str "Caption"]]) [Para [Image ("",[],[]) [] ("foo.png", "fig:")]]]++^D+@node Top+@top Top++@float Figure+@image{foo,,,,png}+@caption{Caption}+@end float+```++Float that has no caption and doesn't contain a `SimpleFigure`++```+% pandoc -f native -t texinfo+[Figure ("fig-id",[],[]) (Caption Nothing []) [Para [Image ("",[],[]) [] ("foo.png", "")]]]++^D+@node Top+@top Top++@float+@image{foo,,,,png}+@end float+```++Table float with caption at the figure level.++```+% pandoc -f native -t texinfo+[Figure ("fig-id",[],[]) (Caption Nothing [Para [Str "Caption"]])+[Table ("",[],[]) (Caption Nothing+ [])+ [(AlignDefault,ColWidthDefault)+ ,(AlignDefault,ColWidthDefault)+ ,(AlignDefault,ColWidthDefault)]+ (TableHead ("",[],[])+ [Row ("",[],[])+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "Fruit"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "Price"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "Quantity"]]]])+ [(TableBody ("",[],[]) (RowHeadColumns 0)+ []+ [Row ("",[],[])+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "Apple"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "25",Space,Str "cents"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "33"]]]+ ,Row ("",[],[])+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "\"Navel\"",Space,Str "Orange"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "35",Space,Str "cents"]]+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "22"]]]+ ,Row ("",[],[])+ [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ []+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ []+ ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)+ [Plain [Str "45"]]]])]+ (TableFoot ("",[],[])+ [])]]++^D+@node Top+@top Top++@float Table+@multitable {"Navel" Orange} {35 cents} {Quantity} +@headitem +Fruit+ @tab Price+ @tab Quantity+@item +Apple+ @tab 25 cents+ @tab 33+@item +"Navel" Orange+ @tab 35 cents+ @tab 22+@item +45+@end multitable+@caption{Caption}+@end float+```++Float the isn't a table nor a figure.++```+% pandoc -f native -t texinfo+[Figure ("fig-id",[],[]) (Caption Nothing [Para[ Str "Caption"]]) [Para [Str "Content"]]]++^D+@node Top+@top Top++@float+Content+@caption{Caption}+@end float+```
@@ -0,0 +1,31 @@+```+% pandoc -f native -t textile+[Figure ("fig-id",[],[]) (Caption Nothing [Para [Str "Caption"]]) [Para [Image ("",[],[]) [] ("foo.png", "")]]]++^D+<figure id="fig-id">++<figcaption>++Caption++</figcaption>++!foo.png!+++</figure>+```++```+% pandoc -f native -t textile+[Figure ("fig-id",[],[]) (Caption Nothing []) [Para [Image ("",[],[]) [] ("foo.png", "")]]]++^D+<figure id="fig-id">++!foo.png!+++</figure>+```
@@ -0,0 +1,10 @@+```+% pandoc -f native -t xwiki+[Figure ("fig-id",[],[]) (Caption Nothing []) [Para [Str "content"]]]++^D+(((+{{id name="fig-id" /}}content++)))+```
@@ -0,0 +1,9 @@+```+% pandoc -f native -t zimwiki+[Figure ("fig-id",[],[]) (Caption Nothing []) [Para [Str "content"]]]++^D+content+++```
@@ -0,0 +1,9 @@+# Zed++[foo]: bar++[foo]+and [Zed](#zed)+and [other Zed](command/file2.txt#zed)+and [other file](command/file2.txt)+and [foreign Zed](c.md#zed)
@@ -0,0 +1,5 @@+## Zed++[foo]: baz++[foo]
@@ -0,0 +1,65 @@+Like other block-level constructs, grid tables may be indented by up to+three spaces and are still recognized as tables.++```+% pandoc -f markdown -t html+ +---+---++ | a | b |+ +===+===++ | 1 | 2 |+ +---+---++^D+<table style="width:11%;">+<colgroup>+<col style="width: 5%" />+<col style="width: 5%" />+</colgroup>+<thead>+<tr>+<th>a</th>+<th>b</th>+</tr>+</thead>+<tbody>+<tr>+<td>1</td>+<td>2</td>+</tr>+</tbody>+</table>+```++A headerless indented grid table is recognized too.++```+% pandoc -f markdown -t html+ +------+------++ | foo | bar |+ +------+------++^D+<table style="width:19%;">+<colgroup>+<col style="width: 9%" />+<col style="width: 9%" />+</colgroup>+<tbody>+<tr>+<td>foo</td>+<td>bar</td>+</tr>+</tbody>+</table>+```++A grid table indented four spaces is a code block, not a table.++```+% pandoc -f markdown -t html+ +---+---++ | a | b |+ +---+---++^D+<pre><code>+---+---++| a | b |++---+---+</code></pre>+```
@@ -5,9 +5,11 @@ <figcaption>bar</figcaption> </figure> ^D-[ Para- [ Image- ( "" , [] , [] ) [ Str "bar" ] ( "foo.png" , "fig:voyage" )+[ Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "bar" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "foo.png" , "voyage" ) ] ] ] ```@@ -19,9 +21,11 @@ <img src="foo.png" title="voyage"> </figure> ^D-[ Para- [ Image- ( "" , [] , [] ) [ Str "bar" ] ( "foo.png" , "fig:voyage" )+[ Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "bar" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "foo.png" , "voyage" ) ] ] ] ```@@ -32,8 +36,12 @@ <img src="foo.png" title="voyage"> </figure> ^D-[ Para- [ Image ( "" , [] , [] ) [] ( "foo.png" , "fig:voyage" ) ]+[ Figure+ ( "" , [] , [] )+ (Caption Nothing [])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "foo.png" , "voyage" ) ]+ ] ] ``` @@ -44,9 +52,11 @@ <figcaption>bar</figcaption> </figure> ^D-[ Para- [ Image- ( "" , [] , [] ) [ Str "bar" ] ( "foo.png" , "fig:voyage" )+[ Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "bar" ] ])+ [ Para+ [ Image ( "" , [] , [] ) [] ( "foo.png" , "voyage" ) ] ] ] ```@@ -55,11 +65,17 @@ % pandoc -f html -t native <figure><img src="foo.png" title="voyage" alt="this is ignored"><figcaption>bar <strong>baz</strong></figcaption></figure> ^D-[ Para- [ Image- ( "" , [] , [] )- [ Str "bar" , Space , Strong [ Str "baz" ] ]- ( "foo.png" , "fig:voyage" )+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Plain [ Str "bar" , Space , Strong [ Str "baz" ] ] ])+ [ Plain+ [ Image+ ( "" , [] , [] )+ [ Str "this" , Space , Str "is" , Space , Str "ignored" ]+ ( "foo.png" , "voyage" )+ ] ] ] ```
@@ -0,0 +1,7 @@+a is not allowed inside a in HTML, so we remove links in link text:+```+% pandoc -f native -t html+[ Link ("",[],[]) [Link ("",[],[]) [Str "Lo"] ("url2","") ] ("url","") ]+^D+<a href="url"><span>Lo</span></a>+```
@@ -0,0 +1,22 @@+```+% pandoc -t plain -f markdown+| 'Twas brillig, and the slithy toves+| Did gyre and gimble in the wabe:+| All mimsy were the borogoves,+| And the mome raths outgrabe.+|+| "Beware the Jabberwock, my son!+| The jaws that bite, the claws that catch!+| Beware the Jubjub bird, and shun+| The frumious Bandersnatch!"+^D+’Twas brillig, and the slithy toves+ Did gyre and gimble in the wabe:+All mimsy were the borogoves,+ And the mome raths outgrabe.++“Beware the Jabberwock, my son!+ The jaws that bite, the claws that catch!+Beware the Jubjub bird, and shun+ The frumious Bandersnatch!”+```
@@ -5,14 +5,18 @@ <p>bar</p> </caption> <alt-text>alternative-decription</alt-text>- <graphic xlink:href="foo.png" xlink:alt-text="baz" />+ <graphic xlink:href="foo.png">+ <alt-text>baz</alt-text> + </graphic> </fig>+ ^D-[ Para- [ Image- ( "fig-1" , [] , [ ( "alt" , "alternative-decription" ) ] )- [ Str "bar" ]- ( "foo.png" , "fig:" )+[ Figure+ ( "fig-1" , [] , [] )+ (Caption Nothing [ Plain [ Str "bar" ] ])+ [ Plain [ Str "alternative-decription" ]+ , Para+ [ Image ( "" , [] , [] ) [ Str "baz" ] ( "foo.png" , "" ) ] ] ] ```
@@ -169,9 +169,12 @@ ^D [ Div ( "" , [] , [ ( "style" , "background-color: orange" ) ] )- [ BulletList- [ [ Para [ Str "Item" , Space , Str "1" ] ]- , [ Para [ Str "Item" , Space , Str "2" ] ]+ [ Div+ ( "" , [ "minipage" ] , [] )+ [ BulletList+ [ [ Para [ Str "Item" , Space , Str "1" ] ]+ , [ Para [ Str "Item" , Space , Str "2" ] ]+ ] ] ] ]@@ -190,9 +193,12 @@ ^D [ Div ( "" , [] , [ ( "style" , "background-color: blue" ) ] )- [ BulletList- [ [ Para [ Str "Item" , Space , Str "1" ] ]- , [ Para [ Str "Item" , Space , Str "2" ] ]+ [ Div+ ( "" , [ "minipage" ] , [] )+ [ BulletList+ [ [ Para [ Str "Item" , Space , Str "1" ] ]+ , [ Para [ Str "Item" , Space , Str "2" ] ]+ ] ] ] , Para
@@ -0,0 +1,38 @@+Test that trailing spaces before \end{equation} don't create spurious paragraph breaks:++```+% pandoc -f latex -t latex+\begin{equation}+ a+ \end{equation}+^D+\begin{equation}+ a+\end{equation}+```++Same for align environment:++```+% pandoc -f latex -t latex+\begin{align}+ x &= y \\+ \end{align}+^D+\begin{align}+ x &= y \\+\end{align}+```++Test with multiple trailing spaces:++```+% pandoc -f latex -t latex+\begin{equation}+ a + b+ \end{equation}+^D+\begin{equation}+ a + b+\end{equation}+```
@@ -10,11 +10,12 @@ 2. list ^D \begin{description}+\tightlist \item[Definition]+\hfill \begin{enumerate} \def\labelenumi{\arabic{enumi}.} \tightlist-\item[] \item list \item@@ -32,6 +33,7 @@ 2. list ^D \begin{description}+\tightlist \item[Definition] Foo @@ -53,10 +55,11 @@ - list ^D \begin{description}+\tightlist \item[Definition]+\hfill \begin{itemize} \tightlist-\item[] \item list \item
@@ -1,11 +0,0 @@-function report (what, value)- print(string.format('%16s: %s', what, value))-end-report('# input files', #PANDOC_STATE.input_files)-report('output file', PANDOC_STATE.output_file)-report('# request header', #PANDOC_STATE.request_headers)-report('resource path', table.concat(PANDOC_STATE.resource_path, ', '))-report('source URL', PANDOC_STATE.source_url)-report('user data dir', PANDOC_STATE.user_data_dir and 'defined' or 'unset')-report('trace', PANDOC_STATE.trace)-report('verbosity', PANDOC_STATE.verbosity)
@@ -1,14 +0,0 @@-```-% pandoc --lua-filter=command/lua-pandoc-state.lua --data-dir=foo-Hello-^D- # input files: 1- output file: nil-# request header: 0- resource path: .- source URL: nil- user data dir: defined- trace: false- verbosity: WARNING-<p>Hello</p>-```
@@ -61,9 +61,9 @@ ^D \(5-67\) -\[\begin{aligned}+\begin{align} x &= y\\-\end{aligned}\]+\end{align} \emph{hi}
@@ -0,0 +1,15 @@+```+% pandoc -f man -t plain+.de test+ok+..+.test+.br+\A'test'+.br+\A'xyz'+^D+ok+1+0+```
@@ -0,0 +1,17 @@+```+% pandoc -f mdoc -t plain+.Sh DESCRIPTION+.An Emily Brontë ,+.An Anne Brontë+.Pp+.An -split+.An Charlotte Brontë+.An Bramwell Brontë+^D+DESCRIPTION++Emily Brontë, Anne Brontë++Charlotte Brontë+Bramwell Brontë+```
@@ -0,0 +1,24 @@+```+% pandoc -f mdoc -t plain+.Bd -unfilled+’Twas brillig, and the slithy toves+ Did gyre and gimble in the wabe:+All mimsy were the borogoves,+ And the mome raths outgrabe.++“Beware the Jabberwock, my son!+ The jaws that bite, the claws that catch!+Beware the Jubjub bird, and shun+ The frumious Bandersnatch!”+.Ed+^D+’Twas brillig, and the slithy toves+ Did gyre and gimble in the wabe:+All mimsy were the borogoves,+ And the mome raths outgrabe.++“Beware the Jabberwock, my son!+ The jaws that bite, the claws that catch!+Beware the Jubjub bird, and shun+ The frumious Bandersnatch!”+```
@@ -0,0 +1,22 @@+```+% pandoc -f mdoc -t djot+.Bl -column a b+.It a Ta+.Sy b+b+.Ta c+.Pp+.It c Ta d Ta \&+.It Em e+.Ta f+.Ta g+.It h Ta Ta j+.It Pq a Ta b Ta c+.El+^D+| a | *b* b | c |+| c | d | |+| _e_ | f | g |+| h | | j |+| (a) | b | c |+```
@@ -0,0 +1,36 @@+```+% pandoc -f mdoc -t native+.Bl -tag+.It one+one+.It Xo+two+.Xc+two+.It Em three Xo+three+.Xc+three+.It Po one two+.Bq three+.Pc+four+.El+^D+[ DefinitionList+ [ ( [ Str "one" ] , [ [ Para [ Str "one" ] ] ] )+ , ( [ Str "two" ] , [ [ Para [ Str "two" ] ] ] )+ , ( [ Emph [ Str "three" ] , Space , Str "three" ]+ , [ [ Para [ Str "three" ] ] ]+ )+ , ( [ Str "(one"+ , Space+ , Str "two"+ , Space+ , Str "[three])"+ ]+ , [ [ Para [ Str "four" ] ] ]+ )+ ]+]+```
@@ -0,0 +1,16 @@+```+% pandoc -f mediawiki -t native+____INDEX____+__NOINDEX__+__noindex__+__FOOBAR__+^D+[ Para+ [ Str "____"+ , SoftBreak+ , Str "__noindex__"+ , SoftBreak+ , Str "__FOOBAR__"+ ]+]+```
@@ -0,0 +1,5 @@+<?xml version="1.0" standalone="no"?>++<svg viewBox="-.333 -.333 480 150" style="background-color:#ffffff00" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve">+ <path d="M 0 35.5 L 6.5 22.5 L 16 37 L 23 24 L 34.8 43.7 L 42.5 30 L 50.3 47 L 59.7 27.7 L 69 47 L 85 17.7 L 98.3 39 L 113 9.7 L 127.7 42.3 L 136.3 23.7 L 147 44.3 L 158.3 20.3 L 170.3 40.3 L 177.7 25.7 L 189.7 43 L 199.7 21 L 207.7 35 L 219 11 L 233 37 L 240.3 23.7 L 251 43 L 263 18.3 L 272.7 33.3 L 283 10 L 295 32.3 L 301.3 23 L 311.7 37 L 323.7 7.7 L 339.3 39 L 346.3 25.7 L 356.3 42.3 L 369.7 15 L 376.3 25.7 L 384 9 L 393 28.3 L 400.3 19 L 411.7 38.3 L 421 21 L 434.3 43 L 445 25 L 453 36.3 L 464.3 18.3 L 476.2 40.3 L 480 33.5 L 480 215 L 0 215 L 0 35.5 Z" fill="#175720"/>+</svg>
@@ -5,26 +5,26 @@ \iftrue should print \else-should not print+should not print A \fi \else-should not print+should not print B \fi \iffalse-should not print+should not print C \else \iftrue should print \else-should not print+should not print D \fi \fi \newif\ifepub \ifepub-should not print+should not print E \fi \epubtrue@@ -32,13 +32,13 @@ \ifepub should print \else-should not print+should not print F \fi \epubfalse \ifepub-should not print+should not print G \else should print \fi
@@ -19,10 +19,9 @@ ^D (Hitchcock 1959) is a spy thriller film. -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#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. :::+:::: ```
@@ -14,7 +14,7 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body .hanging-indent line-spacing="2"}+:::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0" line-spacing="2"} ::: {#ref-averroes/hercz .csl-entry} Averroes. (1869). *Drei Abhandlungen über die Conjunction des separaten Intellects mit dem Menschen: Von Averroes (Vater und Sohn), aus dem@@ -34,5 +34,5 @@ (K. P. Bland, Ed. & Trans.). New York: Jewish Theological Seminary of America. :::-:::+:::::: ```
@@ -19,11 +19,11 @@ ^D Foo.[^1] -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-item1 .csl-entry} Author, Ann. "Title." *Journal*, 2011. :::-:::+:::: [^1]: Author, "Title." ```
@@ -15,9 +15,9 @@ ^D *Stanze in lode della donna brutta* (1547) is an anoynymous work. -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#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}+:::::: {#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. :::+:::::: ```
@@ -49,7 +49,7 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body .hanging-indent line-spacing="2"}+::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0" line-spacing="2"} ::: {#ref-Feminism2011ces .csl-entry} Communities. (2011, August 14). In *Geek Feminism*. Retrieved from <http://geekfeminism.wikia.com/wiki/Category:Communities>@@ -59,5 +59,5 @@ Geek Feminism. (2013, April 10). *Geek Feminism*. Retrieved April 10, 2013, from <http://geekfeminism.wikia.com/wiki/Geek_Feminism> :::-:::+::::: ```
@@ -36,9 +36,9 @@ > > \[Jane11\] Jane Doe. A book. 2011. -::: {#refs .references .csl-bib-body}+:::: {#refs .references .csl-bib-body} ::: {#ref-item1 .csl-entry} \[Jane11\] Jane Doe. A book. 2011. :::-:::+:::: ```
@@ -35,9 +35,9 @@ > Doe, Jane. 2011. "A Title." *A Magazine*, January--February. -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#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. :::+:::: ```
@@ -21,11 +21,11 @@ ^D This is a test.[^1] -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-test .csl-entry} Abelard, Peter, ed. *Test*. Oxford: Clarendon Press, 1989. :::-:::+:::: [^1]: Peter Abelard, ed., *Test* (Oxford: Clarendon Press, 1989). ```
@@ -25,9 +25,9 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-doe1 .csl-entry} Doe, A. (1999). *Title*. The collection title. The publisher. 789 pp. :::-:::+:::: ```
@@ -22,9 +22,9 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#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}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-doe .csl-entry}-Doe. n.d. "Title."-:::+Doe. n.d. *Title*. :::+:::: ```
@@ -29,10 +29,10 @@ Here is some text that needs a citation (*1*). -::: {#refs .references .csl-bib-body}+:::: {#refs .references .csl-bib-body} ::: {#ref-AuthorOne2014 .csl-entry} [1. ]{.csl-left-margin}[J. AuthorOne, J. AuthorTwo, *Some Journal*, in press.]{.csl-right-inline} :::-:::+:::: ```
@@ -27,7 +27,7 @@ ^D (Roe, 2007; Zoe, 2009; see for comparison Doe, 2007: 3) -::: {#refs .references .csl-bib-body .hanging-indent}+:::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-doe .csl-entry} Doe (2007). :::@@ -39,5 +39,5 @@ ::: {#ref-zoe .csl-entry} Zoe (2009). :::-:::+:::::: ```
@@ -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}+::::: {#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,10 +22,10 @@ ^D Bonjour(Bazin 1954) ! -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#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. :::-:::+:::: ```
@@ -27,7 +27,7 @@ ^D Foo.[^1] Bar.[^2] Baz.[^3] -::: {#refs .references .csl-bib-body}+::::: {#refs .references .csl-bib-body} ::: {#ref-item1 .csl-entry} Olson HA, '[Codes, Costs, and Critiques: The Organization of Information in *Library Quarterly*, 1931--2004](https://doi.org/10.1086/504343)'@@ -37,7 +37,7 @@ ::: {#ref-item2 .csl-entry} 'Second Title' :::-:::+::::: [^1]: Hope A Olson, 'Codes, Costs, and Critiques: The Organization of Information in *Library Quarterly*, 1931--2004' (2006) 76 *Library
@@ -122,7 +122,7 @@ --- ^D-::: {#refs .references .csl-bib-body .hanging-indent line-spacing="2"}+:::::::::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0" line-spacing="2"} ::: {#ref-Y .csl-entry} NN. (1950). Date: Year. :::@@ -167,5 +167,5 @@ ::: {#ref-YS/YS_same .csl-entry} NN. (1966, Summer--Winter). Date range: Year+season, same year. :::-:::+:::::::::::::: ```
@@ -138,7 +138,7 @@ Foo (Sainte-Beuve, n.d.; Saint-Gaudens, n.d.; Saint-Saëns, n.d.; San Martin, n.d.; St. Denis, n.d.; St. Laurent, n.d.). -::: {#refs .references .csl-bib-body .hanging-indent line-spacing="2"}+::::::::::::::::::::::::::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0" line-spacing="2"} ::: {#ref-itemA2 .csl-entry} ben Yaakov, D. (n.d.). :::@@ -250,5 +250,5 @@ ::: {#ref-itemA14 .csl-entry} Villa-Lobos, J. (n.d.). :::-:::+::::::::::::::::::::::::::::::: ```
@@ -1,87 +1,80 @@ ```-% pandoc --citeproc -t markdown-citations+% pandoc --citeproc -t plain --- references: - author: - family: ʾUdhrī given: Jamīl non-dropping-particle: 'al-'- note: ayn+ issued: 2000+ title: hamza id: item1 - author: - family: ʿUdhrī given: Jamīl non-dropping-particle: 'al-'- note: hamza+ issued: 2000+ title: ayn id: item2 - author:- - family: '\''Udhrī'+ - family: "'Udhrī" given: Jamīl non-dropping-particle: 'al-'- note: straight apostrophe+ issued: 2000+ title: straight apostrophe id: item3 - author: - family: '‘Udhrī' given: Jamīl non-dropping-particle: 'al-'- note: inverted apostrophe = opening single curly quote (for ayn)+ issued: 2000+ title: inverted curly apostrophe = opening single curly quote (for ayn) id: item4 - author: - family: '’Udhrī' given: Jamīl non-dropping-particle: 'al-'- note: apostrophe = closing single curly quote (for hamza)+ issued: 2000+ title: curly apostrophe = closing single curly quote (for hamza) id: item5 - author: - family: Uch given: Ann id: item6+ issued: 2000 - author: - family: Uebel given: Joe id: item7+ issued: 2000 - author: - family: Zzz given: Zoe id: item8+ issued: 2000 --- Foo [@item1; @item2; @item3; @item4; @item5; @item6; @item7; @item8]. ^D-Foo (al-ʾUdhrī, n.d.; al-ʿUdhrī, n.d.; al-\'Udhrī, n.d.; al-'Udhrī,-n.d.a, n.d.b; Uch, n.d.; Uebel, n.d.; Zzz, n.d.).+Foo (al-ʾUdhrī 2000; al-ʿUdhrī 2000; al-’Udhrī 2000b, 2000a; al-‘Udhrī+2000; Uch 2000; Uebel 2000; Zzz 2000). -::: {#refs .references .csl-bib-body .hanging-indent}-::: {#ref-item6 .csl-entry}-Uch, Ann. n.d.-:::+Uch, Ann. 2000. -::: {#ref-item1 .csl-entry}-ʾUdhrī, Jamīl al-. n.d.-:::+‘Udhrī, Jamīl al-. 2000. Inverted Curly Apostrophe = Opening Single+Curly Quote (for Ayn). -::: {#ref-item2 .csl-entry}-ʿUdhrī, Jamīl al-. n.d.-:::+ʿUdhrī, Jamīl al-. 2000. Ayn. -::: {#ref-item3 .csl-entry}-\'Udhrī, Jamīl al-. n.d.-:::+’Udhrī, Jamīl al-. 2000a. Curly Apostrophe = Closing Single Curly Quote+(for Hamza). -::: {#ref-item4 .csl-entry}-'Udhrī, Jamīl al-. n.d.a.-:::+ʾUdhrī, Jamīl al-. 2000. Hamza. -::: {#ref-item5 .csl-entry}----------. n.d.b.-:::+’Udhrī, Jamīl al-. 2000b. Straight Apostrophe. -::: {#ref-item7 .csl-entry}-Uebel, Joe. n.d.-:::+Uebel, Joe. 2000. -::: {#ref-item8 .csl-entry}-Zzz, Zoe. n.d.-:::-:::+Zzz, Zoe. 2000.+ ```
@@ -23,12 +23,12 @@ ^D Foo.[^1] -::: {#refs .references .csl-bib-body}+:::: {#refs .references .csl-bib-body} ::: {#ref-timmory__justice_1950 .csl-entry} François [Timmory]{.smallcaps}, « *Justice est faite* : soyons justes », *L'Écran français*, 1950, nᵒ 272, p. 12. :::-:::+:::: [^1]: François [Timmory]{.smallcaps}, « *Justice est faite* : soyons justes », *L'Écran français*, 1950, nᵒ 272, p. 12.
@@ -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}+::::: {#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. :::+::::: ```
@@ -41,11 +41,11 @@ ^D I referenced something here^\[1\]^ -::: {#refs .references .csl-bib-body}+:::: {#refs .references .csl-bib-body entry-spacing="0"} ::: {#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} :::+:::: ```
@@ -24,11 +24,11 @@ --- ^D-::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item-1 .csl-entry} [Wolfinger, Christine]{.smallcaps}: *Keine Angst vor Linux, Unix: ein Lehrbuch für Linux- und Unix-Anwender*. 11., vollst. überarb. Aufl. Aufl. Berlin \[u.a.\] : Springer Vieweg, 2013 --- ISBN 978-3-642-32078-1 :::-:::+:::: ```
@@ -17,11 +17,11 @@ ^D Friedrich Nietzsche (ed.)[^1] -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-Nie72 .csl-entry} Nietzsche, Friedrich (ed.), *Die geburt*, 1872. :::-:::+:::: [^1]: *Die geburt*, 1872. ```
@@ -23,12 +23,12 @@ ^D [^1] -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-lestrange2017 .csl-entry} L'Estrange, Michael, and Stephen Merchant. "2017 Independent Intelligence Review," July 18, 2017. :::-:::+:::: [^1]: Michael L'Estrange and Stephen Merchant, "2017 Independent Intelligence Review," July 18, 2017.
@@ -27,12 +27,12 @@ ^D Foo.[^1] -::: {#refs .references .csl-bib-body}+:::: {#refs .references .csl-bib-body} ::: {#ref-legras_michel_2010 .csl-entry} [Le Gras]{.smallcaps} Gwénaëlle, *Michel Simon : l'art de la disgrâce*, Paris, Scope (coll. « Jeux d'acteurs »), 2010, 128 p. :::-:::+:::: [^1]: Gwénaëlle Le Gras, *Michel Simon : l'art de la disgrâce*, Paris, Scope, 2010, 128 p.
@@ -28,13 +28,13 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body .hanging-indent}+::::: {#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}+:::: {#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*. :::+:::: ```
@@ -26,11 +26,11 @@ ^D ^\[1\]^ -::: {#refs .references .csl-bib-body line-spacing="2"}+:::: {#refs .references .csl-bib-body entry-spacing="0" line-spacing="2"} ::: {#ref-ding_metallic_2012 .csl-entry} [\[1\] ]{.csl-left-margin}[[K. Ding, C. Z. Ning, *Light Sci. Appl.* **2012**, *1*, e20](https://doi.org/10.1038/lsa.2012.20).]{.csl-right-inline} :::-:::+:::: ```
@@ -17,7 +17,7 @@ ^D (1); (2) -::: {#refs .references .csl-bib-body}+::::: {#refs .references .csl-bib-body} ::: {#ref-james .csl-entry} [1. ]{.csl-left-margin}[James MRCEL. ]{.csl-right-inline} :::@@ -25,5 +25,5 @@ ::: {#ref-macfarlane .csl-entry} [2. ]{.csl-left-margin}[MacFarlane JG. ]{.csl-right-inline} :::-:::+::::: ```
@@ -43,17 +43,17 @@ ^D Haslanger (\[2003\] 2012, \[2000\] 2012) says... -::: {#refs .references .csl-bib-body .hanging-indent}+::::: {#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}+::::: {#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}+:::::: {#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}+::::::: {#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}@@ -108,5 +108,5 @@ ::: {#ref-doepoe .csl-entry} Doe, A., and A. Poe. 2000. *Title*. :::-:::+::::::: ```
@@ -33,7 +33,7 @@ ^D Doe (1987--1988); Roe (1987) -::: {#refs .references .csl-bib-body .hanging-indent}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-item1 .csl-entry} Doe, John. 1987--1988. "The Title." *Journal of Something* 3: 12--34. :::@@ -41,5 +41,5 @@ ::: {#ref-item2 .csl-entry} Roe, Ron. 1987. "The Title." *Journal of Something* 4: 12--34. :::-:::+::::: ```
@@ -26,7 +26,7 @@ ^D Doe[^1] Doe[^2] Roe[^3] Roe[^4] Doe[^5] Doe[^6] Roe[^7] Roe[^8] -::: {#refs .references .csl-bib-body}+::::: {#refs .references .csl-bib-body} ::: {#ref-a .csl-entry} [[Doe J.]{.smallcaps} ]{.csl-block} [2000, *Work A*,.]{.csl-left-margin}@@ -36,7 +36,7 @@ [[Roe J.]{.smallcaps} ]{.csl-block} [1990, *Work B*,.]{.csl-left-margin} :::-:::+::::: [^1]: 2000
@@ -27,11 +27,11 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-Faraday-forthcoming .csl-entry} Faraday, Carry. Forthcoming. "Protean Photography." In *Seven Trips Beyond the Asteroid Belt*, edited by James Oring. Cape Canaveral, FL: Launch Press. :::-:::+:::: ```
@@ -24,9 +24,9 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-stanze .csl-entry} *Stanze in lode della donna brutta*. 1547. Florence. :::-:::+:::: ```
@@ -55,7 +55,7 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body .hanging-indent}+::::: {#refs .references .csl-bib-body .hanging-indent} ::: {#ref-doe .csl-entry} Doe, John, *Title* (Publisher, 1985) :::@@ -63,7 +63,7 @@ ::: {#ref-roe .csl-entry} Roe, Rob, *Title* (Publisher, 1985) :::-:::+::::: [^1]: John Doe, *Title* (Publisher, 1985), VIII, 89.
@@ -1,5 +1,5 @@ ```-% pandoc --citeproc -t markdown-citations+% pandoc --citeproc -t markdown-citations --csl command/chicago-fullnote-bibliography.csl --- bibliography: - command/biblio.bib@@ -7,18 +7,18 @@ --- ^D-::: {#refs .references .csl-bib-body .hanging-indent}-::: {#ref-item1 .csl-entry}-Doe, John. 2005. *First Book*. Cambridge: Cambridge University Press.+:::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"}+::: {#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}+:::: {#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. :::+:::: ```
@@ -36,13 +36,13 @@ prose commentary[^2] \... and finally a note starting with a citation.[^3] -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-goering:1992william .csl-entry} Goering, Joseph. *William de Montibus (c. 1140--1213): The Schools and the Literature of Pastoral Care*. Studies and Texts 108. Toronto: Pontifical Institute of Mediaeval Studies, 1992. :::-:::+:::: [^1]: The text of fol. 9r is printed in Joseph Goering, *William de Montibus (c. 1140--1213): The Schools and the Literature of Pastoral
@@ -23,9 +23,9 @@ ^D Author (2011) -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#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,18 +56,18 @@ ^D (Thorndike 1955; Dinkova-Bruun 2009) -::: {#refs .references .csl-bib-body .hanging-indent}+::::: {#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} Thorndike, Lynn. 1955. "Unde versus." *Traditio* 11: 163--93. :::-:::+::::: ```
@@ -59,9 +59,9 @@ (Doe, 2006, no. 6 and 7) -::: {#refs .references .csl-bib-body .hanging-indent line-spacing="2"}+:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0" line-spacing="2"} ::: {#ref-test .csl-entry} Doe, J. (2006). Test, *81*. :::-:::+:::: ```
@@ -44,21 +44,21 @@ ^D Author (1998c), Author (1998d), Author (1998a), Author (1998b) -::: {#refs .references .csl-bib-body .hanging-indent}+::::::: {#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*. :::+::::::: ```
@@ -39,7 +39,7 @@ ^D [^1] -::: {#refs .references .csl-bib-body .hanging-indent}+:::::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-item4 .csl-entry} Bennett, Frank G., Jr., n.d. :::@@ -59,7 +59,7 @@ ::: {#ref-item3 .csl-entry} Humboldt, Alexander von, n.d. :::-:::+:::::::: [^1]: John Doe III, n.d.; Vincent van Gogh, n.d.; Alexander von Humboldt, n.d.; Frank G. Bennett, Jr., n.d.; Ezekiel Dumboldt III,
@@ -28,12 +28,12 @@ Some text.[^1] -::: {#refs .references .csl-bib-body .hanging-indent}+:::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-OCLC_i1099 .csl-entry} OCLC. "WorldCat." Accessed September 19, 2014. <https://www.worldcat.org/>. :::-:::+:::: [^1]: Comment regarding text, supported by citation (OCLC, "WorldCat"). ```
@@ -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}-::: {#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,20 +83,20 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body .hanging-indent}+:::::: {#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. :::+:::::: [^1]: Doe and Roe ([2007, 12](#ref-пункт3)) and a citation without locators ([Doe and Roe 2007](#ref-пункт3)).
@@ -81,7 +81,7 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body .hanging-indent}+:::::: {#refs .references .csl-bib-body .hanging-indent entry-spacing="0"} ::: {#ref-item2 .csl-entry} Doe, John. "Article." *Journal of Generic Studies* 6 (2006): 33--34. :::@@ -94,7 +94,7 @@ Doe, John, and Jenny Roe. "Why Water Is Wet." In *Third Book*, edited by Sam Smith. Oxford: Oxford University Press, 2007. :::-:::+:::::: [^1]: [**Nonexistent?**](#ref-nonexistent)
@@ -84,7 +84,7 @@ # References {#references .unnumbered} -::: {#refs .references .csl-bib-body}+:::::: {#refs .references .csl-bib-body entry-spacing="0"} ::: {#ref-item1 .csl-entry} [\[1\] ]{.csl-left-margin}[J. Doe, *First book*. Cambridge: Cambridge University Press, 2005.]{.csl-right-inline}@@ -100,7 +100,7 @@ *Third book*, S. Smith, Ed. Oxford: Oxford University Press, 2007.]{.csl-right-inline} :::-:::+:::::: [^1]: [\[3, p. 12\]](#ref-пункт3) and a citation without locators [\[3\]](#ref-пункт3).
@@ -100,7 +100,7 @@ [^6]: Subsequent, p. {(a)}. -[^7]: Ibid-with-locator.+[^7]: Ibid. [^8]: Ibid 123-35 numbers are suffix.
@@ -45,29 +45,29 @@ *Magazine* (2012a, 3), *Magazine* (2012b), *Magazine* (2012c), *Magazine* (2012d), *Newspaper* (2012a), *Newspaper* (2012b) -::: {#refs .references .csl-bib-body .hanging-indent}+::::::::: {#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}+:::: {#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. :::+:::: ```
@@ -0,0 +1,616 @@+PDF standard support: basic PDF/A-2b test (infers version 1.7)+```+% pandoc -t latex -s+---+pdfstandard: a-2b+lang: en-US+---++Test document.+^D+\DocumentMetadata{+ pdfversion=1.7,+ pdfstandard={a-2b},+ lang=en-US,+ xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+ american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+ \usepackage[T1]{fontenc}+ \usepackage[utf8]{inputenc}+ \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+ \usepackage{unicode-math} % this also loads fontspec+ \defaultfontfeatures{Scale=MatchLowercase}+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+ % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+ \usepackage[]{microtype}+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+ \IfFileExists{parskip.sty}{%+ \usepackage{parskip}+ }{% else+ \setlength{\parindent}{0pt}+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+ \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+ \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+ pdflang={en-US},+ hidelinks,+ pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++Test document.++\end{document}+```++PDF standard support: PDF/UA-1 with tagging+```+% pandoc -t latex -s+---+pdfstandard: ua-1+lang: en-US+---++Accessible document.+^D+\DocumentMetadata{+ pdfstandard={ua-1},+ tagging=on,+ lang=en-US,+ xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+ american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+ \usepackage[T1]{fontenc}+ \usepackage[utf8]{inputenc}+ \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+ \usepackage{unicode-math} % this also loads fontspec+ \defaultfontfeatures{Scale=MatchLowercase}+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+ % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+ \usepackage[]{microtype}+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+ \IfFileExists{parskip.sty}{%+ \usepackage{parskip}+ }{% else+ \setlength{\parindent}{0pt}+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+ \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+ \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+ pdflang={en-US},+ hidelinks,+ pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++Accessible document.++\end{document}+```++PDF standard support: multiple standards with version+```+% pandoc -t latex -s+---+pdfstandard:+ - a-2b+ - ua-1+ - "1.7"+lang: de-DE+---++Multi-standard document.+^D+\DocumentMetadata{+ pdfversion=1.7,+ pdfstandard={a-2b,ua-1},+ tagging=on,+ lang=de-DE,+ xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+ ngerman,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+ \usepackage[T1]{fontenc}+ \usepackage[utf8]{inputenc}+ \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+ \usepackage{unicode-math} % this also loads fontspec+ \defaultfontfeatures{Scale=MatchLowercase}+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+ % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+ \usepackage[]{microtype}+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+ \IfFileExists{parskip.sty}{%+ \usepackage{parskip}+ }{% else+ \setlength{\parindent}{0pt}+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+ \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+ \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+ pdflang={de-DE},+ hidelinks,+ pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++Multi-standard document.++\end{document}+```++PDF standard support: PDF/A-1b infers version 1.4+```+% pandoc -t latex -s+---+pdfstandard: a-1b+lang: en-US+---++PDF/A-1 document.+^D+\DocumentMetadata{+ pdfversion=1.4,+ pdfstandard={a-1b},+ lang=en-US,+ xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+ american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+ \usepackage[T1]{fontenc}+ \usepackage[utf8]{inputenc}+ \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+ \usepackage{unicode-math} % this also loads fontspec+ \defaultfontfeatures{Scale=MatchLowercase}+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+ % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+ \usepackage[]{microtype}+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+ \IfFileExists{parskip.sty}{%+ \usepackage{parskip}+ }{% else+ \setlength{\parindent}{0pt}+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+ \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+ \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+ pdflang={en-US},+ hidelinks,+ pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++PDF/A-1 document.++\end{document}+```++PDF standard support: PDF/A-4 with no version inference (uses default 2.0)+```+% pandoc -t latex -s+---+pdfstandard: a-4+lang: en-US+---++PDF/A-4 document.+^D+\DocumentMetadata{+ pdfstandard={a-4},+ lang=en-US,+ xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+ american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+ \usepackage[T1]{fontenc}+ \usepackage[utf8]{inputenc}+ \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+ \usepackage{unicode-math} % this also loads fontspec+ \defaultfontfeatures{Scale=MatchLowercase}+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+ % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+ \usepackage[]{microtype}+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+ \IfFileExists{parskip.sty}{%+ \usepackage{parskip}+ }{% else+ \setlength{\parindent}{0pt}+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+ \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+ \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+ pdflang={en-US},+ hidelinks,+ pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++PDF/A-4 document.++\end{document}+```++PDF standard support: numeric YAML version (2 becomes 2.0)+```+% pandoc -t latex -s+---+pdfstandard:+ - ua-1+ - 2+lang: en-US+---++PDF 2.0 document.+^D+\DocumentMetadata{+ pdfversion=2.0,+ pdfstandard={ua-1},+ tagging=on,+ lang=en-US,+ xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+ american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+ \usepackage[T1]{fontenc}+ \usepackage[utf8]{inputenc}+ \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+ \usepackage{unicode-math} % this also loads fontspec+ \defaultfontfeatures{Scale=MatchLowercase}+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+ % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+ \usepackage[]{microtype}+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+ \IfFileExists{parskip.sty}{%+ \usepackage{parskip}+ }{% else+ \setlength{\parindent}{0pt}+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+ \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+ \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+ pdflang={en-US},+ hidelinks,+ pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++PDF 2.0 document.++\end{document}+```++PDF standard support: explicit version overrides inferred version+```+% pandoc -t latex -s+---+pdfstandard:+ - a-2b+ - "1.5"+lang: en-US+---++Explicit version document.+^D+\DocumentMetadata{+ pdfversion=1.5,+ pdfstandard={a-2b},+ lang=en-US,+ xmp=true}+% Options for packages loaded elsewhere+\PassOptionsToPackage{unicode}{hyperref}+\PassOptionsToPackage{hyphens}{url}+\documentclass[+ american,+]{article}+\usepackage{xcolor}+\usepackage{amsmath,amssymb}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering+\usepackage{iftex}+\ifPDFTeX+ \usepackage[T1]{fontenc}+ \usepackage[utf8]{inputenc}+ \usepackage{textcomp} % provide euro and other symbols+\else % if luatex or xetex+ \usepackage{unicode-math} % this also loads fontspec+ \defaultfontfeatures{Scale=MatchLowercase}+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}+\fi+\usepackage{lmodern}+\ifPDFTeX\else+ % xetex/luatex font selection+\fi+% Use upquote if available, for straight quotes in verbatim environments+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}+\IfFileExists{microtype.sty}{% use microtype if available+ \usepackage[]{microtype}+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts+}{}+\makeatletter+\@ifundefined{KOMAClassName}{% if non-KOMA class+ \IfFileExists{parskip.sty}{%+ \usepackage{parskip}+ }{% else+ \setlength{\parindent}{0pt}+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}+}{% if KOMA class+ \KOMAoptions{parskip=half}}+\makeatother+\ifLuaTeX+\usepackage[bidi=basic,shorthands=off]{babel}+\else+\usepackage[bidi=default,shorthands=off]{babel}+\fi+\ifLuaTeX+ \usepackage{selnolig} % disable illegal ligatures+\fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}+\usepackage{bookmark}+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother+\hypersetup{+ pdflang={en-US},+ hidelinks,+ pdfcreator={LaTeX via pandoc}}++\author{}+\date{}++\begin{document}++Explicit version document.++\end{document}+```
@@ -28,7 +28,7 @@ , Link ( "" , []- , [ ( "reference-type" , "ref" )+ , [ ( "reference-type" , "ref+label" ) , ( "reference" , "fig:1" ) ] )@@ -48,7 +48,7 @@ , Link ( "" , []- , [ ( "reference-type" , "ref+page" )+ , [ ( "reference-type" , "ref" ) , ( "reference" , "fig:1" ) ] )@@ -66,7 +66,7 @@ [ Link ( "" , []- , [ ( "reference-type" , "autoref" )+ , [ ( "reference-type" , "ref+label" ) , ( "reference" , "fig:flowchart" ) ] )@@ -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}" ] ] ```@@ -133,11 +133,12 @@ Figure \ref{fig:Logo} illustrated the SVG logo ^D-[ Para- [ Image- ( "fig:Logo" , [] , [] )- [ Str "Logo" ]- ( "command/SVG_logo.svg" , "fig:" )+[ Figure+ ( "fig:Logo" , [] , [] )+ (Caption Nothing [ Plain [ Str "Logo" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "command/SVG_logo.svg" , "" )+ ] ] , Para [ Str "Figure"@@ -195,25 +196,28 @@ Figure \ref{fig:Logo3} illustrated the SVG logo ^D [ Header 1 ( "one" , [] , [] ) [ Str "One" ]-, Para- [ Image- ( "fig:Logo" , [] , [] )- [ Str "Logo" ]- ( "command/SVG_logo.svg" , "fig:" )+, Figure+ ( "fig:Logo" , [] , [] )+ (Caption Nothing [ Plain [ Str "Logo" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "command/SVG_logo.svg" , "" )+ ] ]-, Para- [ Image- ( "fig:Logo2" , [] , [] )- [ Str "Logo2" ]- ( "command/SVG_logo2.svg" , "fig:" )+, Figure+ ( "fig:Logo2" , [] , [] )+ (Caption Nothing [ Plain [ Str "Logo2" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "command/SVG_logo2.svg" , "" )+ ] ] , Header 1 ( "two" , [] , [] ) [ Str "Two" ] , Header 2 ( "subone" , [] , [] ) [ Str "Subone" ]-, Para- [ Image- ( "fig:Logo3" , [] , [] )- [ Str "Logo3" ]- ( "command/SVG_logo3.svg" , "fig:" )+, Figure+ ( "fig:Logo3" , [] , [] )+ (Caption Nothing [ Plain [ Str "Logo3" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "command/SVG_logo3.svg" , "" )+ ] ] , Para [ Str "Figure"
@@ -0,0 +1,41 @@+```+% pandoc --citeproc -t plain --csl command/chicago-fullnote-bibliography.csl+---+suppress-bibliography: true+references:+- id: foo+ name: John doe+ title: A Book+ type: book+ publisher: Oxford University Press+ issued: 2010+...++# Chapter one++Blah [@foo, p. 7].++Blah [@foo, p. 8].++# Chapter two {.reset-citation-positions}++Blah [@foo, p. 57].+^D+Chapter one++Blah.[1]++Blah.[2]++Chapter two++Blah.[3]++[1] A Book (Oxford University Press, 2010), 7.++[2] A Book, 8.++[3] A Book (Oxford University Press, 2010), 57.++```+
@@ -0,0 +1,246 @@+```+% pandoc -f native -t rst+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ [] []+ ]+ (TableFoot ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ ])+]+^D++---+---+---++| 1 | 2 | 3 |++---+ +---++| 1 | | 3 |++---+---+---++| 1 | 2 | 3 |++---+---+---++++---+---+---++| 1 | 2 | 3 |++---+ +---++| 1 | | 3 |++===+===+===++| 1 | 2 | 3 |++---+---+---++++===+===+===++| 1 | 2 | 3 |++---+ +---++| 1 | | 3 |++---+---+---++| 1 | 2 | 3 |++===+===+===++```
@@ -0,0 +1,18 @@+```+% pandoc -f rst -t native+|figure05|++.. |figure05| figure:: img/dummy.png++ capt+^D+[ Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "capt" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] ) [ Str "capt" ] ( "img/dummy.png" , "" )+ ]+ ]+]+```
@@ -0,0 +1,42 @@+```+% pandoc -f latex -t native+\begin{table}+\caption[short caption]{long caption}+\begin{tabular}{ll}+hi & hi \\+\end{tabular}+\end{table}+^D+[ Table+ ( "" , [] , [] )+ (Caption+ (Just [ Str "short" , Space , Str "caption" ])+ [ Plain [ Str "long" , Space , Str "caption" ] ])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "hi" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "hi" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]+```
@@ -315,11 +315,11 @@ <table:table-column table:style-name="Table1.P" /> <table:table-row> <table:table-cell table:style-name="TableRowCell" office:value-type="string" table:number-columns-spanned="8">- <text:p text:style-name="Table_20_Contents"><text:span text:style-name="T1">Octet+ <text:p text:style-name="Table_20_Contents"><text:span text:style-name="Strong_20_Emphasis">Octet no. 1</text:span></text:p> </table:table-cell> <table:table-cell table:style-name="TableRowCell" office:value-type="string" table:number-columns-spanned="8">- <text:p text:style-name="Table_20_Contents"><text:span text:style-name="T1">Octet+ <text:p text:style-name="Table_20_Contents"><text:span text:style-name="Strong_20_Emphasis">Octet no. 2</text:span></text:p> </table:table-cell> </table:table-row>
@@ -6,8 +6,8 @@ - [x] bar ^D <ul class="task-list">-<li><input type="checkbox" disabled="" />foo</li>-<li><input type="checkbox" disabled="" checked="" />bar</li>+<li><label><input type="checkbox" />foo</label></li>+<li><label><input type="checkbox" checked="" />bar</label></li> </ul> ``` @@ -20,12 +20,12 @@ - [ ] bim ^D <ul class="task-list">-<li><input type="checkbox" disabled="" checked="" />foo<ul-class="task-list">-<li><input type="checkbox" disabled="" />bar</li>-<li><input type="checkbox" disabled="" checked="" />baz</li>+<li><label><input type="checkbox" checked="" />foo</label>+<ul class="task-list">+<li><label><input type="checkbox" />bar</label></li>+<li><label><input type="checkbox" checked="" />baz</label></li> </ul></li>-<li><input type="checkbox" disabled="" />bim</li>+<li><label><input type="checkbox" />bim</label></li> </ul> ``` @@ -53,21 +53,23 @@ - [x] checked ^D <ul>-<li><input type="checkbox" disabled="" />unchecked</li>+<li><label><input type="checkbox" />unchecked</label></li> <li>plain item</li>-<li><input type="checkbox" disabled="" checked="" />checked</li>+<li><label><input type="checkbox" checked="" />checked</label></li> </ul> <p>paragraph</p> <ol type="1">-<li><input type="checkbox" disabled="" />ordered unchecked</li>+<li><label><input type="checkbox" />ordered unchecked</label></li> <li>[] plain item</li>-<li><input type="checkbox" disabled="" checked="" />ordered checked</li>+<li><label><input type="checkbox" checked="" />ordered+checked</label></li> </ol> <p>paragraph</p> <ul class="task-list">-<li><p><input type="checkbox" disabled="" />list item with-a</p><p>second paragraph</p></li>-<li><p><input type="checkbox" disabled="" checked="" />checked</p></li>+<li><p><label><input type="checkbox" />list item with a</label></p>+<p>second paragraph</p></li>+<li><p><label><input type="checkbox"+checked="" />checked</label></p></li> </ul> ``` @@ -98,6 +100,6 @@ - [ ] foo - [x] bar ^D-- [ ] foo-- [x] bar+- [ ] foo+- [x] bar ```
@@ -16,12 +16,12 @@ ## e ::: ^D-- [A](#a){#toc-a}- - [b](#b){#toc-b}-- [B](#b-1){#toc-b-1}- - [b](#b-2){#toc-b-2}-- [E](#e){#toc-e}- - [e](#e-1){#toc-e-1}+- [A](#a){#toc-a}+ - [b](#b){#toc-b}+- [B](#b-1){#toc-b-1}+ - [b](#b-2){#toc-b-2}+- [E](#e){#toc-e}+ - [e](#e-1){#toc-e-1} # A
@@ -21,7 +21,7 @@ ``` ```-% pandoc -f latex -t native -M lang=sr+% pandoc -f latex -t native -M lang=sr-Latn \figurename~2 \figurename. ^D
@@ -0,0 +1,55 @@+```+% pandoc -f typst -t native -s+#set document(+ title: [My Title],+)++#title()+^D+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "title"+ , MetaInlines [ Str "My" , Space , Str "Title" ]+ )+ ]+ }+ []+```++```+% pandoc -f typst -t native -s+#set document(+ title: [ignored],+)++#title[My Title]+^D+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "title"+ , MetaInlines [ Str "My" , Space , Str "Title" ]+ )+ ]+ }+ []+```++```+% pandoc -f typst -t native -s+#title[My Title]+^D+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "title"+ , MetaInlines [ Str "My" , Space , Str "Title" ]+ )+ ]+ }+ []+```
@@ -0,0 +1,78 @@+```+% pandoc -f markdown-implicit_figures -t typst++^D+#box(image("image.png", alt: "Alt text from inlines"))+```++```+% pandoc -f markdown-implicit_figures -t typst+{alt="Explicit alt attribute"}+^D+#box(image("image.png", alt: "Explicit alt attribute"))+```++```+% pandoc -f markdown-implicit_figures -t typst+{alt="Explicit wins"}+^D+#box(image("image.png", alt: "Explicit wins"))+```++```+% pandoc -f markdown-implicit_figures -t typst++^D+#box(image("image.png"))+```++```+% pandoc -f markdown-implicit_figures -t typst+{alt=""}+^D+#box(image("image.png"))+```++```+% pandoc -t typst+{alt="Alt text describing the image"}++^D+#figure(image("image.png", alt: "Alt text describing the image"),+ caption: [+ Caption text+ ]+)+```++```+% pandoc -t typst+++^D+#figure(image("image.png", alt: "Caption only"),+ caption: [+ Caption only+ ]+)+```++```+% pandoc -f markdown -t typst+{alt="A \"quoted\" phrase and C:\\path\\file"}+^D+#figure(image("test.png", alt: "A \"quoted\" phrase and C:\\path\\file"),+ caption: [+ Caption+ ]+)++```++```+% pandoc -f html -t typst+<img src="data:image/png;base64,iVBORw0KGgo=" alt="A small red dot">+^D+#box(image(bytes((137,80,78,71,13,10,26,10)), alt: "A small red dot"))++```
@@ -0,0 +1,32 @@+```+% pandoc -t typst+{width=1in}+^D+#figure(image(bytes((137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,10,0,0,0,10,8,6,0,0,0,141,50,207,189,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,73,73,68,65,84,24,25,173,206,91,10,0,32,8,4,64,215,251,223,217,52,18,53,66,127,18,130,30,211,42,136,72,116,141,197,163,56,160,64,145,8,207,123,179,5,118,233,255,33,180,93,12,214,244,230,123,232,151,53,179,19,29,3,118,140,202,247,165,181,63,56,205,31,23,32,166,25,1,179,208,168,31,0,0,0,0,73,69,78,68,174,66,96,130)), width: 1in, alt: "dot"),+ caption: [+ dot+ ]+)+```++```+% pandoc -t typst+{width="1in"}+^D+#figure(image("dot.png", width: 1in, alt: "dot"),+ caption: [+ dot+ ]+)+```++```+% pandoc -t typst++^D+#figure(image(bytes("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\" aria-label=\"Chicken\"> <path d=\"M76.5 33.3l-8.3-6.6 4-5c-1.3-2-1.3-4.7.1-6.6 3.4-3.8 8.7-2 10.2 2.2 4.5.7 7.5 5.4 4.4 9.4a5.7 5.7 0 01-6.4 1.6zM73 26.2l3 2.4 3.8-4.7c1.3 1 3.5 2 4.5.7 2.1-2.9-1.5-5.4-4.7-3.5 1.2-4.6-2.7-6.2-4.5-3.9-.7 2.2.2 3 1.7 4.2z\"/> <path d=\"M54 72.3a19.1 19.1 0 01-19.2-17.8 21.4 21.4 0 014.7-15.2c3.5-4.3 8.4-7.1 13.7-8l3.1-.1c8.2-.9 12.9-5.5 13-5.6l1-1 8.2 6.5-1 1.3c-3.3 4-2.8 11.3-2.5 14.2a21.5 21.5 0 01-4.4 17.5 21.2 21.2 0 01-16.5 8.2zM70.6 29a27 27 0 01-14 5.5l-3 .2a18 18 0 00-11.3 6.7 18 18 0 00-4 12.8 16 16 0 0015.9 14.7c5.4 0 10.4-2.5 14-6.9A18 18 0 0072 49.4c0-.8-.2-1.6-.3-2.2-.5-4-.7-10.7 2.1-15.5z\"/> <path d=\"M46 87C22.6 87 .5 87 .5 66.8c0-19 20.4-34.6 45.5-34.6 1.2 0 2.5 0 3.7.2 10.1.6 9.7-.1.5 3.2a18.3 18.3 0 00-12 18.6 16 16 0 0015.9 14.7c5.4 0 10.4-2.5 14-6.9A18 18 0 0072 49.4c-.6-4-.4-7.4-.2-11.3a35.8 35.8 0 0119.5 26A11.7 11.7 0 0187.8 87H46zm-2.8-51.3c-22 1-39.4 14.6-39.4 31 0 15.8 16 16.9 42.2 16.9h41.8c4.6 0 8.4-3.8 8.4-8.4-.4-4.8-3.2-7.7-8.1-8.4-.3-10.4-7.4-18.4-13.3-22.7.1 2 .5 4.3.7 6.1 0 5-1.6 10-4.8 14A21.2 21.2 0 0154 72.3a19.1 19.1 0 01-19.3-17.8 21.4 21.4 0 018.4-18.8z\"/> </svg>"), alt: "chicken"),+ caption: [+ chicken+ ]+)+```
@@ -0,0 +1,235 @@+```+% pandoc -f html -t typst+<span typst:text:fill="orange">foo</span>+^D+#text(fill: orange)[foo]+```++```+% pandoc -f html -t typst+<span>foo</span>+^D+foo+```++```+% pandoc -f html -t typst+<div typst:inset="10pt">foo</div>+^D+#block(inset: 10pt)[+foo+]+```++```+% pandoc -f html -t typst+<div typst:text:fill="purple">foo</div>+^D+#block[+#set text(fill: purple);+foo+]+```++```+% pandoc -f html -t typst+<div>foo</div>+^D+#block[+foo+]+```++```+% pandoc -f html -t typst+<table typst:fill="blue">+ <tr><td>A</td><td>B</td></tr>+</table>+^D+#figure(+ align(center)[#table(+ columns: 2,+ align: (auto,auto,),+ fill: blue,+ [A], [B],+ )]+ , kind: table+ )+```++```+% pandoc -f html -t typst+<table typst:text:fill="orange">+ <tr><td>A</td><td>B</td></tr>+</table>+^D+#figure(+ align(center)[#set text(fill: orange);#table(+ columns: 2,+ align: (auto,auto,),+ [A], [B],+ )]+ , kind: table+ )+```++```+% pandoc -f html -t typst+<table>+ <tr><td>A</td><td typst:fill="green">B</td></tr>+</table>+^D+#figure(+ align(center)[#table(+ columns: 2,+ align: (auto,auto,),+ [A], table.cell(fill: green)[B],+ )]+ , kind: table+ )+```++```+% pandoc -f html -t typst+<table>+ <tr><td>A</td><td typst:text:fill="fuchsia">B</td></tr>+</table>+^D+#figure(+ align(center)[#table(+ columns: 2,+ align: (auto,auto,),+ [A], [#set text(fill: fuchsia);+ B],+ )]+ , kind: table+ )+```++```+% pandoc -f html -t typst+<table>+ <tr><td>A</td><td typst:text:fill="maroon" align="center">B</td></tr>+</table>+^D+#figure(+ align(center)[#table(+ columns: 2,+ align: (auto,center,),+ [A], table.cell(align: center)[#set text(fill: maroon);+ B],+ )]+ , kind: table+ )+```++```+% pandoc -f html -t typst+<table>+ <tr><td>A</td><td typst:align="horizon" align="center">B</td></tr>+</table>+^D+#figure(+ align(center)[#table(+ columns: 2,+ align: (auto,center,),+ [A], table.cell(align: horizon + center)[B],+ )]+ , kind: table+ )+```+++```+% pandoc -f html -t typst+<table>+ <tr><td>A</td><td>B</td></tr>+</table>+^D+#figure(+ align(center)[#table(+ columns: 2,+ align: (auto,auto,),+ [A], [B],+ )]+ , kind: table+ )+```++```+% pandoc -f html -t typst+<p>Paragraph before.</p>++<table class="typst:no-figure" typst:text:size="3em">+ <tr>+ <td>A</td>+ <td>B</td>+ <td>C</td>+ </tr>+</table>++<p>Paragraph after.</p>+^D+Paragraph before.++#{set text(size: 3em);table(+ columns: 3,+ align: (auto,auto,auto,),+ [A], [B], [C],+)}+Paragraph after.+```+++```+% pandoc -f html -t typst+<p>Paragraph before.</p>++<table typst:text:size="3em">+ <tr>+ <td>A</td>+ <td>B</td>+ <td>C</td>+ </tr>+</table>++<p>Paragraph after.</p>+^D+Paragraph before.++#figure(+ align(center)[#set text(size: 3em);#table(+ columns: 3,+ align: (auto,auto,auto,),+ [A], [B], [C],+ )]+ , kind: table+ )++Paragraph after.+```+++```+% pandoc -f html -t typst+<p>Paragraph before.</p>++<table class="typst:no-figure">+ <tr>+ <td>A</td>+ <td>B</td>+ <td>C</td>+ </tr>+</table>++<p>Paragraph after.</p>+^D+Paragraph before.++#table(+ columns: 3,+ align: (auto,auto,auto,),+ [A], [B], [C],+)+Paragraph after.+```
@@ -0,0 +1,73 @@+# CommonMark++## Reader+```+% pandoc --from commonmark_x+wikilinks_title_after_pipe -t html --columns 90+[[https://example.org]]++[[https://example.org|title]]++[[name of page]]++[[name of page|title]]+^D+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="name of page" class="wikilink">name of page</a></p>+<p><a href="name of page" class="wikilink">title</a></p>+```++## Writer++```+% pandoc -t commonmark_x+wikilinks_title_after_pipe -f html+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Home" class="wikilink">Home</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p>+^D+[[https://example.org]]++[[https://example.org|title]]++[[Home]]++[[Name%20of%20page|Title]]+```++# Markdown+## Reader++```+% pandoc --from markdown+wikilinks_title_after_pipe -t html --columns 90+[[https://example.org]]++[[https://example.org|title]]++[[name of page]]++[[name of page|title]]+^D+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="name of page" class="wikilink">name of page</a></p>+<p><a href="name of page" class="wikilink">title</a></p>+```++## Writer++```+% pandoc -t markdown+wikilinks_title_after_pipe -f html+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Home" class="wikilink">Home</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p>+^D+[[https://example.org]]++[[https://example.org|title]]++[[Home]]++[[Name%20of%20page|Title]]+```
@@ -0,0 +1,84 @@+# CommonMark++## Reader++```+% pandoc -f commonmark+wikilinks_title_before_pipe -t html --columns 90+[[https://example.org]]++[[title|https://example.org]]++[[Name of page]]++[[Title|Name of page]]+^D+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Name of page" class="wikilink">Name of page</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p>+```++## Writer++```+% pandoc -t commonmark_x+wikilinks_title_before_pipe -f html+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Home" class="wikilink">Home</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p>+^D+[[https://example.org]]++[[title|https://example.org]]++[[Home]]++[[Title|Name%20of%20page]]+```++## Regular links should still work++```+% pandoc -f commonmark+wikilinks_title_before_pipe -t html+[Title](Name%20of%20page)+^D+<p><a href="Name%20of%20page">Title</a></p>+```++# Markdown++## Reader++```+% pandoc -f markdown+wikilinks_title_before_pipe -t html --columns 90+[[https://example.org]]++[[title|https://example.org]]++[[Name of page]]++[[Title|Name of page]]+^D+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Name of page" class="wikilink">Name of page</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p>+```++## Writer++```+% pandoc -t markdown+wikilinks_title_before_pipe -f html+<p><a href="https://example.org" class="wikilink">https://example.org</a></p>+<p><a href="https://example.org" class="wikilink">title</a></p>+<p><a href="Home" class="wikilink">Home</a></p>+<p><a href="Name of page" class="wikilink">Title</a></p>+^D+[[https://example.org]]++[[title|https://example.org]]++[[Home]]++[[Title|Name%20of%20page]]+```
@@ -12,13 +12,7 @@ { unMeta = fromList [ ( "ml"- , MetaInlines- [ Str "TEST"- , Space- , Str "\182"- , Space- , Str "BLOCK"- ]+ , MetaInlines [ Str "TEST" , LineBreak , Str "BLOCK" ] ) ] }
@@ -0,0 +1,749 @@+# Pandoc Test Suite++John MacFarlane+Anonymous++July 17, 2006++This is a set of tests for pandoc. Most of them are adapted from John Gruber's+markdown test suite.++* * * *++{#headers}+# Headers++{#level-2-with-an-embedded-link}+## Level 2 with an [embedded link](/url)++{#level-3-with-emphasis}+### Level 3 with _emphasis_++{#level-4}+#### Level 4++{#level-5}+##### Level 5++{#level-1}+# Level 1++{#level-2-with-emphasis}+## Level 2 with _emphasis_++{#level-3}+### Level 3++with no blank line++{#level-2}+## Level 2++with no blank line++* * * *++{#paragraphs}+# Paragraphs++Here's a regular paragraph.++In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.+Because a hard-wrapped line in the middle of a paragraph looked like a list+item.++Here's one with a bullet. \* criminey.++There should be a hard line break\+here.++* * * *++{#block-quotes}+# Block Quotes++E-mail style:++> This is a block quote. It is pretty short.++> Code in a block quote:+>+> ```+> sub status {+> print "working";+> }+> ```+>+> A list:+>+> 1. item one+> 2. item two+>+> Nested block quotes:+>+> > nested+>+> > nested++This should not be a block quote: 2 \> 1.++And a following paragraph.++* * * *++{#code-blocks}+# Code Blocks++Code:++```+---- (should be four hyphens)++sub status {+ print "working";+}++this code block is indented by one tab+```++And:++```+ this code block is indented by two tabs++These should not be escaped: \$ \\ \> \[ \{+```++* * * *++{#lists}+# Lists++{#unordered}+## Unordered++Asterisks tight:++- asterisk 1+- asterisk 2+- asterisk 3++Asterisks loose:++- asterisk 1++- asterisk 2++- asterisk 3++Pluses tight:++- Plus 1+- Plus 2+- Plus 3++Pluses loose:++- Plus 1++- Plus 2++- Plus 3++Minuses tight:++- Minus 1+- Minus 2+- Minus 3++Minuses loose:++- Minus 1++- Minus 2++- Minus 3++{#ordered}+## Ordered++Tight:++1. First+2. Second+3. Third++and:++1. One+2. Two+3. Three++Loose using tabs:++1. First++2. Second++3. Third++and using spaces:++1. One++2. Two++3. Three++Multiple paragraphs:++1. Item 1, graf one.++ Item 1. graf two. The quick brown fox jumped over the lazy dog's back.++2. Item 2.++3. Item 3.++{#nested}+## Nested++- Tab++ - Tab++ - Tab++Here's another:++1. First+2. Second:++ - Fee+ - Fie+ - Foe+3. Third++Same thing but with paragraphs:++1. First++2. Second:++ - Fee+ - Fie+ - Foe++3. Third++{#tabs-and-spaces}+## Tabs and spaces++- this is a list item indented with tabs++- this is a list item indented with spaces++ - this is an example list item indented with tabs++ - this is an example list item indented with spaces++{#fancy-list-markers}+## Fancy list markers++(2) begins with 2++(3) and now 3++ with a continuation++ iv. sublist with roman numerals, starting with 4+ v. more items++ (A) a subsublist+ (B) a subsublist++Nesting:++A. Upper Alpha++ I. Upper Roman.++ (6) Decimal start with 6++ c) Lower alpha with paren++Autonumbering:++1. Autonumber.+2. More.++ 1. Nested.++Should not be a list item:++M.A. 2007++B. Williams++* * * *++{#definition-lists}+# Definition Lists++Tight using spaces:++: apple++ red fruit+: orange++ orange fruit+: banana++ yellow fruit++Tight using tabs:++: apple++ red fruit+: orange++ orange fruit+: banana++ yellow fruit++Loose:++: apple++ red fruit++: orange++ orange fruit++: banana++ yellow fruit++Multiple blocks with italics:++: _apple_++ red fruit++ contains seeds, crisp, pleasant to taste++: _orange_++ orange fruit++ ```+ { orange code block }+ ```++ > orange block quote++Multiple definitions, tight:++: apple++ red fruit++ computer+: orange++ orange fruit++ bank++Multiple definitions, loose:++: apple++ red fruit++ computer++: orange++ orange fruit++ bank++Blank line after term, indented marker, alternate markers:++: apple++ red fruit++ computer++: orange++ orange fruit++ 1. sublist+ 2. sublist++{#html-blocks}+# HTML Blocks++Simple block on one line:++:::+foo++:::++And nested without indentation:++::::::+::::+:::+foo++:::++::::++:::+bar++:::++::::::++Interpreted markdown in a table:++This is _emphasized_++And this is *strong*++Here's a simple block:++:::+foo++:::++This should be a code block, though:++```+<div>+ foo+</div>+```++As should this:++```+<div>foo</div>+```++Now, nested:++:::::+::::+:::+foo++:::++::::++:::::++This should just be an HTML comment:++Multiline:++Code block:++```+<!-- Comment -->+```++Just plain comment, with trailing spaces on the line:++Code:++```+<hr />+```++Hr's:++* * * *++{#inline-markup}+# Inline Markup++This is _emphasized_, and so _is this_.++This is *strong*, and so *is this*.++An _[emphasized link](/url)_.++*_This is strong and em._*++So is *_this_* word.++*_This is strong and em._*++So is *_this_* word.++This is code: `>`, `$`, `\`, `\$`, `<html>`.++{-This is _strikeout_.-}++Superscripts: 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.++* * * *++{#smart-quotes-ellipses-dashes}+# Smart quotes, ellipses, dashes++"Hello," said the spider. "'Shelob' is my name."++'A', 'B', and 'C' are letters.++'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'++'He said, "I want to go."' Were you alive in the 70's?++Here is some quoted '`code`' and a "[quoted+link](http://example.com/?foo=1&bar=2)".++Some dashes: one---two --- three---four --- five.++Dashes between numbers: 5--7, 255--66, 1987--1999.++Ellipses...and...and....++* * * *++{#latex}+# LaTeX++- +- $`2+2=4`+- $`x \in y`+- $`\alpha \wedge \omega`+- $`223`+- $`p`-Tree+- Here's some display math:+ $$`\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}`+- Here's one that has a line break in it: $`\alpha + \omega \times x^2`.++These shouldn't be math:++- To get the famous equation, write `$e = mc^2$`.+- $22,000 is a _lot_ of money. So is $34,000. (It worked if "lot" is+ emphasized.)+- Shoes ($20) and socks ($5).+- Escaped `$`\: $73 _this should be emphasized_ 23$.++Here's a LaTeX table:++* * * *++{#special-characters}+# Special Characters++Here is some unicode:++- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: ©++AT&T has an ampersand in their name.++AT&T is another way to write it.++This & that.++4 \< 5.++6 \> 5.++Backslash: \\++Backtick: \`++Asterisk: \*++Underscore: \_++Left brace: \{++Right brace: \}++Left bracket: \[++Right bracket: \]++Left paren: (++Right paren: )++Greater-than: \>++Hash: #++Period: .++Bang: \!++Plus: +++Minus: -++* * * *++{#links}+# Links++{#explicit}+## Explicit++Just a [URL](/url/).++[URL and title](/url/){title="title"}.++[URL and title](/url/){title="title preceded by two spaces"}.++[URL and title](/url/){title="title preceded by a tab"}.++[URL and title](/url/){title="title with \"quotes\" in it"}++[URL and title](/url/){title="title with single quotes"}++[with\_underscore](/url/with_underscore)++[Email link](mailto:nobody@nowhere.net)++[Empty]().++{#reference}+## Reference++Foo [bar](/url/).++With [embedded \[brackets\]](/url/).++[b](/url/) by itself should be a link.++Indented [once](/url).++Indented [twice](/url).++Indented [thrice](/url).++This should \[not\]\[\] be a link.++```+[not]: /url+```++Foo [bar](/url/){title="Title with \"quotes\" inside"}.++Foo [biz](/url/){title="Title with \"quote\" inside"}.++{#with-ampersands}+## With ampersands++Here's a [link with an ampersand in the URL](http://example.com/?foo=1&bar=2).++Here's a link with an amersand in the link text:+[AT&T](http://att.com/){title="AT&T"}.++Here's an [inline link](/script?foo=1&bar=2).++Here's an [inline link in pointy braces](/script?foo=1&bar=2).++{#autolinks}+## Autolinks++With an ampersand: <http://example.com/?foo=1&bar=2>++- In a list?+- <http://example.com/>+- It should.++An e-mail address: <nobody@nowhere.net>++> Blockquoted: <http://example.com/>++Auto-links should not occur here: `<http://example.com/>`++```+or here: <http://example.com/>+```++* * * *++{#images}+# Images++From "Voyage dans la Lune" by Georges Melies (1902):++::::+{title="Voyage dans la Lune"}++{.caption}+:::+lalune++:::++::::++Here is a movie  icon.++* * * *++{#footnotes}+# Footnotes++Here is a footnote reference,[^1] and another.[^2] This should _not_ be a+footnote reference, because it contains a space.\[\^my note\] Here is an inline+note.[^3]++> Notes can go in quotes.[^4]++1. And in list items.[^5]++This paragraph should not be part of the note, as it is not indented.++[^1]: Here is the footnote. It can go anywhere after the footnote reference. It+ need not be placed at the end of the document.++[^2]: Here's the long note. This one contains multiple blocks.++ Subsequent blocks are indented to show that they belong to the footnote (as+ with list items).++ ```+ { <code> }+ ```++ If you want, you can indent every line, but you can also be lazy and just+ indent the first line of each block.++[^3]: This is _easier_ to type. Inline notes may contain+ [links](http://google.com) and `]` verbatim characters, as well as+ \[bracketed text\].++[^4]: In quote.++[^5]: In list.
@@ -0,0 +1,2365 @@+Pandoc+ Meta { unMeta = fromList [] }+ [ Div+ ( "Pandoc-Test-Suite" , [ "section" ] , [] )+ [ Header+ 1+ ( "" , [] , [] )+ [ Str "Pandoc" , Space , Str "Test" , Space , Str "Suite" ]+ , Para+ [ Str "John"+ , Space+ , Str "MacFarlane"+ , SoftBreak+ , Str "Anonymous"+ ]+ , Para+ [ Str "July" , Space , Str "17," , Space , Str "2006" ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "set"+ , Space+ , Str "of"+ , Space+ , Str "tests"+ , Space+ , Str "for"+ , Space+ , Str "pandoc."+ , Space+ , Str "Most"+ , Space+ , Str "of"+ , Space+ , Str "them"+ , Space+ , Str "are"+ , Space+ , Str "adapted"+ , Space+ , Str "from"+ , Space+ , Str "John"+ , Space+ , Str "Gruber\8217s"+ , SoftBreak+ , Str "markdown"+ , Space+ , Str "test"+ , Space+ , Str "suite."+ ]+ , HorizontalRule+ ]+ , Div+ ( "headers" , [ "section" ] , [] )+ [ Header 1 ( "" , [] , [] ) [ Str "Headers" ]+ , Div+ ( "level-2-with-an-embedded-link" , [ "section" ] , [] )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "Level"+ , Space+ , Str "2"+ , Space+ , Str "with"+ , Space+ , Str "an"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "embedded" , Space , Str "link" ]+ ( "/url" , "" )+ ]+ , Div+ ( "level-3-with-emphasis" , [ "section" ] , [] )+ [ Header+ 3+ ( "" , [] , [] )+ [ Str "Level"+ , Space+ , Str "3"+ , Space+ , Str "with"+ , Space+ , Emph [ Str "emphasis" ]+ ]+ , Div+ ( "level-4" , [ "section" ] , [] )+ [ Header+ 4+ ( "" , [] , [] )+ [ Str "Level" , Space , Str "4" ]+ , Div+ ( "level-5" , [ "section" ] , [] )+ [ Header+ 5+ ( "" , [] , [] )+ [ Str "Level" , Space , Str "5" ]+ ]+ ]+ ]+ ]+ ]+ , Div+ ( "level-1" , [ "section" ] , [] )+ [ Header+ 1 ( "" , [] , [] ) [ Str "Level" , Space , Str "1" ]+ , Div+ ( "level-2-with-emphasis" , [ "section" ] , [] )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "Level"+ , Space+ , Str "2"+ , Space+ , Str "with"+ , Space+ , Emph [ Str "emphasis" ]+ ]+ , Div+ ( "level-3" , [ "section" ] , [] )+ [ Header+ 3 ( "" , [] , [] ) [ Str "Level" , Space , Str "3" ]+ , Para+ [ Str "with"+ , Space+ , Str "no"+ , Space+ , Str "blank"+ , Space+ , Str "line"+ ]+ ]+ ]+ , Div+ ( "level-2" , [ "section" ] , [] )+ [ Header+ 2 ( "" , [] , [] ) [ Str "Level" , Space , Str "2" ]+ , Para+ [ Str "with"+ , Space+ , Str "no"+ , Space+ , Str "blank"+ , Space+ , Str "line"+ ]+ , HorizontalRule+ ]+ ]+ , Div+ ( "paragraphs" , [ "section" ] , [] )+ [ Header 1 ( "" , [] , [] ) [ Str "Paragraphs" ]+ , Para+ [ Str "Here\8217s"+ , Space+ , Str "a"+ , Space+ , Str "regular"+ , Space+ , Str "paragraph."+ ]+ , Para+ [ Str "In"+ , Space+ , Str "Markdown"+ , Space+ , Str "1.0.0"+ , Space+ , Str "and"+ , Space+ , Str "earlier."+ , Space+ , Str "Version"+ , Space+ , Str "8."+ , Space+ , Str "This"+ , Space+ , Str "line"+ , Space+ , Str "turns"+ , Space+ , Str "into"+ , Space+ , Str "a"+ , Space+ , Str "list"+ , Space+ , Str "item."+ , SoftBreak+ , Str "Because"+ , Space+ , Str "a"+ , Space+ , Str "hard-wrapped"+ , Space+ , Str "line"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "middle"+ , Space+ , Str "of"+ , Space+ , Str "a"+ , Space+ , Str "paragraph"+ , Space+ , Str "looked"+ , Space+ , Str "like"+ , Space+ , Str "a"+ , Space+ , Str "list"+ , SoftBreak+ , Str "item."+ ]+ , Para+ [ Str "Here\8217s"+ , Space+ , Str "one"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "bullet."+ , Space+ , Str "*"+ , Space+ , Str "criminey."+ ]+ , Para+ [ Str "There"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "a"+ , Space+ , Str "hard"+ , Space+ , Str "line"+ , Space+ , Str "break"+ , LineBreak+ , Str "here."+ ]+ , HorizontalRule+ ]+ , Div+ ( "block-quotes" , [ "section" ] , [] )+ [ Header+ 1 ( "" , [] , [] ) [ Str "Block" , Space , Str "Quotes" ]+ , Para [ Str "E-mail" , Space , Str "style:" ]+ , BlockQuote+ [ Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "block"+ , Space+ , Str "quote."+ , Space+ , Str "It"+ , Space+ , Str "is"+ , Space+ , Str "pretty"+ , Space+ , Str "short."+ ]+ ]+ , BlockQuote+ [ Para+ [ Str "Code"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "block"+ , Space+ , Str "quote:"+ ]+ , CodeBlock+ ( "" , [ "" ] , [] )+ "sub status {\n print \"working\";\n}\n"+ , Para [ Str "A" , Space , Str "list:" ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain [ Str "item" , Space , Str "one" ] ]+ , [ Plain [ Str "item" , Space , Str "two" ] ]+ ]+ , Para+ [ Str "Nested"+ , Space+ , Str "block"+ , Space+ , Str "quotes:"+ ]+ , BlockQuote [ Para [ Str "nested" ] ]+ , BlockQuote [ Para [ Str "nested" ] ]+ ]+ , Para+ [ Str "This"+ , Space+ , Str "should"+ , Space+ , Str "not"+ , Space+ , Str "be"+ , Space+ , Str "a"+ , Space+ , Str "block"+ , Space+ , Str "quote:"+ , Space+ , Str "2"+ , Space+ , Str ">"+ , Space+ , Str "1."+ ]+ , Para+ [ Str "And"+ , Space+ , Str "a"+ , Space+ , Str "following"+ , Space+ , Str "paragraph."+ ]+ , HorizontalRule+ ]+ , Div+ ( "code-blocks" , [ "section" ] , [] )+ [ Header+ 1 ( "" , [] , [] ) [ Str "Code" , Space , Str "Blocks" ]+ , Para [ Str "Code:" ]+ , CodeBlock+ ( "" , [ "" ] , [] )+ "---- (should be four hyphens)\n\nsub status {\n print \"working\";\n}\n\nthis code block is indented by one tab\n"+ , Para [ Str "And:" ]+ , CodeBlock+ ( "" , [ "" ] , [] )+ " this code block is indented by two tabs\n\nThese should not be escaped: \\$ \\\\ \\> \\[ \\{\n"+ , HorizontalRule+ ]+ , Div+ ( "lists" , [ "section" ] , [] )+ [ Header 1 ( "" , [] , [] ) [ Str "Lists" ]+ , Div+ ( "unordered" , [ "section" ] , [] )+ [ Header 2 ( "" , [] , [] ) [ Str "Unordered" ]+ , Para [ Str "Asterisks" , Space , Str "tight:" ]+ , BulletList+ [ [ Plain [ Str "asterisk" , Space , Str "1" ] ]+ , [ Plain [ Str "asterisk" , Space , Str "2" ] ]+ , [ Plain [ Str "asterisk" , Space , Str "3" ] ]+ ]+ , Para [ Str "Asterisks" , Space , Str "loose:" ]+ , BulletList+ [ [ Para [ Str "asterisk" , Space , Str "1" ] ]+ , [ Para [ Str "asterisk" , Space , Str "2" ] ]+ , [ Para [ Str "asterisk" , Space , Str "3" ] ]+ ]+ , Para [ Str "Pluses" , Space , Str "tight:" ]+ , BulletList+ [ [ Plain [ Str "Plus" , Space , Str "1" ] ]+ , [ Plain [ Str "Plus" , Space , Str "2" ] ]+ , [ Plain [ Str "Plus" , Space , Str "3" ] ]+ ]+ , Para [ Str "Pluses" , Space , Str "loose:" ]+ , BulletList+ [ [ Para [ Str "Plus" , Space , Str "1" ] ]+ , [ Para [ Str "Plus" , Space , Str "2" ] ]+ , [ Para [ Str "Plus" , Space , Str "3" ] ]+ ]+ , Para [ Str "Minuses" , Space , Str "tight:" ]+ , BulletList+ [ [ Plain [ Str "Minus" , Space , Str "1" ] ]+ , [ Plain [ Str "Minus" , Space , Str "2" ] ]+ , [ Plain [ Str "Minus" , Space , Str "3" ] ]+ ]+ , Para [ Str "Minuses" , Space , Str "loose:" ]+ , BulletList+ [ [ Para [ Str "Minus" , Space , Str "1" ] ]+ , [ Para [ Str "Minus" , Space , Str "2" ] ]+ , [ Para [ Str "Minus" , Space , Str "3" ] ]+ ]+ ]+ , Div+ ( "ordered" , [ "section" ] , [] )+ [ Header 2 ( "" , [] , [] ) [ Str "Ordered" ]+ , Para [ Str "Tight:" ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain [ Str "First" ] ]+ , [ Plain [ Str "Second" ] ]+ , [ Plain [ Str "Third" ] ]+ ]+ , Para [ Str "and:" ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain [ Str "One" ] ]+ , [ Plain [ Str "Two" ] ]+ , [ Plain [ Str "Three" ] ]+ ]+ , Para+ [ Str "Loose"+ , Space+ , Str "using"+ , Space+ , Str "tabs:"+ ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Para [ Str "First" ] ]+ , [ Para [ Str "Second" ] ]+ , [ Para [ Str "Third" ] ]+ ]+ , Para+ [ Str "and"+ , Space+ , Str "using"+ , Space+ , Str "spaces:"+ ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Para [ Str "One" ] ]+ , [ Para [ Str "Two" ] ]+ , [ Para [ Str "Three" ] ]+ ]+ , Para [ Str "Multiple" , Space , Str "paragraphs:" ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Para+ [ Str "Item"+ , Space+ , Str "1,"+ , Space+ , Str "graf"+ , Space+ , Str "one."+ ]+ , Para+ [ Str "Item"+ , Space+ , Str "1."+ , Space+ , Str "graf"+ , Space+ , Str "two."+ , Space+ , Str "The"+ , Space+ , Str "quick"+ , Space+ , Str "brown"+ , Space+ , Str "fox"+ , Space+ , Str "jumped"+ , Space+ , Str "over"+ , Space+ , Str "the"+ , Space+ , Str "lazy"+ , Space+ , Str "dog\8217s"+ , Space+ , Str "back."+ ]+ ]+ , [ Para [ Str "Item" , Space , Str "2." ] ]+ , [ Para [ Str "Item" , Space , Str "3." ] ]+ ]+ ]+ , Div+ ( "nested" , [ "section" ] , [] )+ [ Header 2 ( "" , [] , [] ) [ Str "Nested" ]+ , BulletList+ [ [ Plain [ Str "Tab" ]+ , BulletList+ [ [ Plain [ Str "Tab" ]+ , BulletList [ [ Plain [ Str "Tab" ] ] ]+ ]+ ]+ ]+ ]+ , Para [ Str "Here\8217s" , Space , Str "another:" ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain [ Str "First" ] ]+ , [ Plain [ Str "Second:" ]+ , BulletList+ [ [ Plain [ Str "Fee" ] ]+ , [ Plain [ Str "Fie" ] ]+ , [ Plain [ Str "Foe" ] ]+ ]+ ]+ , [ Plain [ Str "Third" ] ]+ ]+ , Para+ [ Str "Same"+ , Space+ , Str "thing"+ , Space+ , Str "but"+ , Space+ , Str "with"+ , Space+ , Str "paragraphs:"+ ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Para [ Str "First" ] ]+ , [ Para [ Str "Second:" ]+ , BulletList+ [ [ Plain [ Str "Fee" ] ]+ , [ Plain [ Str "Fie" ] ]+ , [ Plain [ Str "Foe" ] ]+ ]+ ]+ , [ Para [ Str "Third" ] ]+ ]+ ]+ , Div+ ( "tabs-and-spaces" , [ "section" ] , [] )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "Tabs" , Space , Str "and" , Space , Str "spaces" ]+ , BulletList+ [ [ Para+ [ Str "this"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "list"+ , Space+ , Str "item"+ , Space+ , Str "indented"+ , Space+ , Str "with"+ , Space+ , Str "tabs"+ ]+ ]+ , [ Para+ [ Str "this"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "list"+ , Space+ , Str "item"+ , Space+ , Str "indented"+ , Space+ , Str "with"+ , Space+ , Str "spaces"+ ]+ , BulletList+ [ [ Para+ [ Str "this"+ , Space+ , Str "is"+ , Space+ , Str "an"+ , Space+ , Str "example"+ , Space+ , Str "list"+ , Space+ , Str "item"+ , Space+ , Str "indented"+ , Space+ , Str "with"+ , Space+ , Str "tabs"+ ]+ ]+ , [ Para+ [ Str "this"+ , Space+ , Str "is"+ , Space+ , Str "an"+ , Space+ , Str "example"+ , Space+ , Str "list"+ , Space+ , Str "item"+ , Space+ , Str "indented"+ , Space+ , Str "with"+ , Space+ , Str "spaces"+ ]+ ]+ ]+ ]+ ]+ ]+ , Div+ ( "fancy-list-markers" , [ "section" ] , [] )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "Fancy"+ , Space+ , Str "list"+ , Space+ , Str "markers"+ ]+ , OrderedList+ ( 2 , Decimal , TwoParens )+ [ [ Para+ [ Str "begins"+ , Space+ , Str "with"+ , Space+ , Str "2"+ ]+ ]+ , [ Para+ [ Str "and" , Space , Str "now" , Space , Str "3" ]+ , Para+ [ Str "with"+ , Space+ , Str "a"+ , Space+ , Str "continuation"+ ]+ , OrderedList+ ( 4 , LowerRoman , Period )+ [ [ Plain+ [ Str "sublist"+ , Space+ , Str "with"+ , Space+ , Str "roman"+ , Space+ , Str "numerals,"+ , Space+ , Str "starting"+ , Space+ , Str "with"+ , Space+ , Str "4"+ ]+ ]+ , [ Plain [ Str "more" , Space , Str "items" ]+ , OrderedList+ ( 1 , UpperAlpha , TwoParens )+ [ [ Plain+ [ Str "a" , Space , Str "subsublist" ]+ ]+ , [ Plain+ [ Str "a" , Space , Str "subsublist" ]+ ]+ ]+ ]+ ]+ ]+ ]+ , Para [ Str "Nesting:" ]+ , OrderedList+ ( 1 , UpperAlpha , Period )+ [ [ Plain [ Str "Upper" , Space , Str "Alpha" ]+ , OrderedList+ ( 1 , UpperRoman , Period )+ [ [ Plain [ Str "Upper" , Space , Str "Roman." ]+ , OrderedList+ ( 6 , Decimal , TwoParens )+ [ [ Plain+ [ Str "Decimal"+ , Space+ , Str "start"+ , Space+ , Str "with"+ , Space+ , Str "6"+ ]+ , OrderedList+ ( 3 , LowerAlpha , OneParen )+ [ [ Plain+ [ Str "Lower"+ , Space+ , Str "alpha"+ , Space+ , Str "with"+ , Space+ , Str "paren"+ ]+ ]+ ]+ ]+ ]+ ]+ ]+ ]+ ]+ , Para [ Str "Autonumbering:" ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain [ Str "Autonumber." ] ]+ , [ Plain [ Str "More." ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain [ Str "Nested." ] ] ]+ ]+ ]+ , Para+ [ Str "Should"+ , Space+ , Str "not"+ , Space+ , Str "be"+ , Space+ , Str "a"+ , Space+ , Str "list"+ , Space+ , Str "item:"+ ]+ , Para [ Str "M.A.\160\&2007" ]+ , OrderedList+ ( 2 , UpperAlpha , Period )+ [ [ Plain [ Str "Williams" ] ] ]+ , HorizontalRule+ ]+ ]+ , Div+ ( "definition-lists" , [ "section" ] , [] )+ [ Header+ 1+ ( "" , [] , [] )+ [ Str "Definition" , Space , Str "Lists" ]+ , Para+ [ Str "Tight"+ , Space+ , Str "using"+ , Space+ , Str "spaces:"+ ]+ , DefinitionList+ [ ( [ Str "apple" ]+ , [ [ Plain [ Str "red" , Space , Str "fruit" ] ] ]+ )+ , ( [ Str "orange" ]+ , [ [ Plain [ Str "orange" , Space , Str "fruit" ] ] ]+ )+ , ( [ Str "banana" ]+ , [ [ Plain [ Str "yellow" , Space , Str "fruit" ] ] ]+ )+ ]+ , Para+ [ Str "Tight" , Space , Str "using" , Space , Str "tabs:" ]+ , DefinitionList+ [ ( [ Str "apple" ]+ , [ [ Plain [ Str "red" , Space , Str "fruit" ] ] ]+ )+ , ( [ Str "orange" ]+ , [ [ Plain [ Str "orange" , Space , Str "fruit" ] ] ]+ )+ , ( [ Str "banana" ]+ , [ [ Plain [ Str "yellow" , Space , Str "fruit" ] ] ]+ )+ ]+ , Para [ Str "Loose:" ]+ , DefinitionList+ [ ( [ Str "apple" ]+ , [ [ Para [ Str "red" , Space , Str "fruit" ] ] ]+ )+ , ( [ Str "orange" ]+ , [ [ Para [ Str "orange" , Space , Str "fruit" ] ] ]+ )+ , ( [ Str "banana" ]+ , [ [ Para [ Str "yellow" , Space , Str "fruit" ] ] ]+ )+ ]+ , Para+ [ Str "Multiple"+ , Space+ , Str "blocks"+ , Space+ , Str "with"+ , Space+ , Str "italics:"+ ]+ , DefinitionList+ [ ( [ Emph [ Str "apple" ] ]+ , [ [ Para [ Str "red" , Space , Str "fruit" ]+ , Para+ [ Str "contains"+ , Space+ , Str "seeds,"+ , Space+ , Str "crisp,"+ , Space+ , Str "pleasant"+ , Space+ , Str "to"+ , Space+ , Str "taste"+ ]+ ]+ ]+ )+ , ( [ Emph [ Str "orange" ] ]+ , [ [ Para [ Str "orange" , Space , Str "fruit" ]+ , CodeBlock+ ( "" , [ "" ] , [] ) "{ orange code block }\n"+ , BlockQuote+ [ Para+ [ Str "orange"+ , Space+ , Str "block"+ , Space+ , Str "quote"+ ]+ ]+ ]+ ]+ )+ ]+ , Para+ [ Str "Multiple"+ , Space+ , Str "definitions,"+ , Space+ , Str "tight:"+ ]+ , DefinitionList+ [ ( [ Str "apple" ]+ , [ [ Para [ Str "red" , Space , Str "fruit" ]+ , Para [ Str "computer" ]+ ]+ ]+ )+ , ( [ Str "orange" ]+ , [ [ Para [ Str "orange" , Space , Str "fruit" ]+ , Para [ Str "bank" ]+ ]+ ]+ )+ ]+ , Para+ [ Str "Multiple"+ , Space+ , Str "definitions,"+ , Space+ , Str "loose:"+ ]+ , DefinitionList+ [ ( [ Str "apple" ]+ , [ [ Para [ Str "red" , Space , Str "fruit" ]+ , Para [ Str "computer" ]+ ]+ ]+ )+ , ( [ Str "orange" ]+ , [ [ Para [ Str "orange" , Space , Str "fruit" ]+ , Para [ Str "bank" ]+ ]+ ]+ )+ ]+ , Para+ [ Str "Blank"+ , Space+ , Str "line"+ , Space+ , Str "after"+ , Space+ , Str "term,"+ , Space+ , Str "indented"+ , Space+ , Str "marker,"+ , Space+ , Str "alternate"+ , Space+ , Str "markers:"+ ]+ , DefinitionList+ [ ( [ Str "apple" ]+ , [ [ Para [ Str "red" , Space , Str "fruit" ]+ , Para [ Str "computer" ]+ ]+ ]+ )+ , ( [ Str "orange" ]+ , [ [ Para [ Str "orange" , Space , Str "fruit" ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain [ Str "sublist" ] ]+ , [ Plain [ Str "sublist" ] ]+ ]+ ]+ ]+ )+ ]+ ]+ , Div+ ( "html-blocks" , [ "section" ] , [] )+ [ Header+ 1 ( "" , [] , [] ) [ Str "HTML" , Space , Str "Blocks" ]+ , Para+ [ Str "Simple"+ , Space+ , Str "block"+ , Space+ , Str "on"+ , Space+ , Str "one"+ , Space+ , Str "line:"+ ]+ , Div ( "" , [] , [] ) [ Para [ Str "foo" ] ]+ , Para+ [ Str "And"+ , Space+ , Str "nested"+ , Space+ , Str "without"+ , Space+ , Str "indentation:"+ ]+ , Div+ ( "" , [] , [] )+ [ Div+ ( "" , [] , [] )+ [ Div ( "" , [] , [] ) [ Para [ Str "foo" ] ] ]+ , Div ( "" , [] , [] ) [ Para [ Str "bar" ] ]+ ]+ , Para+ [ Str "Interpreted"+ , Space+ , Str "markdown"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "table:"+ ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Emph [ Str "emphasized" ]+ ]+ , Para+ [ Str "And"+ , Space+ , Str "this"+ , Space+ , Str "is"+ , Space+ , Strong [ Str "strong" ]+ ]+ , Para+ [ Str "Here\8217s"+ , Space+ , Str "a"+ , Space+ , Str "simple"+ , Space+ , Str "block:"+ ]+ , Div ( "" , [] , [] ) [ Para [ Str "foo" ] ]+ , Para+ [ Str "This"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "a"+ , Space+ , Str "code"+ , Space+ , Str "block,"+ , Space+ , Str "though:"+ ]+ , CodeBlock ( "" , [ "" ] , [] ) "<div>\n foo\n</div>\n"+ , Para+ [ Str "As" , Space , Str "should" , Space , Str "this:" ]+ , CodeBlock ( "" , [ "" ] , [] ) "<div>foo</div>\n"+ , Para [ Str "Now," , Space , Str "nested:" ]+ , Div+ ( "" , [] , [] )+ [ Div+ ( "" , [] , [] )+ [ Div ( "" , [] , [] ) [ Para [ Str "foo" ] ] ]+ ]+ , Para+ [ Str "This"+ , Space+ , Str "should"+ , Space+ , Str "just"+ , Space+ , Str "be"+ , Space+ , Str "an"+ , Space+ , Str "HTML"+ , Space+ , Str "comment:"+ ]+ , Para [ Str "Multiline:" ]+ , Para [ Str "Code" , Space , Str "block:" ]+ , CodeBlock ( "" , [ "" ] , [] ) "<!-- Comment -->\n"+ , Para+ [ Str "Just"+ , Space+ , Str "plain"+ , Space+ , Str "comment,"+ , Space+ , Str "with"+ , Space+ , Str "trailing"+ , Space+ , Str "spaces"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Str "line:"+ ]+ , Para [ Str "Code:" ]+ , CodeBlock ( "" , [ "" ] , [] ) "<hr />\n"+ , Para [ Str "Hr\8217s:" ]+ , HorizontalRule+ ]+ , Div+ ( "inline-markup" , [ "section" ] , [] )+ [ Header+ 1 ( "" , [] , [] ) [ Str "Inline" , Space , Str "Markup" ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Emph [ Str "emphasized" ]+ , Str ","+ , Space+ , Str "and"+ , Space+ , Str "so"+ , Space+ , Emph [ Str "is" , Space , Str "this" ]+ , Str "."+ ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Strong [ Str "strong" ]+ , Str ","+ , Space+ , Str "and"+ , Space+ , Str "so"+ , Space+ , Strong [ Str "is" , Space , Str "this" ]+ , Str "."+ ]+ , Para+ [ Str "An"+ , Space+ , Emph+ [ Link+ ( "" , [] , [] )+ [ Str "emphasized" , Space , Str "link" ]+ ( "/url" , "" )+ ]+ , Str "."+ ]+ , Para+ [ Strong+ [ Emph+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "strong"+ , Space+ , Str "and"+ , Space+ , Str "em."+ ]+ ]+ ]+ , Para+ [ Str "So"+ , Space+ , Str "is"+ , Space+ , Strong [ Emph [ Str "this" ] ]+ , Space+ , Str "word."+ ]+ , Para+ [ Strong+ [ Emph+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "strong"+ , Space+ , Str "and"+ , Space+ , Str "em."+ ]+ ]+ ]+ , Para+ [ Str "So"+ , Space+ , Str "is"+ , Space+ , Strong [ Emph [ Str "this" ] ]+ , Space+ , Str "word."+ ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "code:"+ , Space+ , Code ( "" , [] , [] ) ">"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "$"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "\\`, "+ , Str "$"+ , Code ( "" , [] , [] ) ", "+ , Str "<html>"+ , Code ( "" , [] , [] ) "."+ ]+ , Para+ [ Span+ ( "" , [ "deleted" ] , [] )+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Emph [ Str "strikeout" ]+ , Str "."+ ]+ ]+ , Para+ [ Str "Superscripts:"+ , Space+ , Str "a"+ , Superscript [ Str "bc" ]+ , Str "d"+ , Space+ , Str "a"+ , Superscript [ Emph [ Str "hello" ] ]+ , Space+ , Str "a"+ , Superscript [ Str "hello\160there" ]+ , Str "."+ ]+ , Para+ [ Str "Subscripts:"+ , Space+ , Str "H"+ , Subscript [ Str "2" ]+ , Str "O,"+ , Space+ , Str "H"+ , Subscript [ Str "23" ]+ , Str "O,"+ , Space+ , Str "H"+ , Subscript [ Str "many\160of\160them" ]+ , Str "O."+ ]+ , Para+ [ Str "These"+ , Space+ , Str "should"+ , Space+ , Str "not"+ , Space+ , Str "be"+ , Space+ , Str "superscripts"+ , Space+ , Str "or"+ , Space+ , Str "subscripts,"+ , Space+ , Str "because"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "unescaped"+ , Space+ , Str "spaces:"+ , SoftBreak+ , Str "a^b"+ , Space+ , Str "c^d,"+ , Space+ , Str "a~b"+ , Space+ , Str "c~d."+ ]+ , HorizontalRule+ ]+ , Div+ ( "smart-quotes-ellipses-dashes" , [ "section" ] , [] )+ [ Header+ 1+ ( "" , [] , [] )+ [ Str "Smart"+ , Space+ , Str "quotes,"+ , Space+ , Str "ellipses,"+ , Space+ , Str "dashes"+ ]+ , Para+ [ Quoted DoubleQuote [ Str "Hello," ]+ , Space+ , Str "said"+ , Space+ , Str "the"+ , Space+ , Str "spider."+ , Space+ , Quoted+ DoubleQuote+ [ Quoted SingleQuote [ Str "Shelob" ]+ , Space+ , Str "is"+ , Space+ , Str "my"+ , Space+ , Str "name."+ ]+ ]+ , Para+ [ Quoted SingleQuote [ Str "A" ]+ , Str ","+ , Space+ , Quoted SingleQuote [ Str "B" ]+ , Str ","+ , Space+ , Str "and"+ , Space+ , Quoted SingleQuote [ Str "C" ]+ , Space+ , Str "are"+ , Space+ , Str "letters."+ ]+ , Para+ [ Quoted SingleQuote [ Str "Oak," ]+ , Space+ , Quoted SingleQuote [ Str "elm," ]+ , Space+ , Str "and"+ , Space+ , Quoted SingleQuote [ Str "beech" ]+ , Space+ , Str "are"+ , Space+ , Str "names"+ , Space+ , Str "of"+ , Space+ , Str "trees."+ , Space+ , Str "So"+ , Space+ , Str "is"+ , Space+ , Quoted SingleQuote [ Str "pine." ]+ ]+ , Para+ [ Quoted+ SingleQuote+ [ Str "He"+ , Space+ , Str "said,"+ , Space+ , Quoted+ DoubleQuote+ [ Str "I"+ , Space+ , Str "want"+ , Space+ , Str "to"+ , Space+ , Str "go."+ ]+ ]+ , Space+ , Str "Were"+ , Space+ , Str "you"+ , Space+ , Str "alive"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "70\8217s?"+ ]+ , Para+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "some"+ , Space+ , Str "quoted"+ , Space+ , Quoted SingleQuote [ Code ( "" , [] , [] ) "code" ]+ , Space+ , Str "and"+ , Space+ , Str "a"+ , Space+ , Quoted+ DoubleQuote+ [ Link+ ( "" , [] , [] )+ [ Str "quoted" , SoftBreak , Str "link" ]+ ( "http://example.com/?foo=1&bar=2" , "" )+ ]+ , Str "."+ ]+ , Para+ [ Str "Some"+ , Space+ , Str "dashes:"+ , Space+ , Str "one\8212two"+ , Space+ , Str "\8212"+ , Space+ , Str "three\8212four"+ , Space+ , Str "\8212"+ , Space+ , Str "five."+ ]+ , Para+ [ Str "Dashes"+ , Space+ , Str "between"+ , Space+ , Str "numbers:"+ , Space+ , Str "5\8211\&7,"+ , Space+ , Str "255\8211\&66,"+ , Space+ , Str "1987\8211\&1999."+ ]+ , Para [ Str "Ellipses\8230and\8230and\8230." ]+ , HorizontalRule+ ]+ , Div+ ( "latex" , [ "section" ] , [] )+ [ Header 1 ( "" , [] , [] ) [ Str "LaTeX" ]+ , BulletList+ [ []+ , [ Plain [ Math InlineMath "2+2=4" ] ]+ , [ Plain [ Math InlineMath "x \\in y" ] ]+ , [ Plain [ Math InlineMath "\\alpha \\wedge \\omega" ] ]+ , [ Plain [ Math InlineMath "223" ] ]+ , [ Plain [ Math InlineMath "p" , Str "-Tree" ] ]+ , [ Plain+ [ Str "Here\8217s"+ , Space+ , Str "some"+ , Space+ , Str "display"+ , Space+ , Str "math:"+ , SoftBreak+ , Math+ DisplayMath+ "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"+ ]+ ]+ , [ Plain+ [ Str "Here\8217s"+ , Space+ , Str "one"+ , Space+ , Str "that"+ , Space+ , Str "has"+ , Space+ , Str "a"+ , Space+ , Str "line"+ , Space+ , Str "break"+ , Space+ , Str "in"+ , Space+ , Str "it:"+ , Space+ , Math InlineMath "\\alpha + \\omega \\times x^2"+ , Str "."+ ]+ ]+ ]+ , Para+ [ Str "These"+ , Space+ , Str "shouldn\8217t"+ , Space+ , Str "be"+ , Space+ , Str "math:"+ ]+ , BulletList+ [ [ Plain+ [ Str "To"+ , Space+ , Str "get"+ , Space+ , Str "the"+ , Space+ , Str "famous"+ , Space+ , Str "equation,"+ , Space+ , Str "write"+ , Space+ , Code ( "" , [] , [] ) "$e = mc^2$"+ , Str "."+ ]+ ]+ , [ Plain+ [ Str "$22,000"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Emph [ Str "lot" ]+ , Space+ , Str "of"+ , Space+ , Str "money."+ , Space+ , Str "So"+ , Space+ , Str "is"+ , Space+ , Str "$34,000."+ , Space+ , Str "(It"+ , Space+ , Str "worked"+ , Space+ , Str "if"+ , Space+ , Quoted DoubleQuote [ Str "lot" ]+ , Space+ , Str "is"+ , SoftBreak+ , Str "emphasized.)"+ ]+ ]+ , [ Plain+ [ Str "Shoes"+ , Space+ , Str "($20)"+ , Space+ , Str "and"+ , Space+ , Str "socks"+ , Space+ , Str "($5)."+ ]+ ]+ , [ Plain+ [ Str "Escaped"+ , Space+ , Code ( "" , [] , [] ) "$"+ , Str ":"+ , Space+ , Str "$73"+ , Space+ , Emph+ [ Str "this"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "emphasized"+ ]+ , Space+ , Str "23$."+ ]+ ]+ ]+ , Para+ [ Str "Here\8217s"+ , Space+ , Str "a"+ , Space+ , Str "LaTeX"+ , Space+ , Str "table:"+ ]+ , HorizontalRule+ ]+ , Div+ ( "special-characters" , [ "section" ] , [] )+ [ Header+ 1+ ( "" , [] , [] )+ [ Str "Special" , Space , Str "Characters" ]+ , Para+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "some"+ , Space+ , Str "unicode:"+ ]+ , BulletList+ [ [ Plain+ [ Str "I" , Space , Str "hat:" , Space , Str "\206" ]+ ]+ , [ Plain+ [ Str "o" , Space , Str "umlaut:" , Space , Str "\246" ]+ ]+ , [ Plain [ Str "section:" , Space , Str "\167" ] ]+ , [ Plain+ [ Str "set"+ , Space+ , Str "membership:"+ , Space+ , Str "\8712"+ ]+ ]+ , [ Plain [ Str "copyright:" , Space , Str "\169" ] ]+ ]+ , Para+ [ Str "AT&T"+ , Space+ , Str "has"+ , Space+ , Str "an"+ , Space+ , Str "ampersand"+ , Space+ , Str "in"+ , Space+ , Str "their"+ , Space+ , Str "name."+ ]+ , Para+ [ Str "AT&T"+ , Space+ , Str "is"+ , Space+ , Str "another"+ , Space+ , Str "way"+ , Space+ , Str "to"+ , Space+ , Str "write"+ , Space+ , Str "it."+ ]+ , Para+ [ Str "This" , Space , Str "&" , Space , Str "that." ]+ , Para [ Str "4" , Space , Str "<" , Space , Str "5." ]+ , Para [ Str "6" , Space , Str ">" , Space , Str "5." ]+ , Para [ Str "Backslash:" , Space , Str "\\" ]+ , Para [ Str "Backtick:" , Space , Str "`" ]+ , Para [ Str "Asterisk:" , Space , Str "*" ]+ , Para [ Str "Underscore:" , Space , Str "_" ]+ , Para+ [ Str "Left" , Space , Str "brace:" , Space , Str "{" ]+ , Para+ [ Str "Right" , Space , Str "brace:" , Space , Str "}" ]+ , Para+ [ Str "Left" , Space , Str "bracket:" , Space , Str "[" ]+ , Para+ [ Str "Right" , Space , Str "bracket:" , Space , Str "]" ]+ , Para+ [ Str "Left" , Space , Str "paren:" , Space , Str "(" ]+ , Para+ [ Str "Right" , Space , Str "paren:" , Space , Str ")" ]+ , Para [ Str "Greater-than:" , Space , Str ">" ]+ , Para [ Str "Hash:" , Space , Str "#" ]+ , Para [ Str "Period:" , Space , Str "." ]+ , Para [ Str "Bang:" , Space , Str "!" ]+ , Para [ Str "Plus:" , Space , Str "+" ]+ , Para [ Str "Minus:" , Space , Str "-" ]+ , HorizontalRule+ ]+ , Div+ ( "links" , [ "section" ] , [] )+ [ Header 1 ( "" , [] , [] ) [ Str "Links" ]+ , Div+ ( "explicit" , [ "section" ] , [] )+ [ Header 2 ( "" , [] , [] ) [ Str "Explicit" ]+ , Para+ [ Str "Just"+ , Space+ , Str "a"+ , Space+ , Link ( "" , [] , [] ) [ Str "URL" ] ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Link+ ( "" , [] , [ ( "title" , "title" ) ] )+ [ Str "URL"+ , Space+ , Str "and"+ , Space+ , Str "title"+ ]+ ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Link+ ( ""+ , []+ , [ ( "title" , "title preceded by two spaces" ) ]+ )+ [ Str "URL"+ , Space+ , Str "and"+ , Space+ , Str "title"+ ]+ ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Link+ ( ""+ , []+ , [ ( "title" , "title preceded by a tab" ) ]+ )+ [ Str "URL"+ , Space+ , Str "and"+ , Space+ , Str "title"+ ]+ ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Link+ ( ""+ , []+ , [ ( "title" , "title with \"quotes\" in it" ) ]+ )+ [ Str "URL"+ , Space+ , Str "and"+ , Space+ , Str "title"+ ]+ ( "/url/" , "" )+ ]+ , Para+ [ Link+ ( ""+ , []+ , [ ( "title" , "title with single quotes" ) ]+ )+ [ Str "URL"+ , Space+ , Str "and"+ , Space+ , Str "title"+ ]+ ( "/url/" , "" )+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "with_underscore" ]+ ( "/url/with_underscore" , "" )+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "Email" , Space , Str "link" ]+ ( "mailto:nobody@nowhere.net" , "" )+ ]+ , Para+ [ Link ( "" , [] , [] ) [ Str "Empty" ] ( "" , "" )+ , Str "."+ ]+ ]+ , Div+ ( "reference" , [ "section" ] , [] )+ [ Header 2 ( "" , [] , [] ) [ Str "Reference" ]+ , Para+ [ Str "Foo"+ , Space+ , Link ( "" , [] , [] ) [ Str "bar" ] ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Str "With"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "embedded" , Space , Str "[brackets]" ]+ ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Link ( "" , [] , [] ) [ Str "b" ] ( "/url/" , "" )+ , Space+ , Str "by"+ , Space+ , Str "itself"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "a"+ , Space+ , Str "link."+ ]+ , Para+ [ Str "Indented"+ , Space+ , Link ( "" , [] , [] ) [ Str "once" ] ( "/url" , "" )+ , Str "."+ ]+ , Para+ [ Str "Indented"+ , Space+ , Link ( "" , [] , [] ) [ Str "twice" ] ( "/url" , "" )+ , Str "."+ ]+ , Para+ [ Str "Indented"+ , Space+ , Link ( "" , [] , [] ) [ Str "thrice" ] ( "/url" , "" )+ , Str "."+ ]+ , Para+ [ Str "This"+ , Space+ , Str "should"+ , Space+ , Str "[not][]"+ , Space+ , Str "be"+ , Space+ , Str "a"+ , Space+ , Str "link."+ ]+ , CodeBlock ( "" , [ "" ] , [] ) "[not]: /url\n"+ , Para+ [ Str "Foo"+ , Space+ , Link+ ( ""+ , []+ , [ ( "title" , "Title with \"quotes\" inside" ) ]+ )+ [ Str "bar" ]+ ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Str "Foo"+ , Space+ , Link+ ( ""+ , []+ , [ ( "title" , "Title with \"quote\" inside" ) ]+ )+ [ Str "biz" ]+ ( "/url/" , "" )+ , Str "."+ ]+ ]+ , Div+ ( "with-ampersands" , [ "section" ] , [] )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "With" , Space , Str "ampersands" ]+ , Para+ [ Str "Here\8217s"+ , Space+ , Str "a"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "link"+ , Space+ , Str "with"+ , Space+ , Str "an"+ , Space+ , Str "ampersand"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "URL"+ ]+ ( "http://example.com/?foo=1&bar=2" , "" )+ , Str "."+ ]+ , Para+ [ Str "Here\8217s"+ , Space+ , Str "a"+ , Space+ , Str "link"+ , Space+ , Str "with"+ , Space+ , Str "an"+ , Space+ , Str "amersand"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "link"+ , Space+ , Str "text:"+ , SoftBreak+ , Link+ ( "" , [] , [ ( "title" , "AT&T" ) ] )+ [ Str "AT&T" ]+ ( "http://att.com/" , "" )+ , Str "."+ ]+ , Para+ [ Str "Here\8217s"+ , Space+ , Str "an"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "inline" , Space , Str "link" ]+ ( "/script?foo=1&bar=2" , "" )+ , Str "."+ ]+ , Para+ [ Str "Here\8217s"+ , Space+ , Str "an"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "inline"+ , Space+ , Str "link"+ , Space+ , Str "in"+ , Space+ , Str "pointy"+ , Space+ , Str "braces"+ ]+ ( "/script?foo=1&bar=2" , "" )+ , Str "."+ ]+ ]+ , Div+ ( "autolinks" , [ "section" ] , [] )+ [ Header 2 ( "" , [] , [] ) [ Str "Autolinks" ]+ , Para+ [ Str "With"+ , Space+ , Str "an"+ , Space+ , Str "ampersand:"+ , Space+ , Link+ ( "" , [ "uri" ] , [] )+ [ Str "http://example.com/?foo=1&bar=2" ]+ ( "http://example.com/?foo=1&bar=2" , "" )+ ]+ , BulletList+ [ [ Plain+ [ Str "In" , Space , Str "a" , Space , Str "list?" ]+ ]+ , [ Plain+ [ Link+ ( "" , [ "uri" ] , [] )+ [ Str "http://example.com/" ]+ ( "http://example.com/" , "" )+ ]+ ]+ , [ Plain [ Str "It" , Space , Str "should." ] ]+ ]+ , Para+ [ Str "An"+ , Space+ , Str "e-mail"+ , Space+ , Str "address:"+ , Space+ , Link+ ( "" , [ "email" ] , [] )+ [ Str "nobody@nowhere.net" ]+ ( "mailto:nobody@nowhere.net" , "" )+ ]+ , BlockQuote+ [ Para+ [ Str "Blockquoted:"+ , Space+ , Link+ ( "" , [ "uri" ] , [] )+ [ Str "http://example.com/" ]+ ( "http://example.com/" , "" )+ ]+ ]+ , Para+ [ Str "Auto-links"+ , Space+ , Str "should"+ , Space+ , Str "not"+ , Space+ , Str "occur"+ , Space+ , Str "here:"+ , Space+ , Code ( "" , [] , [] ) "<http://example.com/>"+ ]+ , CodeBlock+ ( "" , [ "" ] , [] ) "or here: <http://example.com/>\n"+ , HorizontalRule+ ]+ ]+ , Div+ ( "images" , [ "section" ] , [] )+ [ Header 1 ( "" , [] , [] ) [ Str "Images" ]+ , Para+ [ Str "From"+ , Space+ , Quoted+ DoubleQuote+ [ Str "Voyage"+ , Space+ , Str "dans"+ , Space+ , Str "la"+ , Space+ , Str "Lune"+ ]+ , Space+ , Str "by"+ , Space+ , Str "Georges"+ , Space+ , Str "Melies"+ , Space+ , Str "(1902):"+ ]+ , Div+ ( "" , [] , [] )+ [ Para+ [ Image+ ( "" , [] , [ ( "title" , "Voyage dans la Lune" ) ] )+ [ Str "lalune" ]+ ( "lalune.jpg" , "" )+ ]+ , Div ( "" , [ "caption" ] , [] ) [ Para [ Str "lalune" ] ]+ ]+ , Para+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "movie"+ , Space+ , Image+ ( "" , [] , [] ) [ Str "movie" ] ( "movie.jpg" , "" )+ , Space+ , Str "icon."+ ]+ , HorizontalRule+ ]+ , Div+ ( "footnotes" , [ "section" ] , [] )+ [ Header 1 ( "" , [] , [] ) [ Str "Footnotes" ]+ , Para+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "footnote"+ , Space+ , Str "reference,"+ , Note+ [ Para+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "the"+ , Space+ , Str "footnote."+ , Space+ , Str "It"+ , Space+ , Str "can"+ , Space+ , Str "go"+ , Space+ , Str "anywhere"+ , Space+ , Str "after"+ , Space+ , Str "the"+ , Space+ , Str "footnote"+ , Space+ , Str "reference."+ , Space+ , Str "It"+ , SoftBreak+ , Str "need"+ , Space+ , Str "not"+ , Space+ , Str "be"+ , Space+ , Str "placed"+ , Space+ , Str "at"+ , Space+ , Str "the"+ , Space+ , Str "end"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "document."+ ]+ ]+ , Space+ , Str "and"+ , Space+ , Str "another."+ , Note+ [ Para+ [ Str "Here\8217s"+ , Space+ , Str "the"+ , Space+ , Str "long"+ , Space+ , Str "note."+ , Space+ , Str "This"+ , Space+ , Str "one"+ , Space+ , Str "contains"+ , Space+ , Str "multiple"+ , Space+ , Str "blocks."+ ]+ , Para+ [ Str "Subsequent"+ , Space+ , Str "blocks"+ , Space+ , Str "are"+ , Space+ , Str "indented"+ , Space+ , Str "to"+ , Space+ , Str "show"+ , Space+ , Str "that"+ , Space+ , Str "they"+ , Space+ , Str "belong"+ , Space+ , Str "to"+ , Space+ , Str "the"+ , Space+ , Str "footnote"+ , Space+ , Str "(as"+ , SoftBreak+ , Str "with"+ , Space+ , Str "list"+ , Space+ , Str "items)."+ ]+ , CodeBlock ( "" , [ "" ] , [] ) "{ <code> }\n"+ , Para+ [ Str "If"+ , Space+ , Str "you"+ , Space+ , Str "want,"+ , Space+ , Str "you"+ , Space+ , Str "can"+ , Space+ , Str "indent"+ , Space+ , Str "every"+ , Space+ , Str "line,"+ , Space+ , Str "but"+ , Space+ , Str "you"+ , Space+ , Str "can"+ , Space+ , Str "also"+ , Space+ , Str "be"+ , Space+ , Str "lazy"+ , Space+ , Str "and"+ , Space+ , Str "just"+ , SoftBreak+ , Str "indent"+ , Space+ , Str "the"+ , Space+ , Str "first"+ , Space+ , Str "line"+ , Space+ , Str "of"+ , Space+ , Str "each"+ , Space+ , Str "block."+ ]+ ]+ , Space+ , Str "This"+ , Space+ , Str "should"+ , Space+ , Emph [ Str "not" ]+ , Space+ , Str "be"+ , Space+ , Str "a"+ , SoftBreak+ , Str "footnote"+ , Space+ , Str "reference,"+ , Space+ , Str "because"+ , Space+ , Str "it"+ , Space+ , Str "contains"+ , Space+ , Str "a"+ , Space+ , Str "space.[^my"+ , Space+ , Str "note]"+ , Space+ , Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "an"+ , Space+ , Str "inline"+ , SoftBreak+ , Str "note."+ , Note+ [ Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Emph [ Str "easier" ]+ , Space+ , Str "to"+ , Space+ , Str "type."+ , Space+ , Str "Inline"+ , Space+ , Str "notes"+ , Space+ , Str "may"+ , Space+ , Str "contain"+ , SoftBreak+ , Link+ ( "" , [] , [] )+ [ Str "links" ]+ ( "http://google.com" , "" )+ , Space+ , Str "and"+ , Space+ , Code ( "" , [] , [] ) "]"+ , Space+ , Str "verbatim"+ , Space+ , Str "characters,"+ , Space+ , Str "as"+ , Space+ , Str "well"+ , Space+ , Str "as"+ , SoftBreak+ , Str "[bracketed"+ , Space+ , Str "text]."+ ]+ ]+ ]+ , BlockQuote+ [ Para+ [ Str "Notes"+ , Space+ , Str "can"+ , Space+ , Str "go"+ , Space+ , Str "in"+ , Space+ , Str "quotes."+ , Note [ Para [ Str "In" , Space , Str "quote." ] ]+ ]+ ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain+ [ Str "And"+ , Space+ , Str "in"+ , Space+ , Str "list"+ , Space+ , Str "items."+ , Note [ Para [ Str "In" , Space , Str "list." ] ]+ ]+ ]+ ]+ , Para+ [ Str "This"+ , Space+ , Str "paragraph"+ , Space+ , Str "should"+ , Space+ , Str "not"+ , Space+ , Str "be"+ , Space+ , Str "part"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "note,"+ , Space+ , Str "as"+ , Space+ , Str "it"+ , Space+ , Str "is"+ , Space+ , Str "not"+ , Space+ , Str "indented."+ ]+ ]+ ]
@@ -27,9 +27,9 @@ This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite. </para>-<sect1 id="headers">+<sect1 id="headers" role="sect1role"> <title>Headers</title>- <sect2 id="level-2-with-an-embedded-link">+ <sect2 id="level-2-with-an-embedded-link" role="sect2role"> <title>Level 2 with an <ulink url="/url">embedded link</ulink></title> <sect3 id="level-3-with-emphasis"> <title>Level 3 with <emphasis>emphasis</emphasis></title>@@ -74,6 +74,9 @@ <para> Here’s a regular paragraph. </para>+ <para role="pararole">+ And here’s a regular paragraph with a role.+ </para> <para> In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like@@ -93,6 +96,11 @@ This is a block quote. It is pretty short. </para> </blockquote>+ <blockquote role="roleblockquote">+ <para>+ This is a block quote with a role.+ </para>+ </blockquote> <blockquote> <para> Code in a block quote:@@ -234,6 +242,26 @@ </listitem> </orderedlist> <para>+ with role:+ </para>+ <orderedlist role="listrole" numeration="arabic">+ <listitem>+ <para>+ First+ </para>+ </listitem>+ <listitem>+ <para>+ Second+ </para>+ </listitem>+ <listitem>+ <para>+ Third+ </para>+ </listitem>+ </orderedlist>+ <para> and tight: </para> <orderedlist spacing="compact" numeration="arabic">@@ -405,8 +433,8 @@ </sect2> <sect2 id="fancy-list-markers"> <title>Fancy list markers</title>- <orderedlist numeration="arabic">- <listitem override="2">+ <orderedlist numeration="arabic" startingnumber="2">+ <listitem> <para> begins with 2 </para>@@ -418,8 +446,8 @@ <para> with a continuation </para>- <orderedlist numeration="lowerroman">- <listitem override="4">+ <orderedlist numeration="lowerroman" startingnumber="4">+ <listitem> <para> sublist with roman numerals, starting with 4 </para>@@ -457,13 +485,13 @@ <para> Upper Roman. </para>- <orderedlist numeration="arabic">- <listitem override="6">+ <orderedlist numeration="arabic" startingnumber="6">+ <listitem> <para> Decimal start with 6 </para>- <orderedlist numeration="loweralpha">- <listitem override="3">+ <orderedlist numeration="loweralpha" startingnumber="3">+ <listitem> <para> Lower alpha with paren </para>@@ -703,6 +731,12 @@ So is <emphasis role="strong"><emphasis>this</emphasis></emphasis> word. </para> <para>+ So is <emphasis role="emphasisrole"><emphasis>this</emphasis></emphasis> word with a role.+ </para>+ <para>+ So is <phrase role="phraserole"><phrase>this</phrase></phrase> phrase with a role.+ </para>+ <para> This is code: <literal>></literal>, <literal>$</literal>, <literal>\</literal>, <literal>\$</literal>, <literal><html></literal>.@@ -1406,6 +1440,75 @@ </tgroup> </table> <para>+ Table with attributes+ </para>+ <table xml:id="mytableid1" class="mytableclass1 mytableclass2" tabstyle="mytabstyle1" role="tablerole1">+ <title>+ Attribute table caption+ </title>+ <tgroup>+ <thead>+ <th>+ <para>+ header cell 1+ </para>+ </th>+ <th>+ <para>+ header cell 2+ </para>+ </th>+ </thead>+ <tbody>+ <tr>+ <td>+ <para>+ body cell 1+ </para>+ </td>+ <td>+ <para>+ body cell 2+ </para>+ </td>+ </tr>+ </tbody>+ </tgroup>+ </table>+ <para>+ Table with attributes, without caption+ </para>+ <informaltable xml:id="mytableid2" class="mytableclass3 mytableclass4" tabstyle="mytabstyle2" role="tablerole2">+ <tgroup>+ <thead>+ <th>+ <para>+ header cell 1+ </para>+ </th>+ <th>+ <para>+ header cell 2+ </para>+ </th>+ </thead>+ <tbody>+ <tr>+ <td>+ <para>+ body cell 1+ </para>+ </td>+ <td>+ <para>+ body cell 2+ </para>+ </td>+ </tr>+ </tbody>+ </tgroup>+ </informaltable>+ <para> Multiline table without caption: </para> <informaltable>@@ -1555,6 +1658,39 @@ Here's another one. Note the blank line between rows. </entry> </row>+ </tbody>+ </tgroup>+ </informaltable>+ <para>+ Multiline table with cells spanning multiple columns and rows without caption.+ </para>+ <informaltable>+ <tgroup cols="3">+ <colspec align="left" colname="c1" />+ <colspec align="left" colname="c2" />+ <colspec align="left" colname="c3" />+ <colspec align="left" colname="c4" />+ <thead>+ <tr>+ <th namest="c1" nameend="c3">Columns</th>+ </tr>+ <tr>+ <th>A</th>+ <th>B</th>+ <th>C</th>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td namest="c1" nameend="c2">A1 + B1</td>+ <td morerows="1">C1 + C2</td>+ </tr>+ <tr>+ <td namest="c1" nameend="c2" morerows="1">A2 + B2 + A3 + B3</td>+ </tr>+ <tr>+ <td>C3</td>+ </tr> </tbody> </tgroup> </informaltable>
@@ -62,10 +62,16 @@ , Space , Str "suite." ]- , Header 1 ( "headers" , [] , [] ) [ Str "Headers" ] , Header+ 1+ ( "headers" , [] , [ ( "role" , "sect1role" ) ] )+ [ Str "Headers" ]+ , Header 2- ( "level-2-with-an-embedded-link" , [] , [] )+ ( "level-2-with-an-embedded-link"+ , []+ , [ ( "role" , "sect2role" ) ]+ ) [ Str "Level" , Space , Str "2"@@ -151,6 +157,29 @@ , Space , Str "paragraph." ]+ , Div+ ( ""+ , []+ , [ ( "wrapper" , "1" ) , ( "role" , "pararole" ) ]+ )+ [ Para+ [ Str "And"+ , Space+ , Str "here\8217s"+ , Space+ , Str "a"+ , Space+ , Str "regular"+ , Space+ , Str "paragraph"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "role."+ ]+ ] , Para [ Str "In" , Space@@ -251,6 +280,31 @@ , Str "short." ] ]+ , Div+ ( ""+ , []+ , [ ( "wrapper" , "1" ) , ( "role" , "roleblockquote" ) ]+ )+ [ BlockQuote+ [ Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "block"+ , Space+ , Str "quote"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "role."+ ]+ ]+ ] , BlockQuote [ Para [ Str "Code"@@ -348,6 +402,19 @@ , [ Para [ Str "Second" ] ] , [ Para [ Str "Third" ] ] ]+ , Para [ Str "with" , Space , Str "role:" ]+ , Div+ ( ""+ , []+ , [ ( "wrapper" , "1" ) , ( "role" , "listrole" ) ]+ )+ [ OrderedList+ ( 1 , Decimal , DefaultDelim )+ [ [ Para [ Str "First" ] ]+ , [ Para [ Str "Second" ] ]+ , [ Para [ Str "Third" ] ]+ ]+ ] , Para [ Str "and" , Space , Str "tight:" ] , OrderedList ( 1 , Decimal , DefaultDelim )@@ -932,6 +999,38 @@ , Str "word." ] , Para+ [ Str "So"+ , Space+ , Str "is"+ , Space+ , Emph [ Emph [ Str "this" ] ]+ , Space+ , Str "word"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "role."+ ]+ , Para+ [ Str "So"+ , Space+ , Str "is"+ , Space+ , Span+ ( "" , [ "phraserole" ] , [ ( "role" , "phraserole" ) ] )+ [ Str "this" ]+ , Space+ , Str "phrase"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "role."+ ]+ , Para [ Str "This" , Space , Str "is"@@ -1565,11 +1664,37 @@ , Space , Str "(1902):" ]- , Para- [ Image- ( "" , [] , [] )- [ Str "lalune" , Space , Str "fig" , Space , Str "caption" ]- ( "lalune.jpg" , "fig:" )+ , Figure+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "lalune"+ , Space+ , Str "fig"+ , Space+ , Str "caption"+ ]+ ])+ [ Plain+ [ Image+ ( "" , [] , [] )+ [ Str "lalune"+ , Space+ , Str "alt"+ , Space+ , Str "text"+ , Space+ , Str "shadowed"+ , Space+ , Str "by"+ , Space+ , Str "fig"+ , Space+ , Str "caption"+ ]+ ( "lalune.jpg" , "" )+ ] ] , Para [ Str "Here"@@ -2535,6 +2660,129 @@ ] (TableFoot ( "" , [] , [] ) []) , Para+ [ Str "Table"+ , Space+ , Str "with"+ , Space+ , Str "attributes"+ ]+ , Table+ ( "mytableid1"+ , [ "mytableclass1" , "mytableclass2" ]+ , [ ( "role" , "tablerole1" )+ , ( "custom-style" , "mytabstyle1" )+ ]+ )+ (Caption+ Nothing+ [ Plain+ [ Str "Attribute"+ , Space+ , Str "table"+ , Space+ , Str "caption"+ ]+ ])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "body"+ , Space+ , Str "cell"+ , Space+ , Str "1"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "body"+ , Space+ , Str "cell"+ , Space+ , Str "2"+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ , Para+ [ Str "Table"+ , Space+ , Str "with"+ , Space+ , Str "attributes,"+ , Space+ , Str "without"+ , Space+ , Str "caption"+ ]+ , Table+ ( "mytableid2"+ , [ "mytableclass3" , "mytableclass4" ]+ , [ ( "role" , "tablerole2" )+ , ( "custom-style" , "mytabstyle2" )+ ]+ )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "body"+ , Space+ , Str "cell"+ , Space+ , Str "1"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "body"+ , Space+ , Str "cell"+ , Space+ , Str "2"+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ , Para [ Str "Multiline" , Space , Str "table"@@ -2901,21 +3149,148 @@ ] ] (TableFoot ( "" , [] , [] ) [])- , BulletList+ , 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" ] ] , [ Para [ Str "Another" , Space , Str "Step" ]- , Para- [ Str "Substeps"- , Space- , Str "can"- , Space- , Str "be"- , Space- , Str "nested"- , Space- , Str "indefinitely"- , Space- , Str "deep."+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para+ [ Str "Substeps"+ , Space+ , Str "can"+ , Space+ , Str "be"+ , Space+ , Str "nested"+ , Space+ , Str "indefinitely"+ , Space+ , Str "deep."+ ]+ ] ] ] , [ Para
@@ -1,6 +1,6 @@ <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">-<book><title>An Example Book</title>+<book id='book01'><title>An Example Book</title> <chapter id="ch01"><title>XRef Samples</title> <para> This paragraph demonstrates several features of@@ -27,6 +27,15 @@ <listitem><para>A link to a <sgmltag>figure</sgmltag> element: <xref linkend="fig01"/>. </para></listitem>+<listitem><para>A link to a+<sgmltag>table</sgmltag> element: <xref linkend="table01"/>.+</para></listitem>+<listitem><para>A link to a+<sgmltag>part</sgmltag> element: <xref linkend="part01"/>.+</para></listitem>+<listitem><para>A link to a+<sgmltag>book</sgmltag> element: <xref linkend="book01"/>.+</para></listitem> </itemizedlist> </chapter> @@ -35,6 +44,9 @@ <para>Some content here</para> </chapter> +<part id="part01">+ <title>Later Part</title>+ <chapter id="ch03" xreflabel="Chapter the Third"> <title>The Third Chapter</title> <para>Some content here</para>@@ -77,5 +89,26 @@ </mediaobject> </figure> +<table id="table01" frame="all" rowsep="1" colsep="1">+ <title>Supported features by version</title>+ <tgroup cols="2">+ <colspec colname="col_1" colwidth="50*"/>+ <colspec colname="col_2" colwidth="50*"/>+ <thead>+ <row>+ <entry>Version</entry>+ <entry>Feat</entry>+ </row>+ </thead>+ <tbody>+ <row>+ <entry>Free</entry>+ <entry>no</entry>+ </row>+ </tbody>+ </tgroup>+</table>+ </chapter>+</part> </book>
@@ -14,7 +14,7 @@ ] } [ Header- 1+ 2 ( "ch01" , [] , [] ) [ Str "XRef" , Space , Str "Samples" ] , Para@@ -168,21 +168,97 @@ , Str "." ] ]+ , [ Para+ [ Str "A"+ , Space+ , Str "link"+ , Space+ , Str "to"+ , Space+ , Str "a"+ , SoftBreak+ , Str "table"+ , Space+ , Str "element:"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "Supported"+ , Space+ , Str "features"+ , Space+ , Str "by"+ , Space+ , Str "version"+ ]+ ( "#table01" , "" )+ , Str "."+ ]+ ]+ , [ Para+ [ Str "A"+ , Space+ , Str "link"+ , Space+ , Str "to"+ , Space+ , Str "a"+ , SoftBreak+ , Str "part"+ , Space+ , Str "element:"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "Later" , Space , Str "Part" ]+ ( "#part01" , "" )+ , Str "."+ ]+ ]+ , [ Para+ [ Str "A"+ , Space+ , Str "link"+ , Space+ , Str "to"+ , Space+ , Str "a"+ , SoftBreak+ , Str "book"+ , Space+ , Str "element:"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "An"+ , Space+ , Str "Example"+ , Space+ , Str "Book"+ ]+ ( "#book01" , "" )+ , Str "."+ ]+ ] ] , Header- 1+ 2 ( "ch02" , [] , [] ) [ Str "The" , Space , Str "Second" , Space , Str "Chapter" ] , Para [ Str "Some" , Space , Str "content" , Space , Str "here" ] , Header 1+ ( "part01" , [] , [] )+ [ Str "Later" , Space , Str "Part" ]+ , Header+ 2 ( "ch03" , [] , [] ) [ Str "The" , Space , Str "Third" , Space , Str "Chapter" ] , Para [ Str "Some" , Space , Str "content" , Space , Str "here" ] , Header- 1+ 2 ( "ch04" , [] , [ ( "titleabbrev" , "Chapter 4" ) ] ) [ Str "The" , Space , Str "Fourth" , Space , Str "Chapter" ] , Para@@ -201,17 +277,93 @@ , Plain [ Str "int1" ] , Plain [ Str "int" ] , Plain [ Str "int2" ]- , Para- [ Image- ( "fig01" , [] , [] )- [ Str "The"- , Space- , Str "Pythagorean"- , Space- , Str "Theorem"- , Space- , Str "Illustrated"+ , Figure+ ( "fig01" , [] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "The"+ , Space+ , Str "Pythagorean"+ , Space+ , Str "Theorem"+ , Space+ , Str "Illustrated"+ ]+ ])+ [ Plain+ [ Image+ ( "" , [] , [] )+ [ Str "An"+ , Space+ , Str "illustration"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "Pythagorean"+ , Space+ , Str "Theorem"+ ]+ ( "figures/pythag.png" , "" ) ]- ( "figures/pythag.png" , "fig:" ) ]+ , Table+ ( "table01" , [] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "Supported"+ , Space+ , Str "features"+ , Space+ , Str "by"+ , Space+ , Str "version"+ ]+ ])+ [ ( AlignDefault , ColWidth 0.5 )+ , ( AlignDefault , ColWidth 0.5 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Version" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Feat" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Free" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "no" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) []) ]
@@ -1,52 +1,146 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 1.0)]- (TableHead ("",[],[])- [])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "User\8217s",Space,Str "Guide"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "11",Space,Str "August",Space,Str "2017"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []]])]- (TableFoot ("",[],[])- [])-,Para [Str "CONTENTS"]-,Para [Strong [Str "Section",Space,Str "Page"]]-,Para [Str "FIGURES",Space,Link ("",[],[]) [Str "iv"] ("#figures","")]-,Para [Str "TABLES",Space,Link ("",[],[]) [Str "v"] ("#tables","")]-,Para [Str "SECTION",Space,Str "1",Space,Str "Introduction",Space,Link ("",[],[]) [Str "2"] ("#introduction","")]-,Header 1 ("figures",["Heading-0"],[]) [Str "FIGURES"]-,Para [Strong [Str "Figure",Space,Str "Page"]]-,Para [Strong [Str "No",Space,Str "table",Space,Str "of",Space,Str "figures",Space,Str "entries",Space,Str "found."]]-,Header 1 ("tables",["Heading-0"],[]) [Str "TABLES"]-,Para [Strong [Str "Table",Space,Str "Page"]]-,Para [Strong [Str "No",Space,Str "table",Space,Str "of",Space,Str "figures",Space,Str "entries",Space,Str "found."]]-,Header 1 ("introduction",[],[]) [Str "Introduction"]-,Para [Str "Nothing",Space,Str "to",Space,Str "introduce,",Space,Str "yet."]]+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 0.8615384615384616 ) ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "User\8217s" , Space , Str "Guide" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain+ [ Str "11"+ , Space+ , Str "August"+ , Space+ , Str "2017"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+, Para [ Str "CONTENTS" ]+, Para [ Strong [ Str "Section" , Space , Str "Page" ] ]+, Para+ [ Str "FIGURES"+ , Space+ , Link ( "" , [] , [] ) [ Str "iv" ] ( "#figures" , "" )+ ]+, Para+ [ Str "TABLES"+ , Space+ , Link ( "" , [] , [] ) [ Str "v" ] ( "#tables" , "" )+ ]+, Para+ [ Str "SECTION"+ , Space+ , Str "1"+ , Space+ , Str "Introduction"+ , Space+ , Link ( "" , [] , [] ) [ Str "2" ] ( "#introduction" , "" )+ ]+, Header+ 1 ( "figures" , [ "Heading-0" ] , [] ) [ Str "FIGURES" ]+, Para [ Strong [ Str "Figure" , Space , Str "Page" ] ]+, Para+ [ Strong+ [ Str "No"+ , Space+ , Str "table"+ , Space+ , Str "of"+ , Space+ , Str "figures"+ , Space+ , Str "entries"+ , Space+ , Str "found."+ ]+ ]+, Header+ 1 ( "tables" , [ "Heading-0" ] , [] ) [ Str "TABLES" ]+, Para [ Strong [ Str "Table" , Space , Str "Page" ] ]+, Para+ [ Strong+ [ Str "No"+ , Space+ , Str "table"+ , Space+ , Str "of"+ , Space+ , Str "figures"+ , Space+ , Str "entries"+ , Space+ , Str "found."+ ]+ ]+, Header+ 1 ( "introduction" , [] , [] ) [ Str "Introduction" ]+, Para+ [ Str "Nothing"+ , Space+ , Str "to"+ , Space+ , Str "introduce,"+ , Space+ , Str "yet."+ ]+]
binary file changed (absent → 27098 bytes)
@@ -0,0 +1,6 @@+[Para [Link ("",[],[]) [Str "A",Space,Str "link",Space,Str "to",Space,Str "the",Space,Str "bookmark"] ("#referenced-title" , "")]+,Para [Strong [Str "Accomplices:"]]+,Para [Str "There",Space,Str "are",Space,Str "bookmarks",Space,Str "around",Space,Str "here."]+,Para []+,Header 1 ("referenced-title",[],[]) [Str "Referenced" ,Space ,Str "title"]+,Para [Str "Content"]]
binary file changed (28138 → 12153 bytes)
@@ -0,0 +1,11 @@+[Header 2 ("some-block-quotes-in-different-ways",[],[]) [Str "Some",Space,Str "block",Space,Str "quotes,",Space,Str "in",Space,Str "different",Space,Str "ways"]+,Para [Str "This",Space,Str "is",Space,Str "the",Space,Str "proper",Space,Str "way,",Space,Str "with",Space,Str "a",Space,Str "style"]+,BlockQuote+ [Para [Str "I",Space,Str "don\8217t",Space,Str "know",Space,Str "why",Space,Str "this",Space,Str "would",Space,Str "be",Space,Str "in",Space,Str "italics,",Space,Str "but",Space,Str "so",Space,Str "it",Space,Str "appears",Space,Str "to",Space,Str "be",Space,Str "on",Space,Str "my",Space,Str "screen."]]+,Para [Str "And",Space,Str "this",Space,Str "is",Space,Str "also",Space,Str "a",Space,Str "proper",Space,Str "way,",Space,Str "with",Space,Str "a",Space,Str "different", Space, Str "style"]+,BlockQuote+ [Para [Str "This",Space,Str "is",Space,Str "called",Space,Str "the",Space,Str "Intense",Space,Str "Quote",Space,Str "style."]]+,Para [Str "And",Space,Str "this",Space,Str "is",Space,Str "the",Space,Str "way",Space,Str "that",Space,Str "most",Space,Str "people",Space,Str "do",Space,Str "it:"]+,BlockQuote+ [Para [Str "I",Space,Str "just",Space,Str "indented",Space,Str "this,",Space,Str "so",Space,Str "it",Space,Str "looks",Space,Str "like",Space,Str "a",Space,Str "block",Space,Str "quote.",Space,Str "I",Space,Str "think",Space,Str "this",Space,Str "is",Space,Str "how",Space,Str "most",Space,Str "people",Space,Str "do",Space,Str "block",Space,Str "quotes",Space,Str "in",Space,Str "their",Space,Str "documents."]]+,Para [Str "And",Space,Str "back",Space,Str "to",Space,Str "the",Space,Str "normal",Space,Str "style."]]
@@ -1,8 +0,0 @@-[Header 2 ("some-block-quotes-in-different-ways",[],[]) [Str "Some",Space,Str "block",Space,Str "quotes,",Space,Str "in",Space,Str "different",Space,Str "ways"]-,Para [Str "This",Space,Str "is",Space,Str "the",Space,Str "proper",Space,Str "way,",Space,Str "with",Space,Str "a",Space,Str "style"]-,BlockQuote- [Para [Str "I",Space,Str "don\8217t",Space,Str "know",Space,Str "why",Space,Str "this",Space,Str "would",Space,Str "be",Space,Str "in",Space,Str "italics,",Space,Str "but",Space,Str "so",Space,Str "it",Space,Str "appears",Space,Str "to",Space,Str "be",Space,Str "on",Space,Str "my",Space,Str "screen."]]-,Para [Str "And",Space,Str "this",Space,Str "is",Space,Str "the",Space,Str "way",Space,Str "that",Space,Str "most",Space,Str "people",Space,Str "do",Space,Str "it:"]-,BlockQuote- [Para [Str "I",Space,Str "just",Space,Str "indented",Space,Str "this,",Space,Str "so",Space,Str "it",Space,Str "looks",Space,Str "like",Space,Str "a",Space,Str "block",Space,Str "quote.",Space,Str "I",Space,Str "think",Space,Str "this",Space,Str "is",Space,Str "how",Space,Str "most",Space,Str "people",Space,Str "do",Space,Str "block",Space,Str "quotes",Space,Str "in",Space,Str "their",Space,Str "documents."]]-,Para [Str "And",Space,Str "back",Space,Str "to",Space,Str "the",Space,Str "normal",Space,Str "style."]]
@@ -1,4 +1,4 @@ [Para [Str "I",Space,Str "want",Space,Span ("",["comment-start"],[("id","0"),("author","Jesse Rosenthal"),("date","2016-05-09T16:13:00Z")]) [Str "I",Space,Str "left",Space,Str "a",Space,Str "comment."],Str "some",Space,Str "text",Space,Str "to",Space,Str "have",Space,Str "a",Space,Str "comment",Space,Span ("",["comment-end"],[("id","0")]) [],Str "on",Space,Str "it."] ,Para [Str "This",Space,Str "is",Space,Span ("",["comment-start"],[("id","1"),("author","Jesse Rosenthal"),("date","2016-05-09T16:13:00Z")]) [Str "A",Space,Str "comment",Space,Str "across",Space,Str "paragraphs."],Str "a",Space,Str "new",Space,Str "paragraph."] ,Para [Str "And",Space,Str "so",Span ("",["comment-end"],[("id","1")]) [],Space,Str "is",Space,Str "this."]-,Para [Str "One",Space,Span ("",["comment-start"],[("id","2"),("author","Jesse Rosenthal"),("date","2016-05-09T16:14:00Z")]) [Str "This",Space,Str "one",Space,Str "has",Space,Str "multiple",Space,Str "paragraphs.",Space,Str "\182",Space,Str "See?"],Str "more",Span ("",["comment-end"],[("id","2")]) [],Str ".",Space,Str "And",Space,Str "this",Space,Str "is",Space,Str "one",Space,Str "with",Space,Str "a",Space,Span ("",["comment-start"],[("id","3"),("author","Jesse Rosenthal"),("date","2016-06-22T14:35:00Z")]) [Str "Do",Space,Str "something."],Span ("",["comment-start"],[("id","4"),("author","Jesse Rosenthal"),("date","2016-06-22T14:36:00Z")]) [Str "Do",Space,Str "something",Space,Str "else."],Str "comment",Space,Str "in",Space,Str "a",Space,Str "comment",Span ("",["comment-end"],[("id","3")]) [Span ("",["comment-end"],[("id","4")]) []],Str "."]]+,Para [Str "One",Space,Span ("",["comment-start"],[("id","2"),("author","Jesse Rosenthal"),("date","2016-05-09T16:14:00Z")]) [Str "This",Space,Str "one",Space,Str "has",Space,Str "multiple",Space,Str "paragraphs.",LineBreak, Str "See?"],Str "more",Span ("",["comment-end"],[("id","2")]) [],Str ".",Space,Str "And",Space,Str "this",Space,Str "is",Space,Str "one",Space,Str "with",Space,Str "a",Space,Span ("",["comment-start"],[("id","3"),("author","Jesse Rosenthal"),("date","2016-06-22T14:35:00Z")]) [Str "Do",Space,Str "something."],Span ("",["comment-start"],[("id","4"),("author","Jesse Rosenthal"),("date","2016-06-22T14:36:00Z")]) [Str "Do",Space,Str "something",Space,Str "else."],Str "comment",Space,Str "in",Space,Str "a",Space,Str "comment",Span ("",["comment-end"],[("id","3")]) [Span ("",["comment-end"],[("id","4")]) []],Str "."]]
binary file changed (absent → 14978 bytes)
@@ -0,0 +1,7 @@+[ Header 1 ( "title" , [] , [] ) [ Str "TITLE" ]+, Para+ [ Str "Cross-reference:"+ , Space+ , Link ( "" , [] , [] ) [ Str "TITLE" ] ( "#title" , "" )+ ]+]
binary file changed (14846 → 14838 bytes)
@@ -1,6 +1,6 @@ [OrderedList (1,Decimal,OneParen) [[Para [Str "This",Space,Str "is",Space,Str "at",Space,Str "the",Space,Str "first",Space,Str "level"]- ,OrderedList (1,LowerAlpha,DefaultDelim)+ ,OrderedList (1,LowerAlpha,OneParen) [[Para [Str "This",Space,Str "is",Space,Str "at",Space,Str "the",Space,Str "second",Space,Str "level"]- ,OrderedList (1,LowerRoman,DefaultDelim)- [[Para [Str "This",Space,Str "is",Space,Emph [Str "at",Space,Strong [Str "the",Space,Str "third",Space,Str "level"],Str ",",Space,Str "and",Space,Str "I",Space,Str "want",Space,Str "to"],Space,Str "test",Space,Str "normalization",Space,Str "here."]]]]]]]]+ ,OrderedList (1,LowerRoman,OneParen)+ [[Para [Str "This",Space,Str "is",Space,Emph [Str "at",Space,Strong [Str "the",Space,Span ("",["mark"],[]) [Str "th"],Str "i",Span ("",["mark"],[]) [Str "rd"],Space,Str "level"],Str ",",Space,Str "and",Space,Str "I",Space,Str "want",Space,Str "to"],Space,Str "test",Space,Str "normalization",Space,Str "here."]]]]]]]]
binary file changed (8455 → 9174 bytes)
@@ -1,7 +1,33 @@-[DefinitionList- [([Str "Term",Space,Str "1"],- [[Para [Str "Definition",Space,Str "1"]]])- ,([Str "Term",Space,Str "2",Space,Str "with",Space,Emph [Str "inline",Space,Str "markup"]],- [[Para [Str "Definition",Space,Str "2"]- ,CodeBlock ("",[],[]) "{ some code, part of Definition 2 }"- ,Para [Str "Third",Space,Str "paragraph",Space,Str "of",Space,Str "definition",Space,Str "2."]]])]]+[ DefinitionList+ [ ( [ Str "Term" , Space , Str "1" ]+ , [ [ Para [ Str "Definition" , Space , Str "1" ] ] ]+ )+ , ( [ Str "Term"+ , Space+ , Str "2"+ , Space+ , Str "with"+ , Space+ , Emph [ Str "inline" , Space , Str "markup" ]+ ]+ , [ [ Para [ Str "Definition" , Space , Str "2" ]+ , Para+ [ Code+ ( "" , [] , [] ) "{ some code, part of Definition 2 }"+ ]+ , Para+ [ Str "Third"+ , Space+ , Str "paragraph"+ , Space+ , Str "of"+ , Space+ , Str "definition"+ , Space+ , Str "2."+ ]+ ]+ ]+ )+ ]+]
@@ -1,5 +1,5 @@ [Para- [Str "\24076\26395\28145\20837\20102\35299\30340\35835\32773\21487\20197\21435\30475David",Space,Str "French",Space,Str "Belding\21644Kevin",Space,Str "J.",Space,Str "Mitchell\30340"+ [Str "\24076\26395\28145\20837\20102\35299\30340\35835\32773\21487\20197\21435\30475David",Space,Str "French",Span ( "" , [ "indexref" ] , [ ( "entry" , "French" ) ] ) [],Space,Str "Belding\21644Kevin",Space,Str "J.",Space,Str "Mitchell\30340" ,Link ("",[],[]) [Str "Foundations",Space,Str "of",Space,Str "Analysis,",Space,Str "2nd",Space,Str "Edition"] ("https://books.google.com/books?id=sp_Zcb9ot90C&lpg=PR4&hl=zh-CN&pg=PA19#v=onepage&q&f=true",""),Str ",\21487\20174\&19\39029\30475\36215\65292\25110D.C.",Space,Str "Goldrei\30340",Space ,Link ("",[],[]) [Str "Classic",Space,Str "Set",Space,Str "Theory:",Space,Str "For",Space,Str "Guided",Space,Str "Independent",Space,Str "Study"] ("https://books.google.ae/books?id=dlc0DwAAQBAJ&lpg=PT29&hl=zh-CN&pg=PT26#v=onepage&q&f=true","") ,Str "\65292\20174\31532\20108\31456\30475\36215\65292\38405\35835\26102\35201\27880\24847\26412\25991\19982\36825\20123\20070\25152\19981\21516\30340\26159\24182\27809\26377\25226\23454\25968\30475\20316\26159\26377\29702\25968\38598\30340\20998\21106\12290"]
binary file changed (absent → 10405 bytes)
binary file changed (9981 → 10692 bytes)
binary file changed (9830 → 10510 bytes)
binary file changed (10168 → 10824 bytes)
binary file changed (9931 → 10609 bytes)
binary file changed (10560 → 11236 bytes)
binary file changed (12368 → 12542 bytes)
binary file changed (9830 → 10501 bytes)
binary file changed (9835 → 10515 bytes)
binary file changed (10314 → 11000 bytes)
binary file changed (9969 → 10655 bytes)
binary file changed (26861 → 27383 bytes)
binary file changed (9769 → 10451 bytes)
binary file changed (9949 → 10627 bytes)
binary file changed (26711 → 27383 bytes)
binary file changed (9991 → 10664 bytes)
binary file changed (10162 → 10842 bytes)
binary file changed (10228 → 11034 bytes)
binary file changed (absent → 10788 bytes)
binary file changed (10024 → 10702 bytes)
binary file changed (9878 → 10685 bytes)
binary file changed (10106 → 10918 bytes)
binary file changed (10022 → 10699 bytes)
binary file changed (10163 → 10845 bytes)
binary file changed (9938 → 10615 bytes)
binary file changed (9870 → 10544 bytes)
binary file changed (10004 → 10683 bytes)
binary file changed (9840 → 10496 bytes)
binary file changed (10162 → 10946 bytes)
binary file changed (10200 → 10882 bytes)
binary file changed (10202 → 10870 bytes)
binary file changed (9852 → 10519 bytes)
binary file changed (absent → 10783 bytes)
binary file changed (9813 → 10492 bytes)
binary file changed (9796 → 10476 bytes)
binary file changed (9830 → 10506 bytes)
binary file changed (9942 → 10617 bytes)
binary file changed (9755 → 10468 bytes)
binary file changed (9802 → 10479 bytes)
binary file changed (absent → 19882 bytes)
@@ -0,0 +1,44 @@+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Para+ [ Str "1"+ , Space+ , Str "Daniel"+ , Space+ , Str "Schliebner:"+ , Space+ , Str "Cantor'sches"+ , Space+ , Str "Diagonalverfahren."+ , Space+ , Str "Von"+ , Space+ , Str "Mengen,"+ , Space+ , Str "Unendlichkeiten"+ , Space+ , Str "und"+ , Space+ , Str "Wahnsinn,"+ , Space+ , Str "Pdf:"+ , Space+ , Str+ "https://www2.informatik.hu-berlin.de/~kossahl/Uni/Ma1/Cantor.pdf"+ ]+ ])+ [ Plain+ [ Image+ ( ""+ , []+ , [ ( "width" , "2.3680555555555554in" )+ , ( "height" , "0.9340277777777778in" )+ ]+ )+ []+ ( "media/image1.emf" , "" )+ ]+ ]+]
@@ -2,7 +2,7 @@ ,OrderedList (1,Decimal,Period) [[Para [Str "one"]] ,[Para [Str "two"]- ,OrderedList (1,LowerAlpha,DefaultDelim)+ ,OrderedList (1,LowerAlpha,Period) [[Para [Str "a"]] ,[Para [Str "b"]]]]] ,BulletList
@@ -0,0 +1,8 @@+[ OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain [ Str "one" ]+ , BulletList [ [ Plain [ Str "bul" ] ] ]+ ]+ , [ Plain [ Str "two" ] ]+ ]+]
@@ -1,37 +1,266 @@-[Para [Str "For",Space,Str "each",Space,Str "initiative",Space,Str "below",Space,Str "is",Space,Str "outlined",Space,Str "the",Space,Str "goals,",Space,Str "an",Space,Str "approximate",Space,Str "roadmap",Space,Str "which",Space,Str "will",Space,Str "likely",Space,Str "change",Space,Str "as",Space,Str "we",Space,Str "iterate,",Space,Str "signals/metrics",Space,Str "to",Space,Str "measure",Space,Str "success,",Space,Str "and",Space,Str "initial",Space,Str "workitems",Space,Str "with",Space,Str "a",Space,Str "rough",Space,Strong [Str "schedule"],Space,Str "and",Space,Str "contacts",Space,Str "where",Space,Str "available:"]-,Para [Str "\160"]-,OrderedList (1,Decimal,Period)- [[BlockQuote- [Para [Str "State",Space,Str "of",Space,Str "Documentation"]]]]-,BlockQuote- [Para [Strong [Str "Goal:",Space,Str "Baseline",Space,Str "and",Space,Str "ongoing",Space,Str "metrics",Space,Str "tracking",Space,Str "doc",Space,Str "usefulness",Space,Str "and",Space,Str "completeness."]]- ,Para [Str "\160"]]-,OrderedList (2,Decimal,Period)- [[BlockQuote- [Para [Str "Content",Space,Str "Migration"]]]]-,BlockQuote- [Para [Str "Goal:",Space,Str "Content",Space,Str "is",Space,Str "accessible",Space,Str "to",Space,Str "new",Space,Str "employees",Space,Str "and",Space,Str "is",Space,Str "better",Space,Str "organized/archived."]- ,Para [Str "\160"]]-,OrderedList (3,Decimal,Period)- [[BlockQuote- [Para [Str "Wiki",Space,Str "(xl)"]]]]-,BlockQuote- [Para [Strong [Str "Goal:",Space,Str "Useful",Space,Str "documentation",Space,Str "that",Space,Str "is",Space,Str "archived,",Space,Str "searchable",Space,Str "and",Space,Str "easy",Space,Str "to",Space,Str "create"]]- ,Para [Str "\160\160"]]-,OrderedList (4,Decimal,Period)- [[BlockQuote- [Para [Str "XL",Space,Str "Code",Space,Str "Autoreview",Space,Str "Bot",Space,Str "(XLCRBot)."]]]]-,BlockQuote- [Para [Strong [Str "Goal:",Space,Str "Feedback",Space,Str "on",Space,Str "basic",Space,Str "violations",Space,Str "in",Space,Str "seconds",Space,Str "or",Space,Str "minutes",Space,Str "at",Space,Str "most",Space,Str "in",Space,Str "either",Space,Str "VS",Space,Str "or",Space,Str "Codeflow."]]]-,OrderedList (5,Decimal,Period)- [[BlockQuote- [Para [Str "Code",Space,Str "documentation"]]]]-,BlockQuote- [Para [Strong [Str "Goal:",Space,Str "Useful,",Space,Str "consistent,",Space,Str "tool",Space,Str "supported",Space,Str "comments"]]]-,Para [Strong [Str "\160"],Str "\160"]-,OrderedList (6,Decimal,Period)- [[BlockQuote- [Para [Str "Education",Space,Str "efforts"]]]]-,BlockQuote- [Para [Strong [Str "Goal:",Space,Str "Broad,",Space,Str "discoverable",Space,Str "channels",Space,Str "for",Space,Str "updates",Space,Str "and",Space,Str "news"]]]-,Para [Strong [Str "\160"]]]+Pandoc+ Meta { unMeta = fromList [] }+ [ Para+ [ Str "For"+ , Space+ , Str "each"+ , Space+ , Str "initiative"+ , Space+ , Str "below"+ , Space+ , Str "is"+ , Space+ , Str "outlined"+ , Space+ , Str "the"+ , Space+ , Str "goals,"+ , Space+ , Str "an"+ , Space+ , Str "approximate"+ , Space+ , Str "roadmap"+ , Space+ , Str "which"+ , Space+ , Str "will"+ , Space+ , Str "likely"+ , Space+ , Str "change"+ , Space+ , Str "as"+ , Space+ , Str "we"+ , Space+ , Str "iterate,"+ , Space+ , Str "signals/metrics"+ , Space+ , Str "to"+ , Space+ , Str "measure"+ , Space+ , Str "success,"+ , Space+ , Str "and"+ , Space+ , Str "initial"+ , Space+ , Str "workitems"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "rough"+ , Space+ , Strong [ Str "schedule" ]+ , Space+ , Str "and"+ , Space+ , Str "contacts"+ , Space+ , Str "where"+ , Space+ , Str "available:"+ ]+ , Para [ Str "\160" ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Para+ [ Str "State"+ , Space+ , Str "of"+ , Space+ , Str "Documentation"+ ]+ ]+ ]+ , BlockQuote+ [ Para+ [ Strong+ [ Str "Goal:"+ , Space+ , Str "Baseline"+ , Space+ , Str "and"+ , Space+ , Str "ongoing"+ , Space+ , Str "metrics"+ , Space+ , Str "tracking"+ , Space+ , Str "doc"+ , Space+ , Str "usefulness"+ , Space+ , Str "and"+ , Space+ , Str "completeness."+ ]+ ]+ , Para [ Str "\160" ]+ ]+ , OrderedList+ ( 2 , Decimal , Period )+ [ [ Para [ Str "Content" , Space , Str "Migration" ] ] ]+ , BlockQuote+ [ Para+ [ Str "Goal:"+ , Space+ , Str "Content"+ , Space+ , Str "is"+ , Space+ , Str "accessible"+ , Space+ , Str "to"+ , Space+ , Str "new"+ , Space+ , Str "employees"+ , Space+ , Str "and"+ , Space+ , Str "is"+ , Space+ , Str "better"+ , Space+ , Str "organized/archived."+ ]+ , Para [ Str "\160" ]+ ]+ , OrderedList+ ( 3 , Decimal , Period )+ [ [ Para [ Str "Wiki" , Space , Str "(xl)" ] ] ]+ , BlockQuote+ [ Para+ [ Strong+ [ Str "Goal:"+ , Space+ , Str "Useful"+ , Space+ , Str "documentation"+ , Space+ , Str "that"+ , Space+ , Str "is"+ , Space+ , Str "archived,"+ , Space+ , Str "searchable"+ , Space+ , Str "and"+ , Space+ , Str "easy"+ , Space+ , Str "to"+ , Space+ , Str "create"+ ]+ ]+ , Para [ Str "\160\160" ]+ ]+ , OrderedList+ ( 4 , Decimal , Period )+ [ [ Para+ [ Str "XL"+ , Space+ , Str "Code"+ , Space+ , Str "Autoreview"+ , Space+ , Str "Bot"+ , Space+ , Str "(XLCRBot)."+ ]+ ]+ ]+ , BlockQuote+ [ Para+ [ Strong+ [ Str "Goal:"+ , Space+ , Str "Feedback"+ , Space+ , Str "on"+ , Space+ , Str "basic"+ , Space+ , Str "violations"+ , Space+ , Str "in"+ , Space+ , Str "seconds"+ , Space+ , Str "or"+ , Space+ , Str "minutes"+ , Space+ , Str "at"+ , Space+ , Str "most"+ , Space+ , Str "in"+ , Space+ , Str "either"+ , Space+ , Str "VS"+ , Space+ , Str "or"+ , Space+ , Str "Codeflow."+ ]+ ]+ ]+ , OrderedList+ ( 5 , Decimal , Period )+ [ [ Para [ Str "Code" , Space , Str "documentation" ] ] ]+ , BlockQuote+ [ Para+ [ Strong+ [ Str "Goal:"+ , Space+ , Str "Useful,"+ , Space+ , Str "consistent,"+ , Space+ , Str "tool"+ , Space+ , Str "supported"+ , Space+ , Str "comments"+ ]+ ]+ ]+ , Para [ Strong [ Str "\160" ] , Str "\160" ]+ , OrderedList+ ( 6 , Decimal , Period )+ [ [ Para [ Str "Education" , Space , Str "efforts" ] ] ]+ , BlockQuote+ [ Para+ [ Strong+ [ Str "Goal:"+ , Space+ , Str "Broad,"+ , Space+ , Str "discoverable"+ , Space+ , Str "channels"+ , Space+ , Str "for"+ , Space+ , Str "updates"+ , Space+ , Str "and"+ , Space+ , Str "news"+ ]+ ]+ ]+ , Para [ Strong [ Str "\160" ] ]+ ]
@@ -7,9 +7,9 @@ [ MetaMap (fromList [ ( "DOI"- , MetaInlines [ Str "10.1145/1929887.1929902" ]+ , MetaString "10.1145/1929887.1929902" )- , ( "ISSN" , MetaInlines [ Str "2153-2184" ] )+ , ( "ISSN" , MetaString "2153-2184" ) , ( "author" , MetaList [ MetaMap@@ -121,9 +121,9 @@ [ Str "ACM" , Space , Str "Inroads" ] ) , ( "id" , MetaString "ITEM-1" )- , ( "issue" , MetaString "1" )+ , ( "issue" , MetaInlines [ Str "1" ] ) , ( "issued" , MetaString "2011-02" )- , ( "page" , MetaString "32-37" )+ , ( "page" , MetaInlines [ Str "32-37" ] ) , ( "publisher" , MetaInlines [ Str "ACM" ] ) , ( "publisher-place" , MetaInlines@@ -152,7 +152,7 @@ ] ) , ( "type" , MetaString "article-journal" )- , ( "volume" , MetaString "2" )+ , ( "volume" , MetaInlines [ Str "2" ] ) ]) , MetaMap (fromList@@ -206,7 +206,7 @@ ] ) , ( "id" , MetaString "ITEM-2" )- , ( "issue" , MetaString "4" )+ , ( "issue" , MetaInlines [ Str "4" ] ) , ( "issued" , MetaString "2015" ) , ( "title" , MetaInlines@@ -246,7 +246,7 @@ ] ) , ( "type" , MetaString "article-journal" )- , ( "volume" , MetaString "6" )+ , ( "volume" , MetaInlines [ Str "6" ] ) ]) ] )@@ -268,7 +268,7 @@ { citationId = "ITEM-1" , citationPrefix = [ Str "prefix" ] , citationSuffix =- [ Str ",", Space , Str "123" , Space , Str "suffix" ]+ [ Str "," , Space , Str "123" , Space , Str "suffix" ] , citationMode = NormalCitation , citationNoteNum = 0 , citationHash = 0@@ -302,7 +302,12 @@ { citationId = "ITEM-1" , citationPrefix = [ Str "prefix" ] , citationSuffix =- [ Str ",", Space , Str "10-20" , Space , Str "suffix" ]+ [ Str ","+ , Space+ , Str "10-20"+ , Space+ , Str "suffix"+ ] , citationMode = NormalCitation , citationNoteNum = 0 , citationHash = 0
binary file changed (14622 → 14672 bytes)
@@ -1,24 +1,60 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.22069570301081556)- ,(AlignDefault,ColWidth 0.22069570301081556)- ,(AlignDefault,ColWidth 0.5586085939783689)]- (TableHead ("",[],[])- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Strong [Str "col1Header"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Strong [Str "col2Header"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Strong [Str "col3Header"]]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "col1",Space,Str "content"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Body",Space,Str "copy"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "col3",Space,Str "content"]]]])]- (TableFoot ("",[],[])- [])]+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 0.16167023554603854 )+ , ( AlignDefault , ColWidth 0.16167023554603854 )+ , ( AlignDefault , ColWidth 0.40920770877944324 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Strong [ Str "col1Header" ] ] ]+ , Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Strong [ Str "col2Header" ] ] ]+ , Cell+ ( "" , [] , [] )+ AlignCenter+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Strong [ Str "col3Header" ] ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "col1" , Space , Str "content" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Body" , Space , Str "copy" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "col3" , Space , Str "content" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]
binary file changed (40482 → 40487 bytes)
@@ -1,34 +1,81 @@-[Para [Str "See",Space,Str "Table",Space,Str "5.1."]-,Para [Str "Table",Space,Str "5.1"]-,Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.7605739372523825)- ,(AlignDefault,ColWidth 0.11971303137380876)- ,(AlignDefault,ColWidth 0.11971303137380876)]- (TableHead ("",[],[])-[Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Count"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "%"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "First",Space,Str "option"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "242"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "45"]]]-,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Second",Space,Str "option"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "99"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "18"]]]])]- (TableFoot ("",[],[])- [])-,Header 2 ("section", [], []) []]+[ Para+ [ Str "See" , Space , Str "Table" , Space , Str "5.1." ]+, Table+ ( "" , [] , [] )+ (Caption+ Nothing [ Para [ Str "Table" , Space , Str "5.1" ] ])+ [ ( AlignDefault , ColWidth 0.7605739372523824 )+ , ( AlignDefault , ColWidth 0.11971303137380876 )+ , ( AlignDefault , ColWidth 0.11971303137380876 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Count" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "%" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "First" , Space , Str "option" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "242" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "45" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Second" , Space , Str "option" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "99" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "18" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+, Header 2 ( "section" , [] , [] ) []+]
@@ -1,54 +1,145 @@-[Para [Str "See",Space,Str "Table",Space,Str "1."]-,Para []-,Table ("",[],[]) (Caption Nothing- [Para [Str "Table",Space,Str "1"]])- [(AlignDefault,ColWidth 0.7605739372523825)- ,(AlignDefault,ColWidth 0.11971303137380876)- ,(AlignDefault,ColWidth 0.11971303137380876)]- (TableHead ("",[],[])-[Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Count"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "%"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "First",Space,Str "option"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "242"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "45"]]]-,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Second",Space,Str "option"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "99"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "18"]]]])]- (TableFoot ("",[],[])- [])-,Header 2 ("section", [], []) []-,Table ("",[],[]) (Caption Nothing- [Para [Str "Table",Space,Str "2"]])- [(AlignDefault,ColWidth 0.3332963620230701)- ,(AlignDefault,ColWidth 0.3332963620230701)- ,(AlignDefault,ColWidth 0.3334072759538598)]- (TableHead ("",[],[])- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "One"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Two"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Three"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [])]- (TableFoot ("",[],[])- [])-,Para []-,Para [Str "See",Space,Str "Table",Space,Str "2."]]+[ Para+ [ Str "See"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "Table" , Space , Str "1" ]+ ( "#_Ref71265628" , "" )+ , Str "."+ ]+, Table+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Para+ [ Span ( "_Ref71265628" , [ "anchor" ] , [] ) []+ , Str "Table"+ , Space+ , Str "1"+ ]+ ])+ [ ( AlignDefault , ColWidth 0.7605739372523824 )+ , ( AlignDefault , ColWidth 0.11971303137380876 )+ , ( AlignDefault , ColWidth 0.11971303137380876 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Count" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "%" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "First" , Space , Str "option" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "242" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "45" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Second" , Space , Str "option" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "99" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "18" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+, Header 2 ( "section" , [] , [] ) []+, Table+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Para+ [ Span ( "_Ref71265695" , [ "anchor" ] , [] ) []+ , Str "Table"+ , Space+ , Str "2"+ ]+ ])+ [ ( AlignDefault , ColWidth 0.33329636202307006 )+ , ( AlignDefault , ColWidth 0.33329636202307006 )+ , ( AlignDefault , ColWidth 0.33340727595385977 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "One" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Two" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Three" ] ]+ ]+ ])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot ( "" , [] , [] ) [])+, Para+ [ Str "See"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "Table" , Space , Str "2" ]+ ( "#_Ref71265695" , "" )+ , Str "."+ ]+]
binary file changed (absent → 13143 bytes)
@@ -0,0 +1,823 @@+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 7.883369330453563e-3 )+ , ( AlignDefault , ColWidth 3.0669546436285097e-2 )+ , ( AlignDefault , ColWidth 3.0669546436285097e-2 )+ , ( AlignDefault , ColWidth 3.0669546436285097e-2 )+ , ( AlignDefault , ColWidth 3.0669546436285097e-2 )+ , ( AlignDefault , ColWidth 3.0669546436285097e-2 )+ , ( AlignDefault , ColWidth 3.0669546436285097e-2 )+ , ( AlignDefault , ColWidth 3.0669546436285097e-2 )+ , ( AlignDefault , ColWidth 3.0669546436285097e-2 )+ , ( AlignDefault , ColWidth 3.0669546436285097e-2 )+ , ( AlignDefault , ColWidth 0.42861771058315334 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 8)+ [ Plain [ Str "Bits" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "8" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "7" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "6" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "TEXT" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "BINARY" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "HYPERLINKS" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "FILEURL" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "LOCATION" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "ENHANCED" , Space , Str "STATUS" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain+ [ Str "Value"+ , Space+ , Str "allocated"+ , Space+ , Str "for"+ , Space+ , Str "use"+ , Space+ , Str "in"+ , Space+ , Str "interworking"+ , Space+ , Str "(NOTE)"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "LOCATION" , Space , Str "ALTITUDE" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "LOCATION" , Space , Str "TIMESTAMP" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "0" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "CODED" , Space , Str "TEXT" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 10)+ [ Plain+ [ Str "All"+ , Space+ , Str "other"+ , Space+ , Str "values"+ , Space+ , Str "are"+ , Space+ , Str "reserved."+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 10)+ [ Plain+ [ Str "NOTE:"+ , Space+ , Str "Usage"+ , Space+ , Str "of"+ , Space+ , Str "this"+ , Space+ , Str "value"+ , Space+ , Str "is"+ , Space+ , Str "described"+ , Space+ , Str "in"+ , Space+ , Str "3GPP\160TS\160\&29.582\160[48]."+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]
@@ -1,189 +1,542 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.30701754385964913)- ,(AlignDefault,ColWidth 0.1364522417153996)- ,(AlignDefault,ColWidth 0.10009746588693957)- ,(AlignDefault,ColWidth 9.707602339181287e-2)- ,(AlignDefault,ColWidth 7.719298245614035e-2)- ,(AlignDefault,ColWidth 7.085769980506823e-2)- ,(AlignDefault,ColWidth 7.09551656920078e-2)- ,(AlignDefault,ColWidth 0.14035087719298245)]- (TableHead ("",[],[])-[Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)- [Plain [Str "A"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)- [Plain [Strong [Str "B"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)- [Plain [Strong [Str "C"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)- [Plain [Strong [Str "D"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 3)- [Plain [Str "E"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 2) (ColSpan 1)- [Plain [Str "F"]]]-,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Strong [Str "G"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Strong [Str "H"]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Strong [Str "I"]]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "1"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "2"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "3"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "4"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "5"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "6"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "7"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "8"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "1"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "2"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "3"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "4"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "5"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "6"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "7"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "8"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "1"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "2"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "3"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "4"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "5"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "6"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "7"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "8"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "1"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "2"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "3"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "4"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "5"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "6"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "7"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "8"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "1"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "2"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "3"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "4"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "5"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "6"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "7"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "8"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "1"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "2"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "3"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "4"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "5"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "6"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "7"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "8"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "1"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "2"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "3"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "4"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "5"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "6"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "7"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "8"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "1"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "2"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "3"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "4"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "5"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "6"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "7"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "8"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "1"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "2"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "3"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "4"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "5"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "6"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "7"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "8"]]]- ])]- (TableFoot ("",[],[])- [])]+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidth 0.30701754385964913 )+ , ( AlignDefault , ColWidth 0.13645224171539963 )+ , ( AlignDefault , ColWidth 0.10009746588693959 )+ , ( AlignDefault , ColWidth 9.707602339181289e-2 )+ , ( AlignDefault , ColWidth 7.719298245614035e-2 )+ , ( AlignDefault , ColWidth 7.085769980506823e-2 )+ , ( AlignDefault , ColWidth 7.09551656920078e-2 )+ , ( AlignDefault , ColWidth 0.14035087719298248 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "A" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Strong [ Str "B" ] ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Strong [ Str "C" ] ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Strong [ Str "D" ] ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 3)+ [ Plain [ Str "E" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain [ Str "F" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Strong [ Str "G" ] ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Strong [ Str "H" ] ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Strong [ Str "I" ] ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "6" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "7" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "8" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "6" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "7" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "8" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "6" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "7" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "8" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "6" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "7" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "8" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "6" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "7" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "8" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "6" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "7" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "8" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "6" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "7" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "8" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "6" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "7" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "8" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "6" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "7" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "8" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]
@@ -1,18 +1,34 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.33302433371958284)- ,(AlignDefault,ColWidth 0.3332560834298957)- ,(AlignDefault,ColWidth 0.33371958285052145)]- (TableHead ("",[],[])- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "One"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Row"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Table"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [])]- (TableFoot ("",[],[])- [])]+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 0.3330243337195829 )+ , ( AlignDefault , ColWidth 0.33325608342989577 )+ , ( AlignDefault , ColWidth 0.33371958285052145 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "One" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Row" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Table" ] ]+ ]+ ])+ [ TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [] ]+ (TableFoot ( "" , [] , [] ) [])+]
@@ -1,18 +1,37 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.3333333333333333)- ,(AlignDefault,ColWidth 0.3333333333333333)- ,(AlignDefault,ColWidth 0.3333333333333333)]- (TableHead ("",[],[])- [])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "One"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Row"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Table"]]]])]- (TableFoot ("",[],[])- [])]+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 0.33333333333333337 )+ , ( AlignDefault , ColWidth 0.33333333333333337 )+ , ( AlignDefault , ColWidth 0.33333333333333337 )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "One" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Row" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Table" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]
@@ -1,40 +1,78 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 2.0096205237840725e-2)- ,(AlignDefault,ColWidth 1.9882415820416888e-2)- ,(AlignDefault,ColWidth 0.22202030999465527)- ,(AlignDefault,ColWidth 0.4761090326028862)- ,(AlignDefault,ColWidth 1.0689470871191876e-4)- ,(AlignDefault,ColWidth 0.26178514163548905)]- (TableHead ("",[],[])- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "h3"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2)- [Plain [Str "h4"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "h5"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 3)- [Plain [Str "c11"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2)- []]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- []- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2)- [Plain [Str "c22"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "c23"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 2)- []]])]- (TableFoot ("",[],[])- [])]+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 1.9673503557974047e-2 )+ , ( AlignDefault , ColWidth 1.946421096693177e-2 )+ , ( AlignDefault , ColWidth 0.21735035579740478 )+ , ( AlignDefault , ColWidth 0.4660946002511511 )+ , ( AlignDefault , ColWidth 1.0464629552113855e-4 )+ , ( AlignDefault , ColWidth 0.25627877773126834 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "h3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "h4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "h5" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 3)+ [ Plain [ Str "c11" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 2) []+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "c22" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "c23" ] ]+ , Cell+ ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 2) []+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]
@@ -1,25 +1,72 @@-[Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.5)- ,(AlignDefault,ColWidth 0.5)]- (TableHead ("",[],[])- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Cell",Space,Str "with",Space,Str "text"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Cell",Space,Str "with",Space,Str "text"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [BulletList- [[Para [Str "Cell",Space,Str "with"]]- ,[Para [Str "A"]]- ,[Para [Str "Bullet",Space,Str "list"]]]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [OrderedList (1,Decimal,Period)- [[Para [Str "Cell",Space,Str "with"]]- ,[Para [Str "A"]]- ,[Para [Str "Numbered",Space,Str "list."]]]]]])]- (TableFoot ("",[],[])- [])]+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 0.5 )+ , ( AlignDefault , ColWidth 0.5 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain+ [ Str "Cell"+ , Space+ , Str "with"+ , Space+ , Str "text"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain+ [ Str "Cell"+ , Space+ , Str "with"+ , Space+ , Str "text"+ ]+ ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ BulletList+ [ [ Para [ Str "Cell" , Space , Str "with" ] ]+ , [ Para [ Str "A" ] ]+ , [ Para [ Str "Bullet" , Space , Str "list" ] ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ OrderedList+ ( 1 , Decimal , Period )+ [ [ Para [ Str "Cell" , Space , Str "with" ] ]+ , [ Para [ Str "A" ] ]+ , [ Para [ Str "Numbered" , Space , Str "list." ] ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]
@@ -1,92 +1,238 @@-[Header 2 ("a-table-with-and-without-a-header-row",[],[]) [Str "A",Space,Str "table,",Space,Str "with",Space,Str "and",Space,Str "without",Space,Str "a",Space,Str "header",Space,Str "row"]-,Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.25)- ,(AlignDefault,ColWidth 0.25)- ,(AlignDefault,ColWidth 0.25)- ,(AlignDefault,ColWidth 0.25)]- (TableHead ("",[],[])- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Name"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Game"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Fame"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Blame"]]]])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Lebron",Space,Str "James"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Basketball"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Very",Space,Str "High"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Leaving",Space,Str "Cleveland"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Ryan",Space,Str "Braun"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Baseball"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Moderate"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Steroids"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Russell",Space,Str "Wilson"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Football"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "High"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Tacky",Space,Str "uniform"]]]])]- (TableFoot ("",[],[])- [])-,Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.5)- ,(AlignDefault,ColWidth 0.5)]- (TableHead ("",[],[])- [])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Sinple"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Table"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Without"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Plain [Str "Header"]]]])]- (TableFoot ("",[],[])- [])-,Table ("",[],[]) (Caption Nothing- [])- [(AlignDefault,ColWidth 0.5)- ,(AlignDefault,ColWidth 0.5)]- (TableHead ("",[],[])- [])- [(TableBody ("",[],[]) (RowHeadColumns 0)- []- [Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Para [Str "Simple"]- ,Para [Str "Multiparagraph"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Para [Str "Table"]- ,Para [Str "Full"]]]- ,Row ("",[],[])- [Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Para [Str "Of"]- ,Para [Str "Paragraphs"]]- ,Cell ("",[],[]) AlignDefault (RowSpan 1) (ColSpan 1)- [Para [Str "In",Space,Str "each"]- ,Para [Str "Cell."]]]])]- (TableFoot ("",[],[])- [])]+[ Header+ 2+ ( "a-table-with-and-without-a-header-row" , [] , [] )+ [ Str "A"+ , Space+ , Str "table,"+ , Space+ , Str "with"+ , Space+ , Str "and"+ , Space+ , Str "without"+ , Space+ , Str "a"+ , Space+ , Str "header"+ , Space+ , Str "row"+ ]+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 0.25 )+ , ( AlignDefault , ColWidth 0.25 )+ , ( AlignDefault , ColWidth 0.25 )+ , ( AlignDefault , ColWidth 0.25 )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Name" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Game" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Fame" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Blame" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Lebron" , Space , Str "James" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Basketball" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Very" , Space , Str "High" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Leaving" , Space , Str "Cleveland" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Ryan" , Space , Str "Braun" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Baseball" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Moderate" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Steroids" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Russell" , Space , Str "Wilson" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Football" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "High" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Tacky" , Space , Str "uniform" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 0.5 )+ , ( AlignDefault , ColWidth 0.5 )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Sinple" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Table" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Without" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Header" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidth 0.5 )+ , ( AlignDefault , ColWidth 0.5 )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Simple" ]+ , Para [ Str "Multiparagraph" ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Table" ] , Para [ Str "Full" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Of" ] , Para [ Str "Paragraphs" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "In" , Space , Str "each" ]+ , Para [ Str "Cell." ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+]
binary file changed (absent → 10749 bytes)
@@ -0,0 +1,40 @@+[ BulletList+ [ [ Para [ Str "\9744" , Space , Str "Unchecked" ] ]+ , [ Para [ Str "\9746" , Space , Str "Checked" ]+ , Para+ [ Str "with"+ , Space+ , Str "continuation"+ , Space+ , Str "paragraph"+ ]+ ]+ , [ Para [ Str "\9744" , Space , Str "Unchecked" ]+ , BulletList+ [ [ Plain+ [ Str "\9746"+ , Space+ , Str "Checked"+ , Space+ , Str "sublist"+ ]+ , BulletList+ [ [ Plain+ [ Str "\9744"+ , Space+ , Str "Unchecked"+ , Space+ , Str "subsublist"+ ]+ , OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain [ Str "Numbered" , Space , Str "child" ]+ ]+ ]+ ]+ ]+ ]+ ]+ ]+ ]+]
binary file changed (absent → 42504 bytes)
@@ -0,0 +1,33 @@+[ Para+ [ Str "Last"+ , Space+ , Str "update:"+ , Space+ , Str "May"+ , Space+ , Str "1,"+ , Space+ , Str "2017"+ ]+, Para+ [ Str "U"+ , Str "sing"+ , Space+ , Str "Microsoft"+ , Space+ , Str "Word"+ , Space+ , Str "2007/2010"+ , LineBreak+ , Str "for"+ , Space+ , Str "Writing"+ , Space+ , Str "Technical"+ , Space+ , Str "Documents"+ ]+, Para [ Str "Valter" , Space , Str "Kiisk" ]+, Para [ Str "Institute" , Space , Str "of" , Space , Str "Physics," , Space , Str "University" , Space , Str "of" , Space , Str "Tartu" ]+, Para []+]
binary file changed (absent → 40379 bytes)
@@ -0,0 +1,30 @@+[ Para+ [ Str "The"+ , Space+ , Str "image"+ , Space+ , Str "is"+ , Space+ , Str "below."+ ]+, Para+ [ Image+ ( ""+ , []+ , [ ( "width" , "4.543038057742782in" )+ , ( "height" , "2.9166666666666665in" )+ ]+ )+ []+ ( "media/image1.png" , "" )+ ]+, Para+ [ Str "The"+ , Space+ , Str "image"+ , Space+ , Str "is"+ , Space+ , Str "above."+ ]+]
binary file changed (absent → 36750 bytes)
@@ -0,0 +1,30 @@+[ Para+ [ Str "The"+ , Space+ , Str "image"+ , Space+ , Str "is"+ , Space+ , Str "below."+ ]+, Para+ [ Image+ ( ""+ , []+ , [ ( "width" , "4.543038057742782in" )+ , ( "height" , "2.9166666666666665in" )+ ]+ )+ []+ ( "media/image1.png" , "" )+ ]+, Para+ [ Str "The"+ , Space+ , Str "image"+ , Space+ , Str "is"+ , Space+ , Str "above."+ ]+]
@@ -6,9 +6,7 @@ , MetaList [ MetaMap (fromList- [ ( "DOI"- , MetaInlines [ Str "10.1002/2016GL069961" ]- )+ [ ( "DOI" , MetaString "10.1002/2016GL069961" ) , ( "author" , MetaList [ MetaMap@@ -54,10 +52,12 @@ ] ) , ( "id" , MetaString "10" )- , ( "issue" , MetaString "18" )+ , ( "issue" , MetaInlines [ Str "18" ] ) , ( "issued" , MetaString "2016" ) , ( "language" , MetaInlines [ Str "en" ] )- , ( "page" , MetaString "9852\8211\&9859" )+ , ( "page"+ , MetaInlines [ Str "9852\8211\&9859" ]+ ) , ( "title" , MetaInlines [ Str "New"@@ -90,21 +90,14 @@ ] ) , ( "type" , MetaString "article-journal" )- , ( "volume" , MetaString "43" )+ , ( "volume" , MetaInlines [ Str "43" ] ) ]) , MetaMap (fromList [ ( "DOI"- , MetaInlines- [ Str "10.1007/s00382-013-1683-2" ]- )- , ( "ISSN"- , MetaInlines- [ Str "0930-7575,"- , Space- , Str "1432-0894"- ]+ , MetaString "10.1007/s00382-013-1683-2" )+ , ( "ISSN" , MetaString "0930-7575, 1432-0894" ) , ( "author" , MetaList [ MetaMap@@ -131,10 +124,12 @@ [ Str "Climate" , Space , Str "Dynamics" ] ) , ( "id" , MetaString "109" )- , ( "issue" , MetaString "11-12" )+ , ( "issue" , MetaInlines [ Str "11-12" ] ) , ( "issued" , MetaString "2013-12" ) , ( "language" , MetaInlines [ Str "en" ] )- , ( "page" , MetaString "3325\8211\&3338" )+ , ( "page"+ , MetaInlines [ Str "3325\8211\&3338" ]+ ) , ( "title" , MetaInlines [ Str "A"@@ -165,12 +160,12 @@ ] ) , ( "type" , MetaString "article-journal" )- , ( "volume" , MetaString "41" )+ , ( "volume" , MetaInlines [ Str "41" ] ) ]) , MetaMap (fromList [ ( "DOI"- , MetaInlines [ Str "10.5194/gmd-9-3751-2016" ]+ , MetaString "10.5194/gmd-9-3751-2016" ) , ( "author" , MetaList@@ -280,7 +275,9 @@ , ( "id" , MetaString "6" ) , ( "issued" , MetaString "2016" ) , ( "language" , MetaInlines [ Str "en" ] )- , ( "page" , MetaString "3751\8211\&3777" )+ , ( "page"+ , MetaInlines [ Str "3751\8211\&3777" ]+ ) , ( "title" , MetaInlines [ Str "The"@@ -297,7 +294,7 @@ ] ) , ( "type" , MetaString "article-journal" )- , ( "volume" , MetaString "9" )+ , ( "volume" , MetaInlines [ Str "9" ] ) ]) ] )@@ -412,7 +409,7 @@ { citationId = "10" , citationPrefix = [ Str "prefix" ] , citationSuffix =- [ Str ",", Space , Str "2" , Space , Str "suffix" ]+ [ Str "," , Space , Str "2" , Space , Str "suffix" ] , citationMode = NormalCitation , citationNoteNum = 0 , citationHash = 0
@@ -1,1686 +1,1721 @@-[ Para [ Span ( "front.xhtml" , [] , [] ) [] ]-, Div- ( "" , [ "section" ] , [] )- [ Header- 1- ( "" , [] , [] )- [ Str "Reflowable"- , Space- , Str "EPUB"- , Space- , Str "3"- , Space- , Str "Conformance"- , Space- , Str "Test"- , Space- , Str "Document:"- , Space- , Str "0100"- ]- , Div- ( "" , [ "section" ] , [] )- [ Header- 2- ( "" , [] , [] )- [ Str "Status"- , Space- , Str "of"- , Space- , Str "this"- , Space- , Str "Document"- ]- , Para- [ Str "This"- , Space- , Str "publication"- , Space- , Str "is"- , Space- , Str "currently"- , Space- , Str "considered"- , Space- , Span- ( "" , [ "status" ] , [] )- [ Str "[UNDER" , Space , Str "DEVELOPMENT]" ]- , Space- , Str "by"- , Space- , Str "the"- , Space- , Str "IDPF."- ]- , Para- [ Str "This"- , Space- , Str "publication"- , Space- , Str "is"- , Space- , Str "part"- , Space- , Str "of"- , Space- , Str "version"- , Space- , Span ( "" , [ "version" ] , [] ) [ Str "X.X" ]- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "EPUB"- , Space- , Str "3.0"- , Space- , Str "Compliance"- , Space- , Str "Test"- , Space- , Str "Suite"- , Space- , Str "released"- , SoftBreak- , Str "on"- , Space- , RawInline (Format "html") "<time class=\"release\">"- , Str "TBD"- , RawInline (Format "html") "</time>"- , Str "."- ]- , Para- [ Str "Before"- , Space- , Str "using"- , Space- , Str "this"- , Space- , Str "publication"- , Space- , Str "to"- , Space- , Str "evaluate"- , Space- , Str "reading"- , Space- , Str "systems,"- , Space- , Str "testers"- , Space- , Str "are"- , Space- , Str "strongly"- , Space- , Str "encouraged"- , Space- , Str "to"- , SoftBreak- , Str "verify"- , Space- , Str "that"- , Space- , Str "they"- , Space- , Str "have"- , Space- , Str "the"- , Space- , Str "latest"- , Space- , Str "release"- , Space- , Str "by"- , Space- , Str "checking"- , Space- , Str "the"- , Space- , Str "current"- , Space- , Str "release"- , Space- , Str "version"- , Space- , Str "and"- , Space- , Str "date"- , Space- , Str "of"- , SoftBreak- , Str "the"- , Space- , Str "test"- , Space- , Str "suite"- , Space- , Str "at"- , Space- , Link- ( "" , [] , [] )- [ Str "TBD" ]- ( "http://idpf.org/" , "" )- ]- , Para- [ Str "This"- , Space- , Str "publication"- , Space- , Str "is"- , Space- , Str "one"- , Space- , Str "of"- , Space- , Str "several"- , Space- , Str "that"- , Space- , Str "currently"- , Space- , Str "comprise"- , Space- , Str "the"- , Space- , Str "EPUB"- , Space- , Str "3"- , Space- , Str "conformance"- , Space- , Str "test"- , Space- , Str "suite"- , SoftBreak- , Str "for"- , Space- , Str "reflowable"- , Space- , Str "content."- , Space- , Str "The"- , Space- , Str "complete"- , Space- , Str "test"- , Space- , Str "suite"- , Space- , Str "includes"- , Space- , Str "all"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "following"- , Space- , Str "publications:"- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "." ] ] ]- ]- , Div- ( "" , [ "section" ] , [] )- [ Header- 2- ( "" , [] , [] )- [ Str "About"- , Space- , Str "this"- , Space- , Str "Document"- ]- , Para- [ Str "This"- , Space- , Str "document"- , Space- , Str "focuses"- , Space- , Str "on"- , Space- , Str "human-evaluated"- , Space- , Str "binary"- , Space- , Str "(pass/fail)"- , Space- , Str "tests"- , Space- , Str "in"- , Space- , Str "a"- , SoftBreak- , Str "reflowable"- , Space- , Str "context."- , Space- , Str "Tests"- , Space- , Str "for"- , Space- , Str "fixed-layout"- , Space- , Str "content"- , Space- , Str "and"- , Space- , Str "other"- , Space- , Str "individual"- , Space- , Str "tests"- , Space- , Str "that"- , SoftBreak- , Str "require"- , Space- , Str "a"- , Space- , Str "dedicated"- , Space- , Str "epub"- , Space- , Str "file"- , Space- , Str "are"- , Space- , Str "available"- , Space- , Str "in"- , Space- , Str "additional"- , Space- , Str "sibling"- , Space- , Str "documents;"- , Space- , Str "refer"- , Space- , Str "to"- , SoftBreak- , Str "the"- , Space- , Link- ( "" , [] , [] )- [ Str "test"- , Space- , Str "suite"- , SoftBreak- , Str "wiki"- ]- ( "https://github.com/mgylling/epub-testsuite/wiki/Overview"- , ""- )- , Space- , Str "("- , Code- ( "" , [] , [] )- "https://github.com/mgylling/epub-testsuite/wiki/Overview"- , Str ")"- , Space- , Str "for"- , Space- , Str "additional"- , SoftBreak- , Str "information."- ]- ]- , Div- ( "" , [ "section" ] , [] )- [ Header 2 ( "" , [] , [] ) [ Str "Conventions" ]- , Para- [ Str "The"- , Space- , Str "following"- , Space- , Str "conventions"- , Space- , Str "are"- , Space- , Str "used"- , Space- , Str "throughout"- , Space- , Str "the"- , Space- , Str "document:"- ]- , DefinitionList- [ ( [ Str "1."- , Space- , Str "Locating"- , Space- , Str "a"- , Space- , Str "test"- ]- , [ [ Div- ( "" , [ "ctest" ] , [] )- [ Para- [ Str "Tests"- , Space- , Str "for"- , Space- , Emph [ Str "required" ]- , Space- , Str "Reading"- , Space- , Str "System"- , Space- , Str "functionality"- , Space- , Str "are"- , SoftBreak- , Str "preceded"- , Space- , Str "by"- , Space- , Str "the"- , Space- , Str "label:"- , Space- , Span- ( ""- , [ "nature" ]- , [ ( "style"- , "display: inline; font-size: 100%"- )- ]- )- [ Str "[REQUIRED]" ]- ]- ]- , Div- ( "" , [ "otest" ] , [] )- [ Para- [ Str "Tests"- , Space- , Str "for"- , Space- , Emph [ Str "optional" ]- , Space- , Str "Reading"- , Space- , Str "System"- , Space- , Str "functionality"- , Space- , Str "are"- , SoftBreak- , Str "preceded"- , Space- , Str "by"- , Space- , Str "the"- , Space- , Str "label:"- , Space- , Span- ( ""- , [ "nature" ]- , [ ( "style"- , "display: inline; font-size: 100%"- )- ]- )- [ Str "[OPTIONAL]" ]- ]- ]- ]- ]- )- , ( [ Str "2."- , Space- , Str "Performing"- , Space- , Str "the"- , Space- , Str "test"- ]- , [ [ Plain- [ Str "Each"- , Space- , Str "test"- , Space- , Str "includes"- , Space- , Str "a"- , Space- , Str "description"- , Space- , Str "of"- , Space- , Str "its"- , Space- , Str "purpose"- , Space- , Str "followed"- , Space- , Str "by"- , Space- , Str "the"- , Space- , Str "actual"- , Space- , Strong- [ Str "test"- , Space- , Str "statement,"- , SoftBreak- , Str "which"- , Space- , Str "can"- , Space- , Str "always"- , Space- , Str "be"- , Space- , Str "evaluated"- , Space- , Str "to"- , Space- , Str "true"- , Space- , Str "or"- , Space- , Str "false"- ]- , Str "."- , Space- , Str "These"- , Space- , Str "statements"- , Space- , Str "typically"- , Space- , Str "have"- , Space- , Str "the"- , Space- , Str "form:"- , SoftBreak- , Str "\"If"- , Space- , Str "[some"- , Space- , Str "condition],"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes\"."- ]- ]- ]- )- , ( [ Str "3."- , Space- , Str "Scoring"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "results"- , Space- , Str "form"- ]- , [ [ Plain- [ Str "@@@TODO"- , Space- , Str "provide"- , Space- , Str "info"- , Space- , Str "on"- , Space- , Str "where"- , Space- , Str "to"- , Space- , Str "get"- , Space- , Str "the"- , Space- , Str "results"- , Space- , Str "form"- ]- ]- ]- )- ]- ]- ]-, Para [ Span ( "content-mathml-001.xhtml" , [] , [] ) [] ]-, Div- ( "" , [ "section" ] , [] )- [ Header- 2- ( "content-mathml-001.xhtml#mathml" , [] , [] )- [ Str "MathML" ]- , Div- ( "content-mathml-001.xhtml#mathml-010"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , SoftBreak- , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-010" ]- , Space- , Str "Rendering"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "MathML"- , Space- , Str "equation"- , Space- , Str "rendering"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Plain- [ Math- DisplayMath- "\\int_{- \\infty}^{\\infty}e^{- x^{2}}\\, dx = \\sqrt{\\pi}"- , SoftBreak- , Math- DisplayMath- "\\sum\\limits_{n = 1}^{\\infty}\\frac{1}{n^{2}} = \\frac{\\pi^{2}}{6}"- , SoftBreak- , Math- DisplayMath- "x = \\frac{- b \\pm \\sqrt{b^{2} - 4ac}}{2a}"- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "equations"- , Space- , Str "are"- , Space- , Str "not"- , Space- , Str "presented"- , Space- , Str "as"- , Space- , Str "linear"- , Space- , Str "text"- , Space- , Str "(e.g.,"- , Space- , Str "x=-b\177b2-4ac2a),"- , SoftBreak- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "content-mathml-001.xhtml#mathml-020"- , [ "section" , "otest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[OPTIONAL]" ]- , SoftBreak- , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-020" ]- , Space- , Str "CSS"- , Space- , Str "Styling"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "math"- , Space- , Str "element"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "basic"- , Space- , Str "CSS"- , Space- , Str "styling"- , Space- , Str "of"- , Space- , Str "MathML"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "math"- , Space- , Str "element."- ]- , Plain [ Math InlineMath "{2x}{+ y - z}" ]- , Para- [ Str "The"- , Space- , Str "test"- , Space- , Str "passes"- , Space- , Str "if"- , Space- , Str "the"- , Space- , Str "equation"- , Space- , Str "has"- , Space- , Str "a"- , Space- , Str "yellow"- , Space- , Str "background"- , Space- , Str "and"- , Space- , Str "a"- , Space- , Str "dashed"- , Space- , Str "border."- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "reading"- , Space- , Str "system"- , Space- , Str "does"- , Space- , Str "not"- , Space- , Str "have"- , Space- , Str "a"- , Space- , Str "viewport,"- , Space- , Str "or"- , Space- , Str "does"- , Space- , Str "not"- , Space- , Str "support"- , SoftBreak- , Str "CSS"- , Space- , Str "styles,"- , Space- , Str "this"- , Space- , Str "test"- , Space- , Str "should"- , Space- , Str "be"- , Space- , Str "marked"- , Space- , Code ( "" , [] , [] ) "Not Supported"- , Str "."- ]- ]- , Div- ( "content-mathml-001.xhtml#mathml-021"- , [ "section" , "otest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[OPTIONAL]" ]- , SoftBreak- , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-021" ]- , Space- , Str "CSS"- , Space- , Str "Styling"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "mo"- , Space- , Str "element"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "basic"- , Space- , Str "CSS"- , Space- , Str "styling"- , Space- , Str "of"- , Space- , Str "MathML"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "mo"- , Space- , Str "element."- ]- , Plain [ Math InlineMath "{2x}{+ y - z}" ]- , Para- [ Str "The"- , Space- , Str "test"- , Space- , Str "passes"- , Space- , Str "if"- , Space- , Str "the"- , Space- , Str "operators"- , Space- , Str "are"- , Space- , Str "enlarged"- , Space- , Str "relative"- , Space- , Str "to"- , Space- , Str "the"- , Space- , Str "other"- , Space- , Str "symbols"- , Space- , Str "and"- , Space- , Str "numbers."- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "reading"- , Space- , Str "system"- , Space- , Str "does"- , Space- , Str "not"- , Space- , Str "have"- , Space- , Str "a"- , Space- , Str "viewport,"- , Space- , Str "or"- , Space- , Str "does"- , Space- , Str "not"- , Space- , Str "support"- , SoftBreak- , Str "CSS"- , Space- , Str "styles,"- , Space- , Str "this"- , Space- , Str "test"- , Space- , Str "should"- , Space- , Str "be"- , Space- , Str "marked"- , Space- , Code ( "" , [] , [] ) "Not Supported"- , Str "."- ]- ]- , Div- ( "content-mathml-001.xhtml#mathml-022"- , [ "section" , "otest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[OPTIONAL]" ]- , SoftBreak- , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-022" ]- , Space- , Str "CSS"- , Space- , Str "Styling"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "mi"- , Space- , Str "element"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "basic"- , Space- , Str "CSS"- , Space- , Str "styling"- , Space- , Str "of"- , Space- , Str "MathML"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "mi"- , Space- , Str "element."- ]- , Plain [ Math InlineMath "{2x}{+ y - z}" ]- , Para- [ Str "The"- , Space- , Str "test"- , Space- , Str "passes"- , Space- , Str "if"- , Space- , Str "the"- , Space- , Str "identifiers"- , Space- , Str "are"- , Space- , Str "bolded"- , Space- , Str "and"- , Space- , Str "blue."- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "reading"- , Space- , Str "system"- , Space- , Str "does"- , Space- , Str "not"- , Space- , Str "have"- , Space- , Str "a"- , Space- , Str "viewport,"- , Space- , Str "or"- , Space- , Str "does"- , Space- , Str "not"- , Space- , Str "support"- , SoftBreak- , Str "CSS"- , Space- , Str "styles,"- , Space- , Str "this"- , Space- , Str "test"- , Space- , Str "should"- , Space- , Str "be"- , Space- , Str "marked"- , Space- , Code ( "" , [] , [] ) "Not Supported"- , Str "."- ]- ]- , Div- ( "content-mathml-001.xhtml#mathml-023"- , [ "section" , "otest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[OPTIONAL]" ]- , SoftBreak- , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-023" ]- , Space- , Str "CSS"- , Space- , Str "Styling"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "mn"- , Space- , Str "element"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "basic"- , Space- , Str "CSS"- , Space- , Str "styling"- , Space- , Str "of"- , Space- , Str "MathML"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "mn"- , Space- , Str "element."- ]- , Plain [ Math InlineMath "{2x}{+ y - z}" ]- , Para- [ Str "The"- , Space- , Str "test"- , Space- , Str "passes"- , Space- , Str "if"- , Space- , Str "the"- , Space- , Str "number"- , Space- , Str "2"- , Space- , Str "is"- , Space- , Str "italicized"- , Space- , Str "and"- , Space- , Str "blue."- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "reading"- , Space- , Str "system"- , Space- , Str "does"- , Space- , Str "not"- , Space- , Str "have"- , Space- , Str "a"- , Space- , Str "viewport,"- , Space- , Str "or"- , Space- , Str "does"- , Space- , Str "not"- , Space- , Str "support"- , SoftBreak- , Str "CSS"- , Space- , Str "styles,"- , Space- , Str "this"- , Space- , Str "test"- , Space- , Str "should"- , Space- , Str "be"- , Space- , Str "marked"- , Space- , Code ( "" , [] , [] ) "Not Supported"- , Str "."- ]- ]- , Div- ( "content-mathml-001.xhtml#mathml-024"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , SoftBreak- , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-024" ]- , Str "Horizontal"- , Space- , Str "stretch,"- , Space- , Code ( "" , [] , [] ) "mover"- , Str ","- , Space- , Code ( "" , [] , [] ) "munder"- , Str ","- , Space- , Str "and"- , Space- , Code ( "" , [] , [] ) "mspace"- , Space- , Str "elements"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "horizontal"- , Space- , Str "stretch,"- , Space- , Code ( "" , [] , [] ) "mover"- , Str ","- , Space- , Code ( "" , [] , [] ) "munder"- , Str ","- , Space- , Code ( "" , [] , [] ) "mspace"- , Space- , Str "elements"- , Space- , Str "are"- , Space- , Str "supported."- ]- , Plain- [ Math- DisplayMath- "c = \\overset{\\text{complex\\ number}}{\\overbrace{\\underset{\\text{real}}{\\underbrace{\\mspace{20mu} a\\mspace{20mu}}} + \\underset{\\text{imaginary}}{\\underbrace{\\quad b{\\mathbb{i}}\\quad}}}}"- ]- , Para- [ Str "The"- , Space- , Str "test"- , Space- , Str "passes"- , Space- , Str "if"- , Space- , Str "the"- , Space- , Str "rendering"- , Space- , Str "looks"- , Space- , Str "like"- , Space- , Str "."- ]- ]- , Div- ( "content-mathml-001.xhtml#mathml-025"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , SoftBreak- , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-025" ]- , Str "Testing"- , Space- , Code ( "" , [] , [] ) "mtable"- , Space- , Str "with"- , Space- , Code ( "" , [] , [] ) "colspan"- , Space- , Str "and"- , Space- , Code ( "" , [] , [] ) "rowspan"- , Space- , Str "attributes,"- , Space- , Str "Hebrew"- , Space- , Str "and"- , Space- , Str "Script"- , Space- , Str "fonts"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Code ( "" , [] , [] ) "mtable"- , Space- , Str "with"- , Space- , Code ( "" , [] , [] ) "colspan"- , Space- , Str "and"- , Space- , Code ( "" , [] , [] ) "mspace"- , Space- , Str "attributes"- , Space- , Str "(column"- , Space- , Str "and"- , Space- , Str "row"- , Space- , Str "spanning)"- , Space- , Str "are"- , Space- , Str "supported;"- , Space- , Str "uses"- , Space- , Str "Hebrew"- , Space- , Str "and"- , Space- , Str "Script"- , Space- , Str "alphabets."- ]- , Plain- [ Math- DisplayMath- "\\begin{matrix}\n & {\\operatorname{cov}(\\mathcal{L})} & \\longrightarrow & {\\operatorname{non}(\\mathcal{K})} & \\longrightarrow & {\\operatorname{cof}(\\mathcal{K})} & \\longrightarrow & {\\operatorname{cof}(\\mathcal{L})} & \\longrightarrow & 2^{\\aleph_{0}} \\\\\n & \\uparrow & & \\uparrow & & \\uparrow & & \\uparrow & & \\\\\n & {\\mathfrak{b}} & \\longrightarrow & {\\mathfrak{d}} & & & & & & \\\\\n & \\uparrow & & \\uparrow & & & & & & \\\\\n\\aleph_{1} & \\longrightarrow & {\\operatorname{add}(\\mathcal{L})} & \\longrightarrow & {\\operatorname{add}(\\mathcal{K})} & \\longrightarrow & {\\operatorname{cov}(\\mathcal{K})} & \\longrightarrow & {\\operatorname{non}(\\mathcal{L})} & \\\\\n\\end{matrix}"- ]- , Para- [ Str "The"- , Space- , Str "test"- , Space- , Str "passes"- , Space- , Str "if"- , Space- , Str "the"- , Space- , Str "rendering"- , Space- , Str "looks"- , Space- , Str "like"- , Space- , Link- ( "" , [] , [] )- [ Str "Cicho\324's" , Space , Str "Diagram" ]- ( "http://en.wikipedia.org/wiki/Cicho%C5%84's_diagram"- , ""- )- , Str ":"- , Space- , Str "."- ]- ]- , Div- ( "content-mathml-001.xhtml#mathml-026"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , SoftBreak- , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-026" ]- , Str "BiDi,"- , Space- , Str "RTL"- , Space- , Str "and"- , Space- , Str "Arabic"- , Space- , Str "alphabets"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "right-to-left"- , Space- , Str "and"- , Space- , Str "Arabic"- , Space- , Str "alphabets"- , Space- , Str "are"- , Space- , Str "supported."- ]- , Plain- [ Math- DisplayMath- "{\1583(\1587)} = \\left\\{ \\begin{matrix}\n{\\sum\\limits_{\1646 = 1}^{\1589}\1587^{\1646}} & {\\text{\1573\1584\1575\1603\1575\1606}\1587 > 0} \\\\\n{\\int_{1}^{\1589}{\1587^{\1646}\1569\1587}} & {\\text{\1573\1584\1575\1603\1575\1606}\1587 \\in \1605} \\\\\n{{\1591\1575}\\pi} & {\\text{\1594\1610\1585\1584\1604\1603}\\left( \\text{\1605\1593}\\pi \\simeq 3,141 \\right)} \\\\\n\\end{matrix} \\right."- ]- , Para- [ Str "The"- , Space- , Str "test"- , Space- , Str "passes"- , Space- , Str "if"- , Space- , Str "the"- , Space- , Str "rendering"- , Space- , Str "looks"- , Space- , Str "like"- , Space- , Str "the"- , Space- , Str "following"- , Space- , Str "image:"- ]- ]- , Div- ( "content-mathml-001.xhtml#mathml-027"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , SoftBreak- , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-027" ]- , Str "Elementary"- , Space- , Str "math:"- , Space- , Str "long"- , Space- , Str "division"- , Space- , Str "notation"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Code ( "" , [] , [] ) "mlongdiv"- , Space- , Str "elements"- , Space- , Str "(from"- , Space- , Str "elementary"- , Space- , Str "math)"- , Space- , Str "are"- , Space- , Str "supported."- ]- , Plain- [ Span- ( ""- , [ "math" ]- , [ ( "xmlns" , "http://www.w3.org/1998/Math/MathML" ) ]- )- [ SoftBreak- , Str "3"- , SoftBreak- , Str "435.3"- , SoftBreak- , Str "1306"- , SoftBreak- , Str "12"- , SoftBreak- , Str "10"- , SoftBreak- , Str "9"- , SoftBreak- , Str "16"- , SoftBreak- , Str "15"- , SoftBreak- , Str "1.0"- , SoftBreak- , Str "9"- , SoftBreak- , Str "1"- , SoftBreak- ]- ]- , Para- [ Str "The"- , Space- , Str "test"- , Space- , Str "passes"- , Space- , Str "if"- , Space- , Str "the"- , Space- , Str "rendering"- , Space- , Str "looks"- , Space- , Str "like"- , Space- , Str "the"- , Space- , Str "following"- , Space- , Str "image:"- , Space- , Str "."- ]- ]- ]-, Para [ Span ( "content-switch-001.xhtml" , [] , [] ) [] ]-, Div- ( "content-switch-001.xhtml#epub-switch"- , [ "section" ]- , []- )- [ Header- 3 ( "" , [] , [] ) [ Code ( "" , [] , [] ) "epub:switch" ]- , Div- ( "content-switch-001.xhtml#switch-010"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "switch-010" ]- , Space- , Str "Support"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Link- ( "" , [] , [] )- [ Code ( "" , [] , [] ) "epub:switch" ]- ( "http://idpf.org/epub/30/spec/epub30-contentdocs.html#sec-xhtml-content-switch"- , ""- )- , Space- , Str "element"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para [ Str "PASS" ]- , Para- [ Str "If"- , Space- , Str "only"- , Space- , Str "the"- , Space- , Str "word"- , Space- , Str "\"PASS\""- , Space- , Str "is"- , Space- , Str "rendered"- , Space- , Str "before"- , Space- , Str "this"- , Space- , Str "paragraph,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- , Space- , Str "If"- , Space- , Str "both"- , Space- , Str "\"PASS\""- , Space- , Str "and"- , Space- , Str "\"FAIL\""- , Space- , Str "are"- , Space- , Str "rendered,"- , Space- , Str "or"- , Space- , Str "neither"- , SoftBreak- , Str "\"PASS\""- , Space- , Str "nor"- , Space- , Str "\"FAIL\""- , Space- , Str "is"- , Space- , Str "rendered,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "fails."- ]- ]- , Div- ( "content-switch-001.xhtml#switch-020"- , [ "section" , "otest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[OPTIONAL]" ]- , SoftBreak- , Span ( "" , [ "test-id" ] , [] ) [ Str "switch-020" ]- , SoftBreak- , Str "MathML"- , Space- , Str "Embedding"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Str "MathML"- , Space- , Str "namespace"- , Space- , Str "is"- , Space- , Str "recognized"- , Space- , Str "when"- , Space- , Str "used"- , Space- , Str "in"- , Space- , Str "an"- , Space- , Link- ( "" , [] , [] )- [ Code ( "" , [] , [] ) "epub:case" ]- ( "http://idpf.org/epub/30/spec/epub30-contentdocs.html#sec-xhtml-epub-case"- , ""- )- , Space- , Str "element."- ]- , Para [ Math InlineMath "{2x}{+ y - z}" ]- , Para- [ Str "If"- , Space- , Str "a"- , Space- , Str "MathML"- , Space- , Str "equation"- , Space- , Str "is"- , Space- , Str "rendered"- , Space- , Str "before"- , Space- , Str "this"- , Space- , Str "paragraph,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- , Para- [ Str "If"- , Space- , Str "test"- , Space- , Code ( "" , [] , [] ) "switch-010"- , Space- , Str "did"- , Space- , Str "not"- , Space- , Str "pass,"- , Space- , Str "this"- , Space- , Str "test"- , Space- , Str "should"- , Space- , Str "be"- , Space- , Str "marked"- , Space- , Code ( "" , [] , [] ) "Not Supported"- , Str "."- ]- ]- ]-]+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "author"+ , MetaList+ [ MetaInlines [ Str "Ori Idan" ]+ , MetaInlines [ Str "Matt Garrish" ]+ , MetaInlines [ Str "Marisa DeMeglio" ]+ , MetaInlines [ Str "Toshiaki Koike" ]+ , MetaInlines [ Str "Vincent Gros" ]+ , MetaInlines [ Str "Markus Gylling" ]+ ]+ )+ , ( "description"+ , MetaInlines+ [ Str+ "Tests for Content Documents in a reflowable context [UNDER CONSTRUCTION]"+ ]+ )+ , ( "identifier"+ , MetaInlines+ [ Str "com.github.epub-testsuite.epub30-test-0100" ]+ )+ , ( "language"+ , MetaList+ [ MetaInlines [ Str "jp" ] , MetaInlines [ Str "en" ] ]+ )+ , ( "title"+ , MetaInlines+ [ Str "EPUBTEST 0100 - Reflowable Content Tests" ]+ )+ ]+ }+ [ Para [ Span ( "front.xhtml" , [] , [] ) [] ]+ , Div+ ( "" , [ "section" ] , [] )+ [ Header+ 1+ ( "" , [] , [] )+ [ Str "Reflowable"+ , Space+ , Str "EPUB"+ , Space+ , Str "3"+ , Space+ , Str "Conformance"+ , Space+ , Str "Test"+ , Space+ , Str "Document:"+ , Space+ , Str "0100"+ ]+ , Div+ ( "" , [ "section" ] , [] )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "Status"+ , Space+ , Str "of"+ , Space+ , Str "this"+ , Space+ , Str "Document"+ ]+ , Para+ [ Str "This"+ , Space+ , Str "publication"+ , Space+ , Str "is"+ , Space+ , Str "currently"+ , Space+ , Str "considered"+ , Space+ , Span+ ( "" , [ "status" ] , [] )+ [ Str "[UNDER" , Space , Str "DEVELOPMENT]" ]+ , Space+ , Str "by"+ , Space+ , Str "the"+ , Space+ , Str "IDPF."+ ]+ , Para+ [ Str "This"+ , Space+ , Str "publication"+ , Space+ , Str "is"+ , Space+ , Str "part"+ , Space+ , Str "of"+ , Space+ , Str "version"+ , Space+ , Span ( "" , [ "version" ] , [] ) [ Str "X.X" ]+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "EPUB"+ , Space+ , Str "3.0"+ , Space+ , Str "Compliance"+ , Space+ , Str "Test"+ , Space+ , Str "Suite"+ , Space+ , Str "released"+ , SoftBreak+ , Str "on"+ , Space+ , RawInline (Format "html") "<time class=\"release\">"+ , Str "TBD"+ , RawInline (Format "html") "</time>"+ , Str "."+ ]+ , Para+ [ Str "Before"+ , Space+ , Str "using"+ , Space+ , Str "this"+ , Space+ , Str "publication"+ , Space+ , Str "to"+ , Space+ , Str "evaluate"+ , Space+ , Str "reading"+ , Space+ , Str "systems,"+ , Space+ , Str "testers"+ , Space+ , Str "are"+ , Space+ , Str "strongly"+ , Space+ , Str "encouraged"+ , Space+ , Str "to"+ , SoftBreak+ , Str "verify"+ , Space+ , Str "that"+ , Space+ , Str "they"+ , Space+ , Str "have"+ , Space+ , Str "the"+ , Space+ , Str "latest"+ , Space+ , Str "release"+ , Space+ , Str "by"+ , Space+ , Str "checking"+ , Space+ , Str "the"+ , Space+ , Str "current"+ , Space+ , Str "release"+ , Space+ , Str "version"+ , Space+ , Str "and"+ , Space+ , Str "date"+ , Space+ , Str "of"+ , SoftBreak+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "suite"+ , Space+ , Str "at"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "TBD" ]+ ( "http://idpf.org/" , "" )+ ]+ , Para+ [ Str "This"+ , Space+ , Str "publication"+ , Space+ , Str "is"+ , Space+ , Str "one"+ , Space+ , Str "of"+ , Space+ , Str "several"+ , Space+ , Str "that"+ , Space+ , Str "currently"+ , Space+ , Str "comprise"+ , Space+ , Str "the"+ , Space+ , Str "EPUB"+ , Space+ , Str "3"+ , Space+ , Str "conformance"+ , Space+ , Str "test"+ , Space+ , Str "suite"+ , SoftBreak+ , Str "for"+ , Space+ , Str "reflowable"+ , Space+ , Str "content."+ , Space+ , Str "The"+ , Space+ , Str "complete"+ , Space+ , Str "test"+ , Space+ , Str "suite"+ , Space+ , Str "includes"+ , Space+ , Str "all"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "following"+ , Space+ , Str "publications:"+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "." ] ] ]+ ]+ , Div+ ( "" , [ "section" ] , [] )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "About"+ , Space+ , Str "this"+ , Space+ , Str "Document"+ ]+ , Para+ [ Str "This"+ , Space+ , Str "document"+ , Space+ , Str "focuses"+ , Space+ , Str "on"+ , Space+ , Str "human-evaluated"+ , Space+ , Str "binary"+ , Space+ , Str "(pass/fail)"+ , Space+ , Str "tests"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , SoftBreak+ , Str "reflowable"+ , Space+ , Str "context."+ , Space+ , Str "Tests"+ , Space+ , Str "for"+ , Space+ , Str "fixed-layout"+ , Space+ , Str "content"+ , Space+ , Str "and"+ , Space+ , Str "other"+ , Space+ , Str "individual"+ , Space+ , Str "tests"+ , Space+ , Str "that"+ , SoftBreak+ , Str "require"+ , Space+ , Str "a"+ , Space+ , Str "dedicated"+ , Space+ , Str "epub"+ , Space+ , Str "file"+ , Space+ , Str "are"+ , Space+ , Str "available"+ , Space+ , Str "in"+ , Space+ , Str "additional"+ , Space+ , Str "sibling"+ , Space+ , Str "documents;"+ , Space+ , Str "refer"+ , Space+ , Str "to"+ , SoftBreak+ , Str "the"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "test"+ , Space+ , Str "suite"+ , SoftBreak+ , Str "wiki"+ ]+ ( "https://github.com/mgylling/epub-testsuite/wiki/Overview"+ , ""+ )+ , Space+ , Str "("+ , Code+ ( "" , [] , [] )+ "https://github.com/mgylling/epub-testsuite/wiki/Overview"+ , Str ")"+ , Space+ , Str "for"+ , Space+ , Str "additional"+ , SoftBreak+ , Str "information."+ ]+ ]+ , Div+ ( "" , [ "section" ] , [] )+ [ Header 2 ( "" , [] , [] ) [ Str "Conventions" ]+ , Para+ [ Str "The"+ , Space+ , Str "following"+ , Space+ , Str "conventions"+ , Space+ , Str "are"+ , Space+ , Str "used"+ , Space+ , Str "throughout"+ , Space+ , Str "the"+ , Space+ , Str "document:"+ ]+ , DefinitionList+ [ ( [ Str "1."+ , Space+ , Str "Locating"+ , Space+ , Str "a"+ , Space+ , Str "test"+ ]+ , [ [ Div+ ( "" , [ "ctest" ] , [] )+ [ Para+ [ Str "Tests"+ , Space+ , Str "for"+ , Space+ , Emph [ Str "required" ]+ , Space+ , Str "Reading"+ , Space+ , Str "System"+ , Space+ , Str "functionality"+ , Space+ , Str "are"+ , SoftBreak+ , Str "preceded"+ , Space+ , Str "by"+ , Space+ , Str "the"+ , Space+ , Str "label:"+ , Space+ , Span+ ( ""+ , [ "nature" ]+ , [ ( "style"+ , "display: inline; font-size: 100%"+ )+ ]+ )+ [ Str "[REQUIRED]" ]+ ]+ ]+ , Div+ ( "" , [ "otest" ] , [] )+ [ Para+ [ Str "Tests"+ , Space+ , Str "for"+ , Space+ , Emph [ Str "optional" ]+ , Space+ , Str "Reading"+ , Space+ , Str "System"+ , Space+ , Str "functionality"+ , Space+ , Str "are"+ , SoftBreak+ , Str "preceded"+ , Space+ , Str "by"+ , Space+ , Str "the"+ , Space+ , Str "label:"+ , Space+ , Span+ ( ""+ , [ "nature" ]+ , [ ( "style"+ , "display: inline; font-size: 100%"+ )+ ]+ )+ [ Str "[OPTIONAL]" ]+ ]+ ]+ ]+ ]+ )+ , ( [ Str "2."+ , Space+ , Str "Performing"+ , Space+ , Str "the"+ , Space+ , Str "test"+ ]+ , [ [ Plain+ [ Str "Each"+ , Space+ , Str "test"+ , Space+ , Str "includes"+ , Space+ , Str "a"+ , Space+ , Str "description"+ , Space+ , Str "of"+ , Space+ , Str "its"+ , Space+ , Str "purpose"+ , Space+ , Str "followed"+ , Space+ , Str "by"+ , Space+ , Str "the"+ , Space+ , Str "actual"+ , Space+ , Strong+ [ Str "test"+ , Space+ , Str "statement,"+ , SoftBreak+ , Str "which"+ , Space+ , Str "can"+ , Space+ , Str "always"+ , Space+ , Str "be"+ , Space+ , Str "evaluated"+ , Space+ , Str "to"+ , Space+ , Str "true"+ , Space+ , Str "or"+ , Space+ , Str "false"+ ]+ , Str "."+ , Space+ , Str "These"+ , Space+ , Str "statements"+ , Space+ , Str "typically"+ , Space+ , Str "have"+ , Space+ , Str "the"+ , Space+ , Str "form:"+ , SoftBreak+ , Str "\"If"+ , Space+ , Str "[some"+ , Space+ , Str "condition],"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes\"."+ ]+ ]+ ]+ )+ , ( [ Str "3."+ , Space+ , Str "Scoring"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "results"+ , Space+ , Str "form"+ ]+ , [ [ Plain+ [ Str "@@@TODO"+ , Space+ , Str "provide"+ , Space+ , Str "info"+ , Space+ , Str "on"+ , Space+ , Str "where"+ , Space+ , Str "to"+ , Space+ , Str "get"+ , Space+ , Str "the"+ , Space+ , Str "results"+ , Space+ , Str "form"+ ]+ ]+ ]+ )+ ]+ ]+ ]+ , Para [ Span ( "content-mathml-001.xhtml" , [] , [] ) [] ]+ , Div+ ( "" , [ "section" ] , [] )+ [ Header+ 2+ ( "content-mathml-001.xhtml_mathml" , [] , [] )+ [ Str "MathML" ]+ , Div+ ( "content-mathml-001.xhtml_mathml-010"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , SoftBreak+ , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-010" ]+ , Space+ , Str "Rendering"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "MathML"+ , Space+ , Str "equation"+ , Space+ , Str "rendering"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Plain+ [ Math+ DisplayMath+ "\\int_{- \\infty}^{\\infty}e^{- x^{2}}\\, dx = \\sqrt{\\pi}"+ , SoftBreak+ , Math+ DisplayMath+ "\\sum\\limits_{n = 1}^{\\infty}\\frac{1}{n^{2}} = \\frac{\\pi^{2}}{6}"+ , SoftBreak+ , Math+ DisplayMath+ "x = \\frac{- b \\pm \\sqrt{b^{2} - 4ac}}{2a}"+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "equations"+ , Space+ , Str "are"+ , Space+ , Str "not"+ , Space+ , Str "presented"+ , Space+ , Str "as"+ , Space+ , Str "linear"+ , Space+ , Str "text"+ , Space+ , Str "(e.g.,"+ , Space+ , Str "x=-b\177b2-4ac2a),"+ , SoftBreak+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "content-mathml-001.xhtml_mathml-020"+ , [ "section" , "otest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[OPTIONAL]" ]+ , SoftBreak+ , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-020" ]+ , Space+ , Str "CSS"+ , Space+ , Str "Styling"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "math"+ , Space+ , Str "element"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "basic"+ , Space+ , Str "CSS"+ , Space+ , Str "styling"+ , Space+ , Str "of"+ , Space+ , Str "MathML"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "math"+ , Space+ , Str "element."+ ]+ , Plain [ Math InlineMath "{2x}{+ y - z}" ]+ , Para+ [ Str "The"+ , Space+ , Str "test"+ , Space+ , Str "passes"+ , Space+ , Str "if"+ , Space+ , Str "the"+ , Space+ , Str "equation"+ , Space+ , Str "has"+ , Space+ , Str "a"+ , Space+ , Str "yellow"+ , Space+ , Str "background"+ , Space+ , Str "and"+ , Space+ , Str "a"+ , Space+ , Str "dashed"+ , Space+ , Str "border."+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "reading"+ , Space+ , Str "system"+ , Space+ , Str "does"+ , Space+ , Str "not"+ , Space+ , Str "have"+ , Space+ , Str "a"+ , Space+ , Str "viewport,"+ , Space+ , Str "or"+ , Space+ , Str "does"+ , Space+ , Str "not"+ , Space+ , Str "support"+ , SoftBreak+ , Str "CSS"+ , Space+ , Str "styles,"+ , Space+ , Str "this"+ , Space+ , Str "test"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "marked"+ , Space+ , Code ( "" , [] , [] ) "Not Supported"+ , Str "."+ ]+ ]+ , Div+ ( "content-mathml-001.xhtml_mathml-021"+ , [ "section" , "otest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[OPTIONAL]" ]+ , SoftBreak+ , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-021" ]+ , Space+ , Str "CSS"+ , Space+ , Str "Styling"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "mo"+ , Space+ , Str "element"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "basic"+ , Space+ , Str "CSS"+ , Space+ , Str "styling"+ , Space+ , Str "of"+ , Space+ , Str "MathML"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "mo"+ , Space+ , Str "element."+ ]+ , Plain [ Math InlineMath "{2x}{+ y - z}" ]+ , Para+ [ Str "The"+ , Space+ , Str "test"+ , Space+ , Str "passes"+ , Space+ , Str "if"+ , Space+ , Str "the"+ , Space+ , Str "operators"+ , Space+ , Str "are"+ , Space+ , Str "enlarged"+ , Space+ , Str "relative"+ , Space+ , Str "to"+ , Space+ , Str "the"+ , Space+ , Str "other"+ , Space+ , Str "symbols"+ , Space+ , Str "and"+ , Space+ , Str "numbers."+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "reading"+ , Space+ , Str "system"+ , Space+ , Str "does"+ , Space+ , Str "not"+ , Space+ , Str "have"+ , Space+ , Str "a"+ , Space+ , Str "viewport,"+ , Space+ , Str "or"+ , Space+ , Str "does"+ , Space+ , Str "not"+ , Space+ , Str "support"+ , SoftBreak+ , Str "CSS"+ , Space+ , Str "styles,"+ , Space+ , Str "this"+ , Space+ , Str "test"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "marked"+ , Space+ , Code ( "" , [] , [] ) "Not Supported"+ , Str "."+ ]+ ]+ , Div+ ( "content-mathml-001.xhtml_mathml-022"+ , [ "section" , "otest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[OPTIONAL]" ]+ , SoftBreak+ , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-022" ]+ , Space+ , Str "CSS"+ , Space+ , Str "Styling"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "mi"+ , Space+ , Str "element"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "basic"+ , Space+ , Str "CSS"+ , Space+ , Str "styling"+ , Space+ , Str "of"+ , Space+ , Str "MathML"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "mi"+ , Space+ , Str "element."+ ]+ , Plain [ Math InlineMath "{2x}{+ y - z}" ]+ , Para+ [ Str "The"+ , Space+ , Str "test"+ , Space+ , Str "passes"+ , Space+ , Str "if"+ , Space+ , Str "the"+ , Space+ , Str "identifiers"+ , Space+ , Str "are"+ , Space+ , Str "bolded"+ , Space+ , Str "and"+ , Space+ , Str "blue."+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "reading"+ , Space+ , Str "system"+ , Space+ , Str "does"+ , Space+ , Str "not"+ , Space+ , Str "have"+ , Space+ , Str "a"+ , Space+ , Str "viewport,"+ , Space+ , Str "or"+ , Space+ , Str "does"+ , Space+ , Str "not"+ , Space+ , Str "support"+ , SoftBreak+ , Str "CSS"+ , Space+ , Str "styles,"+ , Space+ , Str "this"+ , Space+ , Str "test"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "marked"+ , Space+ , Code ( "" , [] , [] ) "Not Supported"+ , Str "."+ ]+ ]+ , Div+ ( "content-mathml-001.xhtml_mathml-023"+ , [ "section" , "otest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[OPTIONAL]" ]+ , SoftBreak+ , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-023" ]+ , Space+ , Str "CSS"+ , Space+ , Str "Styling"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "mn"+ , Space+ , Str "element"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "basic"+ , Space+ , Str "CSS"+ , Space+ , Str "styling"+ , Space+ , Str "of"+ , Space+ , Str "MathML"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "mn"+ , Space+ , Str "element."+ ]+ , Plain [ Math InlineMath "{2x}{+ y - z}" ]+ , Para+ [ Str "The"+ , Space+ , Str "test"+ , Space+ , Str "passes"+ , Space+ , Str "if"+ , Space+ , Str "the"+ , Space+ , Str "number"+ , Space+ , Str "2"+ , Space+ , Str "is"+ , Space+ , Str "italicized"+ , Space+ , Str "and"+ , Space+ , Str "blue."+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "reading"+ , Space+ , Str "system"+ , Space+ , Str "does"+ , Space+ , Str "not"+ , Space+ , Str "have"+ , Space+ , Str "a"+ , Space+ , Str "viewport,"+ , Space+ , Str "or"+ , Space+ , Str "does"+ , Space+ , Str "not"+ , Space+ , Str "support"+ , SoftBreak+ , Str "CSS"+ , Space+ , Str "styles,"+ , Space+ , Str "this"+ , Space+ , Str "test"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "marked"+ , Space+ , Code ( "" , [] , [] ) "Not Supported"+ , Str "."+ ]+ ]+ , Div+ ( "content-mathml-001.xhtml_mathml-024"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , SoftBreak+ , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-024" ]+ , Str "Horizontal"+ , Space+ , Str "stretch,"+ , Space+ , Code ( "" , [] , [] ) "mover"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "munder"+ , Str ","+ , Space+ , Str "and"+ , Space+ , Code ( "" , [] , [] ) "mspace"+ , Space+ , Str "elements"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "horizontal"+ , Space+ , Str "stretch,"+ , Space+ , Code ( "" , [] , [] ) "mover"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "munder"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "mspace"+ , Space+ , Str "elements"+ , Space+ , Str "are"+ , Space+ , Str "supported."+ ]+ , Plain+ [ Math+ DisplayMath+ "c = \\overset{\\text{complex number}}{\\overbrace{\\underset{\\text{real}}{\\underbrace{\\mspace{20mu} a\\mspace{20mu}}} + \\underset{\\text{imaginary}}{\\underbrace{\\quad b{\\mathbb{i}}\\quad}}}}"+ ]+ , Para+ [ Str "The"+ , Space+ , Str "test"+ , Space+ , Str "passes"+ , Space+ , Str "if"+ , Space+ , Str "the"+ , Space+ , Str "rendering"+ , Space+ , Str "looks"+ , Space+ , Str "like"+ , Space+ , Str "."+ ]+ ]+ , Div+ ( "content-mathml-001.xhtml_mathml-025"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , SoftBreak+ , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-025" ]+ , Str "Testing"+ , Space+ , Code ( "" , [] , [] ) "mtable"+ , Space+ , Str "with"+ , Space+ , Code ( "" , [] , [] ) "colspan"+ , Space+ , Str "and"+ , Space+ , Code ( "" , [] , [] ) "rowspan"+ , Space+ , Str "attributes,"+ , Space+ , Str "Hebrew"+ , Space+ , Str "and"+ , Space+ , Str "Script"+ , Space+ , Str "fonts"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Code ( "" , [] , [] ) "mtable"+ , Space+ , Str "with"+ , Space+ , Code ( "" , [] , [] ) "colspan"+ , Space+ , Str "and"+ , Space+ , Code ( "" , [] , [] ) "mspace"+ , Space+ , Str "attributes"+ , Space+ , Str "(column"+ , Space+ , Str "and"+ , Space+ , Str "row"+ , Space+ , Str "spanning)"+ , Space+ , Str "are"+ , Space+ , Str "supported;"+ , Space+ , Str "uses"+ , Space+ , Str "Hebrew"+ , Space+ , Str "and"+ , Space+ , Str "Script"+ , Space+ , Str "alphabets."+ ]+ , Plain+ [ Math+ DisplayMath+ "\\begin{matrix}\n & {\\operatorname{cov}(\\mathcal{L})} & \\longrightarrow & {\\operatorname{non}(\\mathcal{K})} & \\longrightarrow & {\\operatorname{cof}(\\mathcal{K})} & \\longrightarrow & {\\operatorname{cof}(\\mathcal{L})} & \\longrightarrow & 2^{\\aleph_{0}} \\\\\n & \\uparrow & & \\uparrow & & \\uparrow & & \\uparrow & & \\\\\n & {\\mathfrak{b}} & \\longrightarrow & {\\mathfrak{d}} & & & & & & \\\\\n & \\uparrow & & \\uparrow & & & & & & \\\\\n\\aleph_{1} & \\longrightarrow & {\\operatorname{add}(\\mathcal{L})} & \\longrightarrow & {\\operatorname{add}(\\mathcal{K})} & \\longrightarrow & {\\operatorname{cov}(\\mathcal{K})} & \\longrightarrow & {\\operatorname{non}(\\mathcal{L})} & \n\\end{matrix}"+ ]+ , Para+ [ Str "The"+ , Space+ , Str "test"+ , Space+ , Str "passes"+ , Space+ , Str "if"+ , Space+ , Str "the"+ , Space+ , Str "rendering"+ , Space+ , Str "looks"+ , Space+ , Str "like"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "Cicho\324's" , Space , Str "Diagram" ]+ ( "http://en.wikipedia.org/wiki/Cicho%C5%84's_diagram"+ , ""+ )+ , Str ":"+ , Space+ , Str "."+ ]+ ]+ , Div+ ( "content-mathml-001.xhtml_mathml-026"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , SoftBreak+ , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-026" ]+ , Str "BiDi,"+ , Space+ , Str "RTL"+ , Space+ , Str "and"+ , Space+ , Str "Arabic"+ , Space+ , Str "alphabets"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "right-to-left"+ , Space+ , Str "and"+ , Space+ , Str "Arabic"+ , Space+ , Str "alphabets"+ , Space+ , Str "are"+ , Space+ , Str "supported."+ ]+ , Plain+ [ Math+ DisplayMath+ "{\1583(\1587)} = \\left\\{ \\begin{matrix}\n{\\sum\\limits_{\1646 = 1}^{\1589}\1587^{\1646}} & {\\text{\1573\1584\1575\1603\1575\1606}\1587 > 0} \\\\\n{\\int_{1}^{\1589}{\1587^{\1646}\1569\1587}} & {\\text{\1573\1584\1575\1603\1575\1606}\1587 \\in \1605} \\\\\n{{\1591\1575}\\pi} & {\\text{\1594\1610\1585\1584\1604\1603}\\left( \\text{\1605\1593}\\pi \\simeq 3,141 \\right)}\n\\end{matrix} \\right."+ ]+ , Para+ [ Str "The"+ , Space+ , Str "test"+ , Space+ , Str "passes"+ , Space+ , Str "if"+ , Space+ , Str "the"+ , Space+ , Str "rendering"+ , Space+ , Str "looks"+ , Space+ , Str "like"+ , Space+ , Str "the"+ , Space+ , Str "following"+ , Space+ , Str "image:"+ ]+ ]+ , Div+ ( "content-mathml-001.xhtml_mathml-027"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , SoftBreak+ , Span ( "" , [ "test-id" ] , [] ) [ Str "mathml-027" ]+ , Str "Elementary"+ , Space+ , Str "math:"+ , Space+ , Str "long"+ , Space+ , Str "division"+ , Space+ , Str "notation"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Code ( "" , [] , [] ) "mlongdiv"+ , Space+ , Str "elements"+ , Space+ , Str "(from"+ , Space+ , Str "elementary"+ , Space+ , Str "math)"+ , Space+ , Str "are"+ , Space+ , Str "supported."+ ]+ , Plain+ [ Span+ ( ""+ , [ "math" ]+ , [ ( "xmlns" , "http://www.w3.org/1998/Math/MathML" )+ ]+ )+ [ SoftBreak+ , Str "3"+ , SoftBreak+ , Str "435.3"+ , SoftBreak+ , Str "1306"+ , SoftBreak+ , Str "12"+ , SoftBreak+ , Str "10"+ , SoftBreak+ , Str "9"+ , SoftBreak+ , Str "16"+ , SoftBreak+ , Str "15"+ , SoftBreak+ , Str "1.0"+ , SoftBreak+ , Str "9"+ , SoftBreak+ , Str "1"+ , SoftBreak+ ]+ ]+ , Para+ [ Str "The"+ , Space+ , Str "test"+ , Space+ , Str "passes"+ , Space+ , Str "if"+ , Space+ , Str "the"+ , Space+ , Str "rendering"+ , Space+ , Str "looks"+ , Space+ , Str "like"+ , Space+ , Str "the"+ , Space+ , Str "following"+ , Space+ , Str "image:"+ , Space+ , Str "."+ ]+ ]+ ]+ , Para [ Span ( "content-switch-001.xhtml" , [] , [] ) [] ]+ , Div+ ( "content-switch-001.xhtml_epub-switch"+ , [ "section" ]+ , []+ )+ [ Header+ 3 ( "" , [] , [] ) [ Code ( "" , [] , [] ) "epub:switch" ]+ , Div+ ( "content-switch-001.xhtml_switch-010"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "switch-010" ]+ , Space+ , Str "Support"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Link+ ( "" , [] , [] )+ [ Code ( "" , [] , [] ) "epub:switch" ]+ ( "http://idpf.org/epub/30/spec/epub30-contentdocs.html#sec-xhtml-content-switch"+ , ""+ )+ , Space+ , Str "element"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para [ Str "PASS" ]+ , Para+ [ Str "If"+ , Space+ , Str "only"+ , Space+ , Str "the"+ , Space+ , Str "word"+ , Space+ , Str "\"PASS\""+ , Space+ , Str "is"+ , Space+ , Str "rendered"+ , Space+ , Str "before"+ , Space+ , Str "this"+ , Space+ , Str "paragraph,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ , Space+ , Str "If"+ , Space+ , Str "both"+ , Space+ , Str "\"PASS\""+ , Space+ , Str "and"+ , Space+ , Str "\"FAIL\""+ , Space+ , Str "are"+ , Space+ , Str "rendered,"+ , Space+ , Str "or"+ , Space+ , Str "neither"+ , SoftBreak+ , Str "\"PASS\""+ , Space+ , Str "nor"+ , Space+ , Str "\"FAIL\""+ , Space+ , Str "is"+ , Space+ , Str "rendered,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "fails."+ ]+ ]+ , Div+ ( "content-switch-001.xhtml_switch-020"+ , [ "section" , "otest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[OPTIONAL]" ]+ , SoftBreak+ , Span ( "" , [ "test-id" ] , [] ) [ Str "switch-020" ]+ , SoftBreak+ , Str "MathML"+ , Space+ , Str "Embedding"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Str "MathML"+ , Space+ , Str "namespace"+ , Space+ , Str "is"+ , Space+ , Str "recognized"+ , Space+ , Str "when"+ , Space+ , Str "used"+ , Space+ , Str "in"+ , Space+ , Str "an"+ , Space+ , Link+ ( "" , [] , [] )+ [ Code ( "" , [] , [] ) "epub:case" ]+ ( "http://idpf.org/epub/30/spec/epub30-contentdocs.html#sec-xhtml-epub-case"+ , ""+ )+ , Space+ , Str "element."+ ]+ , Para [ Math InlineMath "{2x}{+ y - z}" ]+ , Para+ [ Str "If"+ , Space+ , Str "a"+ , Space+ , Str "MathML"+ , Space+ , Str "equation"+ , Space+ , Str "is"+ , Space+ , Str "rendered"+ , Space+ , Str "before"+ , Space+ , Str "this"+ , Space+ , Str "paragraph,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ , Para+ [ Str "If"+ , Space+ , Str "test"+ , Space+ , Code ( "" , [] , [] ) "switch-010"+ , Space+ , Str "did"+ , Space+ , Str "not"+ , Space+ , Str "pass,"+ , Space+ , Str "this"+ , Space+ , Str "test"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "marked"+ , Space+ , Code ( "" , [] , [] ) "Not Supported"+ , Str "."+ ]+ ]+ ]+ ]
@@ -1,5989 +1,6020 @@-[ Para [ Span ( "front.xhtml" , [] , [] ) [] ]-, Div- ( "" , [ "section" ] , [] )- [ Header- 1- ( "" , [] , [] )- [ Str "EPUB"- , Space- , Str "3"- , Space- , Str "Styling"- , Space- , Str "Test"- , Space- , Str "Document:"- , Space- , Str "0101"- ]- , Div- ( "" , [ "section" ] , [] )- [ Header- 2- ( "" , [] , [] )- [ Str "Status"- , Space- , Str "of"- , Space- , Str "this"- , Space- , Str "Document"- ]- , Para- [ Str "This"- , Space- , Str "publication"- , Space- , Str "is"- , Space- , Str "currently"- , Space- , Str "considered"- , Space- , Span- ( "" , [ "status" ] , [] )- [ Str "[UNDER" , Space , Str "DEVELOPMENT]" ]- , Space- , Str "by"- , Space- , Str "the"- , Space- , Str "IDPF."- ]- , Para- [ Str "This"- , Space- , Str "publication"- , Space- , Str "is"- , Space- , Str "part"- , Space- , Str "of"- , Space- , Str "version"- , Space- , Span ( "" , [ "version" ] , [] ) [ Str "X.X" ]- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "EPUB"- , Space- , Str "3.0"- , Space- , Str "Compliance"- , Space- , Str "Test"- , Space- , Str "Suite"- , Space- , Str "released"- , SoftBreak- , Str "on"- , Space- , RawInline (Format "html") "<time class=\"release\">"- , Str "TBD"- , RawInline (Format "html") "</time>"- , Str "."- ]- , Para- [ Str "Before"- , Space- , Str "using"- , Space- , Str "this"- , Space- , Str "publication"- , Space- , Str "to"- , Space- , Str "evaluate"- , Space- , Str "reading"- , Space- , Str "systems,"- , Space- , Str "testers"- , Space- , Str "are"- , Space- , Str "strongly"- , Space- , Str "encouraged"- , Space- , Str "to"- , SoftBreak- , Str "verify"- , Space- , Str "that"- , Space- , Str "they"- , Space- , Str "have"- , Space- , Str "the"- , Space- , Str "latest"- , Space- , Str "release"- , Space- , Str "by"- , Space- , Str "checking"- , Space- , Str "the"- , Space- , Str "current"- , Space- , Str "release"- , Space- , Str "version"- , Space- , Str "and"- , Space- , Str "date"- , Space- , Str "of"- , SoftBreak- , Str "the"- , Space- , Str "test"- , Space- , Str "suite"- , Space- , Str "at"- , Space- , Link- ( "" , [] , [] )- [ Str "TBD" ]- ( "http://idpf.org/" , "" )- ]- , Para- [ Str "This"- , Space- , Str "publication"- , Space- , Str "is"- , Space- , Str "one"- , Space- , Str "of"- , Space- , Str "several"- , Space- , Str "that"- , Space- , Str "currently"- , Space- , Str "comprise"- , Space- , Str "the"- , Space- , Str "EPUB"- , Space- , Str "3"- , Space- , Str "conformance"- , Space- , Str "test"- , Space- , Str "suite"- , SoftBreak- , Str "for"- , Space- , Str "reflowable"- , Space- , Str "content."- , Space- , Str "The"- , Space- , Str "complete"- , Space- , Str "test"- , Space- , Str "suite"- , Space- , Str "includes"- , Space- , Str "all"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "following"- , Space- , Str "publications:"- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "." ] ] ]- ]- , Div- ( "" , [ "section" ] , [] )- [ Header- 2- ( "" , [] , [] )- [ Str "About"- , Space- , Str "this"- , Space- , Str "Document"- ]- , Para- [ Str "This"- , Space- , Str "document"- , Space- , Str "focuses"- , Space- , Str "on"- , Space- , Str "human-evaluated"- , Space- , Str "binary"- , Space- , Str "(pass/fail)"- , Space- , Str "tests"- , Space- , Str "in"- , Space- , Str "a"- , SoftBreak- , Str "reflowable"- , Space- , Str "context."- , Space- , Str "Tests"- , Space- , Str "for"- , Space- , Str "fixed-layout"- , Space- , Str "content"- , Space- , Str "and"- , Space- , Str "other"- , Space- , Str "individual"- , Space- , Str "tests"- , Space- , Str "that"- , SoftBreak- , Str "require"- , Space- , Str "a"- , Space- , Str "dedicated"- , Space- , Str "epub"- , Space- , Str "file"- , Space- , Str "are"- , Space- , Str "available"- , Space- , Str "in"- , Space- , Str "additional"- , Space- , Str "sibling"- , Space- , Str "documents;"- , Space- , Str "refer"- , Space- , Str "to"- , SoftBreak- , Str "the"- , Space- , Link- ( "" , [] , [] )- [ Str "test"- , Space- , Str "suite"- , SoftBreak- , Str "wiki"- ]- ( "https://github.com/mgylling/epub-testsuite/wiki/Overview"- , ""- )- , Space- , Str "("- , Code- ( "" , [] , [] )- "https://github.com/mgylling/epub-testsuite/wiki/Overview"- , Str ")"- , Space- , Str "for"- , Space- , Str "additional"- , SoftBreak- , Str "information."- ]- ]- , Div- ( "" , [ "section" ] , [] )- [ Header 2 ( "" , [] , [] ) [ Str "Conventions" ]- , Para- [ Str "The"- , Space- , Str "following"- , Space- , Str "conventions"- , Space- , Str "are"- , Space- , Str "used"- , Space- , Str "throughout"- , Space- , Str "the"- , Space- , Str "document:"- ]- , DefinitionList- [ ( [ Str "1."- , Space- , Str "Locating"- , Space- , Str "a"- , Space- , Str "test"- ]- , [ [ Div- ( "" , [ "ctest" ] , [] )- [ Para- [ Str "Tests"- , Space- , Str "for"- , Space- , Emph [ Str "required" ]- , Space- , Str "Reading"- , Space- , Str "System"- , Space- , Str "functionality"- , Space- , Str "are"- , SoftBreak- , Str "preceded"- , Space- , Str "by"- , Space- , Str "the"- , Space- , Str "label:"- , Space- , Span- ( ""- , [ "nature" ]- , [ ( "style"- , "display: inline; font-size: 100%"- )- ]- )- [ Str "[REQUIRED]" ]- ]- ]- , Div- ( "" , [ "otest" ] , [] )- [ Para- [ Str "Tests"- , Space- , Str "for"- , Space- , Emph [ Str "optional" ]- , Space- , Str "Reading"- , Space- , Str "System"- , Space- , Str "functionality"- , Space- , Str "are"- , SoftBreak- , Str "preceded"- , Space- , Str "by"- , Space- , Str "the"- , Space- , Str "label:"- , Space- , Span- ( ""- , [ "nature" ]- , [ ( "style"- , "display: inline; font-size: 100%"- )- ]- )- [ Str "[OPTIONAL]" ]- ]- ]- ]- ]- )- , ( [ Str "2."- , Space- , Str "Performing"- , Space- , Str "the"- , Space- , Str "test"- ]- , [ [ Plain- [ Str "Each"- , Space- , Str "test"- , Space- , Str "includes"- , Space- , Str "a"- , Space- , Str "description"- , Space- , Str "of"- , Space- , Str "its"- , Space- , Str "purpose"- , Space- , Str "followed"- , Space- , Str "by"- , Space- , Str "the"- , Space- , Str "actual"- , Space- , Strong- [ Str "test"- , Space- , Str "statement,"- , SoftBreak- , Str "which"- , Space- , Str "can"- , Space- , Str "always"- , Space- , Str "be"- , Space- , Str "evaluated"- , Space- , Str "to"- , Space- , Str "true"- , Space- , Str "or"- , Space- , Str "false"- ]- , Str "."- , Space- , Str "These"- , Space- , Str "statements"- , Space- , Str "typically"- , Space- , Str "have"- , Space- , Str "the"- , Space- , Str "form:"- , SoftBreak- , Str "\"If"- , Space- , Str "[some"- , Space- , Str "condition],"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes\"."- ]- ]- ]- )- , ( [ Str "3."- , Space- , Str "Scoring"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "results"- , Space- , Str "form"- ]- , [ [ Plain- [ Str "@@@TODO"- , Space- , Str "provide"- , Space- , Str "info"- , Space- , Str "on"- , Space- , Str "where"- , Space- , Str "to"- , Space- , Str "get"- , Space- , Str "the"- , Space- , Str "results"- , Space- , Str "form"- ]- ]- ]- )- ]- ]- ]-, Para [ Span ( "styling-xhtml-001.xhtml" , [] , [] ) [] ]-, Div- ( "styling-xhtml-001.xhtml#epub-css" , [ "section" ] , [] )- [ Header- 1- ( "" , [] , [] )- [ Str "EPUB" , Space , Str "Style" , Space , Str "Sheets" ]- , Para- [ Str "This"- , Space- , Str "section"- , Space- , Str "contains"- , Space- , Str "tests"- , Space- , Str "for"- , Space- , Str "styling"- , Space- , Str "and"- , Space- , Str "layout."- ]- ]-, Para [ Span ( "styling-xhtml-003.xhtml" , [] , [] ) [] ]-, Div- ( "styling-xhtml-003.xhtml#style-110"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-110" ]- , Space- , Str "Multi-Column"- , Space- , Str "Layouts"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Link- ( "" , [] , [] )- [ Code ( "" , [] , [] ) "CSS Multi-Column Layout" ]- ( "http://idpf.org/epub/30/spec/epub30-contentdocs.html#sec-css-multi-column"- , ""- )- , Space- , Str "properties"- , Space- , Str "are"- , Space- , Str "supported."- ]- , Div- ( "" , [ "multicol" ] , [] )- [ Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- , Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- , Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- , Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- , Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- , Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- , Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- , Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- , Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "text"- , Space- , Str "is"- , Space- , Str "rendered"- , Space- , Str "in"- , Space- , Str "three"- , Space- , Str "columns,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]-, Para [ Span ( "styling-xhtml-002.xhtml" , [] , [] ) [] ]-, Div- ( "styling-xhtml-002.xhtml#style-lists"- , [ "section" ]- , []- )- [ Header 2 ( "" , [] , [] ) [ Str "Lists" ]- , Div- ( "styling-xhtml-002.xhtml#style-list-style-type"- , [ "section" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Str "The"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- ]- , Div- ( "styling-xhtml-002.xhtml#style-009"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-009" ]- , Space- , Code ( "" , [] , [] ) "decimal"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "decimal"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "decimal"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-010"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-010" ]- , Space- , Code ( "" , [] , [] ) "circle"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "circle"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ul"- , Space- , Str "element."- ]- , BulletList- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "circle"- , Space- , Str "markers,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-011"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-011" ]- , Space- , Code ( "" , [] , [] ) "square"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "square"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ul"- , Space- , Str "element."- ]- , BulletList- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "square"- , Space- , Str "markers,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-012"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-012" ]- , Space- , Code ( "" , [] , [] ) "disc"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "disc"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ul"- , Space- , Str "element."- ]- , BulletList- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "disc"- , Space- , Str "markers,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-013"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-013" ]- , Space- , Code ( "" , [] , [] ) "lower-latin"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "lower-latin"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "lower-latin"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-014"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-014" ]- , Space- , Code ( "" , [] , [] ) "lower-roman"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "lower-roman"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "lower-roman"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-015"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-015" ]- , Space- , Code ( "" , [] , [] ) "upper-alpha"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "upper-alpha"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "upper-alpha"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-016"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-016" ]- , Space- , Code ( "" , [] , [] ) "hiragana"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "hiragana"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "hiragana"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-017"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-017" ]- , Space- , Code ( "" , [] , [] ) "hiragana-iroha"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "hiragana-iroha"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "hiragana-iroha"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-018"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-018" ]- , Space- , Code ( "" , [] , [] ) "katakana"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "katakana"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "katakana"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-019"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-019" ]- , Space- , Code ( "" , [] , [] ) "katakana-iroha"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "katakana-iroha"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "katakana-iroha"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-020"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-020" ]- , Space- , Code ( "" , [] , [] ) "upper-roman"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "upper-roman"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "upper-roman"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-021"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-021" ]- , Space- , Code ( "" , [] , [] ) "upper-latin"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "upper-latin"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "upper-latin"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-022"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-022" ]- , Space- , Code ( "" , [] , [] ) "lower-alpha"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "lower-alpha"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "lower-alpha"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-023"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-023" ]- , Space- , Code ( "" , [] , [] ) "lower-greek"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "lower-greek"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "lower-greek"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-024"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-024" ]- , Space- , Code ( "" , [] , [] ) "armenian"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "armenian"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "armenian"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-025"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-025" ]- , Space- , Code ( "" , [] , [] ) "cjk-ideographic"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "cjk-ideographic"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "cjk-ideographic"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-026"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-026" ]- , Space- , Code ( "" , [] , [] ) "decimal-leading-zero"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "decimal-leading-zero"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "decimal-leading-zero"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-027"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-027" ]- , Space- , Code ( "" , [] , [] ) "georgian"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "georgian"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "georgian"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-028"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-028" ]- , Space- , Code ( "" , [] , [] ) "hebrew"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "hebrew"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "hebrew"- , Space- , Str "markers"- , Space- , Str "in"- , Space- , Str "ascending"- , Space- , Str "order,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-029"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-029" ]- , Space- , Code ( "" , [] , [] ) "none"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "none"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element."- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "no"- , Space- , Str "markers,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-list-style"- , [ "section" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Str "The"- , Space- , Code ( "" , [] , [] ) "list-style"- , Space- , Str "property"- ]- , Div- ( "styling-xhtml-002.xhtml#style-030"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-030" ]- , Space- , Str "images"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style"- , Space- , Str "shorthand"- , Space- , Str "property"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "using"- , Space- , Str "a"- , Space- , Str "gif"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ul"- , Space- , Str "element."- ]- , BulletList- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "the"- , Space- , Str "purple"- , Space- , Str "and"- , Space- , Str "aqua"- , Space- , Str "square"- , Space- , Str "bullet"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-list-style-position"- , [ "section" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Str "The"- , Space- , Code ( "" , [] , [] ) "list-style-position"- , Space- , Str "property"- ]- , Div- ( "styling-xhtml-002.xhtml#style-040"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-040" ]- , Space- , Str "The"- , Space- , Code ( "" , [] , [] ) "list-style-position"- , Space- , Str "property:"- , Space- , Code ( "" , [] , [] ) "inside"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-position"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "inside"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ul"- , Space- , Str "element."- ]- , BulletList- [ [ Plain- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- ]- ]- , [ Plain- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- ]- ]- , [ Plain- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- ]- ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "markers"- , Space- , Str "inside"- , Space- , Str "the"- , Space- , Str "indentation,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-041"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-041" ]- , Space- , Str "The"- , Space- , Code ( "" , [] , [] ) "list-style-position"- , Space- , Str "property:"- , Space- , Code ( "" , [] , [] ) "outside"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "list-style-position"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "outside"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ul"- , Space- , Str "element."- ]- , BulletList- [ [ Plain- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- ]- ]- , [ Plain- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- ]- ]- , [ Plain- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- ]- ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "has"- , Space- , Str "the"- , Space- , Str "default"- , Space- , Str "setting"- , Space- , Str "(marker"- , Space- , Str "outside"- , Space- , Str "the"- , Space- , Str "indentation),"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-list-start"- , [ "section" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Str "The"- , Space- , Str "HTML"- , Space- , Code ( "" , [] , [] ) "start"- , Space- , Str "attribute"- ]- , Div- ( "styling-xhtml-002.xhtml#style-050"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-050" ]- , Space- , Str "Without"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "set"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "start"- , Space- , Str "attribute"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element"- , Space- , Str "with"- , Space- , Str "no"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property."- ]- , OrderedList- ( 25 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "starts"- , Space- , Str "at"- , Space- , Str "25,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-002.xhtml#style-051"- , [ "section" , "ctest" ]- , []- )- [ Header- 4- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-051" ]- , Space- , Str "With"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "set"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "start"- , Space- , Str "attribute"- , Space- , Str "is"- , Space- , Str "supported"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "ol"- , Space- , Str "element"- , Space- , Str "with"- , Space- , Str "a"- , Space- , Code ( "" , [] , [] ) "list-style-type"- , Space- , Str "property."- ]- , OrderedList- ( 50 , DefaultStyle , DefaultDelim )- [ [ Plain [ Str "Lorem" ] ]- , [ Plain [ Str "Ipsum" ] ]- , [ Plain [ Str "Dolor" ] ]- , [ Plain [ Str "Sit" ] ]- , [ Plain [ Str "Amet" ] ]- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "list"- , Space- , Str "starts"- , Space- , Str "at"- , Space- , Str "'L'"- , Space- , Str "(50),"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- ]- ]-, Para [ Span ( "styling-xhtml-004.xhtml" , [] , [] ) [] ]-, Div- ( "styling-xhtml-004.xhtml#style-media-rules"- , [ "section" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Code ( "" , [] , [] ) "@media" , Space , Str "Rules" ]- , Div- ( "styling-xhtml-004.xhtml#style-210"- , [ "section" , "ctest" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-210" ]- , Space- , Code ( "" , [] , [] ) "all"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "@media"- , Space- , Str "rule"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "all"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para [ Str "FAIL" ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "reads"- , Space- , Str "\"FAIL\","- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "fails."- ]- ]- , Div- ( "styling-xhtml-004.xhtml#style-211"- , [ "section" , "ctest" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-211" ]- , Space- , Code ( "" , [] , [] ) "screen"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "@media"- , Space- , Str "rule"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "screen"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para [ Str "FAIL" ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "reads"- , Space- , Str "\"FAIL\","- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "fails."- ]- ]- , Div- ( "styling-xhtml-004.xhtml#style-212"- , [ "section" , "ctest" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-212" ]- , Space- , Code ( "" , [] , [] ) "handheld"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "@media"- , Space- , Str "rule"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "handheld"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para [ Str "FAIL" ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "reads"- , Space- , Str "\"FAIL\","- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "fails."- ]- ]- , Div- ( "styling-xhtml-004.xhtml#style-213"- , [ "section" , "ctest" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-213" ]- , Space- , Code ( "" , [] , [] ) "tv"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "@media"- , Space- , Str "rule"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "tv"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para [ Str "FAIL" ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "reads"- , Space- , Str "\"FAIL\","- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "fails."- ]- ]- , Div- ( "styling-xhtml-004.xhtml#style-220"- , [ "section" , "ctest" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-220" ]- , Space- , Code ( "" , [] , [] ) "orientation:landscape"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "@media"- , Space- , Str "rule"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "orientation:landscape"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para [ Str "FAIL" ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "reads"- , Space- , Str "\"FAIL\""- , Space- , Str "when"- , Space- , Str "the"- , Space- , Str "device"- , Space- , Str "is"- , Space- , Str "held"- , Space- , Str "in"- , Space- , Str "landscape"- , Space- , Str "mode,"- , Space- , Str "and"- , Space- , Str "the"- , Space- , Str "device"- , Space- , Str "supports"- , Space- , Str "multiple"- , Space- , Str "orientations,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "fails."- ]- ]- , Div- ( "styling-xhtml-004.xhtml#style-221"- , [ "section" , "ctest" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-221" ]- , Space- , Code ( "" , [] , [] ) "orientation:portrait"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "@media"- , Space- , Str "rule"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "orientation:portrait"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para [ Str "FAIL" ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "reads"- , Space- , Str "\"FAIL\""- , Space- , Str "when"- , Space- , Str "the"- , Space- , Str "device"- , Space- , Str "is"- , Space- , Str "held"- , Space- , Str "in"- , Space- , Str "portrait"- , Space- , Str "mode,"- , Space- , Str "and"- , Space- , Str "the"- , Space- , Str "device"- , Space- , Str "supports"- , Space- , Str "multiple"- , Space- , Str "orientations,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "fails."- ]- ]- , Div- ( "styling-xhtml-004.xhtml#style-230"- , [ "section" , "ctest" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-230" ]- , Space- , Code ( "" , [] , [] ) "min-width"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "@media"- , Space- , Str "rule"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "min-width:200px"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para [ Str "FAIL" ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "reads"- , Space- , Str "\"FAIL\","- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "fails."- ]- ]- , Div- ( "styling-xhtml-004.xhtml#style-231"- , [ "section" , "ctest" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-231" ]- , Space- , Code ( "" , [] , [] ) "max-width"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "@media"- , Space- , Str "rule"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "max-width:2000px"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para [ Str "FAIL" ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "reads"- , Space- , Str "\"FAIL\","- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "fails."- ]- ]- , Div- ( "styling-xhtml-004.xhtml#style-240"- , [ "section" , "ctest" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-240" ]- , Space- , Code ( "" , [] , [] ) "min-device-width"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "@media"- , Space- , Str "rule"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "min-device-width:200px"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para [ Str "FAIL" ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "reads"- , Space- , Str "\"FAIL\","- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "fails."- ]- ]- , Div- ( "styling-xhtml-004.xhtml#style-241"- , [ "section" , "ctest" ]- , []- )- [ Header- 3- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-241" ]- , Space- , Code ( "" , [] , [] ) "max-device-width"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "@media"- , Space- , Str "rule"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Code ( "" , [] , [] ) "max-device-width:2000px"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para [ Str "FAIL" ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "reads"- , Space- , Str "\"FAIL\","- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "fails."- ]- ]- ]-, Para [ Span ( "styling-xhtml-005.xhtml" , [] , [] ) [] ]-, Div- ( "styling-xhtml-005.xhtml#style-text-xform"- , [ "section" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Str "The"- , Space- , Code ( "" , [] , [] ) "text-transform"- , Space- , Str "property"- ]- , Div- ( "styling-xhtml-005.xhtml#style-310"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-310" ]- , Space- , Code ( "" , [] , [] ) "uppercase"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "text-transform"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Str "uppercase"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "is"- , Space- , Str "in"- , Space- , Str "upper"- , Space- , Str "case,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-005.xhtml#style-311"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-311" ]- , Space- , Code ( "" , [] , [] ) "capitalize"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "text-transform"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Str "capitalize"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- , Para- [ Str "If"- , Space- , Str "each"- , Space- , Str "first"- , Space- , Str "letter"- , Space- , Str "of"- , Space- , Str "each"- , Space- , Str "word"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "is"- , Space- , Str "in"- , Space- , Str "upper"- , Space- , Str "case,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-005.xhtml#style-312"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-312" ]- , Space- , Code ( "" , [] , [] ) "lowercase"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "text-transform"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Str "lowercase"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Para- [ Str "Lorem"- , Space- , Str "ipsum"- , Space- , Str "dolor"- , Space- , Str "sit"- , Space- , Str "amet,"- , Space- , Str "consectetur"- , Space- , Str "adipisicing"- , Space- , Str "elit,"- , Space- , Str "sed"- , Space- , Str "do"- , Space- , Str "eiusmod"- , Space- , Str "tempor"- , Space- , Str "incididunt"- , Space- , Str "ut"- , Space- , Str "labore"- , Space- , Str "et"- , Space- , Str "dolore"- , Space- , Str "magna"- , Space- , Str "aliqua."- , Space- , Str "Ut"- , Space- , Str "enim"- , Space- , Str "ad"- , Space- , Str "minim"- , Space- , Str "veniam,"- , Space- , Str "quis"- , Space- , Str "nostrud"- , Space- , Str "exercitation"- , Space- , Str "ullamco"- , Space- , Str "laboris"- , Space- , Str "nisi"- , Space- , Str "ut"- , Space- , Str "aliquip"- , Space- , Str "ex"- , Space- , Str "ea"- , Space- , Str "commodo"- , Space- , Str "consequat."- , Space- , Str "Duis"- , Space- , Str "aute"- , Space- , Str "irure"- , Space- , Str "dolor"- , Space- , Str "in"- , Space- , Str "reprehenderit"- , Space- , Str "in"- , Space- , Str "voluptate"- , Space- , Str "velit"- , Space- , Str "esse"- , Space- , Str "cillum"- , Space- , Str "dolore"- , Space- , Str "eu"- , Space- , Str "fugiat"- , Space- , Str "nulla"- , Space- , Str "pariatur."- , Space- , Str "Excepteur"- , Space- , Str "sint"- , Space- , Str "occaecat"- , Space- , Str "cupidatat"- , Space- , Str "non"- , Space- , Str "proident,"- , Space- , Str "sunt"- , Space- , Str "in"- , Space- , Str "culpa"- , Space- , Str "qui"- , Space- , Str "officia"- , Space- , Str "deserunt"- , Space- , Str "mollit"- , Space- , Str "anim"- , Space- , Str "id"- , Space- , Str "est"- , Space- , Str "laborum."- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "preceding"- , Space- , Str "paragraph"- , Space- , Str "is"- , Space- , Str "in"- , Space- , Str "lower"- , Space- , Str "case,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- ]-, Para [ Span ( "styling-xhtml-006.xhtml" , [] , [] ) [] ]-, Div- ( "styling-xhtml-006.xhtml#style-ruby"- , [ "section" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Str "The"- , Space- , Code ( "" , [] , [] ) "epub-ruby-position"- , Space- , Str "property"- ]- , Div- ( "styling-xhtml-006.xhtml#style-410"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-410" ]- , Space- , Code ( "" , [] , [] ) "over"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "-epub-ruby-position"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Str "over"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Plain- [ RawInline (Format "html") "<ruby class=\"ruby-over\">"- , Strong [ Str "Lorem" , Space , Str "Ipsum" ]- , Space- , RawInline (Format "html") "<rp>"- , Str "("- , RawInline (Format "html") "</rp>"- , RawInline (Format "html") "<rt>"- , Str "Lorem"- , Space- , Str "Ipsum"- , RawInline (Format "html") "</rt>"- , RawInline (Format "html") "<rp>"- , Str ")"- , RawInline (Format "html") "</rp>"- , RawInline (Format "html") "</ruby>"- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "Ruby"- , Space- , Str "text"- , Space- , Str "is"- , Space- , Str "positioned"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Link- ( "" , [] , [] )- [ Str "over" ]- ( "http://www.w3.org/TR/css3-writing-modes/#over" , "" )- , Space- , Str "side"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "ruby"- , Space- , Str "base,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-006.xhtml#style-411"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-411" ]- , Space- , Code ( "" , [] , [] ) "under"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "-epub-ruby-position"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Str "under"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Plain- [ RawInline (Format "html") "<ruby class=\"ruby-under\">"- , Strong [ Str "Lorem" , Space , Str "Ipsum" ]- , Space- , RawInline (Format "html") "<rp>"- , Str "("- , RawInline (Format "html") "</rp>"- , RawInline (Format "html") "<rt>"- , Str "Lorem"- , Space- , Str "Ipsum"- , RawInline (Format "html") "</rt>"- , RawInline (Format "html") "<rp>"- , Str ")"- , RawInline (Format "html") "</rp>"- , RawInline (Format "html") "</ruby>"- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "Ruby"- , Space- , Str "text"- , Space- , Str "is"- , Space- , Str "positioned"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Link- ( "" , [] , [] )- [ Str "under" ]- ( "http://www.w3.org/TR/css3-writing-modes/#under"- , ""- )- , Space- , Str "side"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "ruby"- , Space- , Str "base,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- , Div- ( "styling-xhtml-006.xhtml#style-412"- , [ "section" , "ctest" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]- , Space- , Span ( "" , [ "test-id" ] , [] ) [ Str "style-412" ]- , Space- , Code ( "" , [] , [] ) "inter-character"- ]- , Para- [ Str "Tests"- , Space- , Str "whether"- , Space- , Str "the"- , Space- , Code ( "" , [] , [] ) "-epub-ruby-position"- , Space- , Str "property"- , Space- , Str "set"- , Space- , Str "to"- , Space- , Str "inter-caracter"- , Space- , Str "is"- , Space- , Str "supported."- ]- , Plain- [ RawInline- (Format "html") "<ruby class=\"ruby-inter-character\">"- , Strong [ Str "Lorem" , Space , Str "Ipsum" ]- , Space- , RawInline (Format "html") "<rp>"- , Str "("- , RawInline (Format "html") "</rp>"- , RawInline (Format "html") "<rt>"- , Str "Lorem"- , Space- , Str "Ipsum"- , RawInline (Format "html") "</rt>"- , RawInline (Format "html") "<rp>"- , Str ")"- , RawInline (Format "html") "</rp>"- , RawInline (Format "html") "</ruby>"- ]- , Para- [ Str "If"- , Space- , Str "the"- , Space- , Str "Ruby"- , Space- , Str "text"- , Space- , Str "is"- , Space- , Str "positioned"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Str "right"- , Space- , Str "side"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "base"- , Space- , Str "text,"- , Space- , Str "the"- , Space- , Str "test"- , Space- , Str "passes."- ]- ]- ]-]+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "author"+ , MetaList+ [ MetaInlines [ Str "Ori Idan" ]+ , MetaInlines [ Str "Matt Garrish" ]+ , MetaInlines [ Str "Marisa DeMeglio" ]+ , MetaInlines [ Str "Toshiaki Koike" ]+ , MetaInlines [ Str "Vincent Gros" ]+ , MetaInlines [ Str "Markus Gylling" ]+ ]+ )+ , ( "description"+ , MetaInlines+ [ Str "Tests for Styling [UNDER CONSTRUCTION]" ]+ )+ , ( "identifier"+ , MetaInlines+ [ Str "com.github.epub-testsuite.epub30-test-0101" ]+ )+ , ( "language" , MetaInlines [ Str "en" ] )+ , ( "title"+ , MetaInlines [ Str "EPUBTEST 0101 - Styling Tests" ]+ )+ ]+ }+ [ Para [ Span ( "front.xhtml" , [] , [] ) [] ]+ , Div+ ( "" , [ "section" ] , [] )+ [ Header+ 1+ ( "" , [] , [] )+ [ Str "EPUB"+ , Space+ , Str "3"+ , Space+ , Str "Styling"+ , Space+ , Str "Test"+ , Space+ , Str "Document:"+ , Space+ , Str "0101"+ ]+ , Div+ ( "" , [ "section" ] , [] )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "Status"+ , Space+ , Str "of"+ , Space+ , Str "this"+ , Space+ , Str "Document"+ ]+ , Para+ [ Str "This"+ , Space+ , Str "publication"+ , Space+ , Str "is"+ , Space+ , Str "currently"+ , Space+ , Str "considered"+ , Space+ , Span+ ( "" , [ "status" ] , [] )+ [ Str "[UNDER" , Space , Str "DEVELOPMENT]" ]+ , Space+ , Str "by"+ , Space+ , Str "the"+ , Space+ , Str "IDPF."+ ]+ , Para+ [ Str "This"+ , Space+ , Str "publication"+ , Space+ , Str "is"+ , Space+ , Str "part"+ , Space+ , Str "of"+ , Space+ , Str "version"+ , Space+ , Span ( "" , [ "version" ] , [] ) [ Str "X.X" ]+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "EPUB"+ , Space+ , Str "3.0"+ , Space+ , Str "Compliance"+ , Space+ , Str "Test"+ , Space+ , Str "Suite"+ , Space+ , Str "released"+ , SoftBreak+ , Str "on"+ , Space+ , RawInline (Format "html") "<time class=\"release\">"+ , Str "TBD"+ , RawInline (Format "html") "</time>"+ , Str "."+ ]+ , Para+ [ Str "Before"+ , Space+ , Str "using"+ , Space+ , Str "this"+ , Space+ , Str "publication"+ , Space+ , Str "to"+ , Space+ , Str "evaluate"+ , Space+ , Str "reading"+ , Space+ , Str "systems,"+ , Space+ , Str "testers"+ , Space+ , Str "are"+ , Space+ , Str "strongly"+ , Space+ , Str "encouraged"+ , Space+ , Str "to"+ , SoftBreak+ , Str "verify"+ , Space+ , Str "that"+ , Space+ , Str "they"+ , Space+ , Str "have"+ , Space+ , Str "the"+ , Space+ , Str "latest"+ , Space+ , Str "release"+ , Space+ , Str "by"+ , Space+ , Str "checking"+ , Space+ , Str "the"+ , Space+ , Str "current"+ , Space+ , Str "release"+ , Space+ , Str "version"+ , Space+ , Str "and"+ , Space+ , Str "date"+ , Space+ , Str "of"+ , SoftBreak+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "suite"+ , Space+ , Str "at"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "TBD" ]+ ( "http://idpf.org/" , "" )+ ]+ , Para+ [ Str "This"+ , Space+ , Str "publication"+ , Space+ , Str "is"+ , Space+ , Str "one"+ , Space+ , Str "of"+ , Space+ , Str "several"+ , Space+ , Str "that"+ , Space+ , Str "currently"+ , Space+ , Str "comprise"+ , Space+ , Str "the"+ , Space+ , Str "EPUB"+ , Space+ , Str "3"+ , Space+ , Str "conformance"+ , Space+ , Str "test"+ , Space+ , Str "suite"+ , SoftBreak+ , Str "for"+ , Space+ , Str "reflowable"+ , Space+ , Str "content."+ , Space+ , Str "The"+ , Space+ , Str "complete"+ , Space+ , Str "test"+ , Space+ , Str "suite"+ , Space+ , Str "includes"+ , Space+ , Str "all"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "following"+ , Space+ , Str "publications:"+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "." ] ] ]+ ]+ , Div+ ( "" , [ "section" ] , [] )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "About"+ , Space+ , Str "this"+ , Space+ , Str "Document"+ ]+ , Para+ [ Str "This"+ , Space+ , Str "document"+ , Space+ , Str "focuses"+ , Space+ , Str "on"+ , Space+ , Str "human-evaluated"+ , Space+ , Str "binary"+ , Space+ , Str "(pass/fail)"+ , Space+ , Str "tests"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , SoftBreak+ , Str "reflowable"+ , Space+ , Str "context."+ , Space+ , Str "Tests"+ , Space+ , Str "for"+ , Space+ , Str "fixed-layout"+ , Space+ , Str "content"+ , Space+ , Str "and"+ , Space+ , Str "other"+ , Space+ , Str "individual"+ , Space+ , Str "tests"+ , Space+ , Str "that"+ , SoftBreak+ , Str "require"+ , Space+ , Str "a"+ , Space+ , Str "dedicated"+ , Space+ , Str "epub"+ , Space+ , Str "file"+ , Space+ , Str "are"+ , Space+ , Str "available"+ , Space+ , Str "in"+ , Space+ , Str "additional"+ , Space+ , Str "sibling"+ , Space+ , Str "documents;"+ , Space+ , Str "refer"+ , Space+ , Str "to"+ , SoftBreak+ , Str "the"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "test"+ , Space+ , Str "suite"+ , SoftBreak+ , Str "wiki"+ ]+ ( "https://github.com/mgylling/epub-testsuite/wiki/Overview"+ , ""+ )+ , Space+ , Str "("+ , Code+ ( "" , [] , [] )+ "https://github.com/mgylling/epub-testsuite/wiki/Overview"+ , Str ")"+ , Space+ , Str "for"+ , Space+ , Str "additional"+ , SoftBreak+ , Str "information."+ ]+ ]+ , Div+ ( "" , [ "section" ] , [] )+ [ Header 2 ( "" , [] , [] ) [ Str "Conventions" ]+ , Para+ [ Str "The"+ , Space+ , Str "following"+ , Space+ , Str "conventions"+ , Space+ , Str "are"+ , Space+ , Str "used"+ , Space+ , Str "throughout"+ , Space+ , Str "the"+ , Space+ , Str "document:"+ ]+ , DefinitionList+ [ ( [ Str "1."+ , Space+ , Str "Locating"+ , Space+ , Str "a"+ , Space+ , Str "test"+ ]+ , [ [ Div+ ( "" , [ "ctest" ] , [] )+ [ Para+ [ Str "Tests"+ , Space+ , Str "for"+ , Space+ , Emph [ Str "required" ]+ , Space+ , Str "Reading"+ , Space+ , Str "System"+ , Space+ , Str "functionality"+ , Space+ , Str "are"+ , SoftBreak+ , Str "preceded"+ , Space+ , Str "by"+ , Space+ , Str "the"+ , Space+ , Str "label:"+ , Space+ , Span+ ( ""+ , [ "nature" ]+ , [ ( "style"+ , "display: inline; font-size: 100%"+ )+ ]+ )+ [ Str "[REQUIRED]" ]+ ]+ ]+ , Div+ ( "" , [ "otest" ] , [] )+ [ Para+ [ Str "Tests"+ , Space+ , Str "for"+ , Space+ , Emph [ Str "optional" ]+ , Space+ , Str "Reading"+ , Space+ , Str "System"+ , Space+ , Str "functionality"+ , Space+ , Str "are"+ , SoftBreak+ , Str "preceded"+ , Space+ , Str "by"+ , Space+ , Str "the"+ , Space+ , Str "label:"+ , Space+ , Span+ ( ""+ , [ "nature" ]+ , [ ( "style"+ , "display: inline; font-size: 100%"+ )+ ]+ )+ [ Str "[OPTIONAL]" ]+ ]+ ]+ ]+ ]+ )+ , ( [ Str "2."+ , Space+ , Str "Performing"+ , Space+ , Str "the"+ , Space+ , Str "test"+ ]+ , [ [ Plain+ [ Str "Each"+ , Space+ , Str "test"+ , Space+ , Str "includes"+ , Space+ , Str "a"+ , Space+ , Str "description"+ , Space+ , Str "of"+ , Space+ , Str "its"+ , Space+ , Str "purpose"+ , Space+ , Str "followed"+ , Space+ , Str "by"+ , Space+ , Str "the"+ , Space+ , Str "actual"+ , Space+ , Strong+ [ Str "test"+ , Space+ , Str "statement,"+ , SoftBreak+ , Str "which"+ , Space+ , Str "can"+ , Space+ , Str "always"+ , Space+ , Str "be"+ , Space+ , Str "evaluated"+ , Space+ , Str "to"+ , Space+ , Str "true"+ , Space+ , Str "or"+ , Space+ , Str "false"+ ]+ , Str "."+ , Space+ , Str "These"+ , Space+ , Str "statements"+ , Space+ , Str "typically"+ , Space+ , Str "have"+ , Space+ , Str "the"+ , Space+ , Str "form:"+ , SoftBreak+ , Str "\"If"+ , Space+ , Str "[some"+ , Space+ , Str "condition],"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes\"."+ ]+ ]+ ]+ )+ , ( [ Str "3."+ , Space+ , Str "Scoring"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "results"+ , Space+ , Str "form"+ ]+ , [ [ Plain+ [ Str "@@@TODO"+ , Space+ , Str "provide"+ , Space+ , Str "info"+ , Space+ , Str "on"+ , Space+ , Str "where"+ , Space+ , Str "to"+ , Space+ , Str "get"+ , Space+ , Str "the"+ , Space+ , Str "results"+ , Space+ , Str "form"+ ]+ ]+ ]+ )+ ]+ ]+ ]+ , Para [ Span ( "styling-xhtml-001.xhtml" , [] , [] ) [] ]+ , Div+ ( "styling-xhtml-001.xhtml_epub-css" , [ "section" ] , [] )+ [ Header+ 1+ ( "" , [] , [] )+ [ Str "EPUB" , Space , Str "Style" , Space , Str "Sheets" ]+ , Para+ [ Str "This"+ , Space+ , Str "section"+ , Space+ , Str "contains"+ , Space+ , Str "tests"+ , Space+ , Str "for"+ , Space+ , Str "styling"+ , Space+ , Str "and"+ , Space+ , Str "layout."+ ]+ ]+ , Para [ Span ( "styling-xhtml-003.xhtml" , [] , [] ) [] ]+ , Div+ ( "styling-xhtml-003.xhtml_style-110"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-110" ]+ , Space+ , Str "Multi-Column"+ , Space+ , Str "Layouts"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Link+ ( "" , [] , [] )+ [ Code ( "" , [] , [] ) "CSS Multi-Column Layout" ]+ ( "http://idpf.org/epub/30/spec/epub30-contentdocs.html#sec-css-multi-column"+ , ""+ )+ , Space+ , Str "properties"+ , Space+ , Str "are"+ , Space+ , Str "supported."+ ]+ , Div+ ( "" , [ "multicol" ] , [] )+ [ Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ , Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ , Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ , Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ , Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ , Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ , Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ , Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ , Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "text"+ , Space+ , Str "is"+ , Space+ , Str "rendered"+ , Space+ , Str "in"+ , Space+ , Str "three"+ , Space+ , Str "columns,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Para [ Span ( "styling-xhtml-002.xhtml" , [] , [] ) [] ]+ , Div+ ( "styling-xhtml-002.xhtml_style-lists"+ , [ "section" ]+ , []+ )+ [ Header 2 ( "" , [] , [] ) [ Str "Lists" ]+ , Div+ ( "styling-xhtml-002.xhtml_style-list-style-type"+ , [ "section" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Str "The"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-009"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-009" ]+ , Space+ , Code ( "" , [] , [] ) "decimal"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "decimal"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "decimal"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-010"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-010" ]+ , Space+ , Code ( "" , [] , [] ) "circle"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "circle"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ul"+ , Space+ , Str "element."+ ]+ , BulletList+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "circle"+ , Space+ , Str "markers,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-011"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-011" ]+ , Space+ , Code ( "" , [] , [] ) "square"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "square"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ul"+ , Space+ , Str "element."+ ]+ , BulletList+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "square"+ , Space+ , Str "markers,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-012"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-012" ]+ , Space+ , Code ( "" , [] , [] ) "disc"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "disc"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ul"+ , Space+ , Str "element."+ ]+ , BulletList+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "disc"+ , Space+ , Str "markers,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-013"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-013" ]+ , Space+ , Code ( "" , [] , [] ) "lower-latin"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "lower-latin"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "lower-latin"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-014"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-014" ]+ , Space+ , Code ( "" , [] , [] ) "lower-roman"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "lower-roman"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "lower-roman"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-015"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-015" ]+ , Space+ , Code ( "" , [] , [] ) "upper-alpha"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "upper-alpha"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "upper-alpha"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-016"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-016" ]+ , Space+ , Code ( "" , [] , [] ) "hiragana"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "hiragana"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "hiragana"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-017"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-017" ]+ , Space+ , Code ( "" , [] , [] ) "hiragana-iroha"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "hiragana-iroha"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "hiragana-iroha"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-018"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-018" ]+ , Space+ , Code ( "" , [] , [] ) "katakana"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "katakana"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "katakana"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-019"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-019" ]+ , Space+ , Code ( "" , [] , [] ) "katakana-iroha"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "katakana-iroha"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "katakana-iroha"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-020"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-020" ]+ , Space+ , Code ( "" , [] , [] ) "upper-roman"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "upper-roman"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "upper-roman"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-021"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-021" ]+ , Space+ , Code ( "" , [] , [] ) "upper-latin"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "upper-latin"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "upper-latin"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-022"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-022" ]+ , Space+ , Code ( "" , [] , [] ) "lower-alpha"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "lower-alpha"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "lower-alpha"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-023"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-023" ]+ , Space+ , Code ( "" , [] , [] ) "lower-greek"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "lower-greek"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "lower-greek"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-024"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-024" ]+ , Space+ , Code ( "" , [] , [] ) "armenian"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "armenian"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "armenian"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-025"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-025" ]+ , Space+ , Code ( "" , [] , [] ) "cjk-ideographic"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "cjk-ideographic"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "cjk-ideographic"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-026"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-026" ]+ , Space+ , Code ( "" , [] , [] ) "decimal-leading-zero"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "decimal-leading-zero"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "decimal-leading-zero"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-027"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-027" ]+ , Space+ , Code ( "" , [] , [] ) "georgian"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "georgian"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "georgian"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-028"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-028" ]+ , Space+ , Code ( "" , [] , [] ) "hebrew"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "hebrew"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "hebrew"+ , Space+ , Str "markers"+ , Space+ , Str "in"+ , Space+ , Str "ascending"+ , Space+ , Str "order,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-029"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-029" ]+ , Space+ , Code ( "" , [] , [] ) "none"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "none"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element."+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "no"+ , Space+ , Str "markers,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-list-style"+ , [ "section" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Str "The"+ , Space+ , Code ( "" , [] , [] ) "list-style"+ , Space+ , Str "property"+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-030"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-030" ]+ , Space+ , Str "images"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style"+ , Space+ , Str "shorthand"+ , Space+ , Str "property"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "using"+ , Space+ , Str "a"+ , Space+ , Str "gif"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ul"+ , Space+ , Str "element."+ ]+ , BulletList+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "the"+ , Space+ , Str "purple"+ , Space+ , Str "and"+ , Space+ , Str "aqua"+ , Space+ , Str "square"+ , Space+ , Str "bullet"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-list-style-position"+ , [ "section" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Str "The"+ , Space+ , Code ( "" , [] , [] ) "list-style-position"+ , Space+ , Str "property"+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-040"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-040" ]+ , Space+ , Str "The"+ , Space+ , Code ( "" , [] , [] ) "list-style-position"+ , Space+ , Str "property:"+ , Space+ , Code ( "" , [] , [] ) "inside"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-position"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "inside"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ul"+ , Space+ , Str "element."+ ]+ , BulletList+ [ [ Plain+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ ]+ ]+ , [ Plain+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ ]+ ]+ , [ Plain+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ ]+ ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "markers"+ , Space+ , Str "inside"+ , Space+ , Str "the"+ , Space+ , Str "indentation,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-041"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-041" ]+ , Space+ , Str "The"+ , Space+ , Code ( "" , [] , [] ) "list-style-position"+ , Space+ , Str "property:"+ , Space+ , Code ( "" , [] , [] ) "outside"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "list-style-position"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "outside"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ul"+ , Space+ , Str "element."+ ]+ , BulletList+ [ [ Plain+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ ]+ ]+ , [ Plain+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ ]+ ]+ , [ Plain+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ ]+ ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "has"+ , Space+ , Str "the"+ , Space+ , Str "default"+ , Space+ , Str "setting"+ , Space+ , Str "(marker"+ , Space+ , Str "outside"+ , Space+ , Str "the"+ , Space+ , Str "indentation),"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-list-start"+ , [ "section" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Str "The"+ , Space+ , Str "HTML"+ , Space+ , Code ( "" , [] , [] ) "start"+ , Space+ , Str "attribute"+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-050"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-050" ]+ , Space+ , Str "Without"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "set"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "start"+ , Space+ , Str "attribute"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element"+ , Space+ , Str "with"+ , Space+ , Str "no"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property."+ ]+ , OrderedList+ ( 25 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "starts"+ , Space+ , Str "at"+ , Space+ , Str "25,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-002.xhtml_style-051"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 4+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-051" ]+ , Space+ , Str "With"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "set"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "start"+ , Space+ , Str "attribute"+ , Space+ , Str "is"+ , Space+ , Str "supported"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "ol"+ , Space+ , Str "element"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Code ( "" , [] , [] ) "list-style-type"+ , Space+ , Str "property."+ ]+ , OrderedList+ ( 50 , DefaultStyle , DefaultDelim )+ [ [ Plain [ Str "Lorem" ] ]+ , [ Plain [ Str "Ipsum" ] ]+ , [ Plain [ Str "Dolor" ] ]+ , [ Plain [ Str "Sit" ] ]+ , [ Plain [ Str "Amet" ] ]+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "list"+ , Space+ , Str "starts"+ , Space+ , Str "at"+ , Space+ , Str "'L'"+ , Space+ , Str "(50),"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ ]+ ]+ , Para [ Span ( "styling-xhtml-004.xhtml" , [] , [] ) [] ]+ , Div+ ( "styling-xhtml-004.xhtml_style-media-rules"+ , [ "section" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Code ( "" , [] , [] ) "@media" , Space , Str "Rules" ]+ , Div+ ( "styling-xhtml-004.xhtml_style-210"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-210" ]+ , Space+ , Code ( "" , [] , [] ) "all"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "@media"+ , Space+ , Str "rule"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "all"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para [ Str "FAIL" ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "reads"+ , Space+ , Str "\"FAIL\","+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "fails."+ ]+ ]+ , Div+ ( "styling-xhtml-004.xhtml_style-211"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-211" ]+ , Space+ , Code ( "" , [] , [] ) "screen"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "@media"+ , Space+ , Str "rule"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "screen"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para [ Str "FAIL" ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "reads"+ , Space+ , Str "\"FAIL\","+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "fails."+ ]+ ]+ , Div+ ( "styling-xhtml-004.xhtml_style-212"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-212" ]+ , Space+ , Code ( "" , [] , [] ) "handheld"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "@media"+ , Space+ , Str "rule"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "handheld"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para [ Str "FAIL" ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "reads"+ , Space+ , Str "\"FAIL\","+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "fails."+ ]+ ]+ , Div+ ( "styling-xhtml-004.xhtml_style-213"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-213" ]+ , Space+ , Code ( "" , [] , [] ) "tv"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "@media"+ , Space+ , Str "rule"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "tv"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para [ Str "FAIL" ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "reads"+ , Space+ , Str "\"FAIL\","+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "fails."+ ]+ ]+ , Div+ ( "styling-xhtml-004.xhtml_style-220"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-220" ]+ , Space+ , Code ( "" , [] , [] ) "orientation:landscape"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "@media"+ , Space+ , Str "rule"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "orientation:landscape"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para [ Str "FAIL" ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "reads"+ , Space+ , Str "\"FAIL\""+ , Space+ , Str "when"+ , Space+ , Str "the"+ , Space+ , Str "device"+ , Space+ , Str "is"+ , Space+ , Str "held"+ , Space+ , Str "in"+ , Space+ , Str "landscape"+ , Space+ , Str "mode,"+ , Space+ , Str "and"+ , Space+ , Str "the"+ , Space+ , Str "device"+ , Space+ , Str "supports"+ , Space+ , Str "multiple"+ , Space+ , Str "orientations,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "fails."+ ]+ ]+ , Div+ ( "styling-xhtml-004.xhtml_style-221"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-221" ]+ , Space+ , Code ( "" , [] , [] ) "orientation:portrait"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "@media"+ , Space+ , Str "rule"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "orientation:portrait"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para [ Str "FAIL" ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "reads"+ , Space+ , Str "\"FAIL\""+ , Space+ , Str "when"+ , Space+ , Str "the"+ , Space+ , Str "device"+ , Space+ , Str "is"+ , Space+ , Str "held"+ , Space+ , Str "in"+ , Space+ , Str "portrait"+ , Space+ , Str "mode,"+ , Space+ , Str "and"+ , Space+ , Str "the"+ , Space+ , Str "device"+ , Space+ , Str "supports"+ , Space+ , Str "multiple"+ , Space+ , Str "orientations,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "fails."+ ]+ ]+ , Div+ ( "styling-xhtml-004.xhtml_style-230"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-230" ]+ , Space+ , Code ( "" , [] , [] ) "min-width"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "@media"+ , Space+ , Str "rule"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "min-width:200px"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para [ Str "FAIL" ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "reads"+ , Space+ , Str "\"FAIL\","+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "fails."+ ]+ ]+ , Div+ ( "styling-xhtml-004.xhtml_style-231"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-231" ]+ , Space+ , Code ( "" , [] , [] ) "max-width"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "@media"+ , Space+ , Str "rule"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "max-width:2000px"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para [ Str "FAIL" ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "reads"+ , Space+ , Str "\"FAIL\","+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "fails."+ ]+ ]+ , Div+ ( "styling-xhtml-004.xhtml_style-240"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-240" ]+ , Space+ , Code ( "" , [] , [] ) "min-device-width"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "@media"+ , Space+ , Str "rule"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "min-device-width:200px"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para [ Str "FAIL" ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "reads"+ , Space+ , Str "\"FAIL\","+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "fails."+ ]+ ]+ , Div+ ( "styling-xhtml-004.xhtml_style-241"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 3+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-241" ]+ , Space+ , Code ( "" , [] , [] ) "max-device-width"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "@media"+ , Space+ , Str "rule"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Code ( "" , [] , [] ) "max-device-width:2000px"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para [ Str "FAIL" ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "reads"+ , Space+ , Str "\"FAIL\","+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "fails."+ ]+ ]+ ]+ , Para [ Span ( "styling-xhtml-005.xhtml" , [] , [] ) [] ]+ , Div+ ( "styling-xhtml-005.xhtml_style-text-xform"+ , [ "section" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "The"+ , Space+ , Code ( "" , [] , [] ) "text-transform"+ , Space+ , Str "property"+ ]+ , Div+ ( "styling-xhtml-005.xhtml_style-310"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-310" ]+ , Space+ , Code ( "" , [] , [] ) "uppercase"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "text-transform"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Str "uppercase"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "is"+ , Space+ , Str "in"+ , Space+ , Str "upper"+ , Space+ , Str "case,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-005.xhtml_style-311"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-311" ]+ , Space+ , Code ( "" , [] , [] ) "capitalize"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "text-transform"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Str "capitalize"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ , Para+ [ Str "If"+ , Space+ , Str "each"+ , Space+ , Str "first"+ , Space+ , Str "letter"+ , Space+ , Str "of"+ , Space+ , Str "each"+ , Space+ , Str "word"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "is"+ , Space+ , Str "in"+ , Space+ , Str "upper"+ , Space+ , Str "case,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-005.xhtml_style-312"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-312" ]+ , Space+ , Code ( "" , [] , [] ) "lowercase"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "text-transform"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Str "lowercase"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Para+ [ Str "Lorem"+ , Space+ , Str "ipsum"+ , Space+ , Str "dolor"+ , Space+ , Str "sit"+ , Space+ , Str "amet,"+ , Space+ , Str "consectetur"+ , Space+ , Str "adipisicing"+ , Space+ , Str "elit,"+ , Space+ , Str "sed"+ , Space+ , Str "do"+ , Space+ , Str "eiusmod"+ , Space+ , Str "tempor"+ , Space+ , Str "incididunt"+ , Space+ , Str "ut"+ , Space+ , Str "labore"+ , Space+ , Str "et"+ , Space+ , Str "dolore"+ , Space+ , Str "magna"+ , Space+ , Str "aliqua."+ , Space+ , Str "Ut"+ , Space+ , Str "enim"+ , Space+ , Str "ad"+ , Space+ , Str "minim"+ , Space+ , Str "veniam,"+ , Space+ , Str "quis"+ , Space+ , Str "nostrud"+ , Space+ , Str "exercitation"+ , Space+ , Str "ullamco"+ , Space+ , Str "laboris"+ , Space+ , Str "nisi"+ , Space+ , Str "ut"+ , Space+ , Str "aliquip"+ , Space+ , Str "ex"+ , Space+ , Str "ea"+ , Space+ , Str "commodo"+ , Space+ , Str "consequat."+ , Space+ , Str "Duis"+ , Space+ , Str "aute"+ , Space+ , Str "irure"+ , Space+ , Str "dolor"+ , Space+ , Str "in"+ , Space+ , Str "reprehenderit"+ , Space+ , Str "in"+ , Space+ , Str "voluptate"+ , Space+ , Str "velit"+ , Space+ , Str "esse"+ , Space+ , Str "cillum"+ , Space+ , Str "dolore"+ , Space+ , Str "eu"+ , Space+ , Str "fugiat"+ , Space+ , Str "nulla"+ , Space+ , Str "pariatur."+ , Space+ , Str "Excepteur"+ , Space+ , Str "sint"+ , Space+ , Str "occaecat"+ , Space+ , Str "cupidatat"+ , Space+ , Str "non"+ , Space+ , Str "proident,"+ , Space+ , Str "sunt"+ , Space+ , Str "in"+ , Space+ , Str "culpa"+ , Space+ , Str "qui"+ , Space+ , Str "officia"+ , Space+ , Str "deserunt"+ , Space+ , Str "mollit"+ , Space+ , Str "anim"+ , Space+ , Str "id"+ , Space+ , Str "est"+ , Space+ , Str "laborum."+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "preceding"+ , Space+ , Str "paragraph"+ , Space+ , Str "is"+ , Space+ , Str "in"+ , Space+ , Str "lower"+ , Space+ , Str "case,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ ]+ , Para [ Span ( "styling-xhtml-006.xhtml" , [] , [] ) [] ]+ , Div+ ( "styling-xhtml-006.xhtml_style-ruby"+ , [ "section" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "The"+ , Space+ , Code ( "" , [] , [] ) "epub-ruby-position"+ , Space+ , Str "property"+ ]+ , Div+ ( "styling-xhtml-006.xhtml_style-410"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-410" ]+ , Space+ , Code ( "" , [] , [] ) "over"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "-epub-ruby-position"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Str "over"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Plain+ [ RawInline (Format "html") "<ruby class=\"ruby-over\">"+ , Strong [ Str "Lorem" , Space , Str "Ipsum" ]+ , Space+ , RawInline (Format "html") "<rp>"+ , Str "("+ , RawInline (Format "html") "</rp>"+ , RawInline (Format "html") "<rt>"+ , Str "Lorem"+ , Space+ , Str "Ipsum"+ , RawInline (Format "html") "</rt>"+ , RawInline (Format "html") "<rp>"+ , Str ")"+ , RawInline (Format "html") "</rp>"+ , RawInline (Format "html") "</ruby>"+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "Ruby"+ , Space+ , Str "text"+ , Space+ , Str "is"+ , Space+ , Str "positioned"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "over" ]+ ( "http://www.w3.org/TR/css3-writing-modes/#over"+ , ""+ )+ , Space+ , Str "side"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "ruby"+ , Space+ , Str "base,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-006.xhtml_style-411"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-411" ]+ , Space+ , Code ( "" , [] , [] ) "under"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "-epub-ruby-position"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Str "under"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Plain+ [ RawInline (Format "html") "<ruby class=\"ruby-under\">"+ , Strong [ Str "Lorem" , Space , Str "Ipsum" ]+ , Space+ , RawInline (Format "html") "<rp>"+ , Str "("+ , RawInline (Format "html") "</rp>"+ , RawInline (Format "html") "<rt>"+ , Str "Lorem"+ , Space+ , Str "Ipsum"+ , RawInline (Format "html") "</rt>"+ , RawInline (Format "html") "<rp>"+ , Str ")"+ , RawInline (Format "html") "</rp>"+ , RawInline (Format "html") "</ruby>"+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "Ruby"+ , Space+ , Str "text"+ , Space+ , Str "is"+ , Space+ , Str "positioned"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "under" ]+ ( "http://www.w3.org/TR/css3-writing-modes/#under"+ , ""+ )+ , Space+ , Str "side"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "ruby"+ , Space+ , Str "base,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ , Div+ ( "styling-xhtml-006.xhtml_style-412"+ , [ "section" , "ctest" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Span ( "" , [ "nature" ] , [] ) [ Str "[REQUIRED]" ]+ , Space+ , Span ( "" , [ "test-id" ] , [] ) [ Str "style-412" ]+ , Space+ , Code ( "" , [] , [] ) "inter-character"+ ]+ , Para+ [ Str "Tests"+ , Space+ , Str "whether"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "-epub-ruby-position"+ , Space+ , Str "property"+ , Space+ , Str "set"+ , Space+ , Str "to"+ , Space+ , Str "inter-caracter"+ , Space+ , Str "is"+ , Space+ , Str "supported."+ ]+ , Plain+ [ RawInline+ (Format "html")+ "<ruby class=\"ruby-inter-character\">"+ , Strong [ Str "Lorem" , Space , Str "Ipsum" ]+ , Space+ , RawInline (Format "html") "<rp>"+ , Str "("+ , RawInline (Format "html") "</rp>"+ , RawInline (Format "html") "<rt>"+ , Str "Lorem"+ , Space+ , Str "Ipsum"+ , RawInline (Format "html") "</rt>"+ , RawInline (Format "html") "<rp>"+ , Str ")"+ , RawInline (Format "html") "</rp>"+ , RawInline (Format "html") "</ruby>"+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "Ruby"+ , Space+ , Str "text"+ , Space+ , Str "is"+ , Space+ , Str "positioned"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Str "right"+ , Space+ , Str "side"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "base"+ , Space+ , Str "text,"+ , Space+ , Str "the"+ , Space+ , Str "test"+ , Space+ , Str "passes."+ ]+ ]+ ]+ ]
@@ -1,4551 +1,4602 @@-[ Para- [ Image ( "" , [] , [] ) [] ( "wasteland-cover.jpg" , "" ) ]-, Para [ Span ( "wasteland-content.xhtml" , [] , [] ) [] ]-, Div- ( "wasteland-content.xhtml#frontmatter"- , [ "section" , "frontmatter" ]- , []- )- []-, Div- ( "wasteland-content.xhtml#bodymatter"- , [ "section" , "bodymatter" ]- , []- )- [ Div- ( "wasteland-content.xhtml#ch1" , [ "section" ] , [] )- [ Header- 2- ( "" , [] , [] )- [ Str "I."- , Space- , Str "THE"- , Space- , Str "BURIAL"- , Space- , Str "OF"- , Space- , Str "THE"- , Space- , Str "DEAD"- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "" , [] , [] )- [ Plain- [ Str "April"- , Space- , Str "is"- , Space- , Str "the"- , Space- , Str "cruellest"- , Space- , Str "month,"- , Space- , Str "breeding"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Lilacs"- , Space- , Str "out"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "dead"- , Space- , Str "land,"- , Space- , Str "mixing"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Memory"- , Space- , Str "and"- , Space- , Str "desire,"- , Space- , Str "stirring"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Dull"- , Space- , Str "roots"- , Space- , Str "with"- , Space- , Str "spring"- , Space- , Str "rain."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Winter"- , Space- , Str "kept"- , Space- , Str "us"- , Space- , Str "warm,"- , Space- , Str "covering"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Earth"- , Space- , Str "in"- , Space- , Str "forgetful"- , Space- , Str "snow,"- , Space- , Str "feeding"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "A"- , Space- , Str "little"- , Space- , Str "life"- , Space- , Str "with"- , Space- , Str "dried"- , Space- , Str "tubers."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Summer"- , Space- , Str "surprised"- , Space- , Str "us,"- , Space- , Str "coming"- , Space- , Str "over"- , Space- , Str "the"- , Space- , Str "Starnbergersee"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "With"- , Space- , Str "a"- , Space- , Str "shower"- , Space- , Str "of"- , Space- , Str "rain;"- , Space- , Str "we"- , Space- , Str "stopped"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "colonnade,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "went"- , Space- , Str "on"- , Space- , Str "in"- , Space- , Str "sunlight,"- , Space- , Str "into"- , Space- , Str "the"- , Space- , Str "Hofgarten,"- , Span ( "" , [ "lnum" ] , [] ) [ Str "10" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "drank"- , Space- , Str "coffee,"- , Space- , Str "and"- , Space- , Str "talked"- , Space- , Str "for"- , Space- , Str "an"- , Space- , Str "hour."- ]- ]- , Div- ( "" , [] , [ ( "lang" , "de" ) ] )- [ Plain- [ Str "Bin"- , Space- , Str "gar"- , Space- , Str "keine"- , Space- , Str "Russin,"- , Space- , Str "stamm'"- , Space- , Str "aus"- , Space- , Str "Litauen,"- , Space- , Str "echt"- , SoftBreak- , Str "deutsch."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "when"- , Space- , Str "we"- , Space- , Str "were"- , Space- , Str "children,"- , Space- , Str "staying"- , Space- , Str "at"- , Space- , Str "the"- , Space- , Str "archduke's,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "My"- , Space- , Str "cousin's,"- , Space- , Str "he"- , Space- , Str "took"- , Space- , Str "me"- , Space- , Str "out"- , Space- , Str "on"- , Space- , Str "a"- , Space- , Str "sled,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "I"- , Space- , Str "was"- , Space- , Str "frightened."- , Space- , Str "He"- , Space- , Str "said,"- , Space- , Str "Marie,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Marie,"- , Space- , Str "hold"- , Space- , Str "on"- , Space- , Str "tight."- , Space- , Str "And"- , Space- , Str "down"- , Space- , Str "we"- , Space- , Str "went."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "In"- , Space- , Str "the"- , Space- , Str "mountains,"- , Space- , Str "there"- , Space- , Str "you"- , Space- , Str "feel"- , Space- , Str "free."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "I"- , Space- , Str "read,"- , Space- , Str "much"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "night,"- , Space- , Str "and"- , Space- , Str "go"- , Space- , Str "south"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "winter."- ]- ]- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "" , [] , [] )- [ Plain- [ Str "What"- , Space- , Str "are"- , Space- , Str "the"- , Space- , Str "roots"- , Space- , Str "that"- , Space- , Str "clutch,"- , Space- , Str "what"- , Space- , Str "branches"- , Space- , Str "grow"- ]- ]- , Div- ( "wasteland-content.xhtml#ln20" , [] , [] )- [ Plain- [ Str "Out"- , Space- , Str "of"- , Space- , Str "this"- , Space- , Str "stony"- , Space- , Str "rubbish?"- , Space- , Str "Son"- , Space- , Str "of"- , Space- , Str "man,"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "Line" , Space , Str "20." ]- ( "#wasteland-content.xhtml#ln20" , "" )- , Space- , Str "Cf."- , Space- , Str "Ezekiel"- , Space- , Str "2:1."- ]- ]- , Span ( "" , [ "lnum" ] , [] ) [ Str "20" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "You"- , Space- , Str "cannot"- , Space- , Str "say,"- , Space- , Str "or"- , Space- , Str "guess,"- , Space- , Str "for"- , Space- , Str "you"- , Space- , Str "know"- , Space- , Str "only"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "A"- , Space- , Str "heap"- , Space- , Str "of"- , Space- , Str "broken"- , Space- , Str "images,"- , Space- , Str "where"- , Space- , Str "the"- , Space- , Str "sun"- , Space- , Str "beats,"- ]- ]- , Div- ( "wasteland-content.xhtml#ln23" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "the"- , Space- , Str "dead"- , Space- , Str "tree"- , Space- , Str "gives"- , Space- , Str "no"- , Space- , Str "shelter,"- , Space- , Str "the"- , Space- , Str "cricket"- , Space- , Str "no"- , Space- , Str "relief,"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "23." ]- ( "#wasteland-content.xhtml#ln23" , "" )- , Space- , Str "Cf."- , Space- , Str "Ecclesiastes"- , Space- , Str "12:5."- ]- ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "the"- , Space- , Str "dry"- , Space- , Str "stone"- , Space- , Str "no"- , Space- , Str "sound"- , Space- , Str "of"- , Space- , Str "water."- , Space- , Str "Only"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "There"- , Space- , Str "is"- , Space- , Str "shadow"- , Space- , Str "under"- , Space- , Str "this"- , Space- , Str "red"- , Space- , Str "rock,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "(Come"- , Space- , Str "in"- , Space- , Str "under"- , Space- , Str "the"- , Space- , Str "shadow"- , Space- , Str "of"- , Space- , Str "this"- , Space- , Str "red"- , Space- , Str "rock),"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "I"- , Space- , Str "will"- , Space- , Str "show"- , Space- , Str "you"- , Space- , Str "something"- , Space- , Str "different"- , Space- , Str "from"- , Space- , Str "either"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Your"- , Space- , Str "shadow"- , Space- , Str "at"- , Space- , Str "morning"- , Space- , Str "striding"- , Space- , Str "behind"- , Space- , Str "you"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Or"- , Space- , Str "your"- , Space- , Str "shadow"- , Space- , Str "at"- , Space- , Str "evening"- , Space- , Str "rising"- , Space- , Str "to"- , Space- , Str "meet"- , Space- , Str "you;"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "I"- , Space- , Str "will"- , Space- , Str "show"- , Space- , Str "you"- , Space- , Str "fear"- , Space- , Str "in"- , Space- , Str "a"- , Space- , Str "handful"- , Space- , Str "of"- , Space- , Str "dust."- , Span ( "" , [ "lnum" ] , [] ) [ Str "30" ]- ]- ]- , BlockQuote- [ Div- ( "" , [] , [] )- [ Div- ( "wasteland-content.xhtml#ln31" , [] , [] )- [ Plain- [ Str "Frisch"- , Space- , Str "weht"- , Space- , Str "der"- , Space- , Str "Wind"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "31." ]- ( "#wasteland-content.xhtml#ln31"- , ""- )- , Space- , Str "V."- , Space- , Str "Tristan"- , Space- , Str "und"- , Space- , Str "Isolde,"- , Space- , Str "i,"- , Space- , Str "verses"- , Space- , Str "5-8."- ]- ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Der"- , Space- , Str "Heimat"- , Space- , Str "zu"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Mein"- , Space- , Str "Irisch"- , Space- , Str "Kind,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Wo"- , Space- , Str "weilest"- , Space- , Str "du?"- ]- ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"You"- , Space- , Str "gave"- , Space- , Str "me"- , Space- , Str "hyacinths"- , Space- , Str "first"- , Space- , Str "a"- , Space- , Str "year"- , Space- , Str "ago;"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"They"- , Space- , Str "called"- , Space- , Str "me"- , Space- , Str "the"- , Space- , Str "hyacinth"- , Space- , Str "girl.\""- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\8213Yet"- , Space- , Str "when"- , Space- , Str "we"- , Space- , Str "came"- , Space- , Str "back,"- , Space- , Str "late,"- , Space- , Str "from"- , Space- , Str "the"- , Space- , Str "Hyacinth"- , SoftBreak- , Str "garden,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Your"- , Space- , Str "arms"- , Space- , Str "full,"- , Space- , Str "and"- , Space- , Str "your"- , Space- , Str "hair"- , Space- , Str "wet,"- , Space- , Str "I"- , Space- , Str "could"- , Space- , Str "not"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Speak,"- , Space- , Str "and"- , Space- , Str "my"- , Space- , Str "eyes"- , Space- , Str "failed,"- , Space- , Str "I"- , Space- , Str "was"- , Space- , Str "neither"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Living"- , Space- , Str "nor"- , Space- , Str "dead,"- , Space- , Str "and"- , Space- , Str "I"- , Space- , Str "knew"- , Space- , Str "nothing,"- , Span ( "" , [ "lnum" ] , [] ) [ Str "40" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Looking"- , Space- , Str "into"- , Space- , Str "the"- , Space- , Str "heart"- , Space- , Str "of"- , Space- , Str "light,"- , Space- , Str "the"- , Space- , Str "silence."- ]- ]- , Div- ( "wasteland-content.xhtml#ln42"- , []- , [ ( "lang" , "de" ) ]- )- [ Plain- [ Emph- [ Str "Od'"- , Space- , Str "und"- , Space- , Str "leer"- , Space- , Str "das"- , Space- , Str "Meer"- ]- , Str "."- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "42." ]- ( "#wasteland-content.xhtml#ln42" , "" )- , Space- , Str "Id."- , Space- , Str "iii,"- , Space- , Str "verse"- , Space- , Str "24."- ]- ]- ]- ]- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "" , [] , [] )- [ Plain- [ Str "Madame"- , Space- , Str "Sosostris,"- , Space- , Str "famous"- , Space- , Str "clairvoyante,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Had"- , Space- , Str "a"- , Space- , Str "bad"- , Space- , Str "cold,"- , Space- , Str "nevertheless"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Is"- , Space- , Str "known"- , Space- , Str "to"- , Space- , Str "be"- , Space- , Str "the"- , Space- , Str "wisest"- , Space- , Str "woman"- , Space- , Str "in"- , Space- , Str "Europe,"- ]- ]- , Div- ( "wasteland-content.xhtml#ln46" , [] , [] )- [ Plain- [ Str "With"- , Space- , Str "a"- , Space- , Str "wicked"- , Space- , Str "pack"- , Space- , Str "of"- , Space- , Str "cards."- , Space- , Str "Here,"- , Space- , Str "said"- , Space- , Str "she,"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "46." ]- ( "#wasteland-content.xhtml#ln46" , "" )- , Space- , Str "I"- , Space- , Str "am"- , Space- , Str "not"- , Space- , Str "familiar"- , Space- , Str "with"- , Space- , Str "the"- , Space- , Str "exact"- , Space- , Str "constitution"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "Tarot"- , Space- , Str "pack"- , Space- , Str "of"- , SoftBreak- , Str "cards,"- , Space- , Str "from"- , Space- , Str "which"- , Space- , Str "I"- , Space- , Str "have"- , Space- , Str "obviously"- , Space- , Str "departed"- , Space- , Str "to"- , Space- , Str "suit"- , Space- , Str "my"- , Space- , Str "own"- , Space- , Str "convenience."- , SoftBreak- , Str "The"- , Space- , Str "Hanged"- , Space- , Str "Man,"- , Space- , Str "a"- , Space- , Str "member"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "traditional"- , Space- , Str "pack,"- , Space- , Str "fits"- , Space- , Str "my"- , Space- , Str "purpose"- , Space- , Str "in"- , Space- , Str "two"- , SoftBreak- , Str "ways:"- , Space- , Str "because"- , Space- , Str "he"- , Space- , Str "is"- , Space- , Str "associated"- , Space- , Str "in"- , Space- , Str "my"- , Space- , Str "mind"- , Space- , Str "with"- , Space- , Str "the"- , Space- , Str "Hanged"- , Space- , Str "God"- , Space- , Str "of"- , Space- , Str "Frazer,"- , SoftBreak- , Str "and"- , Space- , Str "because"- , Space- , Str "I"- , Space- , Str "associate"- , Space- , Str "him"- , Space- , Str "with"- , Space- , Str "the"- , Space- , Str "hooded"- , Space- , Str "figure"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "passage"- , Space- , Str "of"- , Space- , Str "the"- , SoftBreak- , Str "disciples"- , Space- , Str "to"- , Space- , Str "Emmaus"- , Space- , Str "in"- , Space- , Str "Part"- , Space- , Str "V."- , Space- , Str "The"- , Space- , Str "Phoenician"- , Space- , Str "Sailor"- , Space- , Str "and"- , Space- , Str "the"- , Space- , Str "Merchant"- , SoftBreak- , Str "appear"- , Space- , Str "later;"- , Space- , Str "also"- , Space- , Str "the"- , Space- , Str "\"crowds"- , Space- , Str "of"- , Space- , Str "people,\""- , Space- , Str "and"- , Space- , Str "Death"- , Space- , Str "by"- , Space- , Str "Water"- , Space- , Str "is"- , SoftBreak- , Str "executed"- , Space- , Str "in"- , Space- , Str "Part"- , Space- , Str "IV."- , Space- , Str "The"- , Space- , Str "Man"- , Space- , Str "with"- , Space- , Str "Three"- , Space- , Str "Staves"- , Space- , Str "(an"- , Space- , Str "authentic"- , Space- , Str "member"- , Space- , Str "of"- , SoftBreak- , Str "the"- , Space- , Str "Tarot"- , Space- , Str "pack)"- , Space- , Str "I"- , Space- , Str "associate,"- , Space- , Str "quite"- , Space- , Str "arbitrarily,"- , Space- , Str "with"- , Space- , Str "the"- , Space- , Str "Fisher"- , Space- , Str "King"- , SoftBreak- , Str "himself."- ]- ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Is"- , Space- , Str "your"- , Space- , Str "card,"- , Space- , Str "the"- , Space- , Str "drowned"- , Space- , Str "Phoenician"- , Space- , Str "Sailor,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "(Those"- , Space- , Str "are"- , Space- , Str "pearls"- , Space- , Str "that"- , Space- , Str "were"- , Space- , Str "his"- , Space- , Str "eyes."- , Space- , Str "Look!)"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Here"- , Space- , Str "is"- , Space- , Str "Belladonna,"- , Space- , Str "the"- , Space- , Str "Lady"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "Rocks,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "The"- , Space- , Str "lady"- , Space- , Str "of"- , Space- , Str "situations."- , Span ( "" , [ "lnum" ] , [] ) [ Str "50" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Here"- , Space- , Str "is"- , Space- , Str "the"- , Space- , Str "man"- , Space- , Str "with"- , Space- , Str "three"- , Space- , Str "staves,"- , Space- , Str "and"- , Space- , Str "here"- , Space- , Str "the"- , Space- , Str "Wheel,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "here"- , Space- , Str "is"- , Space- , Str "the"- , Space- , Str "one-eyed"- , Space- , Str "merchant,"- , Space- , Str "and"- , Space- , Str "this"- , Space- , Str "card,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Which"- , Space- , Str "is"- , Space- , Str "blank,"- , Space- , Str "is"- , Space- , Str "something"- , Space- , Str "he"- , Space- , Str "carries"- , Space- , Str "on"- , Space- , Str "his"- , Space- , Str "back,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Which"- , Space- , Str "I"- , Space- , Str "am"- , Space- , Str "forbidden"- , Space- , Str "to"- , Space- , Str "see."- , Space- , Str "I"- , Space- , Str "do"- , Space- , Str "not"- , Space- , Str "find"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "The"- , Space- , Str "Hanged"- , Space- , Str "Man."- , Space- , Str "Fear"- , Space- , Str "death"- , Space- , Str "by"- , Space- , Str "water."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "I"- , Space- , Str "see"- , Space- , Str "crowds"- , Space- , Str "of"- , Space- , Str "people,"- , Space- , Str "walking"- , Space- , Str "round"- , Space- , Str "in"- , Space- , Str "a"- , Space- , Str "ring."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Thank"- , Space- , Str "you."- , Space- , Str "If"- , Space- , Str "you"- , Space- , Str "see"- , Space- , Str "dear"- , Space- , Str "Mrs."- , Space- , Str "Equitone,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Tell"- , Space- , Str "her"- , Space- , Str "I"- , Space- , Str "bring"- , Space- , Str "the"- , Space- , Str "horoscope"- , Space- , Str "myself:"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "One"- , Space- , Str "must"- , Space- , Str "be"- , Space- , Str "so"- , Space- , Str "careful"- , Space- , Str "these"- , Space- , Str "days."- ]- ]- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "wasteland-content.xhtml#ln60" , [] , [] )- [ Plain- [ Str "Unreal"- , Space- , Str "City,"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "60." ]- ( "#wasteland-content.xhtml#ln60" , "" )- , Space- , Str "Cf."- , Space- , Str "Baudelaire:"- ]- , BlockQuote- [ Para- [ Str "\"Fourmillante"- , Space- , Str "cite;,"- , Space- , Str "cite;"- , Space- , Str "pleine"- , Space- , Str "de"- , Space- , Str "reves,"- , LineBreak- , Str "Ou"- , Space- , Str "le"- , Space- , Str "spectre"- , Space- , Str "en"- , SoftBreak- , Str "plein"- , Space- , Str "jour"- , Space- , Str "raccroche"- , Space- , Str "le"- , Space- , Str "passant.\""- ]- ]- ]- , Span ( "" , [ "lnum" ] , [] ) [ Str "60" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Under"- , Space- , Str "the"- , Space- , Str "brown"- , Space- , Str "fog"- , Space- , Str "of"- , Space- , Str "a"- , Space- , Str "winter"- , Space- , Str "dawn,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "A"- , Space- , Str "crowd"- , Space- , Str "flowed"- , Space- , Str "over"- , Space- , Str "London"- , Space- , Str "Bridge,"- , Space- , Str "so"- , Space- , Str "many,"- ]- ]- , Div- ( "wasteland-content.xhtml#ln63" , [] , [] )- [ Plain- [ Str "I"- , Space- , Str "had"- , Space- , Str "not"- , Space- , Str "thought"- , Space- , Str "death"- , Space- , Str "had"- , Space- , Str "undone"- , Space- , Str "so"- , Space- , Str "many."- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "63." ]- ( "#wasteland-content.xhtml#ln63" , "" )- , Space- , Str "Cf."- , Space- , Str "Inferno,"- , Space- , Str "iii."- , Space- , Str "55-7."- ]- , BlockQuote- [ Para- [ Str "\"si"- , Space- , Str "lunga"- , Space- , Str "tratta"- , LineBreak- , Str "di"- , Space- , Str "gente,"- , Space- , Str "ch'io"- , Space- , Str "non"- , Space- , Str "avrei"- , Space- , Str "mai"- , Space- , Str "creduto"- , LineBreak- , Str "che"- , SoftBreak- , Str "morte"- , Space- , Str "tanta"- , Space- , Str "n'avesse"- , Space- , Str "disfatta.\""- ]- ]- ]- ]- ]- , Div- ( "wasteland-content.xhtml#ln64" , [] , [] )- [ Plain- [ Str "Sighs,"- , Space- , Str "short"- , Space- , Str "and"- , Space- , Str "infrequent,"- , Space- , Str "were"- , Space- , Str "exhaled,"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "64." ]- ( "#wasteland-content.xhtml#ln64" , "" )- , Space- , Str "Cf."- , Space- , Str "Inferno,"- , Space- , Str "iv."- , Space- , Str "25-7:"- ]- , BlockQuote- [ Para- [ Str "\"Quivi,"- , Space- , Str "secondo"- , Space- , Str "che"- , Space- , Str "per"- , Space- , Str "ascoltahre,"- , LineBreak- , Str "\"non"- , Space- , Str "avea"- , Space- , Str "pianto,"- , Space- , Str "ma'"- , Space- , Str "che"- , Space- , Str "di"- , SoftBreak- , Str "sospiri,"- , LineBreak- , Str "\"che"- , Space- , Str "l'aura"- , Space- , Str "eterna"- , Space- , Str "facevan"- , Space- , Str "tremare.\""- ]- ]- ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "each"- , Space- , Str "man"- , Space- , Str "fixed"- , Space- , Str "his"- , Space- , Str "eyes"- , Space- , Str "before"- , Space- , Str "his"- , Space- , Str "feet."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Flowed"- , Space- , Str "up"- , Space- , Str "the"- , Space- , Str "hill"- , Space- , Str "and"- , Space- , Str "down"- , Space- , Str "King"- , Space- , Str "William"- , Space- , Str "Street,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "To"- , Space- , Str "where"- , Space- , Str "Saint"- , Space- , Str "Mary"- , Space- , Str "Woolnoth"- , Space- , Str "kept"- , Space- , Str "the"- , Space- , Str "hours"- ]- ]- , Div- ( "wasteland-content.xhtml#ln68" , [] , [] )- [ Plain- [ Str "With"- , Space- , Str "a"- , Space- , Str "dead"- , Space- , Str "sound"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Str "final"- , Space- , Str "stroke"- , Space- , Str "of"- , Space- , Str "nine."- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "68." ]- ( "#wasteland-content.xhtml#ln68" , "" )- , Space- , Str "A"- , Space- , Str "phenomenon"- , Space- , Str "which"- , Space- , Str "I"- , Space- , Str "have"- , Space- , Str "often"- , Space- , Str "noticed."- ]- ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "There"- , Space- , Str "I"- , Space- , Str "saw"- , Space- , Str "one"- , Space- , Str "I"- , Space- , Str "knew,"- , Space- , Str "and"- , Space- , Str "stopped"- , Space- , Str "him,"- , Space- , Str "crying"- , SoftBreak- , Str "\"Stetson!"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"You"- , Space- , Str "who"- , Space- , Str "were"- , Space- , Str "with"- , Space- , Str "me"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "ships"- , Space- , Str "at"- , Space- , Str "Mylae!"- , Span ( "" , [ "lnum" ] , [] ) [ Str "70" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"That"- , Space- , Str "corpse"- , Space- , Str "you"- , Space- , Str "planted"- , Space- , Str "last"- , Space- , Str "year"- , Space- , Str "in"- , Space- , Str "your"- , Space- , Str "garden,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"Has"- , Space- , Str "it"- , Space- , Str "begun"- , Space- , Str "to"- , Space- , Str "sprout?"- , Space- , Str "Will"- , Space- , Str "it"- , Space- , Str "bloom"- , Space- , Str "this"- , Space- , Str "year?"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"Or"- , Space- , Str "has"- , Space- , Str "the"- , Space- , Str "sudden"- , Space- , Str "frost"- , Space- , Str "disturbed"- , Space- , Str "its"- , Space- , Str "bed?"- ]- ]- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "wasteland-content.xhtml#ln74" , [] , [] )- [ Plain- [ Str "\"Oh"- , Space- , Str "keep"- , Space- , Str "the"- , Space- , Str "Dog"- , Space- , Str "far"- , Space- , Str "hence,"- , Space- , Str "that's"- , Space- , Str "friend"- , Space- , Str "to"- , Space- , Str "men,"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "74." ]- ( "#wasteland-content.xhtml#ln74" , "" )- , Space- , Str "Cf."- , Space- , Str "the"- , Space- , Str "Dirge"- , Space- , Str "in"- , Space- , Str "Webster's"- , Space- , Str "White"- , Space- , Str "Devil"- , Space- , Str "."- ]- ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"Or"- , Space- , Str "with"- , Space- , Str "his"- , Space- , Str "nails"- , Space- , Str "he'll"- , Space- , Str "dig"- , Space- , Str "it"- , Space- , Str "up"- , Space- , Str "again!"- ]- ]- , Div- ( "wasteland-content.xhtml#ln76" , [] , [] )- [ Plain- [ Str "\"You!"- , Space- , Span- ( "" , [] , [ ( "lang" , "fr" ) ] )- [ Str "hypocrite"- , Space- , Str "lecteur!"- , Space- , Str "-"- , Space- , Str "mon"- , Space- , Str "semblable,"- , Space- , Str "-"- , SoftBreak- , Str "mon"- , Space- , Str "frere"- ]- , Space- , Str "!\""- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "76." ]- ( "#wasteland-content.xhtml#ln76" , "" )- , Space- , Str "V."- , Space- , Str "Baudelaire,"- , Space- , Str "Preface"- , Space- , Str "to"- , Space- , Str "Fleurs"- , Space- , Str "du"- , Space- , Str "Mal."- ]- ]- ]- ]- ]- ]- , Div- ( "wasteland-content.xhtml#ch2" , [ "section" ] , [] )- [ Header- 2- ( "" , [] , [] )- [ Str "II."- , Space- , Str "A"- , Space- , Str "GAME"- , Space- , Str "OF"- , Space- , Str "CHESS"- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "wasteland-content.xhtml#ln77" , [] , [] )- [ Plain- [ Str "The"- , Space- , Str "Chair"- , Space- , Str "she"- , Space- , Str "sat"- , Space- , Str "in,"- , Space- , Str "like"- , Space- , Str "a"- , Space- , Str "burnished"- , Space- , Str "throne,"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "77." ]- ( "#wasteland-content.xhtml#ln77" , "" )- , Space- , Str "Cf."- , Space- , Str "Antony"- , Space- , Str "and"- , Space- , Str "Cleopatra,"- , Space- , Str "II."- , Space- , Str "ii.,"- , Space- , Str "l."- , Space- , Str "190."- ]- ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Glowed"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Str "marble,"- , Space- , Str "where"- , Space- , Str "the"- , Space- , Str "glass"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Held"- , Space- , Str "up"- , Space- , Str "by"- , Space- , Str "standards"- , Space- , Str "wrought"- , Space- , Str "with"- , Space- , Str "fruited"- , Space- , Str "vines"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "From"- , Space- , Str "which"- , Space- , Str "a"- , Space- , Str "golden"- , Space- , Str "Cupidon"- , Space- , Str "peeped"- , Space- , Str "out"- , Span ( "" , [ "lnum" ] , [] ) [ Str "80" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "(Another"- , Space- , Str "hid"- , Space- , Str "his"- , Space- , Str "eyes"- , Space- , Str "behind"- , Space- , Str "his"- , Space- , Str "wing)"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Doubled"- , Space- , Str "the"- , Space- , Str "flames"- , Space- , Str "of"- , Space- , Str "sevenbranched"- , Space- , Str "candelabra"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Reflecting"- , Space- , Str "light"- , Space- , Str "upon"- , Space- , Str "the"- , Space- , Str "table"- , Space- , Str "as"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "The"- , Space- , Str "glitter"- , Space- , Str "of"- , Space- , Str "her"- , Space- , Str "jewels"- , Space- , Str "rose"- , Space- , Str "to"- , Space- , Str "meet"- , Space- , Str "it,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "From"- , Space- , Str "satin"- , Space- , Str "cases"- , Space- , Str "poured"- , Space- , Str "in"- , Space- , Str "rich"- , Space- , Str "profusion;"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "In"- , Space- , Str "vials"- , Space- , Str "of"- , Space- , Str "ivory"- , Space- , Str "and"- , Space- , Str "coloured"- , Space- , Str "glass"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Unstoppered,"- , Space- , Str "lurked"- , Space- , Str "her"- , Space- , Str "strange"- , Space- , Str "synthetic"- , Space- , Str "perfumes,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Unguent,"- , Space- , Str "powdered,"- , Space- , Str "or"- , Space- , Str "liquid"- , Space- , Str "-"- , Space- , Str "troubled,"- , Space- , Str "confused"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "drowned"- , Space- , Str "the"- , Space- , Str "sense"- , Space- , Str "in"- , Space- , Str "odours;"- , Space- , Str "stirred"- , Space- , Str "by"- , Space- , Str "the"- , Space- , Str "air"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "That"- , Space- , Str "freshened"- , Space- , Str "from"- , Space- , Str "the"- , Space- , Str "window,"- , Space- , Str "these"- , Space- , Str "ascended"- , Span ( "" , [ "lnum" ] , [] ) [ Str "90" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "In"- , Space- , Str "fattening"- , Space- , Str "the"- , Space- , Str "prolonged"- , Space- , Str "candle-flames,"- ]- ]- , Div- ( "wasteland-content.xhtml#ln92" , [] , [] )- [ Plain- [ Str "Flung"- , Space- , Str "their"- , Space- , Str "smoke"- , Space- , Str "into"- , Space- , Str "the"- , Space- , Str "laquearia,"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "92." ]- ( "#wasteland-content.xhtml#ln92" , "" )- , Space- , Str "Laquearia."- , Space- , Str "V."- , Space- , Str "Aeneid,"- , Space- , Str "I."- , Space- , Str "726:"- ]- , BlockQuote- [ Para- [ Str "dependent"- , Space- , Str "lychni"- , Space- , Str "laquearibus"- , Space- , Str "aureis"- , Space- , Str "incensi,"- , Space- , Str "et"- , Space- , Str "noctem"- , SoftBreak- , Str "flammis"- , LineBreak- , Str "funalia"- , Space- , Str "vincunt."- ]- ]- ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Stirring"- , Space- , Str "the"- , Space- , Str "pattern"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Str "coffered"- , Space- , Str "ceiling."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Huge"- , Space- , Str "sea-wood"- , Space- , Str "fed"- , Space- , Str "with"- , Space- , Str "copper"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Burned"- , Space- , Str "green"- , Space- , Str "and"- , Space- , Str "orange,"- , Space- , Str "framed"- , Space- , Str "by"- , Space- , Str "the"- , Space- , Str "coloured"- , Space- , Str "stone,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "In"- , Space- , Str "which"- , Space- , Str "sad"- , Space- , Str "light"- , Space- , Str "a"- , Space- , Str "carved"- , Space- , Str "dolphin"- , Space- , Str "swam."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Above"- , Space- , Str "the"- , Space- , Str "antique"- , Space- , Str "mantel"- , Space- , Str "was"- , Space- , Str "displayed"- ]- ]- , Div- ( "wasteland-content.xhtml#ln98" , [] , [] )- [ Plain- [ Str "As"- , Space- , Str "though"- , Space- , Str "a"- , Space- , Str "window"- , Space- , Str "gave"- , Space- , Str "upon"- , Space- , Str "the"- , Space- , Str "sylvan"- , Space- , Str "scene"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "98." ]- ( "#wasteland-content.xhtml#ln98" , "" )- , Space- , Str "Sylvan"- , Space- , Str "scene."- , Space- , Str "V."- , Space- , Str "Milton,"- , Space- , Str "Paradise"- , Space- , Str "Lost,"- , Space- , Str "iv."- , Space- , Str "140."- ]- ]- ]- ]- , Div- ( "wasteland-content.xhtml#ln99" , [] , [] )- [ Plain- [ Str "The"- , Space- , Str "change"- , Space- , Str "of"- , Space- , Str "Philomel,"- , Space- , Str "by"- , Space- , Str "the"- , Space- , Str "barbarous"- , Space- , Str "king"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "99." ]- ( "#wasteland-content.xhtml#ln99" , "" )- , Space- , Str "V."- , Space- , Str "Ovid,"- , Space- , Str "Metamorphoses,"- , Space- , Str "vi,"- , Space- , Str "Philomela."- ]- ]- ]- ]- , Div- ( "wasteland-content.xhtml#ln100" , [] , [] )- [ Plain- [ Str "So"- , Space- , Str "rudely"- , Space- , Str "forced;"- , Space- , Str "yet"- , Space- , Str "there"- , Space- , Str "the"- , Space- , Str "nightingale"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "100." ]- ( "#wasteland-content.xhtml#ln100"- , ""- )- , Space- , Str "Cf."- , Space- , Str "Part"- , Space- , Str "III,"- , Space- , Str "l."- , Space- , Str "204."- ]- ]- , SoftBreak- , Span ( "" , [ "lnum" ] , [] ) [ Str "100" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Filled"- , Space- , Str "all"- , Space- , Str "the"- , Space- , Str "desert"- , Space- , Str "with"- , Space- , Str "inviolable"- , Space- , Str "voice"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "still"- , Space- , Str "she"- , Space- , Str "cried,"- , Space- , Str "and"- , Space- , Str "still"- , Space- , Str "the"- , Space- , Str "world"- , Space- , Str "pursues,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"Jug"- , Space- , Str "Jug\""- , Space- , Str "to"- , Space- , Str "dirty"- , Space- , Str "ears."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "other"- , Space- , Str "withered"- , Space- , Str "stumps"- , Space- , Str "of"- , Space- , Str "time"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Were"- , Space- , Str "told"- , Space- , Str "upon"- , Space- , Str "the"- , Space- , Str "walls;"- , Space- , Str "staring"- , Space- , Str "forms"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Leaned"- , Space- , Str "out,"- , Space- , Str "leaning,"- , Space- , Str "hushing"- , Space- , Str "the"- , Space- , Str "room"- , Space- , Str "enclosed."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Footsteps"- , Space- , Str "shuffled"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Str "stair."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Under"- , Space- , Str "the"- , Space- , Str "firelight,"- , Space- , Str "under"- , Space- , Str "the"- , Space- , Str "brush,"- , Space- , Str "her"- , Space- , Str "hair"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Spread"- , Space- , Str "out"- , Space- , Str "in"- , Space- , Str "fiery"- , Space- , Str "points"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Glowed"- , Space- , Str "into"- , Space- , Str "words,"- , Space- , Str "then"- , Space- , Str "would"- , Space- , Str "be"- , Space- , Str "savagely"- , Space- , Str "still."- , Span ( "" , [ "lnum" ] , [] ) [ Str "110" ]- ]- ]- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "" , [] , [] )- [ Plain- [ Str "\"My"- , Space- , Str "nerves"- , Space- , Str "are"- , Space- , Str "bad"- , Space- , Str "to-night."- , Space- , Str "Yes,"- , Space- , Str "bad."- , Space- , Str "Stay"- , Space- , Str "with"- , Space- , Str "me."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"Speak"- , Space- , Str "to"- , Space- , Str "me."- , Space- , Str "Why"- , Space- , Str "do"- , Space- , Str "you"- , Space- , Str "never"- , Space- , Str "speak."- , Space- , Str "Speak."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"What"- , Space- , Str "are"- , Space- , Str "you"- , Space- , Str "thinking"- , Space- , Str "of?"- , Space- , Str "What"- , Space- , Str "thinking?"- , Space- , Str "What?"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"I"- , Space- , Str "never"- , Space- , Str "know"- , Space- , Str "what"- , Space- , Str "you"- , Space- , Str "are"- , Space- , Str "thinking."- , Space- , Str "Think.\""- ]- ]- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "wasteland-content.xhtml#ln115" , [] , [] )- [ Plain- [ Str "I"- , Space- , Str "think"- , Space- , Str "we"- , Space- , Str "are"- , Space- , Str "in"- , Space- , Str "rats'"- , Space- , Str "alley"- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "115." ]- ( "#wasteland-content.xhtml#ln115"- , ""- )- , Space- , Str "Cf."- , Space- , Str "Part"- , Space- , Str "III,"- , Space- , Str "l."- , Space- , Str "195."- ]- ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Where"- , Space- , Str "the"- , Space- , Str "dead"- , Space- , Str "men"- , Space- , Str "lost"- , Space- , Str "their"- , Space- , Str "bones."- ]- ]- ]- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "" , [] , [] )- [ Plain- [ Str "\"What"- , Space- , Str "is"- , Space- , Str "that"- , Space- , Str "noise?\""- ]- ]- , Div- ( "wasteland-content.xhtml#ln118" , [ "indent" ] , [] )- [ Plain- [ Str "The"- , Space- , Str "wind"- , Space- , Str "under"- , Space- , Str "the"- , Space- , Str "door."- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "118." ]- ( "#wasteland-content.xhtml#ln118"- , ""- )- , Space- , Str "Cf."- , Space- , Str "Webster:"- ]- , BlockQuote- [ Para- [ Str "\"Is"- , Space- , Str "the"- , Space- , Str "wind"- , Space- , Str "in"- , Space- , Str "that"- , Space- , Str "door"- , Space- , Str "still?\""- ]- ]- ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"What"- , Space- , Str "is"- , Space- , Str "that"- , Space- , Str "noise"- , Space- , Str "now?"- , Space- , Str "What"- , Space- , Str "is"- , Space- , Str "the"- , Space- , Str "wind"- , Space- , Str "doing?\""- ]- ]- , Div- ( "" , [ "indent" ] , [] )- [ Plain- [ Str "Nothing"- , Space- , Str "again"- , Space- , Str "nothing."- , Span ( "" , [ "lnum" ] , [] ) [ Str "120" ]- ]- ]- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div ( "" , [] , [] ) [ Plain [ Str "\"Do" ] ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"You"- , Space- , Str "know"- , Space- , Str "nothing?"- , Space- , Str "Do"- , Space- , Str "you"- , Space- , Str "see"- , Space- , Str "nothing?"- , Space- , Str "Do"- , Space- , Str "you"- , Space- , Str "remember"- ]- ]- , Div ( "" , [] , [] ) [ Plain [ Str "\"Nothing?\"" ] ]- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "" , [] , [] )- [ Plain [ Str "I" , Space , Str "remember" ] ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Those"- , Space- , Str "are"- , Space- , Str "pearls"- , Space- , Str "that"- , Space- , Str "were"- , Space- , Str "his"- , Space- , Str "eyes."- ]- ]- , Div- ( "wasteland-content.xhtml#ln126" , [] , [] )- [ Plain- [ Str "\"Are"- , Space- , Str "you"- , Space- , Str "alive,"- , Space- , Str "or"- , Space- , Str "not?"- , Space- , Str "Is"- , Space- , Str "there"- , Space- , Str "nothing"- , Space- , Str "in"- , Space- , Str "your"- , Space- , Str "head?\""- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "126." ]- ( "#wasteland-content.xhtml#ln126"- , ""- )- , Space- , Str "Cf."- , Space- , Str "Part"- , Space- , Str "I,"- , Space- , Str "l."- , Space- , Str "37,"- , Space- , Str "48."- ]- ]- ]- ]- , Div ( "" , [] , [] ) [ Plain [ Str "But" ] ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "O"- , Space- , Str "O"- , Space- , Str "O"- , Space- , Str "O"- , Space- , Str "that"- , Space- , Str "Shakespeherian"- , Space- , Str "Rag\8213"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "It's"- , Space- , Str "so"- , Space- , Str "elegant"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "So"- , Space- , Str "intelligent"- , Span ( "" , [ "lnum" ] , [] ) [ Str "130" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"What"- , Space- , Str "shall"- , Space- , Str "I"- , Space- , Str "do"- , Space- , Str "now?"- , Space- , Str "What"- , Space- , Str "shall"- , Space- , Str "I"- , Space- , Str "do?\""- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "I"- , Space- , Str "shall"- , Space- , Str "rush"- , Space- , Str "out"- , Space- , Str "as"- , Space- , Str "I"- , Space- , Str "am,"- , Space- , Str "and"- , Space- , Str "walk"- , Space- , Str "the"- , Space- , Str "street"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"With"- , Space- , Str "my"- , Space- , Str "hair"- , Space- , Str "down,"- , Space- , Str "so."- , Space- , Str "What"- , Space- , Str "shall"- , Space- , Str "we"- , Space- , Str "do"- , Space- , Str "to-morrow?"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "\"What"- , Space- , Str "shall"- , Space- , Str "we"- , Space- , Str "ever"- , Space- , Str "do?\""- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "The"- , Space- , Str "hot"- , Space- , Str "water"- , Space- , Str "at"- , Space- , Str "ten."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "if"- , Space- , Str "it"- , Space- , Str "rains,"- , Space- , Str "a"- , Space- , Str "closed"- , Space- , Str "car"- , Space- , Str "at"- , Space- , Str "four."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "we"- , Space- , Str "shall"- , Space- , Str "play"- , Space- , Str "a"- , Space- , Str "game"- , Space- , Str "of"- , Space- , Str "chess,"- ]- ]- , Div- ( "wasteland-content.xhtml#ln138" , [] , [] )- [ Plain- [ Str "Pressing"- , Space- , Str "lidless"- , Space- , Str "eyes"- , Space- , Str "and"- , Space- , Str "waiting"- , Space- , Str "for"- , Space- , Str "a"- , Space- , Str "knock"- , Space- , Str "upon"- , Space- , Str "the"- , Space- , Str "door."- , Note- [ Para- [ Link- ( "" , [] , [] )- [ Str "138." ]- ( "#wasteland-content.xhtml#ln138"- , ""- )- , Space- , Str "Cf."- , Space- , Str "the"- , Space- , Str "game"- , Space- , Str "of"- , Space- , Str "chess"- , Space- , Str "in"- , Space- , Str "Middleton's"- , Space- , Str "Women"- , Space- , Str "beware"- , Space- , Str "Women."- ]- ]- ]- ]- ]- , Div- ( "" , [ "linegroup" ] , [] )- [ Div- ( "" , [] , [] )- [ Plain- [ Str "When"- , Space- , Str "Lil's"- , Space- , Str "husband"- , Space- , Str "got"- , Space- , Str "demobbed,"- , Space- , Str "I"- , Space- , Str "said"- , Space- , Str "-"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "I"- , Space- , Str "didn't"- , Space- , Str "mince"- , Space- , Str "my"- , Space- , Str "words,"- , Space- , Str "I"- , Space- , Str "said"- , Space- , Str "to"- , Space- , Str "her"- , Space- , Str "myself,"- , Span ( "" , [ "lnum" ] , [] ) [ Str "140" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "HURRY"- , Space- , Str "UP"- , Space- , Str "PLEASE"- , Space- , Str "ITS"- , Space- , Str "TIME"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Now"- , Space- , Str "Albert's"- , Space- , Str "coming"- , Space- , Str "back,"- , Space- , Str "make"- , Space- , Str "yourself"- , Space- , Str "a"- , Space- , Str "bit"- , Space- , Str "smart."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "He'll"- , Space- , Str "want"- , Space- , Str "to"- , Space- , Str "know"- , Space- , Str "what"- , Space- , Str "you"- , Space- , Str "done"- , Space- , Str "with"- , Space- , Str "that"- , Space- , Str "money"- , Space- , Str "he"- , Space- , Str "gave"- , SoftBreak- , Str "you"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "To"- , Space- , Str "get"- , Space- , Str "yourself"- , Space- , Str "some"- , Space- , Str "teeth."- , Space- , Str "He"- , Space- , Str "did,"- , Space- , Str "I"- , Space- , Str "was"- , Space- , Str "there."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "You"- , Space- , Str "have"- , Space- , Str "them"- , Space- , Str "all"- , Space- , Str "out,"- , Space- , Str "Lil,"- , Space- , Str "and"- , Space- , Str "get"- , Space- , Str "a"- , Space- , Str "nice"- , Space- , Str "set,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "He"- , Space- , Str "said,"- , Space- , Str "I"- , Space- , Str "swear,"- , Space- , Str "I"- , Space- , Str "can't"- , Space- , Str "bear"- , Space- , Str "to"- , Space- , Str "look"- , Space- , Str "at"- , Space- , Str "you."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "no"- , Space- , Str "more"- , Space- , Str "can't"- , Space- , Str "I,"- , Space- , Str "I"- , Space- , Str "said,"- , Space- , Str "and"- , Space- , Str "think"- , Space- , Str "of"- , Space- , Str "poor"- , Space- , Str "Albert,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "He's"- , Space- , Str "been"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "army"- , Space- , Str "four"- , Space- , Str "years,"- , Space- , Str "he"- , Space- , Str "wants"- , Space- , Str "a"- , Space- , Str "good"- , Space- , Str "time,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "if"- , Space- , Str "you"- , Space- , Str "don't"- , Space- , Str "give"- , Space- , Str "it"- , Space- , Str "him,"- , Space- , Str "there's"- , Space- , Str "others"- , Space- , Str "will,"- , Space- , Str "I"- , SoftBreak- , Str "said."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Oh"- , Space- , Str "is"- , Space- , Str "there,"- , Space- , Str "she"- , Space- , Str "said."- , Space- , Str "Something"- , Space- , Str "o'"- , Space- , Str "that,"- , Space- , Str "I"- , Space- , Str "said."- , Span ( "" , [ "lnum" ] , [] ) [ Str "150" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Then"- , Space- , Str "I'll"- , Space- , Str "know"- , Space- , Str "who"- , Space- , Str "to"- , Space- , Str "thank,"- , Space- , Str "she"- , Space- , Str "said,"- , Space- , Str "and"- , Space- , Str "give"- , Space- , Str "me"- , Space- , Str "a"- , Space- , Str "straight"- , SoftBreak- , Str "look."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "HURRY"- , Space- , Str "UP"- , Space- , Str "PLEASE"- , Space- , Str "ITS"- , Space- , Str "TIME"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "If"- , Space- , Str "you"- , Space- , Str "don't"- , Space- , Str "like"- , Space- , Str "it"- , Space- , Str "you"- , Space- , Str "can"- , Space- , Str "get"- , Space- , Str "on"- , Space- , Str "with"- , Space- , Str "it,"- , Space- , Str "I"- , Space- , Str "said."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Others"- , Space- , Str "can"- , Space- , Str "pick"- , Space- , Str "and"- , Space- , Str "choose"- , Space- , Str "if"- , Space- , Str "you"- , Space- , Str "can't."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "But"- , Space- , Str "if"- , Space- , Str "Albert"- , Space- , Str "makes"- , Space- , Str "off,"- , Space- , Str "it"- , Space- , Str "won't"- , Space- , Str "be"- , Space- , Str "for"- , Space- , Str "lack"- , Space- , Str "of"- , SoftBreak- , Str "telling."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "You"- , Space- , Str "ought"- , Space- , Str "to"- , Space- , Str "be"- , Space- , Str "ashamed,"- , Space- , Str "I"- , Space- , Str "said,"- , Space- , Str "to"- , Space- , Str "look"- , Space- , Str "so"- , Space- , Str "antique."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "(And"- , Space- , Str "her"- , Space- , Str "only"- , Space- , Str "thirty-one.)"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "I"- , Space- , Str "can't"- , Space- , Str "help"- , Space- , Str "it,"- , Space- , Str "she"- , Space- , Str "said,"- , Space- , Str "pulling"- , Space- , Str "a"- , Space- , Str "long"- , Space- , Str "face,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "It's"- , Space- , Str "them"- , Space- , Str "pills"- , Space- , Str "I"- , Space- , Str "took,"- , Space- , Str "to"- , Space- , Str "bring"- , Space- , Str "it"- , Space- , Str "off,"- , Space- , Str "she"- , Space- , Str "said."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "(She's"- , Space- , Str "had"- , Space- , Str "five"- , Space- , Str "already,"- , Space- , Str "and"- , Space- , Str "nearly"- , Space- , Str "died"- , Space- , Str "of"- , Space- , Str "young"- , Space- , Str "George.)"- , Span ( "" , [ "lnum" ] , [] ) [ Str "160" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "The"- , Space- , Str "chemist"- , Space- , Str "said"- , Space- , Str "it"- , Space- , Str "would"- , Space- , Str "be"- , Space- , Str "all"- , Space- , Str "right,"- , Space- , Str "but"- , Space- , Str "I've"- , Space- , Str "never"- , Space- , Str "been"- , Space- , Str "the"- , SoftBreak- , Str "same."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "You"- , Space- , Emph [ Str "are" ]- , Space- , Str "a"- , Space- , Str "proper"- , Space- , Str "fool,"- , Space- , Str "I"- , Space- , Str "said."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Well,"- , Space- , Str "if"- , Space- , Str "Albert"- , Space- , Str "won't"- , Space- , Str "leave"- , Space- , Str "you"- , Space- , Str "alone,"- , Space- , Str "there"- , Space- , Str "it"- , Space- , Str "is,"- , Space- , Str "I"- , SoftBreak- , Str "said,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "What"- , Space- , Str "you"- , Space- , Str "get"- , Space- , Str "married"- , Space- , Str "for"- , Space- , Str "if"- , Space- , Str "you"- , Space- , Str "don't"- , Space- , Str "want"- , Space- , Str "children?"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "HURRY"- , Space- , Str "UP"- , Space- , Str "PLEASE"- , Space- , Str "ITS"- , Space- , Str "TIME"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Well,"- , Space- , Str "that"- , Space- , Str "Sunday"- , Space- , Str "Albert"- , Space- , Str "was"- , Space- , Str "home,"- , Space- , Str "they"- , Space- , Str "had"- , Space- , Str "a"- , Space- , Str "hot"- , SoftBreak- , Str "gammon,"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "And"- , Space- , Str "they"- , Space- , Str "asked"- , Space- , Str "me"- , Space- , Str "in"- , Space- , Str "to"- , Space- , Str "dinner,"- , Space- , Str "to"- , Space- , Str "get"- , Space- , Str "the"- , Space- , Str "beauty"- , Space- , Str "of"- , Space- , Str "it"- , SoftBreak- , Str "hot\8213"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "HURRY"- , Space- , Str "UP"- , Space- , Str "PLEASE"- , Space- , Str "ITS"- , Space- , Str "TIME"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "HURRY"- , Space- , Str "UP"- , Space- , Str "PLEASE"- , Space- , Str "ITS"- , Space- , Str "TIME"- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Goonight"- , Space- , Str "Bill."- , Space- , Str "Goonight"- , Space- , Str "Lou."- , Space- , Str "Goonight"- , Space- , Str "May."- , Space- , Str "Goonight."- , Span ( "" , [ "lnum" ] , [] ) [ Str "170" ]- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Ta"- , Space- , Str "ta."- , Space- , Str "Goonight."- , Space- , Str "Goonight."- ]- ]- , Div- ( "" , [] , [] )- [ Plain- [ Str "Good"- , Space- , Str "night,"- , Space- , Str "ladies,"- , Space- , Str "good"- , Space- , Str "night,"- , Space- , Str "sweet"- , Space- , Str "ladies,"- , Space- , Str "good"- , Space- , Str "night,"- , Space- , Str "good"- , SoftBreak- , Str "night."- ]- ]- ]- ]- ]-, Div- ( "wasteland-content.xhtml#backmatter"- , [ "section" , "backmatter" ]- , []- )- [ Div- ( "wasteland-content.xhtml#rearnotes"- , [ "rearnotes" ]- , []- )- [ Header- 2- ( "" , [] , [] )- [ Str "NOTES"- , Space- , Str "ON"- , Space- , Str "\"THE"- , Space- , Str "WASTE"- , Space- , Str "LAND\""- ]- , Para- [ Str "Not"- , Space- , Str "only"- , Space- , Str "the"- , Space- , Str "title,"- , Space- , Str "but"- , Space- , Str "the"- , Space- , Str "plan"- , Space- , Str "and"- , Space- , Str "a"- , Space- , Str "good"- , Space- , Str "deal"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "incidental"- , Space- , Str "symbolism"- , Space- , Str "of"- , SoftBreak- , Str "the"- , Space- , Str "poem"- , Space- , Str "were"- , Space- , Str "suggested"- , Space- , Str "by"- , Space- , Str "Miss"- , Space- , Str "Jessie"- , Space- , Str "L."- , Space- , Str "Weston's"- , Space- , Str "book"- , Space- , Str "on"- , Space- , Str "the"- , Space- , Str "Grail"- , Space- , Str "legend:"- , SoftBreak- , Str "From"- , Space- , Str "Ritual"- , Space- , Str "to"- , Space- , Str "Romance"- ]- , Para- [ Str "Indeed,"- , Space- , Str "so"- , Space- , Str "deeply"- , Space- , Str "am"- , Space- , Str "I"- , Space- , Str "indebted,"- , Space- , Str "Miss"- , Space- , Str "Weston's"- , Space- , Str "book"- , Space- , Str "will"- , Space- , Str "elucidate"- , Space- , Str "the"- , SoftBreak- , Str "difficulties"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "poem"- , Space- , Str "much"- , Space- , Str "better"- , Space- , Str "than"- , Space- , Str "my"- , Space- , Str "notes"- , Space- , Str "can"- , Space- , Str "do;"- , Space- , Str "and"- , Space- , Str "I"- , Space- , Str "recommend"- , Space- , Str "it"- , SoftBreak- , Str "(apart"- , Space- , Str "from"- , Space- , Str "the"- , Space- , Str "great"- , Space- , Str "interest"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "book"- , Space- , Str "itself)"- , Space- , Str "to"- , Space- , Str "any"- , Space- , Str "who"- , Space- , Str "think"- , Space- , Str "such"- , SoftBreak- , Str "elucidation"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "poem"- , Space- , Str "worth"- , Space- , Str "the"- , Space- , Str "trouble."- , Space- , Str "To"- , Space- , Str "another"- , Space- , Str "work"- , Space- , Str "of"- , Space- , Str "anthropology"- , Space- , Str "I"- , Space- , Str "am"- , SoftBreak- , Str "indebted"- , Space- , Str "in"- , Space- , Str "general,"- , Space- , Str "one"- , Space- , Str "which"- , Space- , Str "has"- , Space- , Str "influenced"- , Space- , Str "our"- , Space- , Str "generation"- , Space- , Str "profoundly;"- , Space- , Str "I"- , Space- , Str "mean"- , SoftBreak- , Str "The"- , Space- , Str "Golden"- , Space- , Str "Bough;"- , Space- , Str "I"- , Space- , Str "have"- , Space- , Str "used"- , Space- , Str "especially"- , Space- , Str "the"- , Space- , Str "two"- , Space- , Str "volumes"- , Space- , Str "Adonis,"- , Space- , Str "Attis,"- , Space- , Str "Osiris."- , SoftBreak- , Str "Anyone"- , Space- , Str "who"- , Space- , Str "is"- , Space- , Str "acquainted"- , Space- , Str "with"- , Space- , Str "these"- , Space- , Str "works"- , Space- , Str "will"- , Space- , Str "immediately"- , Space- , Str "recognise"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "poem"- , SoftBreak- , Str "certain"- , Space- , Str "references"- , Space- , Str "to"- , Space- , Str "vegetation"- , Space- , Str "ceremonies."- ]- , Div- ( "" , [ "section" ] , [] )- [ Header- 3- ( "" , [] , [] )- [ Str "I."- , Space- , Str "THE"- , Space- , Str "BURIAL"- , Space- , Str "OF"- , Space- , Str "THE"- , Space- , Str "DEAD"- ]- ]- , Div- ( "" , [ "section" ] , [] )- [ Header- 3- ( "" , [] , [] )- [ Str "II."- , Space- , Str "A"- , Space- , Str "GAME"- , Space- , Str "OF"- , Space- , Str "CHESS"- ]- ]- ]- ]-]+Pandoc+ Meta+ { unMeta =+ fromList+ [ ( "author" , MetaInlines [ Str "T.S. Eliot" ] )+ , ( "date" , MetaInlines [ Str "2011-09-01" ] )+ , ( "identifier"+ , MetaInlines+ [ Str "code.google.com.epub-samples.wasteland-basic" ]+ )+ , ( "language" , MetaInlines [ Str "en-US" ] )+ , ( "rights"+ , MetaInlines+ [ Str+ "This work is shared with the public using the Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) license."+ ]+ )+ , ( "title" , MetaInlines [ Str "The Waste Land" ] )+ ]+ }+ [ Para+ [ Image ( "" , [] , [] ) [] ( "wasteland-cover.jpg" , "" ) ]+ , Para [ Span ( "wasteland-content.xhtml" , [] , [] ) [] ]+ , Div+ ( "wasteland-content.xhtml_frontmatter"+ , [ "section" , "frontmatter" ]+ , []+ )+ []+ , Div+ ( "wasteland-content.xhtml_bodymatter"+ , [ "section" , "bodymatter" ]+ , []+ )+ [ Div+ ( "wasteland-content.xhtml_ch1" , [ "section" ] , [] )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "I."+ , Space+ , Str "THE"+ , Space+ , Str "BURIAL"+ , Space+ , Str "OF"+ , Space+ , Str "THE"+ , Space+ , Str "DEAD"+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "" , [] , [] )+ [ Plain+ [ Str "April"+ , Space+ , Str "is"+ , Space+ , Str "the"+ , Space+ , Str "cruellest"+ , Space+ , Str "month,"+ , Space+ , Str "breeding"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Lilacs"+ , Space+ , Str "out"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "dead"+ , Space+ , Str "land,"+ , Space+ , Str "mixing"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Memory"+ , Space+ , Str "and"+ , Space+ , Str "desire,"+ , Space+ , Str "stirring"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Dull"+ , Space+ , Str "roots"+ , Space+ , Str "with"+ , Space+ , Str "spring"+ , Space+ , Str "rain."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Winter"+ , Space+ , Str "kept"+ , Space+ , Str "us"+ , Space+ , Str "warm,"+ , Space+ , Str "covering"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Earth"+ , Space+ , Str "in"+ , Space+ , Str "forgetful"+ , Space+ , Str "snow,"+ , Space+ , Str "feeding"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "A"+ , Space+ , Str "little"+ , Space+ , Str "life"+ , Space+ , Str "with"+ , Space+ , Str "dried"+ , Space+ , Str "tubers."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Summer"+ , Space+ , Str "surprised"+ , Space+ , Str "us,"+ , Space+ , Str "coming"+ , Space+ , Str "over"+ , Space+ , Str "the"+ , Space+ , Str "Starnbergersee"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "With"+ , Space+ , Str "a"+ , Space+ , Str "shower"+ , Space+ , Str "of"+ , Space+ , Str "rain;"+ , Space+ , Str "we"+ , Space+ , Str "stopped"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "colonnade,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "went"+ , Space+ , Str "on"+ , Space+ , Str "in"+ , Space+ , Str "sunlight,"+ , Space+ , Str "into"+ , Space+ , Str "the"+ , Space+ , Str "Hofgarten,"+ , Span ( "" , [ "lnum" ] , [] ) [ Str "10" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "drank"+ , Space+ , Str "coffee,"+ , Space+ , Str "and"+ , Space+ , Str "talked"+ , Space+ , Str "for"+ , Space+ , Str "an"+ , Space+ , Str "hour."+ ]+ ]+ , Div+ ( "" , [] , [ ( "lang" , "de" ) ] )+ [ Plain+ [ Str "Bin"+ , Space+ , Str "gar"+ , Space+ , Str "keine"+ , Space+ , Str "Russin,"+ , Space+ , Str "stamm'"+ , Space+ , Str "aus"+ , Space+ , Str "Litauen,"+ , Space+ , Str "echt"+ , SoftBreak+ , Str "deutsch."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "when"+ , Space+ , Str "we"+ , Space+ , Str "were"+ , Space+ , Str "children,"+ , Space+ , Str "staying"+ , Space+ , Str "at"+ , Space+ , Str "the"+ , Space+ , Str "archduke's,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "My"+ , Space+ , Str "cousin's,"+ , Space+ , Str "he"+ , Space+ , Str "took"+ , Space+ , Str "me"+ , Space+ , Str "out"+ , Space+ , Str "on"+ , Space+ , Str "a"+ , Space+ , Str "sled,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "I"+ , Space+ , Str "was"+ , Space+ , Str "frightened."+ , Space+ , Str "He"+ , Space+ , Str "said,"+ , Space+ , Str "Marie,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Marie,"+ , Space+ , Str "hold"+ , Space+ , Str "on"+ , Space+ , Str "tight."+ , Space+ , Str "And"+ , Space+ , Str "down"+ , Space+ , Str "we"+ , Space+ , Str "went."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "In"+ , Space+ , Str "the"+ , Space+ , Str "mountains,"+ , Space+ , Str "there"+ , Space+ , Str "you"+ , Space+ , Str "feel"+ , Space+ , Str "free."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "I"+ , Space+ , Str "read,"+ , Space+ , Str "much"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "night,"+ , Space+ , Str "and"+ , Space+ , Str "go"+ , Space+ , Str "south"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "winter."+ ]+ ]+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "" , [] , [] )+ [ Plain+ [ Str "What"+ , Space+ , Str "are"+ , Space+ , Str "the"+ , Space+ , Str "roots"+ , Space+ , Str "that"+ , Space+ , Str "clutch,"+ , Space+ , Str "what"+ , Space+ , Str "branches"+ , Space+ , Str "grow"+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln20" , [] , [] )+ [ Plain+ [ Str "Out"+ , Space+ , Str "of"+ , Space+ , Str "this"+ , Space+ , Str "stony"+ , Space+ , Str "rubbish?"+ , Space+ , Str "Son"+ , Space+ , Str "of"+ , Space+ , Str "man,"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "Line" , Space , Str "20." ]+ ( "#wasteland-content.xhtml_ln20"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "Ezekiel"+ , Space+ , Str "2:1."+ ]+ ]+ , Span ( "" , [ "lnum" ] , [] ) [ Str "20" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "You"+ , Space+ , Str "cannot"+ , Space+ , Str "say,"+ , Space+ , Str "or"+ , Space+ , Str "guess,"+ , Space+ , Str "for"+ , Space+ , Str "you"+ , Space+ , Str "know"+ , Space+ , Str "only"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "A"+ , Space+ , Str "heap"+ , Space+ , Str "of"+ , Space+ , Str "broken"+ , Space+ , Str "images,"+ , Space+ , Str "where"+ , Space+ , Str "the"+ , Space+ , Str "sun"+ , Space+ , Str "beats,"+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln23" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "the"+ , Space+ , Str "dead"+ , Space+ , Str "tree"+ , Space+ , Str "gives"+ , Space+ , Str "no"+ , Space+ , Str "shelter,"+ , Space+ , Str "the"+ , Space+ , Str "cricket"+ , Space+ , Str "no"+ , Space+ , Str "relief,"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "23." ]+ ( "#wasteland-content.xhtml_ln23"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "Ecclesiastes"+ , Space+ , Str "12:5."+ ]+ ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "the"+ , Space+ , Str "dry"+ , Space+ , Str "stone"+ , Space+ , Str "no"+ , Space+ , Str "sound"+ , Space+ , Str "of"+ , Space+ , Str "water."+ , Space+ , Str "Only"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "There"+ , Space+ , Str "is"+ , Space+ , Str "shadow"+ , Space+ , Str "under"+ , Space+ , Str "this"+ , Space+ , Str "red"+ , Space+ , Str "rock,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "(Come"+ , Space+ , Str "in"+ , Space+ , Str "under"+ , Space+ , Str "the"+ , Space+ , Str "shadow"+ , Space+ , Str "of"+ , Space+ , Str "this"+ , Space+ , Str "red"+ , Space+ , Str "rock),"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "I"+ , Space+ , Str "will"+ , Space+ , Str "show"+ , Space+ , Str "you"+ , Space+ , Str "something"+ , Space+ , Str "different"+ , Space+ , Str "from"+ , Space+ , Str "either"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Your"+ , Space+ , Str "shadow"+ , Space+ , Str "at"+ , Space+ , Str "morning"+ , Space+ , Str "striding"+ , Space+ , Str "behind"+ , Space+ , Str "you"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Or"+ , Space+ , Str "your"+ , Space+ , Str "shadow"+ , Space+ , Str "at"+ , Space+ , Str "evening"+ , Space+ , Str "rising"+ , Space+ , Str "to"+ , Space+ , Str "meet"+ , Space+ , Str "you;"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "I"+ , Space+ , Str "will"+ , Space+ , Str "show"+ , Space+ , Str "you"+ , Space+ , Str "fear"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "handful"+ , Space+ , Str "of"+ , Space+ , Str "dust."+ , Span ( "" , [ "lnum" ] , [] ) [ Str "30" ]+ ]+ ]+ , BlockQuote+ [ Div+ ( "" , [] , [] )+ [ Div+ ( "wasteland-content.xhtml_ln31" , [] , [] )+ [ Plain+ [ Str "Frisch"+ , Space+ , Str "weht"+ , Space+ , Str "der"+ , Space+ , Str "Wind"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "31." ]+ ( "#wasteland-content.xhtml_ln31"+ , ""+ )+ , Space+ , Str "V."+ , Space+ , Str "Tristan"+ , Space+ , Str "und"+ , Space+ , Str "Isolde,"+ , Space+ , Str "i,"+ , Space+ , Str "verses"+ , Space+ , Str "5-8."+ ]+ ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Der"+ , Space+ , Str "Heimat"+ , Space+ , Str "zu"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Mein"+ , Space+ , Str "Irisch"+ , Space+ , Str "Kind,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Wo"+ , Space+ , Str "weilest"+ , Space+ , Str "du?"+ ]+ ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"You"+ , Space+ , Str "gave"+ , Space+ , Str "me"+ , Space+ , Str "hyacinths"+ , Space+ , Str "first"+ , Space+ , Str "a"+ , Space+ , Str "year"+ , Space+ , Str "ago;"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"They"+ , Space+ , Str "called"+ , Space+ , Str "me"+ , Space+ , Str "the"+ , Space+ , Str "hyacinth"+ , Space+ , Str "girl.\""+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\8213Yet"+ , Space+ , Str "when"+ , Space+ , Str "we"+ , Space+ , Str "came"+ , Space+ , Str "back,"+ , Space+ , Str "late,"+ , Space+ , Str "from"+ , Space+ , Str "the"+ , Space+ , Str "Hyacinth"+ , SoftBreak+ , Str "garden,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Your"+ , Space+ , Str "arms"+ , Space+ , Str "full,"+ , Space+ , Str "and"+ , Space+ , Str "your"+ , Space+ , Str "hair"+ , Space+ , Str "wet,"+ , Space+ , Str "I"+ , Space+ , Str "could"+ , Space+ , Str "not"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Speak,"+ , Space+ , Str "and"+ , Space+ , Str "my"+ , Space+ , Str "eyes"+ , Space+ , Str "failed,"+ , Space+ , Str "I"+ , Space+ , Str "was"+ , Space+ , Str "neither"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Living"+ , Space+ , Str "nor"+ , Space+ , Str "dead,"+ , Space+ , Str "and"+ , Space+ , Str "I"+ , Space+ , Str "knew"+ , Space+ , Str "nothing,"+ , Span ( "" , [ "lnum" ] , [] ) [ Str "40" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Looking"+ , Space+ , Str "into"+ , Space+ , Str "the"+ , Space+ , Str "heart"+ , Space+ , Str "of"+ , Space+ , Str "light,"+ , Space+ , Str "the"+ , Space+ , Str "silence."+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln42"+ , []+ , [ ( "lang" , "de" ) ]+ )+ [ Plain+ [ Emph+ [ Str "Od'"+ , Space+ , Str "und"+ , Space+ , Str "leer"+ , Space+ , Str "das"+ , Space+ , Str "Meer"+ ]+ , Str "."+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "42." ]+ ( "#wasteland-content.xhtml_ln42"+ , ""+ )+ , Space+ , Str "Id."+ , Space+ , Str "iii,"+ , Space+ , Str "verse"+ , Space+ , Str "24."+ ]+ ]+ ]+ ]+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Madame"+ , Space+ , Str "Sosostris,"+ , Space+ , Str "famous"+ , Space+ , Str "clairvoyante,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Had"+ , Space+ , Str "a"+ , Space+ , Str "bad"+ , Space+ , Str "cold,"+ , Space+ , Str "nevertheless"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Is"+ , Space+ , Str "known"+ , Space+ , Str "to"+ , Space+ , Str "be"+ , Space+ , Str "the"+ , Space+ , Str "wisest"+ , Space+ , Str "woman"+ , Space+ , Str "in"+ , Space+ , Str "Europe,"+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln46" , [] , [] )+ [ Plain+ [ Str "With"+ , Space+ , Str "a"+ , Space+ , Str "wicked"+ , Space+ , Str "pack"+ , Space+ , Str "of"+ , Space+ , Str "cards."+ , Space+ , Str "Here,"+ , Space+ , Str "said"+ , Space+ , Str "she,"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "46." ]+ ( "#wasteland-content.xhtml_ln46"+ , ""+ )+ , Space+ , Str "I"+ , Space+ , Str "am"+ , Space+ , Str "not"+ , Space+ , Str "familiar"+ , Space+ , Str "with"+ , Space+ , Str "the"+ , Space+ , Str "exact"+ , Space+ , Str "constitution"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "Tarot"+ , Space+ , Str "pack"+ , Space+ , Str "of"+ , SoftBreak+ , Str "cards,"+ , Space+ , Str "from"+ , Space+ , Str "which"+ , Space+ , Str "I"+ , Space+ , Str "have"+ , Space+ , Str "obviously"+ , Space+ , Str "departed"+ , Space+ , Str "to"+ , Space+ , Str "suit"+ , Space+ , Str "my"+ , Space+ , Str "own"+ , Space+ , Str "convenience."+ , SoftBreak+ , Str "The"+ , Space+ , Str "Hanged"+ , Space+ , Str "Man,"+ , Space+ , Str "a"+ , Space+ , Str "member"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "traditional"+ , Space+ , Str "pack,"+ , Space+ , Str "fits"+ , Space+ , Str "my"+ , Space+ , Str "purpose"+ , Space+ , Str "in"+ , Space+ , Str "two"+ , SoftBreak+ , Str "ways:"+ , Space+ , Str "because"+ , Space+ , Str "he"+ , Space+ , Str "is"+ , Space+ , Str "associated"+ , Space+ , Str "in"+ , Space+ , Str "my"+ , Space+ , Str "mind"+ , Space+ , Str "with"+ , Space+ , Str "the"+ , Space+ , Str "Hanged"+ , Space+ , Str "God"+ , Space+ , Str "of"+ , Space+ , Str "Frazer,"+ , SoftBreak+ , Str "and"+ , Space+ , Str "because"+ , Space+ , Str "I"+ , Space+ , Str "associate"+ , Space+ , Str "him"+ , Space+ , Str "with"+ , Space+ , Str "the"+ , Space+ , Str "hooded"+ , Space+ , Str "figure"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "passage"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , SoftBreak+ , Str "disciples"+ , Space+ , Str "to"+ , Space+ , Str "Emmaus"+ , Space+ , Str "in"+ , Space+ , Str "Part"+ , Space+ , Str "V."+ , Space+ , Str "The"+ , Space+ , Str "Phoenician"+ , Space+ , Str "Sailor"+ , Space+ , Str "and"+ , Space+ , Str "the"+ , Space+ , Str "Merchant"+ , SoftBreak+ , Str "appear"+ , Space+ , Str "later;"+ , Space+ , Str "also"+ , Space+ , Str "the"+ , Space+ , Str "\"crowds"+ , Space+ , Str "of"+ , Space+ , Str "people,\""+ , Space+ , Str "and"+ , Space+ , Str "Death"+ , Space+ , Str "by"+ , Space+ , Str "Water"+ , Space+ , Str "is"+ , SoftBreak+ , Str "executed"+ , Space+ , Str "in"+ , Space+ , Str "Part"+ , Space+ , Str "IV."+ , Space+ , Str "The"+ , Space+ , Str "Man"+ , Space+ , Str "with"+ , Space+ , Str "Three"+ , Space+ , Str "Staves"+ , Space+ , Str "(an"+ , Space+ , Str "authentic"+ , Space+ , Str "member"+ , Space+ , Str "of"+ , SoftBreak+ , Str "the"+ , Space+ , Str "Tarot"+ , Space+ , Str "pack)"+ , Space+ , Str "I"+ , Space+ , Str "associate,"+ , Space+ , Str "quite"+ , Space+ , Str "arbitrarily,"+ , Space+ , Str "with"+ , Space+ , Str "the"+ , Space+ , Str "Fisher"+ , Space+ , Str "King"+ , SoftBreak+ , Str "himself."+ ]+ ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Is"+ , Space+ , Str "your"+ , Space+ , Str "card,"+ , Space+ , Str "the"+ , Space+ , Str "drowned"+ , Space+ , Str "Phoenician"+ , Space+ , Str "Sailor,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "(Those"+ , Space+ , Str "are"+ , Space+ , Str "pearls"+ , Space+ , Str "that"+ , Space+ , Str "were"+ , Space+ , Str "his"+ , Space+ , Str "eyes."+ , Space+ , Str "Look!)"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "Belladonna,"+ , Space+ , Str "the"+ , Space+ , Str "Lady"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "Rocks,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "The"+ , Space+ , Str "lady"+ , Space+ , Str "of"+ , Space+ , Str "situations."+ , Span ( "" , [ "lnum" ] , [] ) [ Str "50" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "the"+ , Space+ , Str "man"+ , Space+ , Str "with"+ , Space+ , Str "three"+ , Space+ , Str "staves,"+ , Space+ , Str "and"+ , Space+ , Str "here"+ , Space+ , Str "the"+ , Space+ , Str "Wheel,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "here"+ , Space+ , Str "is"+ , Space+ , Str "the"+ , Space+ , Str "one-eyed"+ , Space+ , Str "merchant,"+ , Space+ , Str "and"+ , Space+ , Str "this"+ , Space+ , Str "card,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Which"+ , Space+ , Str "is"+ , Space+ , Str "blank,"+ , Space+ , Str "is"+ , Space+ , Str "something"+ , Space+ , Str "he"+ , Space+ , Str "carries"+ , Space+ , Str "on"+ , Space+ , Str "his"+ , Space+ , Str "back,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Which"+ , Space+ , Str "I"+ , Space+ , Str "am"+ , Space+ , Str "forbidden"+ , Space+ , Str "to"+ , Space+ , Str "see."+ , Space+ , Str "I"+ , Space+ , Str "do"+ , Space+ , Str "not"+ , Space+ , Str "find"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "The"+ , Space+ , Str "Hanged"+ , Space+ , Str "Man."+ , Space+ , Str "Fear"+ , Space+ , Str "death"+ , Space+ , Str "by"+ , Space+ , Str "water."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "I"+ , Space+ , Str "see"+ , Space+ , Str "crowds"+ , Space+ , Str "of"+ , Space+ , Str "people,"+ , Space+ , Str "walking"+ , Space+ , Str "round"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "ring."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Thank"+ , Space+ , Str "you."+ , Space+ , Str "If"+ , Space+ , Str "you"+ , Space+ , Str "see"+ , Space+ , Str "dear"+ , Space+ , Str "Mrs."+ , Space+ , Str "Equitone,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Tell"+ , Space+ , Str "her"+ , Space+ , Str "I"+ , Space+ , Str "bring"+ , Space+ , Str "the"+ , Space+ , Str "horoscope"+ , Space+ , Str "myself:"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "One"+ , Space+ , Str "must"+ , Space+ , Str "be"+ , Space+ , Str "so"+ , Space+ , Str "careful"+ , Space+ , Str "these"+ , Space+ , Str "days."+ ]+ ]+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "wasteland-content.xhtml_ln60" , [] , [] )+ [ Plain+ [ Str "Unreal"+ , Space+ , Str "City,"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "60." ]+ ( "#wasteland-content.xhtml_ln60"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "Baudelaire:"+ ]+ , BlockQuote+ [ Para+ [ Str "\"Fourmillante"+ , Space+ , Str "cite;,"+ , Space+ , Str "cite;"+ , Space+ , Str "pleine"+ , Space+ , Str "de"+ , Space+ , Str "reves,"+ , LineBreak+ , Str "Ou"+ , Space+ , Str "le"+ , Space+ , Str "spectre"+ , Space+ , Str "en"+ , SoftBreak+ , Str "plein"+ , Space+ , Str "jour"+ , Space+ , Str "raccroche"+ , Space+ , Str "le"+ , Space+ , Str "passant.\""+ ]+ ]+ ]+ , Span ( "" , [ "lnum" ] , [] ) [ Str "60" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Under"+ , Space+ , Str "the"+ , Space+ , Str "brown"+ , Space+ , Str "fog"+ , Space+ , Str "of"+ , Space+ , Str "a"+ , Space+ , Str "winter"+ , Space+ , Str "dawn,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "A"+ , Space+ , Str "crowd"+ , Space+ , Str "flowed"+ , Space+ , Str "over"+ , Space+ , Str "London"+ , Space+ , Str "Bridge,"+ , Space+ , Str "so"+ , Space+ , Str "many,"+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln63" , [] , [] )+ [ Plain+ [ Str "I"+ , Space+ , Str "had"+ , Space+ , Str "not"+ , Space+ , Str "thought"+ , Space+ , Str "death"+ , Space+ , Str "had"+ , Space+ , Str "undone"+ , Space+ , Str "so"+ , Space+ , Str "many."+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "63." ]+ ( "#wasteland-content.xhtml_ln63"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "Inferno,"+ , Space+ , Str "iii."+ , Space+ , Str "55-7."+ ]+ , BlockQuote+ [ Para+ [ Str "\"si"+ , Space+ , Str "lunga"+ , Space+ , Str "tratta"+ , LineBreak+ , Str "di"+ , Space+ , Str "gente,"+ , Space+ , Str "ch'io"+ , Space+ , Str "non"+ , Space+ , Str "avrei"+ , Space+ , Str "mai"+ , Space+ , Str "creduto"+ , LineBreak+ , Str "che"+ , SoftBreak+ , Str "morte"+ , Space+ , Str "tanta"+ , Space+ , Str "n'avesse"+ , Space+ , Str "disfatta.\""+ ]+ ]+ ]+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln64" , [] , [] )+ [ Plain+ [ Str "Sighs,"+ , Space+ , Str "short"+ , Space+ , Str "and"+ , Space+ , Str "infrequent,"+ , Space+ , Str "were"+ , Space+ , Str "exhaled,"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "64." ]+ ( "#wasteland-content.xhtml_ln64"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "Inferno,"+ , Space+ , Str "iv."+ , Space+ , Str "25-7:"+ ]+ , BlockQuote+ [ Para+ [ Str "\"Quivi,"+ , Space+ , Str "secondo"+ , Space+ , Str "che"+ , Space+ , Str "per"+ , Space+ , Str "ascoltahre,"+ , LineBreak+ , Str "\"non"+ , Space+ , Str "avea"+ , Space+ , Str "pianto,"+ , Space+ , Str "ma'"+ , Space+ , Str "che"+ , Space+ , Str "di"+ , SoftBreak+ , Str "sospiri,"+ , LineBreak+ , Str "\"che"+ , Space+ , Str "l'aura"+ , Space+ , Str "eterna"+ , Space+ , Str "facevan"+ , Space+ , Str "tremare.\""+ ]+ ]+ ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "each"+ , Space+ , Str "man"+ , Space+ , Str "fixed"+ , Space+ , Str "his"+ , Space+ , Str "eyes"+ , Space+ , Str "before"+ , Space+ , Str "his"+ , Space+ , Str "feet."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Flowed"+ , Space+ , Str "up"+ , Space+ , Str "the"+ , Space+ , Str "hill"+ , Space+ , Str "and"+ , Space+ , Str "down"+ , Space+ , Str "King"+ , Space+ , Str "William"+ , Space+ , Str "Street,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "To"+ , Space+ , Str "where"+ , Space+ , Str "Saint"+ , Space+ , Str "Mary"+ , Space+ , Str "Woolnoth"+ , Space+ , Str "kept"+ , Space+ , Str "the"+ , Space+ , Str "hours"+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln68" , [] , [] )+ [ Plain+ [ Str "With"+ , Space+ , Str "a"+ , Space+ , Str "dead"+ , Space+ , Str "sound"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Str "final"+ , Space+ , Str "stroke"+ , Space+ , Str "of"+ , Space+ , Str "nine."+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "68." ]+ ( "#wasteland-content.xhtml_ln68"+ , ""+ )+ , Space+ , Str "A"+ , Space+ , Str "phenomenon"+ , Space+ , Str "which"+ , Space+ , Str "I"+ , Space+ , Str "have"+ , Space+ , Str "often"+ , Space+ , Str "noticed."+ ]+ ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "There"+ , Space+ , Str "I"+ , Space+ , Str "saw"+ , Space+ , Str "one"+ , Space+ , Str "I"+ , Space+ , Str "knew,"+ , Space+ , Str "and"+ , Space+ , Str "stopped"+ , Space+ , Str "him,"+ , Space+ , Str "crying"+ , SoftBreak+ , Str "\"Stetson!"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"You"+ , Space+ , Str "who"+ , Space+ , Str "were"+ , Space+ , Str "with"+ , Space+ , Str "me"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "ships"+ , Space+ , Str "at"+ , Space+ , Str "Mylae!"+ , Span ( "" , [ "lnum" ] , [] ) [ Str "70" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"That"+ , Space+ , Str "corpse"+ , Space+ , Str "you"+ , Space+ , Str "planted"+ , Space+ , Str "last"+ , Space+ , Str "year"+ , Space+ , Str "in"+ , Space+ , Str "your"+ , Space+ , Str "garden,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"Has"+ , Space+ , Str "it"+ , Space+ , Str "begun"+ , Space+ , Str "to"+ , Space+ , Str "sprout?"+ , Space+ , Str "Will"+ , Space+ , Str "it"+ , Space+ , Str "bloom"+ , Space+ , Str "this"+ , Space+ , Str "year?"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"Or"+ , Space+ , Str "has"+ , Space+ , Str "the"+ , Space+ , Str "sudden"+ , Space+ , Str "frost"+ , Space+ , Str "disturbed"+ , Space+ , Str "its"+ , Space+ , Str "bed?"+ ]+ ]+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "wasteland-content.xhtml_ln74" , [] , [] )+ [ Plain+ [ Str "\"Oh"+ , Space+ , Str "keep"+ , Space+ , Str "the"+ , Space+ , Str "Dog"+ , Space+ , Str "far"+ , Space+ , Str "hence,"+ , Space+ , Str "that's"+ , Space+ , Str "friend"+ , Space+ , Str "to"+ , Space+ , Str "men,"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "74." ]+ ( "#wasteland-content.xhtml_ln74"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "the"+ , Space+ , Str "Dirge"+ , Space+ , Str "in"+ , Space+ , Str "Webster's"+ , Space+ , Str "White"+ , Space+ , Str "Devil"+ , Space+ , Str "."+ ]+ ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"Or"+ , Space+ , Str "with"+ , Space+ , Str "his"+ , Space+ , Str "nails"+ , Space+ , Str "he'll"+ , Space+ , Str "dig"+ , Space+ , Str "it"+ , Space+ , Str "up"+ , Space+ , Str "again!"+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln76" , [] , [] )+ [ Plain+ [ Str "\"You!"+ , Space+ , Span+ ( "" , [] , [ ( "lang" , "fr" ) ] )+ [ Str "hypocrite"+ , Space+ , Str "lecteur!"+ , Space+ , Str "-"+ , Space+ , Str "mon"+ , Space+ , Str "semblable,"+ , Space+ , Str "-"+ , SoftBreak+ , Str "mon"+ , Space+ , Str "frere"+ ]+ , Space+ , Str "!\""+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "76." ]+ ( "#wasteland-content.xhtml_ln76"+ , ""+ )+ , Space+ , Str "V."+ , Space+ , Str "Baudelaire,"+ , Space+ , Str "Preface"+ , Space+ , Str "to"+ , Space+ , Str "Fleurs"+ , Space+ , Str "du"+ , Space+ , Str "Mal."+ ]+ ]+ ]+ ]+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ch2" , [ "section" ] , [] )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "II."+ , Space+ , Str "A"+ , Space+ , Str "GAME"+ , Space+ , Str "OF"+ , Space+ , Str "CHESS"+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "wasteland-content.xhtml_ln77" , [] , [] )+ [ Plain+ [ Str "The"+ , Space+ , Str "Chair"+ , Space+ , Str "she"+ , Space+ , Str "sat"+ , Space+ , Str "in,"+ , Space+ , Str "like"+ , Space+ , Str "a"+ , Space+ , Str "burnished"+ , Space+ , Str "throne,"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "77." ]+ ( "#wasteland-content.xhtml_ln77"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "Antony"+ , Space+ , Str "and"+ , Space+ , Str "Cleopatra,"+ , Space+ , Str "II."+ , Space+ , Str "ii.,"+ , Space+ , Str "l."+ , Space+ , Str "190."+ ]+ ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Glowed"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Str "marble,"+ , Space+ , Str "where"+ , Space+ , Str "the"+ , Space+ , Str "glass"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Held"+ , Space+ , Str "up"+ , Space+ , Str "by"+ , Space+ , Str "standards"+ , Space+ , Str "wrought"+ , Space+ , Str "with"+ , Space+ , Str "fruited"+ , Space+ , Str "vines"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "From"+ , Space+ , Str "which"+ , Space+ , Str "a"+ , Space+ , Str "golden"+ , Space+ , Str "Cupidon"+ , Space+ , Str "peeped"+ , Space+ , Str "out"+ , Span ( "" , [ "lnum" ] , [] ) [ Str "80" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "(Another"+ , Space+ , Str "hid"+ , Space+ , Str "his"+ , Space+ , Str "eyes"+ , Space+ , Str "behind"+ , Space+ , Str "his"+ , Space+ , Str "wing)"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Doubled"+ , Space+ , Str "the"+ , Space+ , Str "flames"+ , Space+ , Str "of"+ , Space+ , Str "sevenbranched"+ , Space+ , Str "candelabra"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Reflecting"+ , Space+ , Str "light"+ , Space+ , Str "upon"+ , Space+ , Str "the"+ , Space+ , Str "table"+ , Space+ , Str "as"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "The"+ , Space+ , Str "glitter"+ , Space+ , Str "of"+ , Space+ , Str "her"+ , Space+ , Str "jewels"+ , Space+ , Str "rose"+ , Space+ , Str "to"+ , Space+ , Str "meet"+ , Space+ , Str "it,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "From"+ , Space+ , Str "satin"+ , Space+ , Str "cases"+ , Space+ , Str "poured"+ , Space+ , Str "in"+ , Space+ , Str "rich"+ , Space+ , Str "profusion;"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "In"+ , Space+ , Str "vials"+ , Space+ , Str "of"+ , Space+ , Str "ivory"+ , Space+ , Str "and"+ , Space+ , Str "coloured"+ , Space+ , Str "glass"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Unstoppered,"+ , Space+ , Str "lurked"+ , Space+ , Str "her"+ , Space+ , Str "strange"+ , Space+ , Str "synthetic"+ , Space+ , Str "perfumes,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Unguent,"+ , Space+ , Str "powdered,"+ , Space+ , Str "or"+ , Space+ , Str "liquid"+ , Space+ , Str "-"+ , Space+ , Str "troubled,"+ , Space+ , Str "confused"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "drowned"+ , Space+ , Str "the"+ , Space+ , Str "sense"+ , Space+ , Str "in"+ , Space+ , Str "odours;"+ , Space+ , Str "stirred"+ , Space+ , Str "by"+ , Space+ , Str "the"+ , Space+ , Str "air"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "That"+ , Space+ , Str "freshened"+ , Space+ , Str "from"+ , Space+ , Str "the"+ , Space+ , Str "window,"+ , Space+ , Str "these"+ , Space+ , Str "ascended"+ , Span ( "" , [ "lnum" ] , [] ) [ Str "90" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "In"+ , Space+ , Str "fattening"+ , Space+ , Str "the"+ , Space+ , Str "prolonged"+ , Space+ , Str "candle-flames,"+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln92" , [] , [] )+ [ Plain+ [ Str "Flung"+ , Space+ , Str "their"+ , Space+ , Str "smoke"+ , Space+ , Str "into"+ , Space+ , Str "the"+ , Space+ , Str "laquearia,"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "92." ]+ ( "#wasteland-content.xhtml_ln92"+ , ""+ )+ , Space+ , Str "Laquearia."+ , Space+ , Str "V."+ , Space+ , Str "Aeneid,"+ , Space+ , Str "I."+ , Space+ , Str "726:"+ ]+ , BlockQuote+ [ Para+ [ Str "dependent"+ , Space+ , Str "lychni"+ , Space+ , Str "laquearibus"+ , Space+ , Str "aureis"+ , Space+ , Str "incensi,"+ , Space+ , Str "et"+ , Space+ , Str "noctem"+ , SoftBreak+ , Str "flammis"+ , LineBreak+ , Str "funalia"+ , Space+ , Str "vincunt."+ ]+ ]+ ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Stirring"+ , Space+ , Str "the"+ , Space+ , Str "pattern"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Str "coffered"+ , Space+ , Str "ceiling."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Huge"+ , Space+ , Str "sea-wood"+ , Space+ , Str "fed"+ , Space+ , Str "with"+ , Space+ , Str "copper"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Burned"+ , Space+ , Str "green"+ , Space+ , Str "and"+ , Space+ , Str "orange,"+ , Space+ , Str "framed"+ , Space+ , Str "by"+ , Space+ , Str "the"+ , Space+ , Str "coloured"+ , Space+ , Str "stone,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "In"+ , Space+ , Str "which"+ , Space+ , Str "sad"+ , Space+ , Str "light"+ , Space+ , Str "a"+ , Space+ , Str "carved"+ , Space+ , Str "dolphin"+ , Space+ , Str "swam."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Above"+ , Space+ , Str "the"+ , Space+ , Str "antique"+ , Space+ , Str "mantel"+ , Space+ , Str "was"+ , Space+ , Str "displayed"+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln98" , [] , [] )+ [ Plain+ [ Str "As"+ , Space+ , Str "though"+ , Space+ , Str "a"+ , Space+ , Str "window"+ , Space+ , Str "gave"+ , Space+ , Str "upon"+ , Space+ , Str "the"+ , Space+ , Str "sylvan"+ , Space+ , Str "scene"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "98." ]+ ( "#wasteland-content.xhtml_ln98"+ , ""+ )+ , Space+ , Str "Sylvan"+ , Space+ , Str "scene."+ , Space+ , Str "V."+ , Space+ , Str "Milton,"+ , Space+ , Str "Paradise"+ , Space+ , Str "Lost,"+ , Space+ , Str "iv."+ , Space+ , Str "140."+ ]+ ]+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln99" , [] , [] )+ [ Plain+ [ Str "The"+ , Space+ , Str "change"+ , Space+ , Str "of"+ , Space+ , Str "Philomel,"+ , Space+ , Str "by"+ , Space+ , Str "the"+ , Space+ , Str "barbarous"+ , Space+ , Str "king"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "99." ]+ ( "#wasteland-content.xhtml_ln99"+ , ""+ )+ , Space+ , Str "V."+ , Space+ , Str "Ovid,"+ , Space+ , Str "Metamorphoses,"+ , Space+ , Str "vi,"+ , Space+ , Str "Philomela."+ ]+ ]+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln100" , [] , [] )+ [ Plain+ [ Str "So"+ , Space+ , Str "rudely"+ , Space+ , Str "forced;"+ , Space+ , Str "yet"+ , Space+ , Str "there"+ , Space+ , Str "the"+ , Space+ , Str "nightingale"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "100." ]+ ( "#wasteland-content.xhtml_ln100"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "Part"+ , Space+ , Str "III,"+ , Space+ , Str "l."+ , Space+ , Str "204."+ ]+ ]+ , SoftBreak+ , Span ( "" , [ "lnum" ] , [] ) [ Str "100" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Filled"+ , Space+ , Str "all"+ , Space+ , Str "the"+ , Space+ , Str "desert"+ , Space+ , Str "with"+ , Space+ , Str "inviolable"+ , Space+ , Str "voice"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "still"+ , Space+ , Str "she"+ , Space+ , Str "cried,"+ , Space+ , Str "and"+ , Space+ , Str "still"+ , Space+ , Str "the"+ , Space+ , Str "world"+ , Space+ , Str "pursues,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"Jug"+ , Space+ , Str "Jug\""+ , Space+ , Str "to"+ , Space+ , Str "dirty"+ , Space+ , Str "ears."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "other"+ , Space+ , Str "withered"+ , Space+ , Str "stumps"+ , Space+ , Str "of"+ , Space+ , Str "time"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Were"+ , Space+ , Str "told"+ , Space+ , Str "upon"+ , Space+ , Str "the"+ , Space+ , Str "walls;"+ , Space+ , Str "staring"+ , Space+ , Str "forms"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Leaned"+ , Space+ , Str "out,"+ , Space+ , Str "leaning,"+ , Space+ , Str "hushing"+ , Space+ , Str "the"+ , Space+ , Str "room"+ , Space+ , Str "enclosed."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Footsteps"+ , Space+ , Str "shuffled"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Str "stair."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Under"+ , Space+ , Str "the"+ , Space+ , Str "firelight,"+ , Space+ , Str "under"+ , Space+ , Str "the"+ , Space+ , Str "brush,"+ , Space+ , Str "her"+ , Space+ , Str "hair"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Spread"+ , Space+ , Str "out"+ , Space+ , Str "in"+ , Space+ , Str "fiery"+ , Space+ , Str "points"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Glowed"+ , Space+ , Str "into"+ , Space+ , Str "words,"+ , Space+ , Str "then"+ , Space+ , Str "would"+ , Space+ , Str "be"+ , Space+ , Str "savagely"+ , Space+ , Str "still."+ , Span ( "" , [ "lnum" ] , [] ) [ Str "110" ]+ ]+ ]+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"My"+ , Space+ , Str "nerves"+ , Space+ , Str "are"+ , Space+ , Str "bad"+ , Space+ , Str "to-night."+ , Space+ , Str "Yes,"+ , Space+ , Str "bad."+ , Space+ , Str "Stay"+ , Space+ , Str "with"+ , Space+ , Str "me."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"Speak"+ , Space+ , Str "to"+ , Space+ , Str "me."+ , Space+ , Str "Why"+ , Space+ , Str "do"+ , Space+ , Str "you"+ , Space+ , Str "never"+ , Space+ , Str "speak."+ , Space+ , Str "Speak."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"What"+ , Space+ , Str "are"+ , Space+ , Str "you"+ , Space+ , Str "thinking"+ , Space+ , Str "of?"+ , Space+ , Str "What"+ , Space+ , Str "thinking?"+ , Space+ , Str "What?"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"I"+ , Space+ , Str "never"+ , Space+ , Str "know"+ , Space+ , Str "what"+ , Space+ , Str "you"+ , Space+ , Str "are"+ , Space+ , Str "thinking."+ , Space+ , Str "Think.\""+ ]+ ]+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "wasteland-content.xhtml_ln115" , [] , [] )+ [ Plain+ [ Str "I"+ , Space+ , Str "think"+ , Space+ , Str "we"+ , Space+ , Str "are"+ , Space+ , Str "in"+ , Space+ , Str "rats'"+ , Space+ , Str "alley"+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "115." ]+ ( "#wasteland-content.xhtml_ln115"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "Part"+ , Space+ , Str "III,"+ , Space+ , Str "l."+ , Space+ , Str "195."+ ]+ ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Where"+ , Space+ , Str "the"+ , Space+ , Str "dead"+ , Space+ , Str "men"+ , Space+ , Str "lost"+ , Space+ , Str "their"+ , Space+ , Str "bones."+ ]+ ]+ ]+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"What"+ , Space+ , Str "is"+ , Space+ , Str "that"+ , Space+ , Str "noise?\""+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln118"+ , [ "indent" ]+ , []+ )+ [ Plain+ [ Str "The"+ , Space+ , Str "wind"+ , Space+ , Str "under"+ , Space+ , Str "the"+ , Space+ , Str "door."+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "118." ]+ ( "#wasteland-content.xhtml_ln118"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "Webster:"+ ]+ , BlockQuote+ [ Para+ [ Str "\"Is"+ , Space+ , Str "the"+ , Space+ , Str "wind"+ , Space+ , Str "in"+ , Space+ , Str "that"+ , Space+ , Str "door"+ , Space+ , Str "still?\""+ ]+ ]+ ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"What"+ , Space+ , Str "is"+ , Space+ , Str "that"+ , Space+ , Str "noise"+ , Space+ , Str "now?"+ , Space+ , Str "What"+ , Space+ , Str "is"+ , Space+ , Str "the"+ , Space+ , Str "wind"+ , Space+ , Str "doing?\""+ ]+ ]+ , Div+ ( "" , [ "indent" ] , [] )+ [ Plain+ [ Str "Nothing"+ , Space+ , Str "again"+ , Space+ , Str "nothing."+ , Span ( "" , [ "lnum" ] , [] ) [ Str "120" ]+ ]+ ]+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div ( "" , [] , [] ) [ Plain [ Str "\"Do" ] ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"You"+ , Space+ , Str "know"+ , Space+ , Str "nothing?"+ , Space+ , Str "Do"+ , Space+ , Str "you"+ , Space+ , Str "see"+ , Space+ , Str "nothing?"+ , Space+ , Str "Do"+ , Space+ , Str "you"+ , Space+ , Str "remember"+ ]+ ]+ , Div ( "" , [] , [] ) [ Plain [ Str "\"Nothing?\"" ] ]+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "" , [] , [] )+ [ Plain [ Str "I" , Space , Str "remember" ] ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Those"+ , Space+ , Str "are"+ , Space+ , Str "pearls"+ , Space+ , Str "that"+ , Space+ , Str "were"+ , Space+ , Str "his"+ , Space+ , Str "eyes."+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln126" , [] , [] )+ [ Plain+ [ Str "\"Are"+ , Space+ , Str "you"+ , Space+ , Str "alive,"+ , Space+ , Str "or"+ , Space+ , Str "not?"+ , Space+ , Str "Is"+ , Space+ , Str "there"+ , Space+ , Str "nothing"+ , Space+ , Str "in"+ , Space+ , Str "your"+ , Space+ , Str "head?\""+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "126." ]+ ( "#wasteland-content.xhtml_ln126"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "Part"+ , Space+ , Str "I,"+ , Space+ , Str "l."+ , Space+ , Str "37,"+ , Space+ , Str "48."+ ]+ ]+ ]+ ]+ , Div ( "" , [] , [] ) [ Plain [ Str "But" ] ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "O"+ , Space+ , Str "O"+ , Space+ , Str "O"+ , Space+ , Str "O"+ , Space+ , Str "that"+ , Space+ , Str "Shakespeherian"+ , Space+ , Str "Rag\8213"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "It's"+ , Space+ , Str "so"+ , Space+ , Str "elegant"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "So"+ , Space+ , Str "intelligent"+ , Span ( "" , [ "lnum" ] , [] ) [ Str "130" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"What"+ , Space+ , Str "shall"+ , Space+ , Str "I"+ , Space+ , Str "do"+ , Space+ , Str "now?"+ , Space+ , Str "What"+ , Space+ , Str "shall"+ , Space+ , Str "I"+ , Space+ , Str "do?\""+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "I"+ , Space+ , Str "shall"+ , Space+ , Str "rush"+ , Space+ , Str "out"+ , Space+ , Str "as"+ , Space+ , Str "I"+ , Space+ , Str "am,"+ , Space+ , Str "and"+ , Space+ , Str "walk"+ , Space+ , Str "the"+ , Space+ , Str "street"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"With"+ , Space+ , Str "my"+ , Space+ , Str "hair"+ , Space+ , Str "down,"+ , Space+ , Str "so."+ , Space+ , Str "What"+ , Space+ , Str "shall"+ , Space+ , Str "we"+ , Space+ , Str "do"+ , Space+ , Str "to-morrow?"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "\"What"+ , Space+ , Str "shall"+ , Space+ , Str "we"+ , Space+ , Str "ever"+ , Space+ , Str "do?\""+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "The"+ , Space+ , Str "hot"+ , Space+ , Str "water"+ , Space+ , Str "at"+ , Space+ , Str "ten."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "if"+ , Space+ , Str "it"+ , Space+ , Str "rains,"+ , Space+ , Str "a"+ , Space+ , Str "closed"+ , Space+ , Str "car"+ , Space+ , Str "at"+ , Space+ , Str "four."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "we"+ , Space+ , Str "shall"+ , Space+ , Str "play"+ , Space+ , Str "a"+ , Space+ , Str "game"+ , Space+ , Str "of"+ , Space+ , Str "chess,"+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_ln138" , [] , [] )+ [ Plain+ [ Str "Pressing"+ , Space+ , Str "lidless"+ , Space+ , Str "eyes"+ , Space+ , Str "and"+ , Space+ , Str "waiting"+ , Space+ , Str "for"+ , Space+ , Str "a"+ , Space+ , Str "knock"+ , Space+ , Str "upon"+ , Space+ , Str "the"+ , Space+ , Str "door."+ , Note+ [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "138." ]+ ( "#wasteland-content.xhtml_ln138"+ , ""+ )+ , Space+ , Str "Cf."+ , Space+ , Str "the"+ , Space+ , Str "game"+ , Space+ , Str "of"+ , Space+ , Str "chess"+ , Space+ , Str "in"+ , Space+ , Str "Middleton's"+ , Space+ , Str "Women"+ , Space+ , Str "beware"+ , Space+ , Str "Women."+ ]+ ]+ ]+ ]+ ]+ , Div+ ( "" , [ "linegroup" ] , [] )+ [ Div+ ( "" , [] , [] )+ [ Plain+ [ Str "When"+ , Space+ , Str "Lil's"+ , Space+ , Str "husband"+ , Space+ , Str "got"+ , Space+ , Str "demobbed,"+ , Space+ , Str "I"+ , Space+ , Str "said"+ , Space+ , Str "-"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "I"+ , Space+ , Str "didn't"+ , Space+ , Str "mince"+ , Space+ , Str "my"+ , Space+ , Str "words,"+ , Space+ , Str "I"+ , Space+ , Str "said"+ , Space+ , Str "to"+ , Space+ , Str "her"+ , Space+ , Str "myself,"+ , Span ( "" , [ "lnum" ] , [] ) [ Str "140" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "HURRY"+ , Space+ , Str "UP"+ , Space+ , Str "PLEASE"+ , Space+ , Str "ITS"+ , Space+ , Str "TIME"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Now"+ , Space+ , Str "Albert's"+ , Space+ , Str "coming"+ , Space+ , Str "back,"+ , Space+ , Str "make"+ , Space+ , Str "yourself"+ , Space+ , Str "a"+ , Space+ , Str "bit"+ , Space+ , Str "smart."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "He'll"+ , Space+ , Str "want"+ , Space+ , Str "to"+ , Space+ , Str "know"+ , Space+ , Str "what"+ , Space+ , Str "you"+ , Space+ , Str "done"+ , Space+ , Str "with"+ , Space+ , Str "that"+ , Space+ , Str "money"+ , Space+ , Str "he"+ , Space+ , Str "gave"+ , SoftBreak+ , Str "you"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "To"+ , Space+ , Str "get"+ , Space+ , Str "yourself"+ , Space+ , Str "some"+ , Space+ , Str "teeth."+ , Space+ , Str "He"+ , Space+ , Str "did,"+ , Space+ , Str "I"+ , Space+ , Str "was"+ , Space+ , Str "there."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "You"+ , Space+ , Str "have"+ , Space+ , Str "them"+ , Space+ , Str "all"+ , Space+ , Str "out,"+ , Space+ , Str "Lil,"+ , Space+ , Str "and"+ , Space+ , Str "get"+ , Space+ , Str "a"+ , Space+ , Str "nice"+ , Space+ , Str "set,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "He"+ , Space+ , Str "said,"+ , Space+ , Str "I"+ , Space+ , Str "swear,"+ , Space+ , Str "I"+ , Space+ , Str "can't"+ , Space+ , Str "bear"+ , Space+ , Str "to"+ , Space+ , Str "look"+ , Space+ , Str "at"+ , Space+ , Str "you."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "no"+ , Space+ , Str "more"+ , Space+ , Str "can't"+ , Space+ , Str "I,"+ , Space+ , Str "I"+ , Space+ , Str "said,"+ , Space+ , Str "and"+ , Space+ , Str "think"+ , Space+ , Str "of"+ , Space+ , Str "poor"+ , Space+ , Str "Albert,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "He's"+ , Space+ , Str "been"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "army"+ , Space+ , Str "four"+ , Space+ , Str "years,"+ , Space+ , Str "he"+ , Space+ , Str "wants"+ , Space+ , Str "a"+ , Space+ , Str "good"+ , Space+ , Str "time,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "if"+ , Space+ , Str "you"+ , Space+ , Str "don't"+ , Space+ , Str "give"+ , Space+ , Str "it"+ , Space+ , Str "him,"+ , Space+ , Str "there's"+ , Space+ , Str "others"+ , Space+ , Str "will,"+ , Space+ , Str "I"+ , SoftBreak+ , Str "said."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Oh"+ , Space+ , Str "is"+ , Space+ , Str "there,"+ , Space+ , Str "she"+ , Space+ , Str "said."+ , Space+ , Str "Something"+ , Space+ , Str "o'"+ , Space+ , Str "that,"+ , Space+ , Str "I"+ , Space+ , Str "said."+ , Span ( "" , [ "lnum" ] , [] ) [ Str "150" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Then"+ , Space+ , Str "I'll"+ , Space+ , Str "know"+ , Space+ , Str "who"+ , Space+ , Str "to"+ , Space+ , Str "thank,"+ , Space+ , Str "she"+ , Space+ , Str "said,"+ , Space+ , Str "and"+ , Space+ , Str "give"+ , Space+ , Str "me"+ , Space+ , Str "a"+ , Space+ , Str "straight"+ , SoftBreak+ , Str "look."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "HURRY"+ , Space+ , Str "UP"+ , Space+ , Str "PLEASE"+ , Space+ , Str "ITS"+ , Space+ , Str "TIME"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "If"+ , Space+ , Str "you"+ , Space+ , Str "don't"+ , Space+ , Str "like"+ , Space+ , Str "it"+ , Space+ , Str "you"+ , Space+ , Str "can"+ , Space+ , Str "get"+ , Space+ , Str "on"+ , Space+ , Str "with"+ , Space+ , Str "it,"+ , Space+ , Str "I"+ , Space+ , Str "said."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Others"+ , Space+ , Str "can"+ , Space+ , Str "pick"+ , Space+ , Str "and"+ , Space+ , Str "choose"+ , Space+ , Str "if"+ , Space+ , Str "you"+ , Space+ , Str "can't."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "But"+ , Space+ , Str "if"+ , Space+ , Str "Albert"+ , Space+ , Str "makes"+ , Space+ , Str "off,"+ , Space+ , Str "it"+ , Space+ , Str "won't"+ , Space+ , Str "be"+ , Space+ , Str "for"+ , Space+ , Str "lack"+ , Space+ , Str "of"+ , SoftBreak+ , Str "telling."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "You"+ , Space+ , Str "ought"+ , Space+ , Str "to"+ , Space+ , Str "be"+ , Space+ , Str "ashamed,"+ , Space+ , Str "I"+ , Space+ , Str "said,"+ , Space+ , Str "to"+ , Space+ , Str "look"+ , Space+ , Str "so"+ , Space+ , Str "antique."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "(And"+ , Space+ , Str "her"+ , Space+ , Str "only"+ , Space+ , Str "thirty-one.)"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "I"+ , Space+ , Str "can't"+ , Space+ , Str "help"+ , Space+ , Str "it,"+ , Space+ , Str "she"+ , Space+ , Str "said,"+ , Space+ , Str "pulling"+ , Space+ , Str "a"+ , Space+ , Str "long"+ , Space+ , Str "face,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "It's"+ , Space+ , Str "them"+ , Space+ , Str "pills"+ , Space+ , Str "I"+ , Space+ , Str "took,"+ , Space+ , Str "to"+ , Space+ , Str "bring"+ , Space+ , Str "it"+ , Space+ , Str "off,"+ , Space+ , Str "she"+ , Space+ , Str "said."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "(She's"+ , Space+ , Str "had"+ , Space+ , Str "five"+ , Space+ , Str "already,"+ , Space+ , Str "and"+ , Space+ , Str "nearly"+ , Space+ , Str "died"+ , Space+ , Str "of"+ , Space+ , Str "young"+ , Space+ , Str "George.)"+ , Span ( "" , [ "lnum" ] , [] ) [ Str "160" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "The"+ , Space+ , Str "chemist"+ , Space+ , Str "said"+ , Space+ , Str "it"+ , Space+ , Str "would"+ , Space+ , Str "be"+ , Space+ , Str "all"+ , Space+ , Str "right,"+ , Space+ , Str "but"+ , Space+ , Str "I've"+ , Space+ , Str "never"+ , Space+ , Str "been"+ , Space+ , Str "the"+ , SoftBreak+ , Str "same."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "You"+ , Space+ , Emph [ Str "are" ]+ , Space+ , Str "a"+ , Space+ , Str "proper"+ , Space+ , Str "fool,"+ , Space+ , Str "I"+ , Space+ , Str "said."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Well,"+ , Space+ , Str "if"+ , Space+ , Str "Albert"+ , Space+ , Str "won't"+ , Space+ , Str "leave"+ , Space+ , Str "you"+ , Space+ , Str "alone,"+ , Space+ , Str "there"+ , Space+ , Str "it"+ , Space+ , Str "is,"+ , Space+ , Str "I"+ , SoftBreak+ , Str "said,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "What"+ , Space+ , Str "you"+ , Space+ , Str "get"+ , Space+ , Str "married"+ , Space+ , Str "for"+ , Space+ , Str "if"+ , Space+ , Str "you"+ , Space+ , Str "don't"+ , Space+ , Str "want"+ , Space+ , Str "children?"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "HURRY"+ , Space+ , Str "UP"+ , Space+ , Str "PLEASE"+ , Space+ , Str "ITS"+ , Space+ , Str "TIME"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Well,"+ , Space+ , Str "that"+ , Space+ , Str "Sunday"+ , Space+ , Str "Albert"+ , Space+ , Str "was"+ , Space+ , Str "home,"+ , Space+ , Str "they"+ , Space+ , Str "had"+ , Space+ , Str "a"+ , Space+ , Str "hot"+ , SoftBreak+ , Str "gammon,"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "And"+ , Space+ , Str "they"+ , Space+ , Str "asked"+ , Space+ , Str "me"+ , Space+ , Str "in"+ , Space+ , Str "to"+ , Space+ , Str "dinner,"+ , Space+ , Str "to"+ , Space+ , Str "get"+ , Space+ , Str "the"+ , Space+ , Str "beauty"+ , Space+ , Str "of"+ , Space+ , Str "it"+ , SoftBreak+ , Str "hot\8213"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "HURRY"+ , Space+ , Str "UP"+ , Space+ , Str "PLEASE"+ , Space+ , Str "ITS"+ , Space+ , Str "TIME"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "HURRY"+ , Space+ , Str "UP"+ , Space+ , Str "PLEASE"+ , Space+ , Str "ITS"+ , Space+ , Str "TIME"+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Goonight"+ , Space+ , Str "Bill."+ , Space+ , Str "Goonight"+ , Space+ , Str "Lou."+ , Space+ , Str "Goonight"+ , Space+ , Str "May."+ , Space+ , Str "Goonight."+ , Span ( "" , [ "lnum" ] , [] ) [ Str "170" ]+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Ta"+ , Space+ , Str "ta."+ , Space+ , Str "Goonight."+ , Space+ , Str "Goonight."+ ]+ ]+ , Div+ ( "" , [] , [] )+ [ Plain+ [ Str "Good"+ , Space+ , Str "night,"+ , Space+ , Str "ladies,"+ , Space+ , Str "good"+ , Space+ , Str "night,"+ , Space+ , Str "sweet"+ , Space+ , Str "ladies,"+ , Space+ , Str "good"+ , Space+ , Str "night,"+ , Space+ , Str "good"+ , SoftBreak+ , Str "night."+ ]+ ]+ ]+ ]+ ]+ , Div+ ( "wasteland-content.xhtml_backmatter"+ , [ "section" , "backmatter" ]+ , []+ )+ [ Div+ ( "wasteland-content.xhtml_rearnotes"+ , [ "rearnotes" ]+ , []+ )+ [ Header+ 2+ ( "" , [] , [] )+ [ Str "NOTES"+ , Space+ , Str "ON"+ , Space+ , Str "\"THE"+ , Space+ , Str "WASTE"+ , Space+ , Str "LAND\""+ ]+ , Para+ [ Str "Not"+ , Space+ , Str "only"+ , Space+ , Str "the"+ , Space+ , Str "title,"+ , Space+ , Str "but"+ , Space+ , Str "the"+ , Space+ , Str "plan"+ , Space+ , Str "and"+ , Space+ , Str "a"+ , Space+ , Str "good"+ , Space+ , Str "deal"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "incidental"+ , Space+ , Str "symbolism"+ , Space+ , Str "of"+ , SoftBreak+ , Str "the"+ , Space+ , Str "poem"+ , Space+ , Str "were"+ , Space+ , Str "suggested"+ , Space+ , Str "by"+ , Space+ , Str "Miss"+ , Space+ , Str "Jessie"+ , Space+ , Str "L."+ , Space+ , Str "Weston's"+ , Space+ , Str "book"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Str "Grail"+ , Space+ , Str "legend:"+ , SoftBreak+ , Str "From"+ , Space+ , Str "Ritual"+ , Space+ , Str "to"+ , Space+ , Str "Romance"+ ]+ , Para+ [ Str "Indeed,"+ , Space+ , Str "so"+ , Space+ , Str "deeply"+ , Space+ , Str "am"+ , Space+ , Str "I"+ , Space+ , Str "indebted,"+ , Space+ , Str "Miss"+ , Space+ , Str "Weston's"+ , Space+ , Str "book"+ , Space+ , Str "will"+ , Space+ , Str "elucidate"+ , Space+ , Str "the"+ , SoftBreak+ , Str "difficulties"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "poem"+ , Space+ , Str "much"+ , Space+ , Str "better"+ , Space+ , Str "than"+ , Space+ , Str "my"+ , Space+ , Str "notes"+ , Space+ , Str "can"+ , Space+ , Str "do;"+ , Space+ , Str "and"+ , Space+ , Str "I"+ , Space+ , Str "recommend"+ , Space+ , Str "it"+ , SoftBreak+ , Str "(apart"+ , Space+ , Str "from"+ , Space+ , Str "the"+ , Space+ , Str "great"+ , Space+ , Str "interest"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "book"+ , Space+ , Str "itself)"+ , Space+ , Str "to"+ , Space+ , Str "any"+ , Space+ , Str "who"+ , Space+ , Str "think"+ , Space+ , Str "such"+ , SoftBreak+ , Str "elucidation"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "poem"+ , Space+ , Str "worth"+ , Space+ , Str "the"+ , Space+ , Str "trouble."+ , Space+ , Str "To"+ , Space+ , Str "another"+ , Space+ , Str "work"+ , Space+ , Str "of"+ , Space+ , Str "anthropology"+ , Space+ , Str "I"+ , Space+ , Str "am"+ , SoftBreak+ , Str "indebted"+ , Space+ , Str "in"+ , Space+ , Str "general,"+ , Space+ , Str "one"+ , Space+ , Str "which"+ , Space+ , Str "has"+ , Space+ , Str "influenced"+ , Space+ , Str "our"+ , Space+ , Str "generation"+ , Space+ , Str "profoundly;"+ , Space+ , Str "I"+ , Space+ , Str "mean"+ , SoftBreak+ , Str "The"+ , Space+ , Str "Golden"+ , Space+ , Str "Bough;"+ , Space+ , Str "I"+ , Space+ , Str "have"+ , Space+ , Str "used"+ , Space+ , Str "especially"+ , Space+ , Str "the"+ , Space+ , Str "two"+ , Space+ , Str "volumes"+ , Space+ , Str "Adonis,"+ , Space+ , Str "Attis,"+ , Space+ , Str "Osiris."+ , SoftBreak+ , Str "Anyone"+ , Space+ , Str "who"+ , Space+ , Str "is"+ , Space+ , Str "acquainted"+ , Space+ , Str "with"+ , Space+ , Str "these"+ , Space+ , Str "works"+ , Space+ , Str "will"+ , Space+ , Str "immediately"+ , Space+ , Str "recognise"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "poem"+ , SoftBreak+ , Str "certain"+ , Space+ , Str "references"+ , Space+ , Str "to"+ , Space+ , Str "vegetation"+ , Space+ , Str "ceremonies."+ ]+ , Div+ ( "" , [ "section" ] , [] )+ [ Header+ 3+ ( "" , [] , [] )+ [ Str "I."+ , Space+ , Str "THE"+ , Space+ , Str "BURIAL"+ , Space+ , Str "OF"+ , Space+ , Str "THE"+ , Space+ , Str "DEAD"+ ]+ ]+ , Div+ ( "" , [ "section" ] , [] )+ [ Header+ 3+ ( "" , [] , [] )+ [ Str "II."+ , Space+ , Str "A"+ , Space+ , Str "GAME"+ , Space+ , Str "OF"+ , Space+ , Str "CHESS"+ ]+ ]+ ]+ ]+ ]
@@ -1,2 +1,2 @@ <?xml version="1.0" encoding="UTF-8"?>-<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>unrecognised</genre></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><section><image l:href="#image1" l:type="inlineImageType" alt="This image was embedded using data URI scheme" /><p>This image was embedded using data URI scheme</p></section></body><binary id="image1" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAADAAAAAgCAIAAADbtmxLAAABmGlDQ1BpY2MAAHjapdG/axMBGMbxTy4tldJSwSAiHW4ootKCqIOrVShIkRIrJNUluUvaQi4Nd1dEXAQHF4cOXVRcLOLirJv4BygIggqCi7sUBRcpcbiDgtBBfOGF5/315eV9qR7qRUk2EpL087S+MB82mivh2BeBcUcddrwVZYOLS0uLDrRfH1Xgw1wvSjL/ZpNxJ4uohFiKBmlOZYC7t/JBTmUXtWitFROMYDZtNFcIzqDWLvRl1FYL3UAtXa5fIughXC30A4TtQr9AGK2lCcFbzMRJPybYxWScxDFVGE16m1G5ZwUTnf71aziPaXUsYB4h2tjEOnrIMVfG/QJyAC/GtKvYKFlRqQe4jbTkrGKtZM+WvZvI0CnjbtnfKb1XMtBoroR//yzrnjtbbDRxhdFvw+HP04w9Zu/+cPj76XC4t0P1M2+29+c3trnwnerWfm7mCVP3ePl6P9d+xqstjn0dtNIWitMG3S4/njPZ5Mh7xm/8b734Z1m384nlOyy+4+EjTnSZunkyzsP1ft5J+63eKWT1hXn4AzDofghlJQBJAAAACXBIWXMAAAsSAAALEgHS3X78AAACInpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjahVRJtiQhCNx7ijpCMIhyHNPU9/oGffxeaNY3p/5VC5IAQkAhtL9/evh8Pp+PiwaNKZubAYDuugNcMH4ZIAN6A6ATo68kdAA8VQ1DkoEIq2EILiBiALIQDTISWvz3SSQNJHwnilWTGgC/ZMSa1Fc8TDznZH4rgWOtRrwQKGh8VyNZ8bAY9Ccj1EGXUI0JwNE3n3itxrzis7Sq1TgBiNMwesKo1TjfcdZqXBaiWRpLrcbbEjBLU63G9QGv1bit+CSKWi2W8+3QLDluF/wIBgBEaNQWNSjFzHj7/zgOP92EBap3v2BqlNi2pEbGVi0yBNwkcRPiTVxIJDVLRgJxEXGLRgAgLBASkiIIwlIEYgyBJCnC4lKExN6yGSW6SD961nvvQaxhBZq4rbptbX1HlJPSokN37t9m9957a5utDux7Xwk06WnWWOJ2yqgkPqW4e2urnmNPK0HMtq0Hkkc7ZbSXUleHiNMIoGy7r/ppEwAIV+Amv1rS/3ghgCz23ns+m/HrASdJMWT2chsBiS2z73fcLGd+3E8hZ05nQ81zzOW2n8Saj1VzwTMHZ+g6xcPg5ozLASM7Z/hl9kaPnPFQmrcyvm8lFKbrAQwAoegtYFy34rEXRSFP/qEo4tmQ0wywlwPyG5G/BJQXvF5wOR4k7m9HjlupR/y6Mp42RjhWxm+Oh99BvMrwD3UCiGvkpxuRAAAACXZwQWcAAAAwAAAAIACELJ4GAAALGklEQVRYw11YW48dV1b+1tq7qs6t+/TldPsSx3bbcRwncWY0A4LMCOYFXpgHJCR4QvwAnpAQj/wB/gR/ACR4QUKDECMUEjLOZew4zsRxuu122+52n9Pnfuqy9/p4qNNtD1tLpVKpap/vrMu31rdl/nAgIjSpF0kAJAEHGJwAAIQheqeARVqomCQZGUkjSYLmTAyAkCJiESRVNYQAaL3h8k3SzPj6MjEzsr7SqyoAcRABQItRVZ14kqifmNEkTZNiUZiZ934xm4WE3mva8GYGAA5UJ8YYIyCipiKk1ZuTBAhQBGZQFRKvTAgBaQBIeOekBqpa+0gBxFgAlmhqhixJzUKMRVEUx/3RWmel3z9xzrVX2+tuRb3WnrDKVFUEgKlCVWI055WMZ76AieipX0AYzYwQUZqZqJD0tKCqFJAxhKiqSZKooirj06fPMt/odlezhngFYar+0e7jxWLR6/Vc7ubzpNnM4BlDSDLvvQ8hnAYFIlCFRUDEjASgIGFGEcBIoSrMCFAVhgiKTxJPkgJVSeBBhKqaTCb5Ip4cD/efPP/g9q2soSvdTp7nAuv2Vk/2BoHFyWgRYxVjbDezRiMDMicNxqCqqhIZVZxZVK3zaRkgXYaMdeDMoMoapSpo8GSE1t6ihaCqPs3WV/VwPpxOp8fHRw++cUmq7XYzSbLV1W5vu3fw7Emn0xwcD+ZzF8vKQtlI09R7J6SXOldgEDEwAmdguMyYV/lEVWEkARExEkoVBxHWxeUSFefK6fTJ48dlme/sXN7a3vjVnf8NIQ6Hk1ajOZ+Nf/3ZZ9Uij0V+fedqM0v2nz5ut7LtCz1GC2WVJqmry1KgZKLqlbo0qLPanJrAVKgSRX/LPElxQF0smiDy6Ojo7pd3qXLjxo2r1y8fnwxORpN8Nt/u9fLF5OTFcRVKDWE0HJZF2O71IsOzZ0+e7D3tdDo7168miU9SJ6IhBIGD2KuKMpHaPwoFXkXq9Aak+/u//TsFRCEgEAljjFtbW+UiHPb765sbJ8M+Y9HtdAbDgWs0pSge7O1u9Tar+Xwwmy0m03I0XpgbjydZlk2n43armaVOJIqQDEIIIKBABK/iBYuAnT4HwJrx1CkhRosAIRBBo93ImunO25dv/eBmb231+rUrRTH/we1ba+udhw/uSoZGOzt38Vx/1D85folYLhazqpg3mj5ruNWVTqPhxcEsAOa8ihJiAhMEQVChCgXmhKcWT41O6IGq5kCjqPOTk9F4PF7rrlvKRtQHjx/d2Lk+mgy+evrwhzs3Xuzv0tmbb5z79LNPzm9utdorEoNkzPPx+x+812o10tR7DyCqUwCMQUUIUqm2JOolbb/GjmbwoDGS9GZBnYM4IS0E5+TChS1Nk7Z28uPhW29euvPRf2fN1pdffNE1vXnzxsGgf/B036duvbce5tXG2uZkfnL79q3t8+sA4Rws0CJIAOI8LADUusLqeC0rTl4RJgyg1Fe+fB7yUrxTQoRWVoExbWTjl6P5fD7dO6yIF4P+bDK/92T3hzffLWGffPq5c7K1uf7hj3+PrLqbqxffuDQc9VdWVtY31846l1CFqJlalk8gr/UxAIzLLrZkbVK5WHgHhFIYmS+K6ZhFkY/Hi/5gPOhLUzvnu73L59KVxjyffXH314vFIsbYaTXeuXFtcHx4sPd9S+3l84PMwTsyBrMgQhUIgrEUREWUU4O8uhcLdW45BsWpiVRgoSyYTxYn/ee7e9/f/2Z8eOwYm8pko4EktDvpzOZXL5z3Dd3b2/vi/r1G0795cat//GxrvWPTaW+lvdVdXUkTCaVagAUrF6wKVSAGxIAQJEZYiVjSSrBSq4SVWCFWKINYpQzK4FHmhqjOgbF/+Hx0dJyXtv/46ZuXtrrd1V6ruRhNJqPZlfbq5999/Dt/+LNf/tf/nEyH585t73338OrVS3E8Pnl+MJnOi7i4fG1no7cJ79Sh7vPISwCwZYCERN3TjQCFZFxGE3FJV97iXCGIKBZlcyV799zbIdhsNnvyaP/x3r6Z+Tx02i6Kv/7WO8bFX/3ZT37xyZ2yf9Ta2n73vZ1vf/Xlv338+R/97MOVjc63X99fbXduvfuONBJTAlDxiBGAWKQZSVn2BZ4lDYwAlDQzkF7LEmYQyUSTdkvTzNuiZLz25vlOt3N0cPTwxcH7W2/9+NbN0Uef3Pvs6w/+9KcraePb3+z+6NKF+cHLvvN/89d/2SQsTSdr3clwMh0M1nvr0ki4yI0iQgBSu8dYOwxm4BIEyTrTEY1mHrNpZD3KiMIhlLEokljKWueyytsX3ji/2rqzuzt4Obh95eLd3+ztf7Xv1e2sp8OXw73h8Od//FNNtIh5Rqx322tZWoWimo1c7hQi4mgBxtPpA3VBkXQ0M8BOh5VoS3D8j3+CACqsR4EYzUyIalqaCqCxyIsB/uFf//lPfv93R/2jf/z4m0Zmf/6j977af/wXH/7B6ubK+dVV2+g6D0Yzg4OoA0kRrYoiEXcarFfzq7IueJKsYZktAXl7MRURiARakiQ08xAACHCGybj/i3v3ZoNyDa3/vPPg59cuf/fi4GKjPRmH99cuHT5+Ouv3ipV5b2ve2lxRdfPJLMa4ttKxEEl68ZH52bh4xkDhbLI2OYNiBpL+cHfmnKvfq2nf+eWXi2L+6PgQh42nk+GVc1uf7h9+f1T8ZOftXz76flu7L07Gs7FttCYvknH74PiDt24kjWa/PyvLElupJ2OMZFXBROS3hnoz8sxBS9+YYemhrw9L55xCFCYSalgR7Ehy/+DFnChC0kq3m37j9nr2L7uPnrw8UBb//t2emGsnybW8OW9M3uhc+fbprNWW0Qwh6MwKAQGEEIhlpccYSVLl/wkPM4unqEj6+7MyUZeIpj6pRxOJjDGO5qNpbNLsWTiSyt/dex5mR1Ui+9Phxe72w+moI1mmViSbG7xQNNpHlrhKBnkkcbIwi5WZGegpgMYYq6oCoKoiamZAfB1TWCoq+o/2DxzEiU/TNHXeBCGEqqqKGKGIDPOFTedDY8x8M5HEIRlXi5D7TtrsVpv5cDbZyB69eL7a6IjIfD6NNBHJy1A3tcRJCOV4Nmq1OiqZUgFznonzZVWIECoqXjWpijJGevVipFkZqipYKt6JE1XXjj5tJHk+n41jptrtrifqptNpq9WaTMcqyXon9VlqxHgyi5GjWa6qeZ5DJcsyM6OomVm04WQwnY3XIGkCQGEhzktjORoN8yp3zqVpI0lSUNXB59OhiChE1RdaSK0XSTNqoSSbmQe8F8Bi4jRN00WRr3TY7jSzJAEAQZIkCBUQo1aqmtSTHmJkrGApQtu7lodKKXDQGCyaaJo4mgeAEEPM667sd59/dyoQpUYDUQBCpZiqqmrNIgCEIKlgWS1OTl4OYl9gRoo40VgrRhGpP0G9qMZgFieTKgaKOFXQgolaCE7MBOrgnEO0aKWfLI7rWRaAnC4ATv3ZpiLiVQFYoCmzLAuhHI5eMsInIBkNUXTZUAERAVlvFSrziZoZFxOaaK3HAJOw1K9ArQXKMl/MJ7Ld6Z0l/1m86qMCGEXEe7+EW0+g4iFljCHxLQGcWq0NUp/Ur52K+Vc3ohrrFrs8PzhlJgBiKt7MYoxVKIpiIRudtdc9QSxheTPnHIAYCaNzTlXNzKg+YWRQpgKQRjGIB8Pyb0BJnv1ikFoYOwBEBKAEqFQlaRalFtqkc440n3IZrNp7Z4LExMpgy4SAVBaFVp9zhBCIaBQnDqhPSQgKIAJPksal+AG8ogpRnQCIUVRFoSEE9QIaLNCpqiPFQUK0/wPxadi/ncvxsAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxMS0wMi0yOFQwMjo1NTowMiswMTowMGbLlncAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTEtMDItMjhUMDI6NTU6MDIrMDE6MDAXli7LAAAAEXRFWHRqcGVnOmNvbG9yc3BhY2UAMix1VZ8AAAAgdEVYdGpwZWc6c2FtcGxpbmctZmFjdG9yADF4MSwxeDEsMXgx6ZX8cAAAAABJRU5ErkJggg==</binary></FictionBook>+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info><genre>unrecognised</genre></title-info><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><section><image l:href="#image1" l:type="imageType" alt="This image was embedded using data URI scheme" /><p>This image was embedded using data URI scheme</p></section></body><binary id="image1" content-type="image/png">iVBORw0KGgoAAAANSUhEUgAAADAAAAAgCAIAAADbtmxLAAABmGlDQ1BpY2MAAHjapdG/axMBGMbxTy4tldJSwSAiHW4ootKCqIOrVShIkRIrJNUluUvaQi4Nd1dEXAQHF4cOXVRcLOLirJv4BygIggqCi7sUBRcpcbiDgtBBfOGF5/315eV9qR7qRUk2EpL087S+MB82mivh2BeBcUcddrwVZYOLS0uLDrRfH1Xgw1wvSjL/ZpNxJ4uohFiKBmlOZYC7t/JBTmUXtWitFROMYDZtNFcIzqDWLvRl1FYL3UAtXa5fIughXC30A4TtQr9AGK2lCcFbzMRJPybYxWScxDFVGE16m1G5ZwUTnf71aziPaXUsYB4h2tjEOnrIMVfG/QJyAC/GtKvYKFlRqQe4jbTkrGKtZM+WvZvI0CnjbtnfKb1XMtBoroR//yzrnjtbbDRxhdFvw+HP04w9Zu/+cPj76XC4t0P1M2+29+c3trnwnerWfm7mCVP3ePl6P9d+xqstjn0dtNIWitMG3S4/njPZ5Mh7xm/8b734Z1m384nlOyy+4+EjTnSZunkyzsP1ft5J+63eKWT1hXn4AzDofghlJQBJAAAACXBIWXMAAAsSAAALEgHS3X78AAACInpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjahVRJtiQhCNx7ijpCMIhyHNPU9/oGffxeaNY3p/5VC5IAQkAhtL9/evh8Pp+PiwaNKZubAYDuugNcMH4ZIAN6A6ATo68kdAA8VQ1DkoEIq2EILiBiALIQDTISWvz3SSQNJHwnilWTGgC/ZMSa1Fc8TDznZH4rgWOtRrwQKGh8VyNZ8bAY9Ccj1EGXUI0JwNE3n3itxrzis7Sq1TgBiNMwesKo1TjfcdZqXBaiWRpLrcbbEjBLU63G9QGv1bit+CSKWi2W8+3QLDluF/wIBgBEaNQWNSjFzHj7/zgOP92EBap3v2BqlNi2pEbGVi0yBNwkcRPiTVxIJDVLRgJxEXGLRgAgLBASkiIIwlIEYgyBJCnC4lKExN6yGSW6SD961nvvQaxhBZq4rbptbX1HlJPSokN37t9m9957a5utDux7Xwk06WnWWOJ2yqgkPqW4e2urnmNPK0HMtq0Hkkc7ZbSXUleHiNMIoGy7r/ppEwAIV+Amv1rS/3ghgCz23ns+m/HrASdJMWT2chsBiS2z73fcLGd+3E8hZ05nQ81zzOW2n8Saj1VzwTMHZ+g6xcPg5ozLASM7Z/hl9kaPnPFQmrcyvm8lFKbrAQwAoegtYFy34rEXRSFP/qEo4tmQ0wywlwPyG5G/BJQXvF5wOR4k7m9HjlupR/y6Mp42RjhWxm+Oh99BvMrwD3UCiGvkpxuRAAAACXZwQWcAAAAwAAAAIACELJ4GAAALGklEQVRYw11YW48dV1b+1tq7qs6t+/TldPsSx3bbcRwncWY0A4LMCOYFXpgHJCR4QvwAnpAQj/wB/gR/ACR4QUKDECMUEjLOZew4zsRxuu122+52n9Pnfuqy9/p4qNNtD1tLpVKpap/vrMu31rdl/nAgIjSpF0kAJAEHGJwAAIQheqeARVqomCQZGUkjSYLmTAyAkCJiESRVNYQAaL3h8k3SzPj6MjEzsr7SqyoAcRABQItRVZ14kqifmNEkTZNiUZiZ934xm4WE3mva8GYGAA5UJ8YYIyCipiKk1ZuTBAhQBGZQFRKvTAgBaQBIeOekBqpa+0gBxFgAlmhqhixJzUKMRVEUx/3RWmel3z9xzrVX2+tuRb3WnrDKVFUEgKlCVWI055WMZ76AieipX0AYzYwQUZqZqJD0tKCqFJAxhKiqSZKooirj06fPMt/odlezhngFYar+0e7jxWLR6/Vc7ubzpNnM4BlDSDLvvQ8hnAYFIlCFRUDEjASgIGFGEcBIoSrMCFAVhgiKTxJPkgJVSeBBhKqaTCb5Ip4cD/efPP/g9q2soSvdTp7nAuv2Vk/2BoHFyWgRYxVjbDezRiMDMicNxqCqqhIZVZxZVK3zaRkgXYaMdeDMoMoapSpo8GSE1t6ihaCqPs3WV/VwPpxOp8fHRw++cUmq7XYzSbLV1W5vu3fw7Emn0xwcD+ZzF8vKQtlI09R7J6SXOldgEDEwAmdguMyYV/lEVWEkARExEkoVBxHWxeUSFefK6fTJ48dlme/sXN7a3vjVnf8NIQ6Hk1ajOZ+Nf/3ZZ9Uij0V+fedqM0v2nz5ut7LtCz1GC2WVJqmry1KgZKLqlbo0qLPanJrAVKgSRX/LPElxQF0smiDy6Ojo7pd3qXLjxo2r1y8fnwxORpN8Nt/u9fLF5OTFcRVKDWE0HJZF2O71IsOzZ0+e7D3tdDo7168miU9SJ6IhBIGD2KuKMpHaPwoFXkXq9Aak+/u//TsFRCEgEAljjFtbW+UiHPb765sbJ8M+Y9HtdAbDgWs0pSge7O1u9Tar+Xwwmy0m03I0XpgbjydZlk2n43armaVOJIqQDEIIIKBABK/iBYuAnT4HwJrx1CkhRosAIRBBo93ImunO25dv/eBmb231+rUrRTH/we1ba+udhw/uSoZGOzt38Vx/1D85folYLhazqpg3mj5ruNWVTqPhxcEsAOa8ihJiAhMEQVChCgXmhKcWT41O6IGq5kCjqPOTk9F4PF7rrlvKRtQHjx/d2Lk+mgy+evrwhzs3Xuzv0tmbb5z79LNPzm9utdorEoNkzPPx+x+812o10tR7DyCqUwCMQUUIUqm2JOolbb/GjmbwoDGS9GZBnYM4IS0E5+TChS1Nk7Z28uPhW29euvPRf2fN1pdffNE1vXnzxsGgf/B036duvbce5tXG2uZkfnL79q3t8+sA4Rws0CJIAOI8LADUusLqeC0rTl4RJgyg1Fe+fB7yUrxTQoRWVoExbWTjl6P5fD7dO6yIF4P+bDK/92T3hzffLWGffPq5c7K1uf7hj3+PrLqbqxffuDQc9VdWVtY31846l1CFqJlalk8gr/UxAIzLLrZkbVK5WHgHhFIYmS+K6ZhFkY/Hi/5gPOhLUzvnu73L59KVxjyffXH314vFIsbYaTXeuXFtcHx4sPd9S+3l84PMwTsyBrMgQhUIgrEUREWUU4O8uhcLdW45BsWpiVRgoSyYTxYn/ee7e9/f/2Z8eOwYm8pko4EktDvpzOZXL5z3Dd3b2/vi/r1G0795cat//GxrvWPTaW+lvdVdXUkTCaVagAUrF6wKVSAGxIAQJEZYiVjSSrBSq4SVWCFWKINYpQzK4FHmhqjOgbF/+Hx0dJyXtv/46ZuXtrrd1V6ruRhNJqPZlfbq5999/Dt/+LNf/tf/nEyH585t73338OrVS3E8Pnl+MJnOi7i4fG1no7cJ79Sh7vPISwCwZYCERN3TjQCFZFxGE3FJV97iXCGIKBZlcyV799zbIdhsNnvyaP/x3r6Z+Tx02i6Kv/7WO8bFX/3ZT37xyZ2yf9Ta2n73vZ1vf/Xlv338+R/97MOVjc63X99fbXduvfuONBJTAlDxiBGAWKQZSVn2BZ4lDYwAlDQzkF7LEmYQyUSTdkvTzNuiZLz25vlOt3N0cPTwxcH7W2/9+NbN0Uef3Pvs6w/+9KcraePb3+z+6NKF+cHLvvN/89d/2SQsTSdr3clwMh0M1nvr0ki4yI0iQgBSu8dYOwxm4BIEyTrTEY1mHrNpZD3KiMIhlLEokljKWueyytsX3ji/2rqzuzt4Obh95eLd3+ztf7Xv1e2sp8OXw73h8Od//FNNtIh5Rqx322tZWoWimo1c7hQi4mgBxtPpA3VBkXQ0M8BOh5VoS3D8j3+CACqsR4EYzUyIalqaCqCxyIsB/uFf//lPfv93R/2jf/z4m0Zmf/6j977af/wXH/7B6ubK+dVV2+g6D0Yzg4OoA0kRrYoiEXcarFfzq7IueJKsYZktAXl7MRURiARakiQ08xAACHCGybj/i3v3ZoNyDa3/vPPg59cuf/fi4GKjPRmH99cuHT5+Ouv3ipV5b2ve2lxRdfPJLMa4ttKxEEl68ZH52bh4xkDhbLI2OYNiBpL+cHfmnKvfq2nf+eWXi2L+6PgQh42nk+GVc1uf7h9+f1T8ZOftXz76flu7L07Gs7FttCYvknH74PiDt24kjWa/PyvLElupJ2OMZFXBROS3hnoz8sxBS9+YYemhrw9L55xCFCYSalgR7Ehy/+DFnChC0kq3m37j9nr2L7uPnrw8UBb//t2emGsnybW8OW9M3uhc+fbprNWW0Qwh6MwKAQGEEIhlpccYSVLl/wkPM4unqEj6+7MyUZeIpj6pRxOJjDGO5qNpbNLsWTiSyt/dex5mR1Ui+9Phxe72w+moI1mmViSbG7xQNNpHlrhKBnkkcbIwi5WZGegpgMYYq6oCoKoiamZAfB1TWCoq+o/2DxzEiU/TNHXeBCGEqqqKGKGIDPOFTedDY8x8M5HEIRlXi5D7TtrsVpv5cDbZyB69eL7a6IjIfD6NNBHJy1A3tcRJCOV4Nmq1OiqZUgFznonzZVWIECoqXjWpijJGevVipFkZqipYKt6JE1XXjj5tJHk+n41jptrtrifqptNpq9WaTMcqyXon9VlqxHgyi5GjWa6qeZ5DJcsyM6OomVm04WQwnY3XIGkCQGEhzktjORoN8yp3zqVpI0lSUNXB59OhiChE1RdaSK0XSTNqoSSbmQe8F8Bi4jRN00WRr3TY7jSzJAEAQZIkCBUQo1aqmtSTHmJkrGApQtu7lodKKXDQGCyaaJo4mgeAEEPM667sd59/dyoQpUYDUQBCpZiqqmrNIgCEIKlgWS1OTl4OYl9gRoo40VgrRhGpP0G9qMZgFieTKgaKOFXQgolaCE7MBOrgnEO0aKWfLI7rWRaAnC4ATv3ZpiLiVQFYoCmzLAuhHI5eMsInIBkNUXTZUAERAVlvFSrziZoZFxOaaK3HAJOw1K9ArQXKMl/MJ7Ld6Z0l/1m86qMCGEXEe7+EW0+g4iFljCHxLQGcWq0NUp/Ur52K+Vc3ohrrFrs8PzhlJgBiKt7MYoxVKIpiIRudtdc9QSxheTPnHIAYCaNzTlXNzKg+YWRQpgKQRjGIB8Pyb0BJnv1ikFoYOwBEBKAEqFQlaRalFtqkc440n3IZrNp7Z4LExMpgy4SAVBaFVp9zhBCIaBQnDqhPSQgKIAJPksal+AG8ogpRnQCIUVRFoSEE9QIaLNCpqiPFQUK0/wPxadi/ncvxsAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxMS0wMi0yOFQwMjo1NTowMiswMTowMGbLlncAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTEtMDItMjhUMDI6NTU6MDIrMDE6MDAXli7LAAAAEXRFWHRqcGVnOmNvbG9yc3BhY2UAMix1VZ8AAAAgdEVYdGpwZWc6c2FtcGxpbmctZmFjdG9yADF4MSwxeDEsMXgx6ZX8cAAAAABJRU5ErkJggg==</binary></FictionBook>
@@ -524,6 +524,34 @@ <td>2</td> <td>3</td> </tr>+ <tr>+ <td colspan="3">Details</td>+ </tr>+ </tbody>+ <tfoot>+ <tr>+ <th>4</th>+ <td>5</td>+ <td>6</td>+ </tr>+ </tfoot>+</table>+<hr />+<table>+ <tbody>+ <tr>+ <th>X</th>+ <th>Y</th>+ <th>Z</th>+ </tr>+ <tr>+ <td>1</td>+ <td>2</td>+ <td>3</td>+ </tr>+ <tr>+ <td colspan="3">Details</td>+ </tr> </tbody> <tfoot> <tr>
@@ -2262,7 +2262,7 @@ ]) [ TableBody ( "" , [] , [] )- (RowHeadColumns 1)+ (RowHeadColumns 0) [] [ Row ( "" , [] , [] )@@ -2284,6 +2284,105 @@ (RowSpan 1) (ColSpan 1) [ Plain [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 3)+ [ Plain [ Str "Details" ] ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "6" ] ]+ ]+ ])+ , HorizontalRule+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "X" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Y" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Z" ] ]+ ]+ ]+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 3)+ [ Plain [ Str "Details" ] ] ] ] ]
@@ -83,7 +83,7 @@ , Image ( "" , [] , [] ) [ Str "the" , Space , Str "moon" ]- ( "lalune.jpg" , "" )+ ( "uid6-lalune.jpg" , "" ) , Space , Str "will" , Space
@@ -8,2803 +8,3666 @@ , MetaInlines [ Str "Anonymous" ] ] )- , ( "title"- , MetaInlines- [ Str "Pandoc"- , Space- , Str "Test"- , Space- , Str "Suite"- ]- )- ]- }- [ Para- [ Str "This"- , Space- , Str "is"- , Space- , Str "a"- , Space- , Str "set"- , Space- , Str "of"- , Space- , Str "tests"- , Space- , Str "for"- , Space- , Str "pandoc."- , Space- , Str "Most"- , Space- , Str "of"- , Space- , Str "them"- , Space- , Str "are"- , Space- , Str "adapted"- , Space- , Str "from"- , Space- , Str "John"- , Space- , Str "Gruber's"- , Space- , Str "markdown"- , Space- , Str "test"- , Space- , Str "suite."- ]- , Header 1 ( "headers" , [] , [] ) [ Str "Headers" ]- , Header- 2- ( "level-2-with-an-embedded-link" , [] , [] )- [ Str "Level"- , Space- , Str "2"- , Space- , Str "with"- , Space- , Str "an"- , SoftBreak- , Link- ( "" , [] , [] )- [ Str "embedded" , SoftBreak , Str "link" ]- ( "/url" , "" )- ]- , Header- 3- ( "level-3-with-emphasis" , [] , [] )- [ Str "Level"- , Space- , Str "3"- , Space- , Str "with"- , Space- , Emph [ Str "emphasis" ]- ]- , Header- 4 ( "level-4" , [] , [] ) [ Str "Level" , Space , Str "4" ]- , Header- 5 ( "level-5" , [] , [] ) [ Str "Level" , Space , Str "5" ]- , Header- 1 ( "level-1" , [] , [] ) [ Str "Level" , Space , Str "1" ]- , Header- 2- ( "level-2-with-emphasis" , [] , [] )- [ Str "Level"- , Space- , Str "2"- , Space- , Str "with"- , Space- , Emph [ Str "emphasis" ]- ]- , Header- 3 ( "level-3" , [] , [] ) [ Str "Level" , Space , Str "3" ]- , Para- [ Str "with"- , Space- , Str "no"- , Space- , Str "blank"- , Space- , Str "line"- ]- , Header- 2 ( "level-2" , [] , [] ) [ Str "Level" , Space , Str "2" ]- , Para- [ Str "with"- , Space- , Str "no"- , Space- , Str "blank"- , Space- , Str "line"- ]- , Header 1 ( "paragraphs" , [] , [] ) [ Str "Paragraphs" ]- , Para- [ Str "Here's"- , Space- , Str "a"- , Space- , Str "regular"- , Space- , Str "paragraph."- ]- , Para- [ Str "In"- , Space- , Str "Markdown"- , Space- , Str "1.0.0"- , Space- , Str "and"- , Space- , Str "earlier."- , Space- , Str "Version"- , Space- , Str "8."- , Space- , Str "This"- , Space- , Str "line"- , Space- , Str "turns"- , Space- , Str "into"- , Space- , Str "a"- , Space- , Str "list"- , Space- , Str "item."- , Space- , Str "Because"- , Space- , Str "a"- , Space- , Str "hard-wrapped"- , Space- , Str "line"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "middle"- , Space- , Str "of"- , Space- , Str "a"- , Space- , Str "paragraph"- , Space- , Str "looked"- , Space- , Str "like"- , Space- , Str "a"- , Space- , Str "list"- , Space- , Str "item."- ]- , Para- [ Str "Here's"- , Space- , Str "one"- , Space- , Str "with"- , Space- , Str "a"- , Space- , Str "bullet."- , Space- , Str "*"- , Space- , Str "criminey."- ]- , Para- [ Str "There"- , Space- , Str "should"- , Space- , Str "be"- , Space- , Str "a"- , Space- , Str "hard"- , Space- , Str "line"- , Space- , Str "break"- , LineBreak- , Str "here."- ]- , Header- 1- ( "block-quotes" , [] , [] )- [ Str "Block" , Space , Str "Quotes" ]- , Para [ Str "E-mail" , Space , Str "style:" ]- , BlockQuote- [ Para- [ Str "This"- , Space- , Str "is"- , Space- , Str "a"- , Space- , Str "block"- , Space- , Str "quote."- , Space- , Str "It"- , Space- , Str "is"- , Space- , Str "pretty"- , Space- , Str "short."- ]- ]- , BlockQuote- [ Para- [ Str "Code"- , Space- , Str "in"- , Space- , Str "a"- , Space- , Str "block"- , Space- , Str "quote:"- ]- , CodeBlock- ( "" , [] , [] ) "sub status {\n print \"working\";\n}"- , Para [ Str "A" , Space , Str "list:" ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Para [ Str "item" , Space , Str "one" ] ]- , [ Para [ Str "item" , Space , Str "two" ] ]- ]- , Para- [ Str "Nested"- , Space- , Str "block"- , Space- , Str "quotes:"- ]- , BlockQuote [ Para [ Str "nested" ] ]- , BlockQuote [ Para [ Str "nested" ] ]- ]- , Para- [ Str "This"- , Space- , Str "should"- , Space- , Str "not"- , Space- , Str "be"- , Space- , Str "a"- , Space- , Str "block"- , Space- , Str "quote:"- , Space- , Str "2"- , Space- , Str ">"- , Space- , Str "1."- ]- , Para [ Str "Box-style:" ]- , BlockQuote- [ Para [ Str "Example:" ]- , CodeBlock- ( "" , [] , [] ) "sub status {\n print \"working\";\n}"- ]- , BlockQuote- [ OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Para [ Str "do" , Space , Str "laundry" ] ]- , [ Para- [ Str "take"- , Space- , Str "out"- , Space- , Str "the"- , Space- , Str "trash"- ]- ]- ]- ]- , Para- [ Str "Here's"- , Space- , Str "a"- , Space- , Str "nested"- , Space- , Str "one:"- ]- , BlockQuote- [ Para [ Str "Joe" , Space , Str "said:" ]- , BlockQuote- [ Para- [ Str "Don't" , Space , Str "quote" , Space , Str "me." ]- ]- ]- , Para- [ Str "And"- , Space- , Str "a"- , Space- , Str "following"- , Space- , Str "paragraph."- ]- , Header- 1- ( "code-blocks" , [] , [] )- [ Str "Code" , Space , Str "Blocks" ]- , Para [ Str "Code:" ]- , CodeBlock- ( "" , [] , [] )- "---- (should be four hyphens)\n\nsub status {\n print \"working\";\n}\n\nthis code block is indented by one tab"- , Para [ Str "And:" ]- , CodeBlock- ( "" , [] , [] )- " this code block is indented by two tabs\n\nThese should not be escaped: \\$ \\\\ \\> \\[ \\{"- , Header 1 ( "lists" , [] , [] ) [ Str "Lists" ]- , Header 2 ( "unordered" , [] , [] ) [ Str "Unordered" ]- , Para [ Str "Asterisks" , Space , Str "tight:" ]- , BulletList- [ [ Para [ Str "asterisk" , Space , Str "1" ] ]- , [ Para [ Str "asterisk" , Space , Str "2" ] ]- , [ Para [ Str "asterisk" , Space , Str "3" ] ]- ]- , Para [ Str "Asterisks" , Space , Str "loose:" ]- , BulletList- [ [ Para [ Str "asterisk" , Space , Str "1" ] ]- , [ Para [ Str "asterisk" , Space , Str "2" ] ]- , [ Para [ Str "asterisk" , Space , Str "3" ] ]- ]- , Para [ Str "Pluses" , Space , Str "tight:" ]- , BulletList- [ [ Para [ Str "Plus" , Space , Str "1" ] ]- , [ Para [ Str "Plus" , Space , Str "2" ] ]- , [ Para [ Str "Plus" , Space , Str "3" ] ]- ]- , Para [ Str "Pluses" , Space , Str "loose:" ]- , BulletList- [ [ Para [ Str "Plus" , Space , Str "1" ] ]- , [ Para [ Str "Plus" , Space , Str "2" ] ]- , [ Para [ Str "Plus" , Space , Str "3" ] ]- ]- , Para [ Str "Minuses" , Space , Str "tight:" ]- , BulletList- [ [ Para [ Str "Minus" , Space , Str "1" ] ]- , [ Para [ Str "Minus" , Space , Str "2" ] ]- , [ Para [ Str "Minus" , Space , Str "3" ] ]- ]- , Para [ Str "Minuses" , Space , Str "loose:" ]- , BulletList- [ [ Para [ Str "Minus" , Space , Str "1" ] ]- , [ Para [ Str "Minus" , Space , Str "2" ] ]- , [ Para [ Str "Minus" , Space , Str "3" ] ]- ]- , Header 2 ( "ordered" , [] , [] ) [ Str "Ordered" ]- , Para [ Str "Tight:" ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Para [ Str "First" ] ]- , [ Para [ Str "Second" ] ]- , [ Para [ Str "Third" ] ]- ]- , Para [ Str "and:" ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Para [ Str "One" ] ]- , [ Para [ Str "Two" ] ]- , [ Para [ Str "Three" ] ]- ]- , Para- [ Str "Loose" , Space , Str "using" , Space , Str "tabs:" ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Para [ Str "First" ] ]- , [ Para [ Str "Second" ] ]- , [ Para [ Str "Third" ] ]- ]- , Para- [ Str "and" , Space , Str "using" , Space , Str "spaces:" ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Para [ Str "One" ] ]- , [ Para [ Str "Two" ] ]- , [ Para [ Str "Three" ] ]- ]- , Para [ Str "Multiple" , Space , Str "paragraphs:" ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Para- [ Str "Item"- , Space- , Str "1,"- , Space- , Str "graf"- , Space- , Str "one."- ]- , Para- [ Str "Item"- , Space- , Str "1."- , Space- , Str "graf"- , Space- , Str "two."- , Space- , Str "The"- , Space- , Str "quick"- , Space- , Str "brown"- , Space- , Str "fox"- , Space- , Str "jumped"- , Space- , Str "over"- , Space- , Str "the"- , Space- , Str "lazy"- , SoftBreak- , Str "dog's"- , Space- , Str "back."- ]- ]- , [ Para [ Str "Item" , Space , Str "2." ] ]- , [ Para [ Str "Item" , Space , Str "3." ] ]- ]- , Para [ Str "List" , Space , Str "styles:" ]- , OrderedList ( 1 , DefaultStyle , DefaultDelim ) []- , OrderedList ( 1 , LowerRoman , DefaultDelim ) []- , Header 2 ( "nested" , [] , [] ) [ Str "Nested" ]- , BulletList- [ [ Para [ Str "Tab" ]- , BulletList- [ [ Para [ Str "Tab" ]- , BulletList [ [ Para [ Str "Tab" ] ] ]- ]- ]- ]- ]- , Para [ Str "Here's" , Space , Str "another:" ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Para [ Str "First" ] ]- , [ Para [ Str "Second:" ]- , BulletList- [ [ Para [ Str "Fee" ] ]- , [ Para [ Str "Fie" ] ]- , [ Para [ Str "Foe" ] ]- ]- ]- , [ Para [ Str "Third" ] ]- ]- , Para- [ Str "Same"- , Space- , Str "thing"- , Space- , Str "but"- , Space- , Str "with"- , Space- , Str "paragraphs:"- ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Para [ Str "First" ] ]- , [ Para [ Str "Second:" ]- , BulletList- [ [ Para [ Str "Fee" ] ]- , [ Para [ Str "Fie" ] ]- , [ Para [ Str "Foe" ] ]- ]- ]- , [ Para [ Str "Third" ] ]- ]- , Header- 2- ( "tabs-and-spaces" , [] , [] )- [ Str "Tabs" , Space , Str "and" , Space , Str "spaces" ]- , BulletList- [ [ Para- [ Str "this"- , Space- , Str "is"- , Space- , Str "a"- , Space- , Str "list"- , Space- , Str "item"- , Space- , Str "indented"- , Space- , Str "with"- , Space- , Str "tabs"- ]- ]- , [ Para- [ Str "this"- , Space- , Str "is"- , Space- , Str "a"- , Space- , Str "list"- , Space- , Str "item"- , Space- , Str "indented"- , Space- , Str "with"- , Space- , Str "spaces"- ]- , BulletList- [ [ Para- [ Str "this"- , Space- , Str "is"- , Space- , Str "an"- , Space- , Str "example"- , Space- , Str "list"- , Space- , Str "item"- , Space- , Str "indented"- , Space- , Str "with"- , Space- , Str "tabs"- ]- ]- , [ Para- [ Str "this"- , Space- , Str "is"- , Space- , Str "an"- , Space- , Str "example"- , Space- , Str "list"- , Space- , Str "item"- , Space- , Str "indented"- , Space- , Str "with"- , Space- , Str "spaces"- ]- ]- ]- ]- ]- , Header- 2- ( "fancy-list-markers" , [] , [] )- [ Str "Fancy" , Space , Str "list" , Space , Str "markers" ]- , Para [ Str "Autonumbering:" ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Para [ Str "Autonumber." ] ]- , [ Para [ Str "More." ]- , OrderedList- ( 1 , DefaultStyle , DefaultDelim )- [ [ Para [ Str "Nested." ] ] ]- ]- ]- , Header 2 ( "definition" , [] , [] ) [ Str "Definition" ]- , DefinitionList- [ ( [ Str "Violin" ]- , [ [ Para- [ Str "Stringed"- , Space- , Str "musical"- , Space- , Str "instrument."- ]- , Para [ Str "Torture" , Space , Str "device." ]- ]- ]- )- , ( [ Str "Cello" , LineBreak , Str "Violoncello" ]- , [ [ Para- [ Str "Low-voiced"- , Space- , Str "stringed"- , Space- , Str "instrument."- ]- ]- ]- )- ]- , Header- 1- ( "inline-markup" , [] , [] )- [ Str "Inline" , Space , Str "Markup" ]- , Para- [ Str "This"- , Space- , Str "is"- , Space- , Emph [ Str "emphasized" ]- , Str ","- , Space- , Str "and"- , Space- , Str "so"- , Space- , Emph [ Str "is" , SoftBreak , Str "this" ]- , Str "."- ]- , Para- [ Str "This"- , Space- , Str "is"- , Space- , Strong [ Str "strong" ]- , Str ","- , Space- , Str "and"- , Space- , Str "so"- , SoftBreak- , Strong [ Str "is" , Space , Str "this" ]- , Str "."- ]- , Para- [ Str "Empty"- , Space- , Strong []- , Space- , Str "and"- , Space- , Emph []- , Str "."- ]- , Para- [ Str "An"- , SoftBreak- , Emph- [ Link- ( "" , [] , [] )- [ Str "emphasized" , SoftBreak , Str "link" ]- ( "/url" , "" )- ]- , Str "."- ]- , Para- [ Strong- [ Emph- [ Str "This"- , Space- , Str "is"- , Space- , Str "strong"- , Space- , Str "and"- , Space- , Str "em."- ]- ]- ]- , Para- [ Str "So"- , Space- , Str "is"- , Space- , Strong [ Emph [ Str "this" ] ]- , Space- , Str "word."- ]- , Para- [ Strong- [ Emph- [ Str "This"- , Space- , Str "is"- , Space- , Str "strong"- , Space- , Str "and"- , Space- , Str "em."- ]- ]- ]- , Para- [ Str "So"- , Space- , Str "is"- , Space- , Strong [ Emph [ Str "this" ] ]- , Space- , Str "word."- ]- , Para- [ Str "This"- , Space- , Str "is"- , Space- , Str "code:"- , Space- , Code ( "" , [] , [] ) ">"- , Str ","- , Space- , Code ( "" , [] , [] ) "$"- , Str ","- , SoftBreak- , Code ( "" , [] , [] ) "\\"- , Str ","- , Space- , Code ( "" , [] , [] ) "\\$"- , Str ","- , SoftBreak- , Code ( "" , [] , [] ) "<html>"- , Str "."- ]- , Para- [ Str "This"- , Space- , Str "is"- , Space- , SmallCaps [ Str "small" , Space , Str "caps" ]- , Str "."- ]- , Para- [ Str "These"- , Space- , Str "are"- , Space- , Str "all"- , Space- , Str "underlined:"- , Space- , Str "foo"- , Space- , Str "and"- , Space- , Str "bar."- ]- , Para- [ Str "These"- , Space- , Str "are"- , Space- , Str "all"- , Space- , Str "strikethrough:"- , Space- , Strikeout [ Str "foo" ]- , Str ","- , SoftBreak- , Strikeout [ Str "bar" ]- , Str ","- , Space- , Str "and"- , Space- , Strikeout [ Str "baz" ]- , Str "."- ]- , Header- 1- ( "smart-quotes-ellipses-dashes" , [] , [] )- [ Str "Smart"- , Space- , Str "quotes,"- , Space- , Str "ellipses,"- , Space- , Str "dashes"- ]- , Para- [ Str "\"Hello,\""- , Space- , Str "said"- , Space- , Str "the"- , Space- , Str "spider."- , Space- , Str "\"'Shelob'"- , Space- , Str "is"- , Space- , Str "my"- , Space- , Str "name.\""- ]- , Para- [ Str "'A',"- , Space- , Str "'B',"- , Space- , Str "and"- , Space- , Str "'C'"- , Space- , Str "are"- , Space- , Str "letters."- ]- , Para- [ Str "'Oak,'"- , Space- , Str "'elm,'"- , Space- , Str "and"- , Space- , Str "'beech'"- , Space- , Str "are"- , Space- , Str "names"- , Space- , Str "of"- , Space- , Str "trees."- , Space- , Str "So"- , Space- , Str "is"- , Space- , Str "'pine.'"- ]- , Para- [ Str "'He"- , Space- , Str "said,"- , Space- , Str "\"I"- , Space- , Str "want"- , Space- , Str "to"- , Space- , Str "go.\"'"- , Space- , Str "Were"- , Space- , Str "you"- , Space- , Str "alive"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "70's?"- ]- , Para- [ Str "Here"- , Space- , Str "is"- , Space- , Str "some"- , Space- , Str "quoted"- , Space- , Str "'"- , Code ( "" , [] , [] ) "code"- , Str "'"- , Space- , Str "and"- , Space- , Str "a"- , SoftBreak- , Str "\""- , Link- ( "" , [] , [] )- [ Str "quoted" , SoftBreak , Str "link" ]- ( "http://example.com/?foo=1&bar=2" , "" )- , Str "\"."- ]- , Para- [ Str "Some"- , Space- , Str "dashes:"- , Space- , Str "one---two"- , Space- , Str "---"- , Space- , Str "three--four"- , Space- , Str "--"- , Space- , Str "five."- ]- , Para- [ Str "Dashes"- , Space- , Str "between"- , Space- , Str "numbers:"- , Space- , Str "5-7,"- , Space- , Str "255-66,"- , Space- , Str "1987-1999."- ]- , Para- [ Str "Ellipses...and."- , Space- , Str "."- , Space- , Str ".and"- , Space- , Str "."- , Space- , Str "."- , Space- , Str "."- , Space- , Str "."- ]- , Header 1 ( "latex" , [] , [] ) [ Str "LaTeX" ]- , BulletList- [ [ Para [ Str "\\cite[22-23]{smith.1899}" ] ]- , [ Para [ Str "\\doublespacing" ] ]- , [ Para [ Str "$2+2=4$" ] ]- , [ Para- [ Str "$x" , Space , Str "\\in" , Space , Str "y$" ]- ]- , [ Para- [ Str "$\\alpha"- , Space- , Str "\\wedge"- , Space- , Str "\\omega$"- ]- ]- , [ Para [ Str "$223$" ] ]- , [ Para [ Str "$p$-Tree" ] ]- , [ Para- [ Str "$\\frac{d}{dx}f(x)=\\lim_{h\\to"- , Space- , Str "0}\\frac{f(x+h)-f(x)}{h}$"- ]- ]- , [ Para- [ Str "Here's"- , Space- , Str "one"- , Space- , Str "that"- , Space- , Str "has"- , Space- , Str "a"- , Space- , Str "line"- , Space- , Str "break"- , Space- , Str "in"- , Space- , Str "it:"- , Space- , Str "$\\alpha"- , Space- , Str "+"- , Space- , Str "\\omega"- , Space- , Str "\\times"- , SoftBreak- , Str "x^2$."- ]- ]- ]- , Para- [ Str "These"- , Space- , Str "shouldn't"- , Space- , Str "be"- , Space- , Str "math:"- ]- , BulletList- [ [ Para- [ Str "To"- , Space- , Str "get"- , Space- , Str "the"- , Space- , Str "famous"- , Space- , Str "equation,"- , Space- , Str "write"- , SoftBreak- , Code ( "" , [] , [] ) "$e = mc^2$"- , Str "."- ]- ]- , [ Para- [ Str "$22,000"- , Space- , Str "is"- , Space- , Str "a"- , Space- , Emph [ Str "lot" ]- , Space- , Str "of"- , Space- , Str "money."- , Space- , Str "So"- , Space- , Str "is"- , Space- , Str "$34,000."- , Space- , Str "(It"- , SoftBreak- , Str "worked"- , Space- , Str "if"- , Space- , Str "\"lot\""- , Space- , Str "is"- , Space- , Str "emphasized.)"- ]- ]- , [ Para- [ Str "Escaped"- , Space- , Code ( "" , [] , [] ) "$"- , Str ":"- , Space- , Str "$73"- , Space- , Emph- [ Str "this"- , Space- , Str "should"- , Space- , Str "be"- , SoftBreak- , Str "emphasized"- ]- , Space- , Str "23$."- ]- ]- ]- , Para- [ Str "Here's"- , Space- , Str "a"- , Space- , Str "LaTeX"- , Space- , Str "table:"- ]- , Para- [ Str "\\begin{tabular}{|l|l|}\\hline"- , Space- , Str "Animal"- , Space- , Str "&"- , Space- , Str "Number"- , Space- , Str "\\\\"- , Space- , Str "\\hline"- , Space- , Str "Dog"- , Space- , Str "&"- , SoftBreak- , Str "2"- , Space- , Str "\\\\"- , Space- , Str "Cat"- , Space- , Str "&"- , Space- , Str "1"- , Space- , Str "\\\\"- , Space- , Str "\\hline"- , Space- , Str "\\end{tabular}"- ]- , Header- 1- ( "special-characters" , [] , [] )- [ Str "Special" , Space , Str "Characters" ]- , Para- [ Str "Here"- , Space- , Str "is"- , Space- , Str "some"- , Space- , Str "unicode:"- ]- , BulletList- [ [ Para- [ Str "I" , Space , Str "hat:" , Space , Str "\206" ]- ]- , [ Para- [ Str "o" , Space , Str "umlaut:" , Space , Str "\246" ]- ]- , [ Para [ Str "section:" , Space , Str "\167" ] ]- , [ Para- [ Str "set"- , Space- , Str "membership:"- , Space- , Str "elem"- ]- ]- , [ Para [ Str "copyright:" , Space , Str "\169" ] ]- ]- , Para- [ Str "AT&T"- , Space- , Str "has"- , Space- , Str "an"- , Space- , Str "ampersand"- , Space- , Str "in"- , Space- , Str "their"- , Space- , Str "name."- ]- , Para- [ Str "AT&T"- , Space- , Str "is"- , Space- , Str "another"- , Space- , Str "way"- , Space- , Str "to"- , Space- , Str "write"- , Space- , Str "it."- ]- , Para- [ Str "This" , Space , Str "&" , Space , Str "that." ]- , Para [ Str "4" , Space , Str "<" , Space , Str "5." ]- , Para [ Str "6" , Space , Str ">" , Space , Str "5." ]- , Para [ Str "Backslash:" , Space , Str "\\" ]- , Para [ Str "Backtick:" , Space , Str "`" ]- , Para [ Str "Asterisk:" , Space , Str "*" ]- , Para [ Str "Underscore:" , Space , Str "_" ]- , Para- [ Str "Left" , Space , Str "brace:" , Space , Str "{" ]- , Para- [ Str "Right" , Space , Str "brace:" , Space , Str "}" ]- , Para- [ Str "Left" , Space , Str "bracket:" , Space , Str "[" ]- , Para- [ Str "Right" , Space , Str "bracket:" , Space , Str "]" ]- , Para- [ Str "Left" , Space , Str "paren:" , Space , Str "(" ]- , Para- [ Str "Right" , Space , Str "paren:" , Space , Str ")" ]- , Para [ Str "Greater-than:" , Space , Str ">" ]- , Para [ Str "Hash:" , Space , Str "#" ]- , Para [ Str "Period:" , Space , Str "." ]- , Para [ Str "Bang:" , Space , Str "!" ]- , Para [ Str "Plus:" , Space , Str "+" ]- , Para [ Str "Minus:" , Space , Str "-" ]- , Header 1 ( "links" , [] , [] ) [ Str "Links" ]- , Header 2 ( "explicit" , [] , [] ) [ Str "Explicit" ]- , Para- [ Str "Just"- , Space- , Str "a"- , SoftBreak- , Link ( "" , [] , [] ) [ Str "URL" ] ( "/url/" , "" )- , Str "."- ]- , Para- [ Link- ( "" , [] , [] )- [ Str "URL" , SoftBreak , Str "and" , Space , Str "title" ]- ( "/url/" , "title" )- , Str "."- ]- , Para- [ Link- ( "" , [] , [] )- [ Str "URL" , SoftBreak , Str "and" , Space , Str "title" ]- ( "/url/" , "title preceded by two spaces" )- , Str "."- ]- , Para- [ Link- ( "" , [] , [] )- [ Str "URL" , SoftBreak , Str "and" , Space , Str "title" ]- ( "/url/" , "title preceded by a tab" )- , Str "."- ]- , Para- [ Link- ( "" , [] , [] )- [ Str "URL" , SoftBreak , Str "and" , Space , Str "title" ]- ( "/url/" , "title with \"quotes\" in it" )- ]- , Para- [ Link- ( "" , [] , [] )- [ Str "URL" , SoftBreak , Str "and" , Space , Str "title" ]- ( "/url/" , "title with single quotes" )- ]- , Para- [ Str "Email"- , Space- , Str "link"- , Space- , Str "(nobody"- , Space- , Str "[at]"- , Space- , Str "nowhere.net)"- ]- , Para- [ Link ( "" , [] , [] ) [ Str "Empty" ] ( "" , "" )- , Str "."- ]- , Header 2 ( "reference" , [] , [] ) [ Str "Reference" ]- , Para- [ Str "Foo"- , SoftBreak- , Link ( "" , [] , [] ) [ Str "bar" ] ( "/url/" , "" )- , Str "."- ]- , Para- [ Str "Foo"- , SoftBreak- , Link ( "" , [] , [] ) [ Str "bar" ] ( "/url/" , "" )- , Str "."- ]- , Para- [ Str "Foo"- , SoftBreak- , Link ( "" , [] , [] ) [ Str "bar" ] ( "/url/" , "" )- , Str "."- ]- , Para- [ Str "With"- , Space- , Link- ( "" , [] , [] )- [ Str "embedded" , SoftBreak , Str "[brackets]" ]- ( "/url/" , "" )- , Str "."- ]- , Para- [ Link ( "" , [] , [] ) [ Str "b" ] ( "/url/" , "" )- , Space- , Str "by"- , SoftBreak- , Str "itself"- , Space- , Str "should"- , Space- , Str "be"- , Space- , Str "a"- , Space- , Str "link."- ]- , Para- [ Str "Indented"- , SoftBreak- , Link ( "" , [] , [] ) [ Str "once" ] ( "/url" , "" )- , Str "."- ]- , Para- [ Str "Indented"- , SoftBreak- , Link ( "" , [] , [] ) [ Str "twice" ] ( "/url" , "" )- , Str "."- ]- , Para- [ Str "Indented"- , SoftBreak- , Link ( "" , [] , [] ) [ Str "thrice" ] ( "/url" , "" )- , Str "."- ]- , Para- [ Str "This"- , Space- , Str "should"- , Space- , Str "[not]"- , Space- , Str "be"- , Space- , Str "a"- , Space- , Str "link."- ]- , CodeBlock ( "" , [] , [] ) "[not]: /url"- , Para- [ Str "Foo"- , SoftBreak- , Link- ( "" , [] , [] )- [ Str "bar" ]- ( "/url/" , "Title with \"quotes\" inside" )- , Str "."- ]- , Para- [ Str "Foo"- , SoftBreak- , Link- ( "" , [] , [] )- [ Str "biz" ]- ( "/url/" , "Title with \"quote\" inside" )- , Str "."- ]- , Header- 2- ( "with-ampersands" , [] , [] )- [ Str "With" , Space , Str "ampersands" ]- , Para- [ Str "Here's"- , Space- , Str "a"- , SoftBreak- , Link- ( "" , [] , [] )- [ Str "link"- , SoftBreak- , Str "with"- , Space- , Str "an"- , Space- , Str "ampersand"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "URL"- ]- ( "http://example.com/?foo=1&bar=2" , "" )- , Str "."- ]- , Para- [ Str "Here's"- , Space- , Str "a"- , Space- , Str "link"- , Space- , Str "with"- , Space- , Str "an"- , Space- , Str "amersand"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "link"- , Space- , Str "text:"- , SoftBreak- , Link- ( "" , [] , [] )- [ Str "AT&T" ]- ( "http://att.com/" , "AT&T" )- , Str "."- ]- , Para- [ Str "Here's"- , Space- , Str "an"- , SoftBreak- , Link- ( "" , [] , [] )- [ Str "inline" , SoftBreak , Str "link" ]- ( "/script?foo=1&bar=2" , "" )- , Str "."- ]- , Para- [ Str "Here's"- , Space- , Str "an"- , SoftBreak- , Link- ( "" , [] , [] )- [ Str "inline"- , SoftBreak- , Str "link"- , Space- , Str "in"- , Space- , Str "pointy"- , Space- , Str "braces"- ]- ( "/script?foo=1&bar=2" , "" )- , Str "."- ]- , Header 2 ( "autolinks" , [] , [] ) [ Str "Autolinks" ]- , Para- [ Str "With"- , Space- , Str "an"- , Space- , Str "ampersand:"- , SoftBreak- , Link- ( "" , [] , [] )- [ Str "http://example.com/?foo=1&bar=2" ]- ( "http://example.com/?foo=1&bar=2" , "" )- ]- , BulletList- [ [ Para- [ Str "In" , Space , Str "a" , Space , Str "list?" ]- ]- , [ Para- [ Link- ( "" , [] , [] )- [ Str "http://example.com/" ]- ( "http://example.com/" , "" )- ]- ]- , [ Para [ Str "It" , Space , Str "should." ] ]- ]- , Para- [ Str "An"- , Space- , Str "e-mail"- , Space- , Str "address:"- , Space- , Str "nobody"- , Space- , Str "[at]"- , Space- , Str "nowhere.net"- ]- , BlockQuote- [ Para- [ Str "Blockquoted:"- , SoftBreak- , Link- ( "" , [] , [] )- [ Str "http://example.com/" ]- ( "http://example.com/" , "" )- ]- ]- , Para- [ Str "Auto-links"- , Space- , Str "should"- , Space- , Str "not"- , Space- , Str "occur"- , Space- , Str "here:"- , SoftBreak- , Code ( "" , [] , [] ) "<http://example.com/>"- ]- , CodeBlock- ( "" , [] , [] ) "or here: <http://example.com/>"- , Header 1 ( "images" , [] , [] ) [ Str "Images" ]- , Para- [ Str "From"- , Space- , Str "\"Voyage"- , Space- , Str "dans"- , Space- , Str "la"- , Space- , Str "Lune\""- , Space- , Str "by"- , Space- , Str "Georges"- , Space- , Str "Melies"- , Space- , Str "(1902):"- ]- , Para- [ Image- ( "" , [] , [] ) [] ( "lalune.jpg" , "Voyage dans la Lune" )- ]- , Para- [ Str "Here"- , Space- , Str "is"- , Space- , Str "a"- , Space- , Str "movie"- , SoftBreak- , Image ( "" , [] , [] ) [] ( "movie.jpg" , "" )- , SoftBreak- , Str "icon."- ]- , Header 1 ( "footnotes" , [] , [] ) [ Str "Footnotes" ]- , Para- [ Str "Here"- , Space- , Str "is"- , Space- , Str "a"- , Space- , Str "footnote"- , Space- , Str "reference"- , Link ( "" , [] , [] ) [ Str "(1)" ] ( "#note_1" , "" )- , Str ","- , SoftBreak- , Str "and"- , SoftBreak- , Str "another"- , Link- ( "" , [] , [] )- [ Str "(longnote)" ]- ( "#note_longnote" , "" )- , Str "."- , SoftBreak- , Str "This"- , Space- , Str "should"- , Space- , Emph [ Str "not" ]- , Space- , Str "be"- , Space- , Str "a"- , Space- , Str "footnote"- , Space- , Str "reference,"- , Space- , Str "because"- , Space- , Str "it"- , SoftBreak- , Str "contains"- , Space- , Str "a"- , Space- , Str "space^(my"- , Space- , Str "note)."- ]- , Para- [ Link ( "" , [] , [] ) [ Str "(1)" ] ( "#ref_1" , "" )- , Space- , Str "Here"- , Space- , Str "is"- , Space- , Str "the"- , Space- , Str "footnote."- , Space- , Str "It"- , Space- , Str "can"- , SoftBreak- , Str "go"- , Space- , Str "anywhere"- , Space- , Str "in"- , Space- , Str "the"- , Space- , Str "document,"- , Space- , Str "not"- , Space- , Str "just"- , Space- , Str "at"- , Space- , Str "the"- , Space- , Str "end."- ]- , Para- [ Link- ( "" , [] , [] )- [ Str "(longnote)" ]- ( "#ref_longnote" , "" )- , Space- , Str "Here's"- , SoftBreak- , Str "the"- , Space- , Str "other"- , Space- , Str "note."- , Space- , Str "This"- , Space- , Str "one"- , Space- , Str "contains"- , Space- , Str "multiple"- , Space- , Str "blocks."- ]- , Para- [ Str "Caret"- , Space- , Str "characters"- , Space- , Str "are"- , Space- , Str "used"- , Space- , Str "to"- , Space- , Str "indicate"- , Space- , Str "that"- , Space- , Str "the"- , Space- , Str "blocks"- , Space- , Str "all"- , Space- , Str "belong"- , Space- , Str "to"- , SoftBreak- , Str "a"- , Space- , Str "single"- , Space- , Str "footnote"- , Space- , Str "(as"- , Space- , Str "with"- , Space- , Str "block"- , Space- , Str "quotes)."- ]- , CodeBlock ( "" , [] , [] ) " { <code> }"- , Para- [ Str "If"- , Space- , Str "you"- , Space- , Str "want,"- , Space- , Str "you"- , Space- , Str "can"- , Space- , Str "use"- , Space- , Str "a"- , Space- , Str "caret"- , Space- , Str "at"- , Space- , Str "the"- , Space- , Str "beginning"- , Space- , Str "of"- , Space- , Str "every"- , Space- , Str "line,"- , Space- , Str "as"- , SoftBreak- , Str "with"- , Space- , Str "blockquotes,"- , Space- , Str "but"- , Space- , Str "all"- , Space- , Str "that"- , Space- , Str "you"- , Space- , Str "need"- , Space- , Str "is"- , Space- , Str "a"- , Space- , Str "caret"- , Space- , Str "at"- , Space- , Str "the"- , Space- , Str "beginning"- , SoftBreak- , Str "of"- , Space- , Str "the"- , Space- , Str "first"- , Space- , Str "line"- , Space- , Str "of"- , Space- , Str "the"- , Space- , Str "block"- , Space- , Str "and"- , Space- , Str "any"- , Space- , Str "preceding"- , Space- , Str "blank"- , Space- , Str "lines."- ]- , Para- [ Str "text"- , Space- , Emph [ Str "Leading" , Space , Str "space" ]- ]- , Para- [ Emph [ Str "Trailing" , Space , Str "space" ]- , Space- , Str "text"- ]- , Para- [ Str "text"- , Space- , Emph [ Str "Leading" , Space , Str "spaces" ]- ]- , Para- [ Emph [ Str "Trailing" , Space , Str "spaces" ]- , Space- , Str "text"- ]- , Header 1 ( "tables" , [] , [] ) [ Str "Tables" ]- , Header- 2- ( "tables-with-headers" , [] , [] )- [ Str "Tables"- , Space- , Str "with"- , Space- , Str "Headers"- ]- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "X" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Y" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Z" ] ]- ]- ])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "X" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Y" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Z" ] ]- ]- ])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "X" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Y" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Z" ] ]- ]- ])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "X" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Y" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Z" ] ]- ]- ])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "X" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Y" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Z" ] ]- ]- ])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "X" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Y" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Z" ] ]- ]- ])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "X" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Y" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Z" ] ]- ]- ])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "X" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Y" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Z" ] ]- ]- ])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "X" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Y" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "Z" ] ]- ]- ])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Header- 2- ( "tables-without-headers" , [] , [] )- [ Str "Tables"- , Space- , Str "without"- , Space- , Str "Headers"- ]- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead ( "" , [] , [] ) [])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead ( "" , [] , [] ) [])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead ( "" , [] , [] ) [])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Table- ( "" , [] , [] )- (Caption Nothing [])- [ ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- , ( AlignLeft , ColWidthDefault )- ]- (TableHead ( "" , [] , [] ) [])- [ TableBody- ( "" , [] , [] )- (RowHeadColumns 0)- []- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "1" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "2" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "3" ] ]- ]- , Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "4" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "5" ] ]- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- [ Para [ Str "6" ] ]- ]- ]- ]- (TableFoot ( "" , [] , [] ) [])- , Header- 2- ( "empty-tables" , [] , [] )- [ Str "Empty" , Space , Str "Tables" ]- , Para- [ Str "This"- , Space- , Str "section"- , Space- , Str "should"- , Space- , Str "be"- , Space- , Str "empty."- ]+ , ( "copyright"+ , MetaMap+ (fromList+ [ ( "holder" , MetaString "MacFarlane et al" )+ , ( "statement"+ , MetaString "\169 2023, MacFarlane et al"+ )+ , ( "year" , MetaString "2023" )+ ])+ )+ , ( "license"+ , MetaMap+ (fromList+ [ ( "link"+ , MetaString+ "https://creativecommons.org/licenses/by/4.0/"+ )+ , ( "text"+ , MetaString+ "This document is distributed under a Creative Commons Attribution 4.0 International license."+ )+ , ( "type" , MetaString "open-access" )+ ])+ )+ , ( "references"+ , MetaList+ [ MetaMap (fromList [ ( "id" , MetaString "note_1" ) ])+ , MetaMap+ (fromList [ ( "id" , MetaString "note_longnote" ) ])+ ]+ )+ , ( "title"+ , MetaInlines+ [ Str "Pandoc"+ , Space+ , Str "Test"+ , Space+ , Str "Suite"+ ]+ )+ ]+ }+ [ Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "set"+ , Space+ , Str "of"+ , Space+ , Str "tests"+ , Space+ , Str "for"+ , Space+ , Str "pandoc."+ , Space+ , Str "Most"+ , Space+ , Str "of"+ , Space+ , Str "them"+ , Space+ , Str "are"+ , Space+ , Str "adapted"+ , Space+ , Str "from"+ , Space+ , Str "John"+ , Space+ , Str "Gruber's"+ , Space+ , Str "markdown"+ , Space+ , Str "test"+ , Space+ , Str "suite."+ ]+ , Header 1 ( "headers" , [] , [] ) [ Str "Headers" ]+ , Header+ 2+ ( "level-2-with-an-embedded-link" , [] , [] )+ [ Str "Level"+ , Space+ , Str "2"+ , Space+ , Str "with"+ , Space+ , Str "an"+ , SoftBreak+ , Link+ ( "" , [] , [] )+ [ Str "embedded" , SoftBreak , Str "link" ]+ ( "/url" , "" )+ ]+ , Header+ 3+ ( "level-3-with-emphasis" , [] , [] )+ [ Str "Level"+ , Space+ , Str "3"+ , Space+ , Str "with"+ , Space+ , Emph [ Str "emphasis" ]+ ]+ , Header+ 4 ( "level-4" , [] , [] ) [ Str "Level" , Space , Str "4" ]+ , Header+ 5 ( "level-5" , [] , [] ) [ Str "Level" , Space , Str "5" ]+ , Header+ 1 ( "level-1" , [] , [] ) [ Str "Level" , Space , Str "1" ]+ , Header+ 2+ ( "level-2-with-emphasis" , [] , [] )+ [ Str "Level"+ , Space+ , Str "2"+ , Space+ , Str "with"+ , Space+ , Emph [ Str "emphasis" ]+ ]+ , Header+ 3 ( "level-3" , [] , [] ) [ Str "Level" , Space , Str "3" ]+ , Para+ [ Str "with"+ , Space+ , Str "no"+ , Space+ , Str "blank"+ , Space+ , Str "line"+ ]+ , Header+ 2 ( "level-2" , [] , [] ) [ Str "Level" , Space , Str "2" ]+ , Para+ [ Str "with"+ , Space+ , Str "no"+ , Space+ , Str "blank"+ , Space+ , Str "line"+ ]+ , Header 1 ( "paragraphs" , [] , [] ) [ Str "Paragraphs" ]+ , Para+ [ Str "Here's"+ , Space+ , Str "a"+ , Space+ , Str "regular"+ , Space+ , Str "paragraph."+ ]+ , Para+ [ Str "In"+ , Space+ , Str "Markdown"+ , Space+ , Str "1.0.0"+ , Space+ , Str "and"+ , Space+ , Str "earlier."+ , Space+ , Str "Version"+ , Space+ , Str "8."+ , Space+ , Str "This"+ , Space+ , Str "line"+ , Space+ , Str "turns"+ , Space+ , Str "into"+ , Space+ , Str "a"+ , Space+ , Str "list"+ , Space+ , Str "item."+ , Space+ , Str "Because"+ , Space+ , Str "a"+ , Space+ , Str "hard-wrapped"+ , Space+ , Str "line"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "middle"+ , Space+ , Str "of"+ , Space+ , Str "a"+ , Space+ , Str "paragraph"+ , Space+ , Str "looked"+ , Space+ , Str "like"+ , Space+ , Str "a"+ , Space+ , Str "list"+ , Space+ , Str "item."+ ]+ , Para+ [ Str "Here's"+ , Space+ , Str "one"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "bullet."+ , Space+ , Str "*"+ , Space+ , Str "criminey."+ ]+ , Para+ [ Str "There"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "a"+ , Space+ , Strong+ [ Str "hard"+ , Space+ , Str "line"+ , Space+ , Str "break"+ , LineBreak+ ]+ , Str "here."+ ]+ , Header 1 ( "statements" , [] , [] ) [ Str "Statements" ]+ , Header+ 2 ( "" , [] , [] ) [ Str "CAP" , Space , Str "TITLE" ]+ , Para+ [ Str "Some"+ , Space+ , Str "text"+ , Space+ , Str "to"+ , Space+ , Str "make"+ , Space+ , Str "this"+ , Space+ , Str "regular"+ ]+ , Header+ 1+ ( "block-quotes" , [] , [] )+ [ Str "Block" , Space , Str "Quotes" ]+ , Para [ Str "E-mail" , Space , Str "style:" ]+ , BlockQuote+ [ Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "block"+ , Space+ , Str "quote."+ , Space+ , Str "It"+ , Space+ , Str "is"+ , Space+ , Str "pretty"+ , Space+ , Str "short."+ ]+ ]+ , BlockQuote+ [ Para+ [ Str "Code"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "block"+ , Space+ , Str "quote:"+ ]+ , CodeBlock+ ( "" , [] , [] ) "sub status {\n print \"working\";\n}"+ , Para [ Str "A" , Space , Str "list:" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "item" , Space , Str "one" ] ]+ , [ Para [ Str "item" , Space , Str "two" ] ]+ ]+ , Para+ [ Str "Nested"+ , Space+ , Str "block"+ , Space+ , Str "quotes:"+ ]+ , BlockQuote [ Para [ Str "nested" ] ]+ , BlockQuote [ Para [ Str "nested" ] ]+ ]+ , Para+ [ Str "This"+ , Space+ , Str "should"+ , Space+ , Str "not"+ , Space+ , Str "be"+ , Space+ , Str "a"+ , Space+ , Str "block"+ , Space+ , Str "quote:"+ , Space+ , Str "2"+ , Space+ , Str ">"+ , Space+ , Str "1."+ ]+ , Para [ Str "Box-style:" ]+ , BlockQuote+ [ Para [ Str "Example:" ]+ , CodeBlock+ ( "" , [] , [] ) "sub status {\n print \"working\";\n}"+ ]+ , BlockQuote+ [ OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "do" , Space , Str "laundry" ] ]+ , [ Para+ [ Str "take"+ , Space+ , Str "out"+ , Space+ , Str "the"+ , Space+ , Str "trash"+ ]+ ]+ ]+ ]+ , Para+ [ Str "Here's"+ , Space+ , Str "a"+ , Space+ , Str "nested"+ , Space+ , Str "one:"+ ]+ , BlockQuote+ [ Para [ Str "Joe" , Space , Str "said:" ]+ , BlockQuote+ [ Para+ [ Str "Don't" , Space , Str "quote" , Space , Str "me." ]+ ]+ ]+ , Para+ [ Str "And"+ , Space+ , Str "a"+ , Space+ , Str "following"+ , Space+ , Str "paragraph."+ ]+ , Para+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "block"+ , Space+ , Str "quote"+ , Space+ , Str "inside"+ , Space+ , Str "a"+ , Space+ , Str "paragraph."+ , Space+ , Str "Start"+ , Space+ , Str "of"+ , Space+ , Str "a"+ , Space+ , Str "paragraph"+ , Space+ , Str "is"+ , Space+ , Str "here,"+ , Space+ , Str "and"+ , Space+ , Str "the"+ , Space+ , Str "quote"+ , Space+ , Str "is"+ , Space+ , Str "below:"+ ]+ , BlockQuote+ [ Para+ [ Str "My" , Space , Str "block" , Space , Str "quote" ]+ ]+ , Para+ [ Str "End"+ , Space+ , Str "of"+ , Space+ , Str "a"+ , Space+ , Str "paragraph"+ ]+ , Header 1 ( "formulae" , [] , [] ) [ Str "Formulae" ]+ , Header+ 2+ ( "inline-formulae" , [] , [] )+ [ Str "Inline"+ , Space+ , Str "formulae"+ , Space+ , Str "with"+ , Space+ , Emph [ Str "inline-formula" ]+ ]+ , Para+ [ Strong+ [ Str "Inside" , Space , Str "a" , Space , Str "paragraph" ]+ , Str ","+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "natively"+ , Space+ , Str "coded"+ , Space+ , Str "inside"+ , Space+ , Str "the"+ , Space+ , Str "paragraph,"+ , Space+ , Str "and"+ , Space+ , Str "show"+ , Space+ , Str "inline:"+ ]+ , Para+ [ Str "Einstein"+ , Space+ , Str "showed"+ , Space+ , Str "that"+ , Space+ , Math InlineMath "e=mc^2"+ , Str "."+ , SoftBreak+ , Str "This"+ , Space+ , Str "formula"+ , Space+ , Str "is"+ , Space+ , Str "important"+ , Space+ , Str "because\8230"+ ]+ , Header+ 2+ ( "disp-formulae" , [] , [] )+ [ Str "Block"+ , Space+ , Str "formulae"+ , Space+ , Str "with"+ , Space+ , Emph [ Str "disp-formula" ]+ ]+ , Para+ [ Strong+ [ Str "Inside" , Space , Str "a" , Space , Str "paragraph" ]+ , Str ","+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "natively"+ , Space+ , Str "coded"+ , Space+ , Str "inside"+ , Space+ , Str "the"+ , Space+ , Str "paragraph,"+ , Space+ , Str "but"+ , Space+ , Str "show"+ , Space+ , Str "as"+ , Space+ , Str "block:"+ ]+ , Para+ [ Str "Einstein"+ , Space+ , Str "showed"+ , Space+ , Str "that"+ , Space+ , Math DisplayMath "e=mc^2"+ , Str "."+ , SoftBreak+ , Str "This"+ , Space+ , Str "formula"+ , Space+ , Str "is"+ , Space+ , Str "important"+ , Space+ , Str "because\8230"+ ]+ , Para+ [ Strong+ [ Str "Outside"+ , Space+ , Str "a"+ , Space+ , Str "paragraph"+ ]+ , Str ","+ , Space+ , Str "should"+ , Space+ , Str "show"+ , Space+ , Str "as"+ , Space+ , Str "block:"+ ]+ , Para+ [ Str "Einstein"+ , Space+ , Str "showed"+ , Space+ , Str "that"+ ]+ , Div+ ( "" , [ "disp-formula" ] , [] )+ [ Para [ Math DisplayMath "e=mc^2" ] ]+ , Para+ [ Str "This"+ , Space+ , Str "formula"+ , Space+ , Str "is"+ , Space+ , Str "important"+ , Space+ , Str "because\8230"+ ]+ , Header+ 2+ ( "no-formula-wrapper" , [] , [] )+ [ Str "Without"+ , Space+ , Str "a"+ , Space+ , Str "formula"+ , Space+ , Str "wrapper"+ ]+ , Para+ [ Strong+ [ Str "Inside" , Space , Str "a" , Space , Str "paragraph" ]+ , Str ","+ , Space+ , Str "should"+ , Space+ , Str "show"+ , Space+ , Str "inline:"+ ]+ , Para+ [ Str "Einstein"+ , Space+ , Str "showed"+ , Space+ , Str "that"+ , Space+ , Math InlineMath "e=mc^2"+ , Str "."+ , SoftBreak+ , Str "This"+ , Space+ , Str "formula"+ , Space+ , Str "is"+ , Space+ , Str "important"+ , Space+ , Str "because\8230"+ ]+ , Para+ [ Strong+ [ Str "Outside"+ , Space+ , Str "a"+ , Space+ , Str "paragraph"+ ]+ , Str ","+ , Space+ , Str "should"+ , Space+ , Str "show"+ , Space+ , Str "as"+ , Space+ , Str "block:"+ ]+ , Para+ [ Str "Einstein"+ , Space+ , Str "showed"+ , Space+ , Str "that"+ ]+ , Para [ Math DisplayMath "e=mc^2" ]+ , Para+ [ Str "This"+ , Space+ , Str "formula"+ , Space+ , Str "is"+ , Space+ , Str "important"+ , Space+ , Str "because\8230"+ ]+ , Header+ 2+ ( "misc-formulae" , [] , [] )+ [ Str "Formulae"+ , Space+ , Str "with"+ , Space+ , Str "miscelaneus"+ , Space+ , Str "elements"+ ]+ , Para+ [ Str "Regardless"+ , Space+ , Str "of"+ , Space+ , Str "whether"+ , Space+ , Str "or"+ , Space+ , Str "not"+ , Space+ , Str "they"+ , Space+ , Str "are"+ , Space+ , Str "inside"+ , Space+ , Str "a"+ , Space+ , Str "paragraph,"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "wrapped"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "div,"+ , Space+ , Str "and"+ , Space+ , Str "displayed"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "block:"+ ]+ , Para+ [ Strong+ [ Str "Inside"+ , Space+ , Str "a"+ , Space+ , Str "paragraph:"+ ]+ ]+ , Para+ [ Str "Einstein"+ , Space+ , Str "definitely"+ , Space+ , Str "showed"+ , Space+ , Str "that"+ ]+ , Div+ ( "" , [ "disp-formula" ] , [] )+ [ Para [ Str "Abstract" , Space , Str "text" ]+ , Para+ [ Image+ ( "graphic001"+ , [ "This"+ , "is"+ , "the"+ , "role"+ , "of"+ , "the"+ , "graphic"+ ]+ , []+ )+ [ Str "Alternative"+ , Space+ , Str "text"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "graphic"+ ]+ ( "https://lh3.googleusercontent.com/dB7iirJ3ncQaVMBGE2YX-WCeoAVIChb6NAzoFcKCFChMsrixJvD7ZRbvcaC-ceXEzXYaoH4K5vaoRDsUyBHFkpIDPnsn3bnzovbvi0a2Gg=s660"+ , "This is the title of the graphic"+ )+ ]+ , Para [ Math DisplayMath "e=mc^2" ]+ ]+ , Para+ [ Str "."+ , SoftBreak+ , Str "This"+ , Space+ , Str "formula"+ , Space+ , Str "is"+ , Space+ , Str "important"+ , Space+ , Str "because\8230"+ ]+ , Para+ [ Strong+ [ Str "Outside"+ , Space+ , Str "of"+ , Space+ , Str "a"+ , Space+ , Str "paragraph:"+ ]+ ]+ , Para+ [ Str "Paragraph"+ , Space+ , Str "before:"+ , Space+ , Str "Einstein"+ , Space+ , Str "showed"+ , Space+ , Str "that"+ ]+ , Div+ ( "" , [ "disp-formula" ] , [] )+ [ Para [ Str "Abstract" , Space , Str "text" ]+ , Para+ [ Image+ ( "graphic003" , [] , [] )+ [ Str "Alternative"+ , Space+ , Str "text"+ , Space+ , Str "1"+ ]+ ( "Title 3" , "" )+ ]+ , Para [ Math DisplayMath "e=mc^2" ]+ ]+ , Para+ [ Str "This"+ , Space+ , Str "formula"+ , Space+ , Str "is"+ , Space+ , Str "important"+ , Space+ , Str "because\8230"+ ]+ , Figure+ ( "fig-1" , [] , [] )+ (Caption Nothing [ Plain [ Str "bar" ] ])+ [ Plain [ Str "alternative-decription" ]+ , Para [ Image ( "" , [] , [] ) [] ( "foo.png" , "" ) ]+ ]+ , Header+ 1+ ( "code-blocks" , [] , [] )+ [ Str "Code" , Space , Str "Blocks" ]+ , Para [ Str "Code:" ]+ , CodeBlock+ ( "" , [] , [] )+ "---- (should be four hyphens)\n\nsub status {\n print \"working\";\n}\n\nthis code block is indented by one tab"+ , Para [ Str "And:" ]+ , CodeBlock+ ( "" , [] , [] )+ " this code block is indented by two tabs\n\nThese should not be escaped: \\$ \\\\ \\> \\[ \\{"+ , Header 1 ( "lists" , [] , [] ) [ Str "Lists" ]+ , Header 2 ( "unordered" , [] , [] ) [ Str "Unordered" ]+ , Para [ Str "Asterisks" , Space , Str "tight:" ]+ , BulletList+ [ [ Para [ Str "asterisk" , Space , Str "1" ] ]+ , [ Para [ Str "asterisk" , Space , Str "2" ] ]+ , [ Para [ Str "asterisk" , Space , Str "3" ] ]+ ]+ , Para [ Str "Asterisks" , Space , Str "loose:" ]+ , BulletList+ [ [ Para [ Str "asterisk" , Space , Str "1" ] ]+ , [ Para [ Str "asterisk" , Space , Str "2" ] ]+ , [ Para [ Str "asterisk" , Space , Str "3" ] ]+ ]+ , Para [ Str "Pluses" , Space , Str "tight:" ]+ , BulletList+ [ [ Para [ Str "Plus" , Space , Str "1" ] ]+ , [ Para [ Str "Plus" , Space , Str "2" ] ]+ , [ Para [ Str "Plus" , Space , Str "3" ] ]+ ]+ , Para [ Str "Pluses" , Space , Str "loose:" ]+ , BulletList+ [ [ Para [ Str "Plus" , Space , Str "1" ] ]+ , [ Para [ Str "Plus" , Space , Str "2" ] ]+ , [ Para [ Str "Plus" , Space , Str "3" ] ]+ ]+ , Para [ Str "Minuses" , Space , Str "tight:" ]+ , BulletList+ [ [ Para [ Str "Minus" , Space , Str "1" ] ]+ , [ Para [ Str "Minus" , Space , Str "2" ] ]+ , [ Para [ Str "Minus" , Space , Str "3" ] ]+ ]+ , Para [ Str "Minuses" , Space , Str "loose:" ]+ , BulletList+ [ [ Para [ Str "Minus" , Space , Str "1" ] ]+ , [ Para [ Str "Minus" , Space , Str "2" ] ]+ , [ Para [ Str "Minus" , Space , Str "3" ] ]+ ]+ , Header 2 ( "ordered" , [] , [] ) [ Str "Ordered" ]+ , Para [ Str "Tight:" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "First" ] ]+ , [ Para [ Str "Second" ] ]+ , [ Para [ Str "Third" ] ]+ ]+ , Para [ Str "and:" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "One" ] ]+ , [ Para [ Str "Two" ] ]+ , [ Para [ Str "Three" ] ]+ ]+ , Para+ [ Str "Loose" , Space , Str "using" , Space , Str "tabs:" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "First" ] ]+ , [ Para [ Str "Second" ] ]+ , [ Para [ Str "Third" ] ]+ ]+ , Para+ [ Str "and" , Space , Str "using" , Space , Str "spaces:" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "One" ] ]+ , [ Para [ Str "Two" ] ]+ , [ Para [ Str "Three" ] ]+ ]+ , Para [ Str "Multiple" , Space , Str "paragraphs:" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para+ [ Str "Item"+ , Space+ , Str "1,"+ , Space+ , Str "graf"+ , Space+ , Str "one."+ ]+ , Para+ [ Str "Item"+ , Space+ , Str "1."+ , Space+ , Str "graf"+ , Space+ , Str "two."+ , Space+ , Str "The"+ , Space+ , Str "quick"+ , Space+ , Str "brown"+ , Space+ , Str "fox"+ , Space+ , Str "jumped"+ , Space+ , Str "over"+ , Space+ , Str "the"+ , Space+ , Str "lazy"+ , SoftBreak+ , Str "dog's"+ , Space+ , Str "back."+ ]+ ]+ , [ Para [ Str "Item" , Space , Str "2." ] ]+ , [ Para [ Str "Item" , Space , Str "3." ] ]+ ]+ , Para [ Str "List" , Space , Str "styles:" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "one" ] ]+ , [ Para [ Str "two" ] ]+ , [ Para [ Str "three" ] ]+ ]+ , OrderedList+ ( 1 , LowerRoman , DefaultDelim )+ [ [ Para [ Str "one" ] ]+ , [ Para [ Str "two" ] ]+ , [ Para [ Str "three" ] ]+ ]+ , Header 2 ( "nested" , [] , [] ) [ Str "Nested" ]+ , BulletList+ [ [ Para [ Str "Tab" ]+ , BulletList+ [ [ Para [ Str "Tab" ]+ , BulletList [ [ Para [ Str "Tab" ] ] ]+ ]+ ]+ ]+ ]+ , Para [ Str "Here's" , Space , Str "another:" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "First" ] ]+ , [ Para [ Str "Second:" ]+ , BulletList+ [ [ Para [ Str "Fee" ] ]+ , [ Para [ Str "Fie" ] ]+ , [ Para [ Str "Foe" ] ]+ ]+ ]+ , [ Para [ Str "Third" ] ]+ ]+ , Para+ [ Str "Same"+ , Space+ , Str "thing"+ , Space+ , Str "but"+ , Space+ , Str "with"+ , Space+ , Str "paragraphs:"+ ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "First" ] ]+ , [ Para [ Str "Second:" ]+ , BulletList+ [ [ Para [ Str "Fee" ] ]+ , [ Para [ Str "Fie" ] ]+ , [ Para [ Str "Foe" ] ]+ ]+ ]+ , [ Para [ Str "Third" ] ]+ ]+ , Header+ 2+ ( "tabs-and-spaces" , [] , [] )+ [ Str "Tabs" , Space , Str "and" , Space , Str "spaces" ]+ , BulletList+ [ [ Para+ [ Str "this"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "list"+ , Space+ , Str "item"+ , Space+ , Str "indented"+ , Space+ , Str "with"+ , Space+ , Str "tabs"+ ]+ ]+ , [ Para+ [ Str "this"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "list"+ , Space+ , Str "item"+ , Space+ , Str "indented"+ , Space+ , Str "with"+ , Space+ , Str "spaces"+ ]+ , BulletList+ [ [ Para+ [ Str "this"+ , Space+ , Str "is"+ , Space+ , Str "an"+ , Space+ , Str "example"+ , Space+ , Str "list"+ , Space+ , Str "item"+ , Space+ , Str "indented"+ , Space+ , Str "with"+ , Space+ , Str "tabs"+ ]+ ]+ , [ Para+ [ Str "this"+ , Space+ , Str "is"+ , Space+ , Str "an"+ , Space+ , Str "example"+ , Space+ , Str "list"+ , Space+ , Str "item"+ , Space+ , Str "indented"+ , Space+ , Str "with"+ , Space+ , Str "spaces"+ ]+ ]+ ]+ ]+ ]+ , Header+ 2+ ( "fancy-list-markers" , [] , [] )+ [ Str "Fancy" , Space , Str "list" , Space , Str "markers" ]+ , Para [ Str "Autonumbering:" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Autonumber." ] ]+ , [ Para [ Str "More." ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para [ Str "Nested." ] ] ]+ ]+ ]+ , Header 2 ( "definition" , [] , [] ) [ Str "Definition" ]+ , DefinitionList+ [ ( [ Str "Violin" ]+ , [ [ Para+ [ Str "Stringed"+ , Space+ , Str "musical"+ , Space+ , Str "instrument."+ ]+ , Para [ Str "Torture" , Space , Str "device." ]+ ]+ ]+ )+ , ( [ Str "Cello"+ , Strong [ LineBreak ]+ , Str "Violoncello"+ ]+ , [ [ Para+ [ Str "Low-voiced"+ , Space+ , Str "stringed"+ , Space+ , Str "instrument."+ ]+ ]+ ]+ )+ ]+ , Header+ 2+ ( "list-inside-paragraph" , [] , [] )+ [ Str "List"+ , Space+ , Str "inside"+ , Space+ , Str "a"+ , Space+ , Str "paragraph"+ ]+ , Para+ [ Str "Start"+ , Space+ , Str "of"+ , Space+ , Str "a"+ , Space+ , Str "paragraph."+ ]+ , BulletList+ [ [ Para [ Str "Red" ] ] , [ Para [ Str "Blue" ] ] ]+ , Para+ [ Str "End" , Space , Str "of" , Space , Str "paragraph." ]+ , Header+ 1+ ( "inline-markup" , [] , [] )+ [ Str "Inline" , Space , Str "Markup" ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Emph [ Str "emphasized" ]+ , Str ","+ , Space+ , Str "and"+ , Space+ , Str "so"+ , Space+ , Emph [ Str "is" , SoftBreak , Str "this" ]+ , Str "."+ ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Strong [ Str "strong" ]+ , Str ","+ , Space+ , Str "and"+ , Space+ , Str "so"+ , SoftBreak+ , Strong [ Str "is" , Space , Str "this" ]+ , Str "."+ ]+ , Para+ [ Str "Empty"+ , Space+ , Strong []+ , Space+ , Str "and"+ , Space+ , Emph []+ , Str "."+ ]+ , Para+ [ Str "An"+ , SoftBreak+ , Emph+ [ Link+ ( "" , [] , [] )+ [ Str "emphasized" , SoftBreak , Str "link" ]+ ( "/url" , "" )+ ]+ , Str "."+ ]+ , Para+ [ Strong+ [ Emph+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "strong"+ , Space+ , Str "and"+ , Space+ , Str "em."+ ]+ ]+ ]+ , Para+ [ Str "So"+ , Space+ , Str "is"+ , Space+ , Strong [ Emph [ Str "this" ] ]+ , Space+ , Str "word."+ ]+ , Para+ [ Strong+ [ Emph+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "strong"+ , Space+ , Str "and"+ , Space+ , Str "em."+ ]+ ]+ ]+ , Para+ [ Str "So"+ , Space+ , Str "is"+ , Space+ , Strong [ Emph [ Str "this" ] ]+ , Space+ , Str "word."+ ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "code:"+ , Space+ , Code ( "" , [] , [] ) ">"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "$"+ , Str ","+ , SoftBreak+ , Code ( "" , [] , [] ) "\\"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "\\$"+ , Str ","+ , SoftBreak+ , Code ( "" , [] , [] ) "<html>"+ , Str "."+ ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , SmallCaps [ Str "small" , Space , Str "caps" ]+ , Str "."+ ]+ , Para+ [ Str "These"+ , Space+ , Str "are"+ , Space+ , Str "all"+ , Space+ , Str "underlined:"+ , Space+ , Str "foo"+ , Space+ , Str "and"+ , Space+ , Str "bar."+ ]+ , Para+ [ Str "These"+ , Space+ , Str "are"+ , Space+ , Str "all"+ , Space+ , Str "strikethrough:"+ , Space+ , Strikeout [ Str "foo" ]+ , Str ","+ , SoftBreak+ , Strikeout [ Str "bar" ]+ , Str ","+ , Space+ , Str "and"+ , Space+ , Strikeout [ Str "baz" ]+ , Str "."+ ]+ , Header+ 1+ ( "smart-quotes-ellipses-dashes" , [] , [] )+ [ Str "Smart"+ , Space+ , Str "quotes,"+ , Space+ , Str "ellipses,"+ , Space+ , Str "dashes"+ ]+ , Para+ [ Str "\"Hello,\""+ , Space+ , Str "said"+ , Space+ , Str "the"+ , Space+ , Str "spider."+ , Space+ , Str "\"'Shelob'"+ , Space+ , Str "is"+ , Space+ , Str "my"+ , Space+ , Str "name.\""+ ]+ , Para+ [ Str "'A',"+ , Space+ , Str "'B',"+ , Space+ , Str "and"+ , Space+ , Str "'C'"+ , Space+ , Str "are"+ , Space+ , Str "letters."+ ]+ , Para+ [ Str "'Oak,'"+ , Space+ , Str "'elm,'"+ , Space+ , Str "and"+ , Space+ , Str "'beech'"+ , Space+ , Str "are"+ , Space+ , Str "names"+ , Space+ , Str "of"+ , Space+ , Str "trees."+ , Space+ , Str "So"+ , Space+ , Str "is"+ , Space+ , Str "'pine.'"+ ]+ , Para+ [ Str "'He"+ , Space+ , Str "said,"+ , Space+ , Str "\"I"+ , Space+ , Str "want"+ , Space+ , Str "to"+ , Space+ , Str "go.\"'"+ , Space+ , Str "Were"+ , Space+ , Str "you"+ , Space+ , Str "alive"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "70's?"+ ]+ , Para+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "some"+ , Space+ , Str "quoted"+ , Space+ , Str "'"+ , Code ( "" , [] , [] ) "code"+ , Str "'"+ , Space+ , Str "and"+ , Space+ , Str "a"+ , SoftBreak+ , Str "\""+ , Link+ ( "" , [] , [] )+ [ Str "quoted" , SoftBreak , Str "link" ]+ ( "http://example.com/?foo=1&bar=2" , "" )+ , Str "\"."+ ]+ , Para+ [ Str "Some"+ , Space+ , Str "dashes:"+ , Space+ , Str "one---two"+ , Space+ , Str "---"+ , Space+ , Str "three--four"+ , Space+ , Str "--"+ , Space+ , Str "five."+ ]+ , Para+ [ Str "Dashes"+ , Space+ , Str "between"+ , Space+ , Str "numbers:"+ , Space+ , Str "5-7,"+ , Space+ , Str "255-66,"+ , Space+ , Str "1987-1999."+ ]+ , Para+ [ Str "Ellipses...and."+ , Space+ , Str "."+ , Space+ , Str ".and"+ , Space+ , Str "."+ , Space+ , Str "."+ , Space+ , Str "."+ , Space+ , Str "."+ ]+ , Header 1 ( "latex" , [] , [] ) [ Str "LaTeX" ]+ , BulletList+ [ [ Para [ Str "\\cite[22-23]{smith.1899}" ] ]+ , [ Para [ Str "\\doublespacing" ] ]+ , [ Para [ Str "$2+2=4$" ] ]+ , [ Para+ [ Str "$x" , Space , Str "\\in" , Space , Str "y$" ]+ ]+ , [ Para+ [ Str "$\\alpha"+ , Space+ , Str "\\wedge"+ , Space+ , Str "\\omega$"+ ]+ ]+ , [ Para [ Str "$223$" ] ]+ , [ Para [ Str "$p$-Tree" ] ]+ , [ Para+ [ Str "$\\frac{d}{dx}f(x)=\\lim_{h\\to"+ , Space+ , Str "0}\\frac{f(x+h)-f(x)}{h}$"+ ]+ ]+ , [ Para+ [ Str "Here's"+ , Space+ , Str "one"+ , Space+ , Str "that"+ , Space+ , Str "has"+ , Space+ , Str "a"+ , Space+ , Str "line"+ , Space+ , Str "break"+ , Space+ , Str "in"+ , Space+ , Str "it:"+ , Space+ , Str "$\\alpha"+ , Space+ , Str "+"+ , Space+ , Str "\\omega"+ , Space+ , Str "\\times"+ , SoftBreak+ , Str "x^2$."+ ]+ ]+ ]+ , Para+ [ Str "These"+ , Space+ , Str "shouldn't"+ , Space+ , Str "be"+ , Space+ , Str "math:"+ ]+ , BulletList+ [ [ Para+ [ Str "To"+ , Space+ , Str "get"+ , Space+ , Str "the"+ , Space+ , Str "famous"+ , Space+ , Str "equation,"+ , Space+ , Str "write"+ , SoftBreak+ , Code ( "" , [] , [] ) "$e = mc^2$"+ , Str "."+ ]+ ]+ , [ Para+ [ Str "$22,000"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Emph [ Str "lot" ]+ , Space+ , Str "of"+ , Space+ , Str "money."+ , Space+ , Str "So"+ , Space+ , Str "is"+ , Space+ , Str "$34,000."+ , Space+ , Str "(It"+ , SoftBreak+ , Str "worked"+ , Space+ , Str "if"+ , Space+ , Str "\"lot\""+ , Space+ , Str "is"+ , Space+ , Str "emphasized.)"+ ]+ ]+ , [ Para+ [ Str "Escaped"+ , Space+ , Code ( "" , [] , [] ) "$"+ , Str ":"+ , Space+ , Str "$73"+ , Space+ , Emph+ [ Str "this"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , SoftBreak+ , Str "emphasized"+ ]+ , Space+ , Str "23$."+ ]+ ]+ ]+ , Para+ [ Str "Here's"+ , Space+ , Str "a"+ , Space+ , Str "LaTeX"+ , Space+ , Str "table:"+ ]+ , Para+ [ Str "\\begin{tabular}{|l|l|}\\hline"+ , Space+ , Str "Animal"+ , Space+ , Str "&"+ , Space+ , Str "Number"+ , Space+ , Str "\\\\"+ , Space+ , Str "\\hline"+ , Space+ , Str "Dog"+ , Space+ , Str "&"+ , SoftBreak+ , Str "2"+ , Space+ , Str "\\\\"+ , Space+ , Str "Cat"+ , Space+ , Str "&"+ , Space+ , Str "1"+ , Space+ , Str "\\\\"+ , Space+ , Str "\\hline"+ , Space+ , Str "\\end{tabular}"+ ]+ , Header+ 1+ ( "special-characters" , [] , [] )+ [ Str "Special" , Space , Str "Characters" ]+ , Para+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "some"+ , Space+ , Str "unicode:"+ ]+ , BulletList+ [ [ Para+ [ Str "I" , Space , Str "hat:" , Space , Str "\206" ]+ ]+ , [ Para+ [ Str "o" , Space , Str "umlaut:" , Space , Str "\246" ]+ ]+ , [ Para [ Str "section:" , Space , Str "\167" ] ]+ , [ Para+ [ Str "set"+ , Space+ , Str "membership:"+ , Space+ , Str "elem"+ ]+ ]+ , [ Para [ Str "copyright:" , Space , Str "\169" ] ]+ ]+ , Para+ [ Str "AT&T"+ , Space+ , Str "has"+ , Space+ , Str "an"+ , Space+ , Str "ampersand"+ , Space+ , Str "in"+ , Space+ , Str "their"+ , Space+ , Str "name."+ ]+ , Para+ [ Str "AT&T"+ , Space+ , Str "is"+ , Space+ , Str "another"+ , Space+ , Str "way"+ , Space+ , Str "to"+ , Space+ , Str "write"+ , Space+ , Str "it."+ ]+ , Para+ [ Str "This" , Space , Str "&" , Space , Str "that." ]+ , Para [ Str "4" , Space , Str "<" , Space , Str "5." ]+ , Para [ Str "6" , Space , Str ">" , Space , Str "5." ]+ , Para [ Str "Backslash:" , Space , Str "\\" ]+ , Para [ Str "Backtick:" , Space , Str "`" ]+ , Para [ Str "Asterisk:" , Space , Str "*" ]+ , Para [ Str "Underscore:" , Space , Str "_" ]+ , Para+ [ Str "Left" , Space , Str "brace:" , Space , Str "{" ]+ , Para+ [ Str "Right" , Space , Str "brace:" , Space , Str "}" ]+ , Para+ [ Str "Left" , Space , Str "bracket:" , Space , Str "[" ]+ , Para+ [ Str "Right" , Space , Str "bracket:" , Space , Str "]" ]+ , Para+ [ Str "Left" , Space , Str "paren:" , Space , Str "(" ]+ , Para+ [ Str "Right" , Space , Str "paren:" , Space , Str ")" ]+ , Para [ Str "Greater-than:" , Space , Str ">" ]+ , Para [ Str "Hash:" , Space , Str "#" ]+ , Para [ Str "Period:" , Space , Str "." ]+ , Para [ Str "Bang:" , Space , Str "!" ]+ , Para [ Str "Plus:" , Space , Str "+" ]+ , Para [ Str "Minus:" , Space , Str "-" ]+ , Header 1 ( "links" , [] , [] ) [ Str "Links" ]+ , Header 2 ( "explicit" , [] , [] ) [ Str "Explicit" ]+ , Para+ [ Str "Just"+ , Space+ , Str "a"+ , SoftBreak+ , Link ( "" , [] , [] ) [ Str "URL" ] ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "URL" , SoftBreak , Str "and" , Space , Str "title" ]+ ( "/url/" , "title" )+ , Str "."+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "URL" , SoftBreak , Str "and" , Space , Str "title" ]+ ( "/url/" , "title preceded by two spaces" )+ , Str "."+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "URL" , SoftBreak , Str "and" , Space , Str "title" ]+ ( "/url/" , "title preceded by a tab" )+ , Str "."+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "URL" , SoftBreak , Str "and" , Space , Str "title" ]+ ( "/url/" , "title with \"quotes\" in it" )+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "URL" , SoftBreak , Str "and" , Space , Str "title" ]+ ( "/url/" , "title with single quotes" )+ ]+ , Para+ [ Str "Email"+ , Space+ , Str "link"+ , Space+ , Str "(nobody"+ , Space+ , Str "[at]"+ , Space+ , Str "nowhere.net)"+ ]+ , Para+ [ Link ( "" , [] , [] ) [ Str "Empty" ] ( "" , "" )+ , Str "."+ ]+ , Header 2 ( "reference" , [] , [] ) [ Str "Reference" ]+ , Para+ [ Str "Foo"+ , SoftBreak+ , Link ( "" , [] , [] ) [ Str "bar" ] ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Str "Foo"+ , SoftBreak+ , Link ( "" , [] , [] ) [ Str "bar" ] ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Str "Foo"+ , SoftBreak+ , Link ( "" , [] , [] ) [ Str "bar" ] ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Str "With"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "embedded" , SoftBreak , Str "[brackets]" ]+ ( "/url/" , "" )+ , Str "."+ ]+ , Para+ [ Link ( "" , [] , [] ) [ Str "b" ] ( "/url/" , "" )+ , Space+ , Str "by"+ , SoftBreak+ , Str "itself"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "a"+ , Space+ , Str "link."+ ]+ , Para+ [ Str "Indented"+ , SoftBreak+ , Link ( "" , [] , [] ) [ Str "once" ] ( "/url" , "" )+ , Str "."+ ]+ , Para+ [ Str "Indented"+ , SoftBreak+ , Link ( "" , [] , [] ) [ Str "twice" ] ( "/url" , "" )+ , Str "."+ ]+ , Para+ [ Str "Indented"+ , SoftBreak+ , Link ( "" , [] , [] ) [ Str "thrice" ] ( "/url" , "" )+ , Str "."+ ]+ , Para+ [ Str "This"+ , Space+ , Str "should"+ , Space+ , Str "[not]"+ , Space+ , Str "be"+ , Space+ , Str "a"+ , Space+ , Str "link."+ ]+ , CodeBlock ( "" , [] , [] ) "[not]: /url"+ , Para+ [ Str "Foo"+ , SoftBreak+ , Link+ ( "" , [] , [] )+ [ Str "bar" ]+ ( "/url/" , "Title with \"quotes\" inside" )+ , Str "."+ ]+ , Para+ [ Str "Foo"+ , SoftBreak+ , Link+ ( "" , [] , [] )+ [ Str "biz" ]+ ( "/url/" , "Title with \"quote\" inside" )+ , Str "."+ ]+ , Header+ 2+ ( "with-ampersands" , [] , [] )+ [ Str "With" , Space , Str "ampersands" ]+ , Para+ [ Str "Here's"+ , Space+ , Str "a"+ , SoftBreak+ , Link+ ( "" , [] , [] )+ [ Str "link"+ , SoftBreak+ , Str "with"+ , Space+ , Str "an"+ , Space+ , Str "ampersand"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "URL"+ ]+ ( "http://example.com/?foo=1&bar=2" , "" )+ , Str "."+ ]+ , Para+ [ Str "Here's"+ , Space+ , Str "a"+ , Space+ , Str "link"+ , Space+ , Str "with"+ , Space+ , Str "an"+ , Space+ , Str "amersand"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "link"+ , Space+ , Str "text:"+ , SoftBreak+ , Link+ ( "" , [] , [] )+ [ Str "AT&T" ]+ ( "http://att.com/" , "AT&T" )+ , Str "."+ ]+ , Para+ [ Str "Here's"+ , Space+ , Str "an"+ , SoftBreak+ , Link+ ( "" , [] , [] )+ [ Str "inline" , SoftBreak , Str "link" ]+ ( "/script?foo=1&bar=2" , "" )+ , Str "."+ ]+ , Para+ [ Str "Here's"+ , Space+ , Str "an"+ , SoftBreak+ , Link+ ( "" , [] , [] )+ [ Str "inline"+ , SoftBreak+ , Str "link"+ , Space+ , Str "in"+ , Space+ , Str "pointy"+ , Space+ , Str "braces"+ ]+ ( "/script?foo=1&bar=2" , "" )+ , Str "."+ ]+ , Header 2 ( "autolinks" , [] , [] ) [ Str "Autolinks" ]+ , Para+ [ Str "With"+ , Space+ , Str "an"+ , Space+ , Str "ampersand:"+ , SoftBreak+ , Link+ ( "" , [] , [] )+ [ Str "http://example.com/?foo=1&bar=2" ]+ ( "http://example.com/?foo=1&bar=2" , "" )+ ]+ , BulletList+ [ [ Para+ [ Str "In" , Space , Str "a" , Space , Str "list?" ]+ ]+ , [ Para+ [ Link+ ( "" , [] , [] )+ [ Str "http://example.com/" ]+ ( "http://example.com/" , "" )+ ]+ ]+ , [ Para [ Str "It" , Space , Str "should." ] ]+ ]+ , Para+ [ Str "An"+ , Space+ , Str "e-mail"+ , Space+ , Str "address:"+ , Space+ , Str "nobody"+ , Space+ , Str "[at]"+ , Space+ , Str "nowhere.net"+ ]+ , BlockQuote+ [ Para+ [ Str "Blockquoted:"+ , SoftBreak+ , Link+ ( "" , [] , [] )+ [ Str "http://example.com/" ]+ ( "http://example.com/" , "" )+ ]+ ]+ , Para+ [ Str "Auto-links"+ , Space+ , Str "should"+ , Space+ , Str "not"+ , Space+ , Str "occur"+ , Space+ , Str "here:"+ , SoftBreak+ , Code ( "" , [] , [] ) "<http://example.com/>"+ ]+ , CodeBlock+ ( "" , [] , [] ) "or here: <http://example.com/>"+ , Header 1 ( "images" , [] , [] ) [ Str "Images" ]+ , Para+ [ Str "From"+ , Space+ , Str "\"Voyage"+ , Space+ , Str "dans"+ , Space+ , Str "la"+ , Space+ , Str "Lune\""+ , Space+ , Str "by"+ , Space+ , Str "Georges"+ , Space+ , Str "Melies"+ , Space+ , Str "(1902):"+ ]+ , Para+ [ Image+ ( "" , [] , [] ) [] ( "lalune.jpg" , "Voyage dans la Lune" )+ ]+ , Para+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "movie"+ , SoftBreak+ , Image ( "" , [] , [] ) [] ( "movie.jpg" , "" )+ , SoftBreak+ , Str "icon."+ ]+ , Header 1 ( "footnotes" , [] , [] ) [ Str "Footnotes" ]+ , Para+ [ Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "footnote"+ , Space+ , Str "reference"+ , Link ( "" , [] , [] ) [ Str "(1)" ] ( "#note_1" , "" )+ , Str ","+ , SoftBreak+ , Str "and"+ , SoftBreak+ , Str "another"+ , Link+ ( "" , [] , [] )+ [ Str "(longnote)" ]+ ( "#note_longnote" , "" )+ , Str "."+ , SoftBreak+ , Str "This"+ , Space+ , Str "should"+ , Space+ , Emph [ Str "not" ]+ , Space+ , Str "be"+ , Space+ , Str "a"+ , Space+ , Str "footnote"+ , Space+ , Str "reference,"+ , Space+ , Str "because"+ , Space+ , Str "it"+ , SoftBreak+ , Str "contains"+ , Space+ , Str "a"+ , Space+ , Str "space^(my"+ , Space+ , Str "note)."+ ]+ , Para+ [ Link ( "" , [] , [] ) [ Str "(1)" ] ( "#ref_1" , "" )+ , Space+ , Str "Here"+ , Space+ , Str "is"+ , Space+ , Str "the"+ , Space+ , Str "footnote."+ , Space+ , Str "It"+ , Space+ , Str "can"+ , SoftBreak+ , Str "go"+ , Space+ , Str "anywhere"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "document,"+ , Space+ , Str "not"+ , Space+ , Str "just"+ , Space+ , Str "at"+ , Space+ , Str "the"+ , Space+ , Str "end."+ ]+ , Para+ [ Link+ ( "" , [] , [] )+ [ Str "(longnote)" ]+ ( "#ref_longnote" , "" )+ , Space+ , Str "Here's"+ , SoftBreak+ , Str "the"+ , Space+ , Str "other"+ , Space+ , Str "note."+ , Space+ , Str "This"+ , Space+ , Str "one"+ , Space+ , Str "contains"+ , Space+ , Str "multiple"+ , Space+ , Str "blocks."+ ]+ , Para+ [ Str "Caret"+ , Space+ , Str "characters"+ , Space+ , Str "are"+ , Space+ , Str "used"+ , Space+ , Str "to"+ , Space+ , Str "indicate"+ , Space+ , Str "that"+ , Space+ , Str "the"+ , Space+ , Str "blocks"+ , Space+ , Str "all"+ , Space+ , Str "belong"+ , Space+ , Str "to"+ , SoftBreak+ , Str "a"+ , Space+ , Str "single"+ , Space+ , Str "footnote"+ , Space+ , Str "(as"+ , Space+ , Str "with"+ , Space+ , Str "block"+ , Space+ , Str "quotes)."+ ]+ , CodeBlock ( "" , [] , [] ) " { <code> }"+ , Para+ [ Str "If"+ , Space+ , Str "you"+ , Space+ , Str "want,"+ , Space+ , Str "you"+ , Space+ , Str "can"+ , Space+ , Str "use"+ , Space+ , Str "a"+ , Space+ , Str "caret"+ , Space+ , Str "at"+ , Space+ , Str "the"+ , Space+ , Str "beginning"+ , Space+ , Str "of"+ , Space+ , Str "every"+ , Space+ , Str "line,"+ , Space+ , Str "as"+ , SoftBreak+ , Str "with"+ , Space+ , Str "blockquotes,"+ , Space+ , Str "but"+ , Space+ , Str "all"+ , Space+ , Str "that"+ , Space+ , Str "you"+ , Space+ , Str "need"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "caret"+ , Space+ , Str "at"+ , Space+ , Str "the"+ , Space+ , Str "beginning"+ , SoftBreak+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "first"+ , Space+ , Str "line"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "block"+ , Space+ , Str "and"+ , Space+ , Str "any"+ , Space+ , Str "preceding"+ , Space+ , Str "blank"+ , Space+ , Str "lines."+ ]+ , Para+ [ Str "text"+ , Space+ , Emph [ Str "Leading" , Space , Str "space" ]+ ]+ , Para+ [ Emph [ Str "Trailing" , Space , Str "space" ]+ , Space+ , Str "text"+ ]+ , Para+ [ Str "text"+ , Space+ , Emph [ Str "Leading" , Space , Str "spaces" ]+ ]+ , Para+ [ Emph [ Str "Trailing" , Space , Str "spaces" ]+ , Space+ , Str "text"+ ]+ , Header 1 ( "tables" , [] , [] ) [ Str "Tables" ]+ , Header+ 2+ ( "tables-with-headers" , [] , [] )+ [ Str "Tables"+ , Space+ , Str "with"+ , Space+ , Str "Headers"+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "X" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Y" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Z" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "X" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Y" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Z" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "X" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Y" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Z" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "X" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Y" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Z" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "X" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Y" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Z" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "X" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Y" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Z" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "X" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Y" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Z" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "r1a" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "r1b" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "r1c" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "X" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Y" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Z" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "X" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Y" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "Z" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Header+ 2+ ( "tables-without-headers" , [] , [] )+ [ Str "Tables"+ , Space+ , Str "without"+ , Space+ , Str "Headers"+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Header+ 2+ ( "table-with-spans-and-alignments" , [] , [] )+ [ Str "Tables"+ , Space+ , Str "with"+ , Space+ , Str "spans"+ , Space+ , Str "and"+ , Space+ , Str "alignments"+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignLeft+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Para [ Str "4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "6" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Para [ Str "7" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Header+ 2+ ( "table-with-footer" , [] , [] )+ [ Str "Table" , Space , Str "with" , Space , Str "footer" ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ ]+ ]+ ]+ (TableFoot+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "f1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "f2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "f3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "f4" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "f5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "f6" ] ]+ ]+ ])+ ]+ , Header+ 2+ ( "table-with-multiple-bodies" , [] , [] )+ [ Str "Table"+ , Space+ , Str "With"+ , Space+ , Str "Multiple"+ , Space+ , Str "Bodies"+ ]+ , Div+ ( "" , [ "table-wrap" ] , [] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignRight+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "a1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "a2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "a3" ] ]+ ]+ ]+ , TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "b1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "b2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "b3" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Header+ 2+ ( "empty-tables" , [] , [] )+ [ Str "Empty" , Space , Str "Tables" ]+ , Para+ [ Str "This"+ , Space+ , Str "section"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "empty."+ ]+ , Header 1 ( "" , [] , [] ) [ Str "References" ]+ , Div ( "refs" , [] , [] ) []+ , Header 1 ( "" , [] , [] ) [ Str "Notes" ]+ , Div ( "refs" , [] , [] ) [] ]
@@ -2,6 +2,9 @@ <!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.2 20190208//EN" "JATS-archivearticle1.dtd"> <article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.2" article-type="other">+<processing-meta base-tagset="archiving" mathml-version="3.0" table-model="xhtml" tagset-family="jats">+ <restricted-by>pmc</restricted-by>+</processing-meta> <front> <journal-meta> <journal-title-group>@@ -27,6 +30,15 @@ </name> </contrib> </contrib-group>+<permissions>+ <copyright-statement>© 2023, MacFarlane et al</copyright-statement>+ <copyright-year>2023</copyright-year>+ <copyright-holder>MacFarlane et al</copyright-holder>+ <license license-type="open-access">+ <ali:license_ref xmlns:ali="http://www.niso.org/schemas/ali/1.0/">https://creativecommons.org/licenses/by/4.0/</ali:license_ref>+ <license-p>This document is distributed under a Creative Commons Attribution 4.0 International license.</license-p>+ </license>+ </permissions> </article-meta> </front> <body>@@ -67,8 +79,16 @@ <p>Here's a regular paragraph.</p> <p>In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item.</p> <p>Here's one with a bullet. * criminey.</p>- <p>There should be a hard line break<break />here.</p>+ <p>There should be a <bold>hard line break<break /></bold>here.</p> </sec>+<sec id="statements">+ <title> Statements </title>+ <statement>+ <label> A label for a statement</label>+ <title> CAP TITLE </title>+ <p> Some text to make this regular </p>+ </statement>+</sec> <sec id="block-quotes"> <title>Block Quotes</title> <p>E-mail style:</p>@@ -123,7 +143,117 @@ </disp-quote> </disp-quote> <p>And a following paragraph.</p>+ <p>+ Here is a block quote inside a paragraph. Start of a paragraph is here, and the quote is below:+ <disp-quote>+ <p>My block quote</p>+ </disp-quote>+ End of a paragraph+ </p> </sec>+<sec id="formulae">+ <title>Formulae</title>+ <sec id="inline-formulae">+ <title>Inline formulae with <italic>inline-formula</italic></title>+ <p><bold>Inside a paragraph</bold>, should be natively coded inside the paragraph, and show inline:</p>+ <p>Einstein showed that <inline-formula><alternatives>+ <tex-math><![CDATA[e=mc^2]]></tex-math>+ <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>e</mml:mi><mml:mo>=</mml:mo><mml:mi>m</mml:mi><mml:msup><mml:mi>c</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math></alternatives></inline-formula>.+ This formula is important because…</p>+ </sec>+ <sec id="disp-formulae">+ <title>Block formulae with <italic>disp-formula</italic></title>+ <p><bold>Inside a paragraph</bold>, should be natively coded inside the paragraph, but show as block:</p>+ <p>Einstein showed that <disp-formula><alternatives>+ <tex-math><![CDATA[e=mc^2]]></tex-math>+ <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>e</mml:mi><mml:mo>=</mml:mo><mml:mi>m</mml:mi><mml:msup><mml:mi>c</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math></alternatives></disp-formula>.+ This formula is important because…</p>+ <p><bold>Outside a paragraph</bold>, should show as block:</p>+ <p>Einstein showed that </p>+ <disp-formula><alternatives>+ <tex-math><![CDATA[e=mc^2]]></tex-math>+ <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>e</mml:mi><mml:mo>=</mml:mo><mml:mi>m</mml:mi><mml:msup><mml:mi>c</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math></alternatives></disp-formula>+ <p>This formula is important because…</p>+ </sec>+ <sec id="no-formula-wrapper">+ <title>Without a formula wrapper</title>+ <p><bold>Inside a paragraph</bold>, should show inline:</p>+ <p>Einstein showed that <alternatives>+ <tex-math><![CDATA[e=mc^2]]></tex-math>+ <mml:math display="inline" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>e</mml:mi><mml:mo>=</mml:mo><mml:mi>m</mml:mi><mml:msup><mml:mi>c</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math></alternatives>.+ This formula is important because…</p>+ <p><bold>Outside a paragraph</bold>, should show as block:</p>+ <p>Einstein showed that </p>+ <alternatives>+ <tex-math><![CDATA[e=mc^2]]></tex-math>+ <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>e</mml:mi><mml:mo>=</mml:mo><mml:mi>m</mml:mi><mml:msup><mml:mi>c</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math></alternatives>+ <p>This formula is important because…</p>+ </sec>+ <sec id="misc-formulae">+ <title>Formulae with miscelaneus elements</title>+ <p>Regardless of whether or not they are inside a paragraph, should be wrapped in a div, and displayed in a block:</p>+ <p><bold>Inside a paragraph:</bold></p>+ <p>Einstein definitely showed that + <disp-formula>+ <abstract>+ <p>Abstract text</p>+ </abstract>+ <graphic id="graphic001"+ xlink:href="https://lh3.googleusercontent.com/dB7iirJ3ncQaVMBGE2YX-WCeoAVIChb6NAzoFcKCFChMsrixJvD7ZRbvcaC-ceXEzXYaoH4K5vaoRDsUyBHFkpIDPnsn3bnzovbvi0a2Gg=s660"+ xlink:title="This is the title of the graphic"+ xlink:role="This is the role of the graphic">+ <alt-text>Alternative text of the graphic</alt-text>+ <caption>+ <title>This is the title of the caption</title>+ <p>Google doodle from 14 March 2003</p></caption>+ </graphic>+ <alternatives>+ <tex-math><![CDATA[e=mc^2]]></tex-math>+ <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>e</mml:mi><mml:mo>=</mml:mo><mml:mi>m</mml:mi><mml:msup><mml:mi>c</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math>+ <graphic id="graphic001"+ xlink:href="https://lh3.googleusercontent.com/dB7iirJ3ncQaVMBGE2YX-WCeoAVIChb6NAzoFcKCFChMsrixJvD7ZRbvcaC-ceXEzXYaoH4K5vaoRDsUyBHFkpIDPnsn3bnzovbvi0a2Gg=s660"+ xlink:title="Title 2">+ <alt-text>Alternative text 2</alt-text>+ <caption><p>Google doodle from 14 March 2003</p></caption>+ </graphic>+ </alternatives>+ </disp-formula>.+ This formula is important because…</p>+ <p><bold>Outside of a paragraph:</bold></p>+ <p>Paragraph before: Einstein showed that </p>+ <disp-formula>+ <abstract>+ <p>Abstract text</p>+ </abstract>+ <graphic id="graphic003"+ xlink:href="https://lh3.googleusercontent.com/dB7iirJ3ncQaVMBGE2YX-WCeoAVIChb6NAzoFcKCFChMsrixJvD7ZRbvcaC-ceXEzXYaoH4K5vaoRDsUyBHFkpIDPnsn3bnzovbvi0a2Gg=s660"+ xlink:href="Title 3">+ <alt-text>Alternative text 1</alt-text>+ <caption><p>Google doodle from 14 March 2003</p></caption>+ </graphic>+ <alternatives>+ <tex-math><![CDATA[e=mc^2]]></tex-math>+ <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mi>e</mml:mi><mml:mo>=</mml:mo><mml:mi>m</mml:mi><mml:msup><mml:mi>c</mml:mi><mml:mn>2</mml:mn></mml:msup></mml:mrow></mml:math>+ <graphic id="graphic004"+ xlink:href="https://lh3.googleusercontent.com/dB7iirJ3ncQaVMBGE2YX-WCeoAVIChb6NAzoFcKCFChMsrixJvD7ZRbvcaC-ceXEzXYaoH4K5vaoRDsUyBHFkpIDPnsn3bnzovbvi0a2Gg=s660"+ xlink:href="Title 4">+ <alt-text>Alternative text 2</alt-text>+ <caption><p>Google doodle from 14 March 2003</p></caption>+ </graphic>+ </alternatives>+ </disp-formula>+ <p>This formula is important because…</p>+ </sec>+</sec>+<sec id="figures">+ <fig id="fig-1">+ <caption>+ <p>bar</p>+ </caption>+ <alt-text>alternative-decription</alt-text>+ <graphic xlink:href="foo.png" xlink:alt-text="baz" />+ </fig>+</sec> <sec id="code-blocks"> <title>Code Blocks</title> <p>Code:</p>@@ -281,8 +411,16 @@ </list-item> </list> <p>List styles:</p>- <list list-type="order"></list>- <list list-type="roman-lower"></list>+ <list list-type="order">+ <list-item><p>one</p></list-item><x>,</x>+ <list-item><p>two</p></list-item><x>,</x>+ <list-item><p>three</p></list-item>+ </list>+ <list list-type="roman-lower">+ <list-item><p>one</p></list-item><x>,</x>+ <list-item><p>two</p></list-item><x>,</x>+ <list-item><p>three</p></list-item>+ </list> </sec> <sec id="nested"> <title>Nested</title>@@ -398,7 +536,7 @@ </def-item> <def-item> <term>- Cello<break />Violoncello+ Cello<bold><break /></bold>Violoncello </term> <def> <p>Low-voiced stringed instrument.</p>@@ -406,25 +544,42 @@ </def-item> </def-list> </sec>+ <sec id="list-inside-paragraph">+ <title>List inside a paragraph</title>+ <p>+ Start of a paragraph.+ <list list-type="bullet">+ <list-item>+ <label>•</label>+ <p>Red</p>+ </list-item>+ <list-item>+ <label>•</label>+ <p>Blue</p>+ </list-item>+ </list>+ End of paragraph.+ </p>+ </sec> </sec> <sec id="inline-markup"> <title>Inline Markup</title> <p>This is <italic>emphasized</italic>, and so <italic>is this</italic>.</p>- <p>This is <bold role="strong">strong</bold>, and so- <bold role="strong">is this</bold>.</p>- <p>Empty <bold role="strong"></bold> and <italic></italic>.</p>+ <p>This is <bold>strong</bold>, and so+ <bold>is this</bold>.</p>+ <p>Empty <bold></bold> and <italic></italic>.</p> <p>An <italic><ext-link ext-link-type="uri" xlink:href="/url">emphasized link</ext-link></italic>.</p>- <p><bold role="strong"><italic>This is strong and em.</italic></bold></p>- <p>So is <bold role="strong"><italic>this</italic></bold> word.</p>- <p><bold role="strong"><italic>This is strong and em.</italic></bold></p>- <p>So is <bold role="strong"><italic>this</italic></bold> word.</p>+ <p><bold><italic>This is strong and em.</italic></bold></p>+ <p>So is <bold><italic>this</italic></bold> word.</p>+ <p><bold><italic>This is strong and em.</italic></bold></p>+ <p>So is <bold><italic>this</italic></bold> word.</p> <p>This is code: <monospace>></monospace>, <monospace>$</monospace>, <monospace>\</monospace>, <monospace>\$</monospace>, <monospace><html></monospace>.</p>- <p>This is <sc role="smallcaps">small caps</sc>.</p>+ <p>This is <sc>small caps</sc>.</p> <p>These are all underlined: foo and bar.</p> <p>These are all strikethrough: <strike>foo</strike>, <strike>bar</strike>, and <strike>baz</strike>.</p>@@ -652,7 +807,7 @@ <title>Tables</title> <sec id="tables-with-headers"> <title>Tables with Headers</title>- <table>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" />@@ -693,8 +848,8 @@ </td> </tr> </tbody>- </table>- <table>+ </table></table-wrap>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" />@@ -735,8 +890,8 @@ </td> </tr> </tbody>- </table>- <table>+ </table></table-wrap>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" />@@ -777,8 +932,8 @@ </td> </tr> </tbody>- </table>- <table>+ </table></table-wrap>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" />@@ -819,8 +974,8 @@ </td> </tr> </tbody>- </table>- <table>+ </table></table-wrap>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" />@@ -861,8 +1016,8 @@ </td> </tr> </tbody>- </table>- <table>+ </table></table-wrap>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" />@@ -903,8 +1058,8 @@ </td> </tr> </tbody>- </table>- <table>+ </table></table-wrap>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" />@@ -945,14 +1100,25 @@ </td> </tr> </tbody>- </table>- <table>+ </table></table-wrap>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" /> <thead> <tr> <th>+ <p>r1a</p>+ </th>+ <th>+ <p>r1b</p>+ </th>+ <th>+ <p>r1c</p>+ </th>+ </tr>+ <tr>+ <th> <p>X</p> </th> <th>@@ -987,8 +1153,8 @@ </td> </tr> </tbody>- </table>- <table>+ </table></table-wrap>+ <table-wrap><table> <col width="33*" align="left" /> <col width="33*" align="left" /> <col width="33*" align="left" />@@ -1029,11 +1195,11 @@ </td> </tr> </tbody>- </table>+ </table></table-wrap> </sec> <sec id="tables-without-headers"> <title>Tables without Headers</title>- <table>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" />@@ -1061,8 +1227,8 @@ </td> </tr> </tbody>- </table>- <table>+ </table></table-wrap>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" />@@ -1090,8 +1256,8 @@ </td> </tr> </tbody>- </table>- <table>+ </table></table-wrap>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" />@@ -1119,8 +1285,8 @@ </td> </tr> </tbody>- </table>- <table>+ </table></table-wrap>+ <table-wrap><table> <col align="left" /> <col align="left" /> <col align="left" />@@ -1148,8 +1314,131 @@ </td> </tr> </tbody>- </table>+ </table></table-wrap> </sec>+ <sec id="table-with-spans-and-alignments">+ <title>Tables with spans and alignments</title>+ <table-wrap><table>+ <col align="left" />+ <col align="left" />+ <col align="left" />+ <thead>+ <tr>+ <td colspan="2">+ <p>1</p>+ </td>+ <td align="right">+ <p>2</p>+ </td>+ </tr>+ </thead>+ <tbody>+ <tr>+ <td colspan="2">+ <p>1</p>+ </td>+ <td align="left">+ <p>2</p>+ </td>+ </tr>+ <tr>+ <td rowspan="2">+ <p>4</p>+ </td>+ <td>+ <p>5</p>+ </td>+ <td>+ <p>6</p>+ </td>+ </tr>+ <tr>+ <td colspan="2">+ <p>7</p>+ </td>+ </tr>+ </tbody>+ </table></table-wrap>+ </sec>+ <sec id="table-with-footer">+ <title>Table with footer</title>+ <table-wrap><table>+ <col align="left" />+ <col align="left" />+ <col align="left" />+ <tfoot>+ <tr>+ <td align="right">+ <p>f1</p>+ </td>+ <td>+ <p>f2</p>+ </td>+ <td>+ <p>f3</p>+ </td>+ </tr>+ <tr>+ <td align="right">+ <p>f4</p>+ </td>+ <td>+ <p>f5</p>+ </td>+ <td>+ <p>f6</p>+ </td>+ </tr>+ </tfoot>+ <tbody>+ <tr>+ <td>+ <p>1</p>+ </td>+ <td>+ <p>2</p>+ </td>+ <td>+ <p>3</p>+ </td>+ </tr>+ </tbody>+ </table></table-wrap>+ </sec>+ <sec id="table-with-multiple-bodies">+ <title>Table With Multiple Bodies</title>+ <table-wrap><table>+ <col align="left" />+ <col align="left" />+ <col align="left" />+ <tbody>+ <tr>+ <td align="right">+ <p>a1</p>+ </td>+ <td>+ <p>a2</p>+ </td>+ <td>+ <p>a3</p>+ </td>+ </tr>+ </tbody>+ <tbody>+ <tr>+ <td>+ <p>b1</p>+ </td>+ <td>+ <p>b2</p>+ </td>+ <td>+ <p>b3</p>+ </td>+ </tr>+ </tbody>+ </table></table-wrap>+ </sec> <sec id="empty-tables"> <title>Empty Tables</title> <p>This section should be empty.</p>@@ -1157,5 +1446,15 @@ </sec> </body> <back>+ <ref-list>+ <title>References</title>+ <ref id="ref_1"><note><p>This is reference 1</p></note></ref>+ <ref id="ref_longnote"><note><p>This is a long note</p></note></ref>+ </ref-list>+ <ref-list>+ <title>Notes</title>+ <ref id="note_1"><note><p>This is note 1</p></note></ref>+ <ref id="note_longnote"><note><p>This is another long note</p></note></ref>+ </ref-list> </back> </article>
@@ -1,232 +1,3 @@-<!DOCTYPE html>-<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">-<head>- <meta charset="utf-8" />- <meta name="generator" content="pandoc" />- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />- <title>lhs-test</title>- <style>- html {- line-height: 1.5;- font-family: Georgia, serif;- font-size: 20px;- color: #1a1a1a;- background-color: #fdfdfd;- }- body {- margin: 0 auto;- max-width: 36em;- padding-left: 50px;- padding-right: 50px;- padding-top: 50px;- padding-bottom: 50px;- hyphens: auto;- overflow-wrap: break-word;- text-rendering: optimizeLegibility;- font-kerning: normal;- }- @media (max-width: 600px) {- body {- font-size: 0.9em;- padding: 1em;- }- h1 {- font-size: 1.8em;- }- }- @media print {- body {- background-color: transparent;- color: black;- font-size: 12pt;- }- p, h2, h3 {- orphans: 3;- widows: 3;- }- h2, h3, h4 {- page-break-after: avoid;- }- }- p {- margin: 1em 0;- }- a {- color: #1a1a1a;- }- a:visited {- color: #1a1a1a;- }- img {- max-width: 100%;- }- h1, h2, h3, h4, h5, h6 {- margin-top: 1.4em;- }- h5, h6 {- font-size: 1em;- font-style: italic;- }- h6 {- font-weight: normal;- }- ol, ul {- padding-left: 1.7em;- margin-top: 1em;- }- li > ol, li > ul {- margin-top: 0;- }- blockquote {- margin: 1em 0 1em 1.7em;- padding-left: 1em;- border-left: 2px solid #e6e6e6;- color: #606060;- }- code {- font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;- font-size: 85%;- margin: 0;- }- pre {- margin: 1em 0;- overflow: auto;- }- pre code {- padding: 0;- overflow: visible;- overflow-wrap: normal;- }- .sourceCode {- background-color: transparent;- overflow: visible;- }- hr {- background-color: #1a1a1a;- border: none;- height: 1px;- margin: 1em 0;- }- table {- margin: 1em 0;- border-collapse: collapse;- width: 100%;- overflow-x: auto;- display: block;- font-variant-numeric: lining-nums tabular-nums;- }- table caption {- margin-bottom: 0.75em;- }- tbody {- margin-top: 0.5em;- border-top: 1px solid #1a1a1a;- border-bottom: 1px solid #1a1a1a;- }- th {- border-top: 1px solid #1a1a1a;- padding: 0.25em 0.5em 0.25em 0.5em;- }- td {- padding: 0.125em 0.5em 0.25em 0.5em;- }- header {- margin-bottom: 4em;- text-align: center;- }- #TOC li {- list-style: none;- }- #TOC ul {- padding-left: 1.3em;- }- #TOC > ul {- padding-left: 0;- }- #TOC a:not(:hover) {- text-decoration: none;- }- code{white-space: pre-wrap;}- span.smallcaps{font-variant: small-caps;}- div.columns{display: flex; gap: min(4vw, 1.5em);}- div.column{flex: auto; overflow-x: auto;}- div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}- ul.task-list{list-style: none;}- ul.task-list li input[type="checkbox"] {- width: 0.8em;- margin: 0 0.8em 0.2em -1.6em;- vertical-align: middle;- }- pre > code.sourceCode { white-space: pre; position: relative; }- pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }- pre > code.sourceCode > span:empty { height: 1.2em; }- .sourceCode { overflow: visible; }- code.sourceCode > span { color: inherit; text-decoration: inherit; }- div.sourceCode { margin: 1em 0; }- pre.sourceCode { margin: 0; }- @media screen {- div.sourceCode { overflow: auto; }- }- @media print {- pre > code.sourceCode { white-space: pre-wrap; }- pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }- }- pre.numberSource code- { counter-reset: source-line 0; }- pre.numberSource code > span- { position: relative; left: -4em; counter-increment: source-line; }- pre.numberSource code > span > a:first-child::before- { content: counter(source-line);- position: relative; left: -1em; text-align: right; vertical-align: baseline;- border: none; display: inline-block;- -webkit-touch-callout: none; -webkit-user-select: none;- -khtml-user-select: none; -moz-user-select: none;- -ms-user-select: none; user-select: none;- padding: 0 4px; width: 4em;- color: #aaaaaa;- }- pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }- div.sourceCode- { }- @media screen {- pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }- }- code span.al { color: #ff0000; font-weight: bold; } /* Alert */- code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */- code span.at { color: #7d9029; } /* Attribute */- code span.bn { color: #40a070; } /* BaseN */- code span.bu { color: #008000; } /* BuiltIn */- code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */- code span.ch { color: #4070a0; } /* Char */- code span.cn { color: #880000; } /* Constant */- code span.co { color: #60a0b0; font-style: italic; } /* Comment */- code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */- code span.do { color: #ba2121; font-style: italic; } /* Documentation */- code span.dt { color: #902000; } /* DataType */- code span.dv { color: #40a070; } /* DecVal */- code span.er { color: #ff0000; font-weight: bold; } /* Error */- code span.ex { } /* Extension */- code span.fl { color: #40a070; } /* Float */- code span.fu { color: #06287e; } /* Function */- code span.im { color: #008000; font-weight: bold; } /* Import */- code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */- code span.kw { color: #007020; font-weight: bold; } /* Keyword */- code span.op { color: #666666; } /* Operator */- code span.ot { color: #007020; } /* Other */- code span.pp { color: #bc7a00; } /* Preprocessor */- code span.sc { color: #4070a0; } /* SpecialChar */- code span.ss { color: #bb6688; } /* SpecialString */- code span.st { color: #4070a0; } /* String */- code span.va { color: #19177c; } /* Variable */- code span.vs { color: #4070a0; } /* VerbatimString */- code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */- .display.math{display: block; text-align: center; margin: 0.5rem auto;}- </style>- <!--[if lt IE 9]>- <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>- <![endif]-->-</head>-<body> <h1 id="lhs-test">lhs test</h1> <p><code>unsplit</code> is an arrow that takes a pair of values and combines them to return a single value:</p>@@ -241,5 +12,3 @@ <blockquote> <p>foo bar</p> </blockquote>-</body>-</html>
@@ -1,232 +1,3 @@-<!DOCTYPE html>-<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">-<head>- <meta charset="utf-8" />- <meta name="generator" content="pandoc" />- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />- <title>lhs-test</title>- <style>- html {- line-height: 1.5;- font-family: Georgia, serif;- font-size: 20px;- color: #1a1a1a;- background-color: #fdfdfd;- }- body {- margin: 0 auto;- max-width: 36em;- padding-left: 50px;- padding-right: 50px;- padding-top: 50px;- padding-bottom: 50px;- hyphens: auto;- overflow-wrap: break-word;- text-rendering: optimizeLegibility;- font-kerning: normal;- }- @media (max-width: 600px) {- body {- font-size: 0.9em;- padding: 1em;- }- h1 {- font-size: 1.8em;- }- }- @media print {- body {- background-color: transparent;- color: black;- font-size: 12pt;- }- p, h2, h3 {- orphans: 3;- widows: 3;- }- h2, h3, h4 {- page-break-after: avoid;- }- }- p {- margin: 1em 0;- }- a {- color: #1a1a1a;- }- a:visited {- color: #1a1a1a;- }- img {- max-width: 100%;- }- h1, h2, h3, h4, h5, h6 {- margin-top: 1.4em;- }- h5, h6 {- font-size: 1em;- font-style: italic;- }- h6 {- font-weight: normal;- }- ol, ul {- padding-left: 1.7em;- margin-top: 1em;- }- li > ol, li > ul {- margin-top: 0;- }- blockquote {- margin: 1em 0 1em 1.7em;- padding-left: 1em;- border-left: 2px solid #e6e6e6;- color: #606060;- }- code {- font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;- font-size: 85%;- margin: 0;- }- pre {- margin: 1em 0;- overflow: auto;- }- pre code {- padding: 0;- overflow: visible;- overflow-wrap: normal;- }- .sourceCode {- background-color: transparent;- overflow: visible;- }- hr {- background-color: #1a1a1a;- border: none;- height: 1px;- margin: 1em 0;- }- table {- margin: 1em 0;- border-collapse: collapse;- width: 100%;- overflow-x: auto;- display: block;- font-variant-numeric: lining-nums tabular-nums;- }- table caption {- margin-bottom: 0.75em;- }- tbody {- margin-top: 0.5em;- border-top: 1px solid #1a1a1a;- border-bottom: 1px solid #1a1a1a;- }- th {- border-top: 1px solid #1a1a1a;- padding: 0.25em 0.5em 0.25em 0.5em;- }- td {- padding: 0.125em 0.5em 0.25em 0.5em;- }- header {- margin-bottom: 4em;- text-align: center;- }- #TOC li {- list-style: none;- }- #TOC ul {- padding-left: 1.3em;- }- #TOC > ul {- padding-left: 0;- }- #TOC a:not(:hover) {- text-decoration: none;- }- code{white-space: pre-wrap;}- span.smallcaps{font-variant: small-caps;}- div.columns{display: flex; gap: min(4vw, 1.5em);}- div.column{flex: auto; overflow-x: auto;}- div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}- ul.task-list{list-style: none;}- ul.task-list li input[type="checkbox"] {- width: 0.8em;- margin: 0 0.8em 0.2em -1.6em;- vertical-align: middle;- }- pre > code.sourceCode { white-space: pre; position: relative; }- pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }- pre > code.sourceCode > span:empty { height: 1.2em; }- .sourceCode { overflow: visible; }- code.sourceCode > span { color: inherit; text-decoration: inherit; }- div.sourceCode { margin: 1em 0; }- pre.sourceCode { margin: 0; }- @media screen {- div.sourceCode { overflow: auto; }- }- @media print {- pre > code.sourceCode { white-space: pre-wrap; }- pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }- }- pre.numberSource code- { counter-reset: source-line 0; }- pre.numberSource code > span- { position: relative; left: -4em; counter-increment: source-line; }- pre.numberSource code > span > a:first-child::before- { content: counter(source-line);- position: relative; left: -1em; text-align: right; vertical-align: baseline;- border: none; display: inline-block;- -webkit-touch-callout: none; -webkit-user-select: none;- -khtml-user-select: none; -moz-user-select: none;- -ms-user-select: none; user-select: none;- padding: 0 4px; width: 4em;- color: #aaaaaa;- }- pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }- div.sourceCode- { }- @media screen {- pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }- }- code span.al { color: #ff0000; font-weight: bold; } /* Alert */- code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */- code span.at { color: #7d9029; } /* Attribute */- code span.bn { color: #40a070; } /* BaseN */- code span.bu { color: #008000; } /* BuiltIn */- code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */- code span.ch { color: #4070a0; } /* Char */- code span.cn { color: #880000; } /* Constant */- code span.co { color: #60a0b0; font-style: italic; } /* Comment */- code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */- code span.do { color: #ba2121; font-style: italic; } /* Documentation */- code span.dt { color: #902000; } /* DataType */- code span.dv { color: #40a070; } /* DecVal */- code span.er { color: #ff0000; font-weight: bold; } /* Error */- code span.ex { } /* Extension */- code span.fl { color: #40a070; } /* Float */- code span.fu { color: #06287e; } /* Function */- code span.im { color: #008000; font-weight: bold; } /* Import */- code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */- code span.kw { color: #007020; font-weight: bold; } /* Keyword */- code span.op { color: #666666; } /* Operator */- code span.ot { color: #007020; } /* Other */- code span.pp { color: #bc7a00; } /* Preprocessor */- code span.sc { color: #4070a0; } /* SpecialChar */- code span.ss { color: #bb6688; } /* SpecialString */- code span.st { color: #4070a0; } /* String */- code span.va { color: #19177c; } /* Variable */- code span.vs { color: #4070a0; } /* VerbatimString */- code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */- .display.math{display: block; text-align: center; margin: 0.5rem auto;}- </style>- <!--[if lt IE 9]>- <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>- <![endif]-->-</head>-<body> <h1 id="lhs-test">lhs test</h1> <p><code>unsplit</code> is an arrow that takes a pair of values and combines them to return a single value:</p>@@ -241,5 +12,3 @@ <blockquote> <p>foo bar</p> </blockquote>-</body>-</html>
@@ -1,97 +1,4 @@-% Options for packages loaded elsewhere-\PassOptionsToPackage{unicode}{hyperref}-\PassOptionsToPackage{hyphens}{url}-%-\documentclass[-]{article}-\usepackage{amsmath,amssymb}-\usepackage{lmodern}-\usepackage{iftex}-\ifPDFTeX- \usepackage[T1]{fontenc}- \usepackage[utf8]{inputenc}- \usepackage{textcomp} % provide euro and other symbols-\else % if luatex or xetex- \usepackage{unicode-math}- \defaultfontfeatures{Scale=MatchLowercase}- \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}-\fi-% Use upquote if available, for straight quotes in verbatim environments-\IfFileExists{upquote.sty}{\usepackage{upquote}}{}-\IfFileExists{microtype.sty}{% use microtype if available- \usepackage[]{microtype}- \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts-}{}-\makeatletter-\@ifundefined{KOMAClassName}{% if non-KOMA class- \IfFileExists{parskip.sty}{%- \usepackage{parskip}- }{% else- \setlength{\parindent}{0pt}- \setlength{\parskip}{6pt plus 2pt minus 1pt}}-}{% if KOMA class- \KOMAoptions{parskip=half}}-\makeatother-\usepackage{xcolor}-\usepackage{color}-\usepackage{fancyvrb}-\newcommand{\VerbBar}{|}-\newcommand{\VERB}{\Verb[commandchars=\\\{\}]}-\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}-% Add ',fontsize=\small' for more characters per line-\newenvironment{Shaded}{}{}-\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}}-\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}-\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}}-\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}-\newcommand{\BuiltInTok}[1]{\textcolor[rgb]{0.00,0.50,0.00}{#1}}-\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}-\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}}-\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}-\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}}-\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}-\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}}-\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}-\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}}-\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}}-\newcommand{\ExtensionTok}[1]{#1}-\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}-\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}}-\newcommand{\ImportTok}[1]{\textcolor[rgb]{0.00,0.50,0.00}{\textbf{#1}}}-\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}-\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}-\newcommand{\NormalTok}[1]{#1}-\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}}-\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}}-\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}}-\newcommand{\RegionMarkerTok}[1]{#1}-\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}-\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}}-\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}-\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}}-\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}-\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}-\setlength{\emergencystretch}{3em} % prevent overfull lines-\providecommand{\tightlist}{%- \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}-\setcounter{secnumdepth}{-\maxdimen} % remove section numbering-\ifLuaTeX- \usepackage{selnolig} % disable illegal ligatures-\fi-\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}}-\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available-\urlstyle{same} % disable monospaced font for URLs-\hypersetup{- hidelinks,- pdfcreator={LaTeX via pandoc}}--\author{}-\date{}--\begin{document}--\hypertarget{lhs-test}{%-\section{lhs test}\label{lhs-test}}+\section{lhs test}\label{lhs-test} \texttt{unsplit} is an arrow that takes a pair of values and combines them to return a single value:@@ -117,5 +24,3 @@ \begin{quote} foo bar \end{quote}--\end{document}
@@ -1,64 +1,4 @@-% Options for packages loaded elsewhere-\PassOptionsToPackage{unicode}{hyperref}-\PassOptionsToPackage{hyphens}{url}-%-\documentclass[-]{article}-\usepackage{amsmath,amssymb}-\usepackage{lmodern}-\usepackage{iftex}-\ifPDFTeX- \usepackage[T1]{fontenc}- \usepackage[utf8]{inputenc}- \usepackage{textcomp} % provide euro and other symbols-\else % if luatex or xetex- \usepackage{unicode-math}- \defaultfontfeatures{Scale=MatchLowercase}- \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}-\fi-% Use upquote if available, for straight quotes in verbatim environments-\IfFileExists{upquote.sty}{\usepackage{upquote}}{}-\IfFileExists{microtype.sty}{% use microtype if available- \usepackage[]{microtype}- \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts-}{}-\makeatletter-\@ifundefined{KOMAClassName}{% if non-KOMA class- \IfFileExists{parskip.sty}{%- \usepackage{parskip}- }{% else- \setlength{\parindent}{0pt}- \setlength{\parskip}{6pt plus 2pt minus 1pt}}-}{% if KOMA class- \KOMAoptions{parskip=half}}-\makeatother-\usepackage{xcolor}-\usepackage{listings}-\newcommand{\passthrough}[1]{#1}-\lstset{defaultdialect=[5.3]Lua}-\lstset{defaultdialect=[x86masm]Assembler}-\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}-\setlength{\emergencystretch}{3em} % prevent overfull lines-\providecommand{\tightlist}{%- \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}-\setcounter{secnumdepth}{-\maxdimen} % remove section numbering-\ifLuaTeX- \usepackage{selnolig} % disable illegal ligatures-\fi-\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}}-\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available-\urlstyle{same} % disable monospaced font for URLs-\hypersetup{- hidelinks,- pdfcreator={LaTeX via pandoc}}--\author{}-\date{}--\begin{document}--\hypertarget{lhs-test}{%-\section{lhs test}\label{lhs-test}}+\section{lhs test}\label{lhs-test} \texttt{unsplit} is an arrow that takes a pair of values and combines them to return a single value:@@ -82,5 +22,3 @@ \begin{quote} foo bar \end{quote}--\end{document}
@@ -1,6 +0,0 @@-function Div (div)- div.attributes.five = ("%d"):format(div.attributes.two + div.attributes.three)- div.attributes.two = nil- div.attributes.one = "eins"- return div-end
@@ -1,11 +0,0 @@-local num_blocks = 0--function Block(el)- num_blocks = num_blocks + 1-end--function Pandoc(blocks, meta)- return pandoc.Pandoc {- pandoc.Para{pandoc.Str(num_blocks)}- }-end
@@ -1,8 +0,0 @@-function Blocks (blks)- -- verify that this looks like a `pandoc.List`- if not blks.find or not blks.map or not blks.filter then- error("table doesn't seem to be an instance of pandoc.List")- end- -- return plain block containing the number of elements in the list- return {pandoc.Plain {pandoc.Str(tostring(#blks))}}-end
@@ -1,10 +0,0 @@-return {- {- Pandoc = function(doc)- local meta = {}- local hello = { pandoc.Str "Hello,", pandoc.Space(), pandoc.Str "World!" }- local blocks = { pandoc.Para(hello) }- return pandoc.Pandoc(blocks, meta)- end- }-}
@@ -1,6 +0,0 @@-function Pandoc (doc)- local meta = {}- local hello = { pandoc.Str "Hello,", pandoc.Space(), pandoc.Str "World!" }- local blocks = { pandoc.Para(hello) }- return pandoc.Pandoc(blocks, meta)-end
@@ -1,19 +0,0 @@-function isWorldAfterSpace (fst, snd)- return fst and fst.t == 'LineBreak'- and snd and snd.t == 'Str' and snd.text == 'World!'-end--function Inlines (inlns)- -- verify that this looks like a `pandoc.List`- if not inlns.find or not inlns.map or not inlns.filter then- error("table doesn't seem to be an instance of pandoc.List")- end-- -- Remove spaces before string "World"- for i = #inlns-1,1,-1 do- if isWorldAfterSpace(inlns[i], inlns[i+1]) then- inlns[i] = pandoc.Space()- end- end- return inlns-end
@@ -1,12 +0,0 @@-return {- {- RawBlock = function (elem)- if elem.format == "markdown" then- local pd = pandoc.read(elem.text, "markdown")- return pd.blocks[1]- else- return elem- end- end,- }-}
@@ -1,10 +0,0 @@-return {- {- Math = function (elem)- if elem.mathtype == "DisplayMath" then- elem.mathtype = "InlineMath"- end- return elem- end,- }-}
@@ -1,6 +0,0 @@-function Meta (meta)- meta.old = nil- meta.new = "new"- meta.bool = (meta.bool == false)- return meta-end
@@ -1,20 +0,0 @@-local num_inlines = 0--function catch_all(el)- if el.tag and pandoc.Inline.constructor[el.tag] then- num_inlines = num_inlines + 1- end-end--function Pandoc(blocks, meta)- return pandoc.Pandoc {- pandoc.Para{pandoc.Str(num_inlines)}- }-end--return {- setmetatable(- {Pandoc = Pandoc},- {__index = function(_) return catch_all end}- )-}
@@ -1,108 +0,0 @@-local tasty = require 'tasty'--local test = tasty.test_case-local group = tasty.test_group-local assert = tasty.assert---- These tests exist mainly to catch changes to the JSON representation of--- WriterOptions and its components. UPDATE THE DOCS if anything changes.-return {- group 'PANDOC_WRITER_OPTIONS' {- test('cite_method', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.cite_method), 'string')- end),- test('columns', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.columns), 'number')- end),- test('dpi', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.dpi), 'number')- end),- test('email_obfuscation', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.email_obfuscation), 'string')- end),- test('epub_chapter_level', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.epub_chapter_level), 'number')- end),- test('epub_fonts', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.epub_fonts), 'table')- end),- test('epub_metadata', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.epub_metadata), 'nil')- end),- test('epub_subdirectory', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.epub_subdirectory), 'string')- end),- test('extensions', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.extensions), 'table')- for _, v in ipairs(PANDOC_WRITER_OPTIONS.extensions) do- assert.are_equal(type(v), 'string')- end- end),- test('highlight_style', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.highlight_style), 'table')- end),- test('html_math_method', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.html_math_method), 'string')- end),- test('html_q_tags', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.html_q_tags), 'boolean')- end),- test('identifier_prefix', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.identifier_prefix), 'string')- end),- test('incremental', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.incremental), 'boolean')- end),- test('listings', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.listings), 'boolean')- end),- test('number_offset', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.number_offset), 'table')- for _, v in ipairs(PANDOC_WRITER_OPTIONS.number_offset) do- assert.are_equal(type(v), 'number')- end- end),- test('number_sections', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.number_sections), 'boolean')- end),- test('prefer_ascii', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.prefer_ascii), 'boolean')- end),- test('reference_doc', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.reference_doc), 'nil')- end),- test('reference_links', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.reference_links), 'boolean')- end),- test('reference_location', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.reference_location), 'string')- end),- test('section_divs', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.section_divs), 'boolean')- end),- test('setext_headers', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.setext_headers), 'boolean')- end),- test('slide_level', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.slide_level), 'nil')- end),- test('tab_stop', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.tab_stop), 'number')- end),- test('table_of_contents', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.table_of_contents), 'boolean')- end),- test('toc_depth', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.toc_depth), 'number')- end),- test('top_level_division', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.top_level_division), 'string')- end),- test('variables', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.variables), 'table')- end),- test('wrap_text', function ()- assert.are_equal(type(PANDOC_WRITER_OPTIONS.wrap_text), 'string')- end),- }-}
@@ -1,160 +0,0 @@-local tasty = require 'tasty'-local List = require 'pandoc.List'--local assert = tasty.assert-local test = tasty.test_case-local group = tasty.test_group--return {- group 'List as function' {- test('equivalent to List:new', function (x)- local new = List:new {'ramen'}- local list = List {'ramen'}- assert.are_same(new, list)- assert.are_equal(getmetatable(new), getmetatable(list))- end)- },-- group 'clone' {- test('changing the clone does not affect original', function ()- local orig = List:new {23, 42}- local copy = orig:clone()- copy[1] = 5- assert.are_same({23, 42}, orig)- assert.are_same({5, 42}, copy)- end),- test('result is a list', function ()- local orig = List:new {23, 42}- assert.are_equal(List, getmetatable(orig:clone()))- end),- },-- group 'extend' {- test('extends list with other list', function ()- local primes = List:new {2, 3, 5, 7}- primes:extend {11, 13, 17}- assert.are_same({2, 3, 5, 7, 11, 13, 17}, primes)- end)- },-- group 'filter' {- test('keep elements for which property is truthy', function ()- local is_small_prime = function (x)- return List.includes({2, 3, 5, 7}, x)- end- local numbers = List:new {4, 7, 2, 9, 5, 11}- assert.are_same({7, 2, 5}, numbers:filter(is_small_prime))- end),- },-- group 'find' {- test('returns element and index if found', function ()- local list = List:new {5, 23, 71}- local elem, idx = list:find(71)- assert.are_same(71, elem)- assert.are_same(3, idx)- end),- test('respects start index', function ()- local list = List:new {19, 23, 29, 71}- assert.are_equal(23, list:find(23, 1))- assert.are_equal(23, list:find(23, 2))- assert.is_nil(list:find(23, 3))- end),- test('returns nil if element not found', function ()- assert.is_nil((List:new {18, 20, 22, 0, 24}):find('0'))- end),- },-- group 'find_if' {- test('returns element and index if found', function ()- local perm_prime = List:new {2, 3, 5, 7, 11, 13, 17, 31, 37, 71}- local elem, idx = perm_prime:find_if(function (x) return x >= 10 end)- assert.are_same(11, elem)- assert.are_same(5, idx)- end),- test('returns nil if element not found', function ()- local is_null = function (n) return List.includes({23,35,46,59}, n) end- assert.is_nil((List:new {18, 20, 22, 24, 27}):find_if(is_null))- end),- },-- group 'includes' {- test('finds elements in list', function ()- local lst = List:new {'one', 'two', 'three'}- assert.is_truthy(lst:includes('one'))- assert.is_truthy(lst:includes('two'))- assert.is_truthy(lst:includes('three'))- assert.is_falsy(lst:includes('four'))- end)- },-- group 'insert' {- test('insert value at end of list.', function ()- local count_norsk = List {'en', 'to', 'tre'}- count_norsk:insert('fire')- assert.are_same({'en', 'to', 'tre', 'fire'}, count_norsk)- end),- test('insert value in the middle of list.', function ()- local count_norsk = List {'fem', 'syv'}- count_norsk:insert(2, 'seks')- assert.are_same({'fem', 'seks', 'syv'}, count_norsk)- end)- },-- group 'map' {- test('applies function to elements', function ()- local primes = List:new {2, 3, 5, 7}- local squares = primes:map(function (x) return x^2 end)- assert.are_same({4, 9, 25, 49}, squares)- end),- test('leaves original list unchanged', function ()- local primes = List:new {2, 3, 5, 7}- local squares = primes:map(function (x) return x^2 end)- assert.are_same({2, 3, 5, 7}, primes)- end)- },-- group 'new' {- test('make table usable as list', function ()- local test = List:new{1, 1, 2, 3, 5}- assert.are_same(- {1, 1, 4, 9, 25},- test:map(function (x) return x^2 end)- )- end),- test('return empty list if no argument is given', function ()- assert.are_same({}, List:new())- end),- test('metatable of result is pandoc.List', function ()- local test = List:new{5}- assert.are_equal(List, getmetatable(test))- end)- },-- group 'remove' {- test('remove value at end of list.', function ()- local understand = List {'jeg', 'forstår', 'ikke'}- local norsk_not = understand:remove()- assert.are_same({'jeg', 'forstår'}, understand)- assert.are_equal('ikke', norsk_not)- end),- test('remove value at beginning of list.', function ()- local count_norsk = List {'en', 'to', 'tre'}- count_norsk:remove(1)- assert.are_same({'to', 'tre'}, count_norsk)- end)- },-- group 'sort' {- test('sort numeric list', function ()- local numbers = List {71, 5, -1, 42, 23, 0, 1}- numbers:sort()- assert.are_same({-1, 0, 1, 5, 23, 42, 71}, numbers)- end),- test('reverse-sort numeric', function ()- local numbers = List {71, 5, -1, 42, 23, 0, 1}- numbers:sort(function (x, y) return x > y end)- assert.are_same({71, 42, 23, 5, 1, 0, -1}, numbers)- end)- },-}
@@ -1,72 +0,0 @@-local tasty = require 'tasty'--local test = tasty.test_case-local group = tasty.test_group-local assert = tasty.assert--local mediabag = require 'pandoc.mediabag'--return {- group 'insert' {- test('insert adds an item to the mediabag', function ()- local fp = "media/hello.txt"- local mt = "text/plain"- local contents = "Hello, World!"- assert.are_same(mediabag.list(), {})- mediabag.insert(fp, mt, contents)- assert.are_same(- mediabag.list(),- {{['path'] = fp, ['type'] = mt, ['length'] = 13}}- )- mediabag.empty() -- clean up- end),- test('is idempotent', function ()- local fp = "media/hello.txt"- local mt = "text/plain"- local contents = "Hello, World!"- mediabag.insert(fp, mt, contents)- mediabag.insert(fp, mt, contents)- assert.are_same(- mediabag.list(),- {{['path'] = fp, ['type'] = mt, ['length'] = 13}}- )- mediabag.empty() -- clean up- end),- },-- group 'delete' {- test('removes an item', function ()- assert.are_same(mediabag.list(), {})- mediabag.insert('test.html', 'text/html', '<aside>Who cares?</aside>')- mediabag.insert('test.css', 'text/plain', 'aside { color: red; }')- assert.are_equal(#mediabag.list(), 2)- mediabag.delete('test.html')- assert.are_same(- mediabag.list(),- {{['path'] = 'test.css', ['type'] = 'text/plain', ['length'] = 21}}- )- mediabag.empty() -- clean up- end),- },-- group 'items' {- test('iterates over all items', function ()- local input_items = {- ['test.html'] = {'text/html', '<aside>Really?</aside>'},- ['test.css'] = {'text/plain', 'aside { color: red; }'},- ['test.js'] = {'application/javascript', 'alert("HI MOM!")'}- }- -- fill mediabag- for name, v in pairs(input_items) do- mediabag.insert(name, v[1], v[2])- end-- local seen_items = {}- for fp, mt, c in mediabag.items() do- seen_items[fp] = {mt, c}- end- assert.are_same(seen_items, input_items)- mediabag.empty() -- clean up- end)- }-}
@@ -1,44 +0,0 @@-local tasty = require 'tasty'-local path = require 'pandoc.path'--local assert = tasty.assert-local test = tasty.test_case-local group = tasty.test_group--return {- group 'path separator' {- test('is string', function ()- assert.are_same(type(path.separator), 'string')- end),- test('is slash or backslash', function ()- assert.is_truthy(path.separator:match '^[/\\]$')- end),- },- group 'search path separator' {- test('is string', function ()- assert.are_same(type(path.search_path_separator), 'string')- end),- test('is colon or semicolon', function ()- assert.is_truthy(path.search_path_separator:match '^[:;]$')- end)- },- group 'module' {- test('check function existence', function ()- local functions = {- 'directory',- 'filename',- 'is_absolute',- 'is_relative',- 'join',- 'make_relative',- 'normalize',- 'split',- 'split_extension',- 'split_search_path',- }- for _, f in ipairs(functions) do- assert.are_equal(type(path[f]), 'function')- end- end)- }-}
@@ -1,65 +0,0 @@-local tasty = require 'tasty'-local template = require 'pandoc.template'--local assert = tasty.assert-local test = tasty.test_case-local group = tasty.test_group--return {- test('is table', function ()- assert.are_equal(type(template), 'table')- end),- group 'default' {- test('is function', function ()- assert.are_equal(type(template.default), 'function')- end),- test('returns a string for known format', function ()- assert.are_equal(- pandoc.utils.type(template.default 'json'),- 'string'- )- assert.are_equal(- pandoc.utils.type(template.default 'markdown'),- 'string'- )- end),- test('fails on unknown format', function ()- local success, msg = pcall(function ()- return pandoc.utils.type(template.default 'nosuchformat')- end)- assert.is_falsy(success)- end),- },- group 'compile' {- test('is function', function ()- assert.are_equal(type(template.compile), 'function')- end),- test('returns a Template', function ()- assert.are_equal(- pandoc.utils.type(template.compile('$title$')),- 'pandoc Template'- )- end),- test('returns a Template', function ()- local templ_path = pandoc.path.join{'lua', 'module', 'default.test'}- assert.are_equal(- pandoc.utils.type(template.compile('${ partial() }', templ_path)),- 'pandoc Template'- )- end),- test('fails if template has non-existing partial', function ()- assert.error_matches(- function () return template.compile('${ nosuchpartial() }') end,- 'PandocCouldNotFindDataFileError'- )- end),- test('works with default template that uses partials', function ()- local jats_template = template.default 'jats'- assert.are_equal(type(jats_template), 'string')- assert.are_equal(- pandoc.utils.type(template.compile(jats_template)),- 'pandoc Template'- )- end),- },-}
@@ -1,86 +0,0 @@-local tasty = require 'tasty'-local types = require 'pandoc.types'-local Version = types.Version--local assert = tasty.assert-local test = tasty.test_case-local group = tasty.test_group--return {- group 'Version' {-- group 'constructor' {- test('has type `userdata`', function ()- assert.are_same(type(Version {2}), 'userdata')- end),- test('accepts list of integers', function ()- assert.are_same(type(Version {2, 7, 3}), 'userdata')- end),- test('accepts a single integer', function ()- assert.are_same(Version(5), Version {5})- end),- test('accepts version as string', function ()- assert.are_same(- Version '4.45.1',- Version {4, 45, 1}- )- end),- test('non-version string is rejected', function ()- local success, msg = pcall(function () Version '11friends' end)- assert.is_falsy(success)- assert.is_truthy(tostring(msg):match('11friends'))- end)- },-- group 'comparison' {- test('smaller (equal) than', function ()- assert.is_truthy(Version {2, 58, 3} < Version {2, 58, 4})- assert.is_falsy(Version {2, 60, 1} < Version {2, 59, 2})- assert.is_truthy(Version {0, 14, 3} < Version {0, 14, 3, 1})- assert.is_truthy(Version {3, 58, 3} <= Version {4})- assert.is_truthy(Version {0, 14, 3} <= Version {0, 14, 3, 1})- end),- test('larger (equal) than', function ()- assert.is_truthy(Version{2,58,3} > Version {2, 57, 4})- assert.is_truthy(Version{2,58,3} > Version {2, 58, 2})- assert.is_truthy(Version {0, 8} >= Version {0, 8})- assert.is_falsy(Version {0, 8} >= Version {0, 8, 2})- end),- test('equality', function ()- assert.is_truthy(Version '8.8', Version {8, 8})- end),- test('second argument can be a version string', function ()- assert.is_truthy(Version '8' < '9.1')- assert.is_falsy(Version '8.8' < '8.7')- end),- },-- group 'conversion to string' {- test('converting from and to string is a noop', function ()- local version_string = '1.19.4'- assert.are_equal(tostring(Version(version_string)), version_string)- end)- },-- group 'convenience functions' {- test('throws error if version is too old', function ()- local actual = Version {2, 8}- local expected = Version {2, 9}- assert.error_matches(- function () actual:must_be_at_least(expected) end,- 'expected version 2.9 or newer, got 2.8'- )- end),- test('does nothing if expected version is older than actual', function ()- local actual = Version '2.9'- local expected = Version '2.8'- actual:must_be_at_least(expected)- end),- test('does nothing if expected version equals to actual', function ()- local actual = Version '2.8'- local expected = Version '2.8'- actual:must_be_at_least(expected)- end)- }- }-}
@@ -1,333 +0,0 @@-local tasty = require 'tasty'-local utils = require 'pandoc.utils'--local assert = tasty.assert-local test = tasty.test_case-local group = tasty.test_group--return {- group 'blocks_to_inlines' {- test('default separator', function ()- local blocks = {- pandoc.Para { pandoc.Str 'Paragraph1' },- pandoc.Para { pandoc.Emph { pandoc.Str 'Paragraph2' } }- }- local expected = {- pandoc.Str 'Paragraph1',- pandoc.Space(), pandoc.Str '¶', pandoc.Space(),- pandoc.Emph { pandoc.Str 'Paragraph2' }- }- assert.are_same(- expected,- utils.blocks_to_inlines(blocks)- )- end),- test('custom separator', function ()- local blocks = {- pandoc.Para{ pandoc.Str 'Paragraph1' },- pandoc.Para{ pandoc.Emph 'Paragraph2' }- }- local expected = {- pandoc.Str 'Paragraph1',- pandoc.LineBreak(),- pandoc.Emph { pandoc.Str 'Paragraph2' }- }- assert.are_same(- expected,- utils.blocks_to_inlines(blocks, { pandoc.LineBreak() })- )- end)- },-- group 'equals' {- test('compares Pandoc elements', function ()- assert.is_truthy(- utils.equals(pandoc.Pandoc{'foo'}, pandoc.Pandoc{'foo'})- )- end),- test('compares Block elements', function ()- assert.is_truthy(- utils.equals(pandoc.Plain{'foo'}, pandoc.Plain{'foo'})- )- assert.is_falsy(- utils.equals(pandoc.Para{'foo'}, pandoc.Plain{'foo'})- )- end),- test('compares Inline elements', function ()- assert.is_truthy(- utils.equals(pandoc.Emph{'foo'}, pandoc.Emph{'foo'})- )- assert.is_falsy(- utils.equals(pandoc.Emph{'foo'}, pandoc.Strong{'foo'})- )- end),- test('compares Inline with Block elements', function ()- assert.is_falsy(- utils.equals(pandoc.Emph{'foo'}, pandoc.Plain{'foo'})- )- assert.is_falsy(- utils.equals(pandoc.Para{'foo'}, pandoc.Strong{'foo'})- )- end),- test('compares Pandoc with Block elements', function ()- assert.is_falsy(- utils.equals(pandoc.Pandoc{'foo'}, pandoc.Plain{'foo'})- )- assert.is_falsy(- utils.equals(pandoc.Para{'foo'}, pandoc.Pandoc{'foo'})- )- end),- },-- group 'make_sections' {- test('sanity check', function ()- local blks = {- pandoc.Header(1, {pandoc.Str 'First'}),- pandoc.Header(2, {pandoc.Str 'Second'}),- pandoc.Header(2, {pandoc.Str 'Third'}),- }- local hblks = utils.make_sections(true, 1, blks)- assert.are_equal('Div', hblks[1].t)- assert.are_equal('Header', hblks[1].content[1].t)- assert.are_equal('1', hblks[1].content[1].attributes['number'])- end)- },-- group 'normalize_date' {- test('09 Nov 1989', function ()- assert.are_equal('1989-11-09', utils.normalize_date '09 Nov 1989')- end),- test('12/31/2017', function ()- assert.are_equal('2017-12-31', utils.normalize_date '12/31/2017')- end),- },-- group 'references' {- test('gets references from doc', function ()- local ref = {- ['author'] = {- {given = 'Max', family = 'Mustermann'}- },- ['container-title'] = pandoc.Inlines('JOSS'),- ['id'] = 'test',- ['issued'] = {['date-parts'] = {{2021}}},- ['title'] = pandoc.Inlines{- pandoc.Quoted('DoubleQuote', 'Interesting'),- pandoc.Space(),- 'work'- },- ['type'] = 'article-journal',- }- local nocite = pandoc.Cite(- '@test',- {pandoc.Citation('test', 'NormalCitation')}- )- local doc = pandoc.Pandoc({}, {nocite = nocite, references = {ref}})- assert.are_same({ref}, pandoc.utils.references(doc))- end)- },-- group 'sha1' {- test('hashing', function ()- local ref_hash = '0a0a9f2a6772942557ab5355d76af442f8f65e01'- assert.are_equal(ref_hash, utils.sha1 'Hello, World!')- end)- },-- group 'stringify' {- test('Inline', function ()- local inline = pandoc.Emph{- pandoc.Str 'Cogito',- pandoc.Space(),- pandoc.Str 'ergo',- pandoc.Space(),- pandoc.Str 'sum.',- }- assert.are_equal('Cogito ergo sum.', utils.stringify(inline))- end),- test('Block', function ()- local block = pandoc.Para{- pandoc.Str 'Make',- pandoc.Space(),- pandoc.Str 'it',- pandoc.Space(),- pandoc.Str 'so.',- }- assert.are_equal('Make it so.', utils.stringify(block))- end),- test('boolean', function ()- assert.are_equal('true', utils.stringify(true))- assert.are_equal('false', utils.stringify(false))- end),- test('number', function ()- assert.are_equal('5', utils.stringify(5))- assert.are_equal('23.23', utils.stringify(23.23))- end),- test('Attr', function ()- local attr = pandoc.Attr('foo', {'bar'}, {a = 'b'})- assert.are_equal('', utils.stringify(attr))- end),- test('List', function ()- local list = pandoc.List{pandoc.Str 'a', pandoc.Blocks('b')}- assert.are_equal('ab', utils.stringify(list))- end),- test('Blocks', function ()- local blocks = pandoc.Blocks{pandoc.Para 'a', pandoc.Header(1, 'b')}- assert.are_equal('ab', utils.stringify(blocks))- end),- test('Inlines', function ()- local inlines = pandoc.Inlines{pandoc.Str 'a', pandoc.Subscript('b')}- assert.are_equal('ab', utils.stringify(inlines))- end),- test('Meta', function ()- local meta = pandoc.Meta{- a = pandoc.Inlines 'funny and ',- b = 'good movie',- c = pandoc.List{pandoc.Inlines{pandoc.Str '!'}}- }- assert.are_equal('funny and good movie!', utils.stringify(meta))- end),- },-- group 'to_roman_numeral' {- test('convertes number', function ()- assert.are_equal('MDCCCLXXXVIII', utils.to_roman_numeral(1888))- end),- test('fails on non-convertible argument', function ()- assert.is_falsy(pcall(utils.to_roman_numeral, 'not a number'))- end)- },-- group 'type' {- test('nil', function ()- assert.are_equal(utils.type(nil), 'nil')- end),- test('boolean', function ()- assert.are_equal(utils.type(true), 'boolean')- assert.are_equal(utils.type(false), 'boolean')- end),- test('number', function ()- assert.are_equal(utils.type(5), 'number')- assert.are_equal(utils.type(-3.02), 'number')- end),- test('string', function ()- assert.are_equal(utils.type(''), 'string')- assert.are_equal(utils.type('asdf'), 'string')- end),- test('plain table', function ()- assert.are_equal(utils.type({}), 'table')- end),- test('List', function ()- assert.are_equal(utils.type(pandoc.List{}), 'List')- end),- test('Inline', function ()- assert.are_equal(utils.type(pandoc.Str 'a'), 'Inline')- assert.are_equal(utils.type(pandoc.Emph 'emphasized'), 'Inline')- end),- test('Inlines', function ()- assert.are_equal(utils.type(pandoc.Inlines{pandoc.Str 'a'}), 'Inlines')- assert.are_equal(utils.type(pandoc.Inlines{pandoc.Emph 'b'}), 'Inlines')- end),- test('Blocks', function ()- assert.are_equal(utils.type(pandoc.Para 'a'), 'Block')- assert.are_equal(utils.type(pandoc.CodeBlock 'true'), 'Block')- end),- test('Inlines', function ()- assert.are_equal(utils.type(pandoc.Blocks{'a'}), 'Blocks')- assert.are_equal(utils.type(pandoc.Blocks{pandoc.CodeBlock 'b'}), 'Blocks')- end),- },-- group 'to_simple_table' {- test('convertes Table', function ()- function simple_cell (blocks)- return {- attr = pandoc.Attr(),- alignment = "AlignDefault",- contents = blocks,- col_span = 1,- row_span = 1,- }- end- local tbl = pandoc.Table(- {long = {pandoc.Plain {- pandoc.Str "the", pandoc.Space(), pandoc.Str "caption"}}},- {{pandoc.AlignDefault, nil}},- pandoc.TableHead{pandoc.Row{simple_cell{pandoc.Plain "head1"}}},- {{- attr = pandoc.Attr(),- body = {pandoc.Row{simple_cell{pandoc.Plain "cell1"}}},- head = {},- row_head_columns = 0- }},- pandoc.TableFoot(),- pandoc.Attr()- )- local stbl = utils.to_simple_table(tbl)- assert.are_equal('SimpleTable', stbl.t)- assert.are_equal('head1', utils.stringify(stbl.headers[1]))- assert.are_equal('cell1', utils.stringify(stbl.rows[1][1]))- assert.are_equal('the caption', utils.stringify(pandoc.Span(stbl.caption)))- end),- test('fails on para', function ()- assert.is_falsy(pcall(utils.to_simple_table, pandoc.Para "nope"))- end),- },- group 'from_simple_table' {- test('converts SimpleTable to Table', function ()- local caption = {pandoc.Str "Overview"}- local aligns = {pandoc.AlignDefault, pandoc.AlignDefault}- local widths = {0, 0} -- let pandoc determine col widths- local headers = {- {pandoc.Plain "Language"},- {pandoc.Plain "Typing"}- }- local rows = {- {{pandoc.Plain "Haskell"}, {pandoc.Plain "static"}},- {{pandoc.Plain "Lua"}, {pandoc.Plain "Dynamic"}},- }- local simple_table = pandoc.SimpleTable(- caption,- aligns,- widths,- headers,- rows- )- local tbl = utils.from_simple_table(simple_table)- assert.are_equal("Table", tbl.t)- assert.are_same(- {pandoc.Plain(caption)},- tbl.caption.long- )- -- reversible- assert.are_same(simple_table, utils.to_simple_table(tbl))- end),- test('empty caption', function ()- local simple_table = pandoc.SimpleTable(- {},- {pandoc.AlignDefault},- {0},- {{pandoc.Plain 'a'}},- {{{pandoc.Plain 'b'}}}- )- local tbl = utils.from_simple_table(simple_table)- assert.are_equal(- pandoc.Blocks{},- tbl.caption.long- )- assert.is_nil(tbl.caption.short)- end),- test('empty body', function ()- local simple_table = pandoc.SimpleTable(- pandoc.Inlines('a nice caption'),- {pandoc.AlignDefault},- {0},- {{pandoc.Plain 'a'}},- {}- )- local tbl = utils.from_simple_table(simple_table)- tbl.bodies:map(print)- assert.are_same(pandoc.List(), tbl.bodies)- end),- }-}
@@ -1,356 +0,0 @@-local tasty = require 'tasty'--local test = tasty.test_case-local group = tasty.test_group-local assert = tasty.assert--function os_is_windows ()- return package.config:sub(1,1) == '\\'-end---- Constructor behavior is tested in the hslua-pandoc-types module, so--- we just make sure the functions are present.-return {- group 'Constructors' {- group 'Misc' {- test('pandoc.Attr is a function', function ()- assert.are_equal(type(pandoc.Attr), 'function')- end),- test('pandoc.AttributeList is a function', function ()- assert.are_equal(type(pandoc.AttributeList), 'function')- end),- test('pandoc.Blocks is a function', function ()- assert.are_equal(type(pandoc.Blocks), 'function')- end),- test('pandoc.Citation is a function', function ()- assert.are_equal(type(pandoc.Citation), 'function')- end),- test('pandoc.Inlines is a function', function ()- assert.are_equal(type(pandoc.Inlines), 'function')- end),- test('pandoc.SimpleTable is a function', function ()- assert.are_equal(type(pandoc.SimpleTable), 'function')- end),- test('pandoc.Meta is a function', function ()- assert.are_equal(type(pandoc.Meta), 'function')- end),- test('pandoc.Pandoc is a function', function ()- assert.are_equal(type(pandoc.Pandoc), 'function')- end),- },- group "Inline elements" {- test('pandoc.AttributeList is a function', function ()- assert.are_equal(type(pandoc.Cite), 'function')- end),- test('pandoc.AttributeList is a function', function ()- assert.are_equal(type(pandoc.Code), 'function')- end),- test('pandoc.Emph is a function', function ()- assert.are_equal(type(pandoc.Emph), 'function')- end),- test('pandoc.Image is a function', function ()- assert.are_equal(type(pandoc.Image), 'function')- end),- test('pandoc.Link is a function', function ()- assert.are_equal(type(pandoc.Link), 'function')- end),- test('pandoc.Math is a function', function ()- assert.are_equal(type(pandoc.Math), 'function')- end),- test('pandoc.Note is a function', function ()- assert.are_equal(type(pandoc.Note), 'function')- end),- test('pandoc.Quoted is a function', function ()- assert.are_equal(type(pandoc.Quoted), 'function')- end),- test('pandoc.SmallCaps is a function', function ()- assert.are_equal(type(pandoc.SmallCaps), 'function')- end),- test('pandoc.SoftBreak is a function', function ()- assert.are_equal(type(pandoc.SoftBreak), 'function')- end),- test('pandoc.Span is a function', function ()- assert.are_equal(type(pandoc.Span), 'function')- end),- test('pandoc.Str is a function', function ()- assert.are_equal(type(pandoc.Str), 'function')- end),- test('pandoc.Strikeout is a function', function ()- assert.are_equal(type(pandoc.Strikeout), 'function')- end),- test('pandoc.Strong is a function', function ()- assert.are_equal(type(pandoc.Strong), 'function')- end),- test('pandoc.Subscript is a function', function ()- assert.are_equal(type(pandoc.Subscript), 'function')- end),- test('pandoc.Superscript is a function', function ()- assert.are_equal(type(pandoc.Superscript), 'function')- end),- test('pandoc.Underline is a function', function ()- assert.are_equal(type(pandoc.Underline), 'function')- end),- },- group "Block elements" {- test('pandoc.BlockQuote is a function', function ()- assert.are_equal(type(pandoc.BlockQuote), 'function')- end),- test('pandoc.BulletList is a function', function ()- assert.are_equal(type(pandoc.BulletList), 'function')- end),- test('pandoc.CodeBlock is a function', function ()- assert.are_equal(type(pandoc.CodeBlock), 'function')- end),- test('pandoc.DefinitionList is a function', function ()- assert.are_equal(type(pandoc.DefinitionList), 'function')- end),- test('pandoc.Div is a function', function ()- assert.are_equal(type(pandoc.Div), 'function')- end),- test('pandoc.Header is a function', function ()- assert.are_equal(type(pandoc.Header), 'function')- end),- test('pandoc.LineBlock is a function', function ()- assert.are_equal(type(pandoc.LineBlock), 'function')- end),- test('pandoc.Null is a function', function ()- assert.are_equal(type(pandoc.Null), 'function')- end),- test('pandoc.OrderedList is a function', function ()- assert.are_equal(type(pandoc.OrderedList), 'function')- end),- test('pandoc.Para is a function', function ()- assert.are_equal(type(pandoc.Para), 'function')- end),- test('pandoc.Plain is a function', function ()- assert.are_equal(type(pandoc.Plain), 'function')- end),- test('pandoc.RawBlock is a function', function ()- assert.are_equal(type(pandoc.Plain), 'function')- end),- test('pandoc.Table is a function', function ()- assert.are_equal(type(pandoc.Table), 'function')- end),- }- },- group 'MetaValue elements' {- test('MetaList elements behave like lists', function ()- local metalist = pandoc.MetaList{}- assert.are_equal(type(metalist.insert), 'function')- assert.are_equal(type(metalist.remove), 'function')- end),- test('`tag` is an alias for `t``', function ()- assert.are_equal((pandoc.MetaList{}).tag, (pandoc.MetaList{}).t)- assert.are_equal((pandoc.MetaMap{}).tag, (pandoc.MetaMap{}).t)- assert.are_equal((pandoc.MetaInlines{}).tag, (pandoc.MetaInlines{}).t)- assert.are_equal((pandoc.MetaBlocks{}).tag, (pandoc.MetaBlocks{}).t)- end),- },- group 'Meta' {- test('inline list is treated as MetaInlines', function ()- local meta = pandoc.Pandoc({}, {test = {pandoc.Emph 'check'}}).meta- assert.are_same(meta.test, {pandoc.Emph{pandoc.Str 'check'}})- end),- test('inline element is treated as MetaInlines singleton', function ()- local meta = pandoc.Pandoc({}, {test = pandoc.Emph 'check'}).meta- assert.are_same(meta.test, {pandoc.Emph{pandoc.Str 'check'}})- end),- test('block list is treated as MetaBlocks', function ()- local meta = pandoc.Pandoc({}, {test = {pandoc.Plain 'check'}}).meta- assert.are_same(meta.test, {pandoc.Plain{pandoc.Str 'check'}})- end),- test('block element is treated as MetaBlocks singleton', function ()- local meta = pandoc.Pandoc({}, {test = pandoc.Plain 'check'}).meta- assert.are_same(meta.test, {pandoc.Plain{pandoc.Str 'check'}})- end),- },- group 'Other types' {- group 'ReaderOptions' {- test('returns a userdata value', function ()- local opts = pandoc.ReaderOptions {}- assert.are_equal(type(opts), 'userdata')- end),- test('can construct from table', function ()- local opts = pandoc.ReaderOptions {columns = 66}- assert.are_equal(opts.columns, 66)- end),- test('can construct from other ReaderOptions value', function ()- local orig = pandoc.ReaderOptions{columns = 65}- local copy = pandoc.ReaderOptions(orig)- for k, v in pairs(orig) do- assert.are_same(copy[k], v)- end- assert.are_equal(copy.columns, 65)- end),- },- },-- group 'clone' {- test('clones Attr', function ()- local attr = pandoc.Attr('test', {'my-class'}, {foo = 'bar'})- local cloned = attr:clone()- attr.identifier = ''- attr.classes = {}- attr.attributes = {}- assert.are_same(cloned.identifier, 'test')- assert.are_same(cloned.classes, {'my-class'})- assert.are_same(cloned.attributes.foo, 'bar')- end),- test('clones ListAttributes', function ()- local la = pandoc.ListAttributes(2, pandoc.DefaultStyle, pandoc.Period)- local cloned = la:clone()- la.start = 9- assert.are_same(cloned.start, 2)- end),- test('clones Para', function ()- local para = pandoc.Para {pandoc.Str 'Hello'}- local cloned = para:clone()- para.content[1].text = 'bye'- assert.are_same(cloned, pandoc.Para {pandoc.Str 'Hello'})- end),- test('clones Str', function ()- local str = pandoc.Str 'Hello'- local cloned = str:clone()- str.text = 'bye'- assert.are_same(cloned.text, 'Hello')- end),- test('clones Citation', function ()- local cite = pandoc.Citation('leibniz', pandoc.AuthorInText)- local cloned = cite:clone()- cite.id = 'newton'- assert.are_same(cloned.id, 'leibniz')- assert.are_same(cite.id, 'newton')- assert.are_same(cite.mode, cloned.mode)- end),- },-- group 'pipe' {- test('external string processing', function ()- if os_is_windows() then- local pipe_result = pandoc.pipe('find', {'hi'}, 'hi')- assert.are_equal('hi', pipe_result:match '%a+')- else- local pipe_result = pandoc.pipe('tr', {'a', 'b'}, 'abc')- assert.are_equal('bbc', pipe_result:match '%a+')- end- end),- test('failing pipe', function ()- if os_is_windows() then- local success, err = pcall(pandoc.pipe, 'find', {'/a'}, 'hi')- assert.is_falsy(success)- assert.are_equal('find', err.command)- assert.is_truthy(err.error_code ~= 0)- else- local success, err = pcall(pandoc.pipe, 'false', {}, 'abc')- assert.is_falsy(success)- assert.are_equal('false', err.command)- assert.are_equal(1, err.error_code)- assert.are_equal('', err.output)- end- end)- },-- group 'read' {- test('Markdown', function ()- local valid_markdown = '*Hello*, World!\n'- local expected = pandoc.Pandoc({- pandoc.Para {- pandoc.Emph { pandoc.Str 'Hello' },- pandoc.Str ',',- pandoc.Space(),- pandoc.Str 'World!'- }- })- assert.are_same(expected, pandoc.read(valid_markdown))- end),- test('unsupported extension', function ()- assert.error_matches(- function () pandoc.read('foo', 'gfm+empty_paragraphs') end,- 'Extension empty_paragraphs not supported for gfm'- )- end),- test('read with other indented code classes', function()- local indented_code = ' return true'- local expected = pandoc.Pandoc({- pandoc.CodeBlock('return true', {class='foo'})- })- assert.are_same(- expected,- pandoc.read(indented_code, 'markdown', {indented_code_classes={'foo'}})- )- end),- test('can read epub', function ()- local epub = io.open('lua/module/tiny.epub', 'rb')- local blocks = pandoc.read(epub:read'a', 'epub').blocks- assert.are_equal(- blocks[#blocks],- pandoc.Para { pandoc.Emph 'EPUB' }- )- end),- test('failing read', function ()- assert.error_matches(- function () pandoc.read('foo', 'nosuchreader') end,- 'Unknown reader: nosuchreader'- )- end)- },-- group 'walk_block' {- test('block walking order', function ()- local acc = {}- local nested_nums = pandoc.Div {- pandoc.Para{pandoc.Str'1'},- pandoc.Div{- pandoc.Para{pandoc.Str'2'},- pandoc.Para{pandoc.Str'3'}- },- pandoc.Para{pandoc.Str'4'}- }- pandoc.walk_block(- nested_nums,- {Para = function (p) table.insert(acc, p.content[1].text) end}- )- assert.are_equal('1234', table.concat(acc))- end)- },-- group 'walk_inline' {- test('inline walking order', function ()- local acc = {}- local nested_nums = pandoc.Span {- pandoc.Str'1',- pandoc.Emph {- pandoc.Str'2',- pandoc.Str'3'- },- pandoc.Str'4'- }- pandoc.walk_inline(- nested_nums,- {Str = function (s) table.insert(acc, s.text) end}- )- assert.are_equal('1234', table.concat(acc))- end)- },-- group 'Marshal' {- group 'Inlines' {- test('Strings are broken into words', function ()- assert.are_equal(- pandoc.Emph 'Nice, init?',- pandoc.Emph{pandoc.Str 'Nice,', pandoc.Space(), pandoc.Str 'init?'}- )- end)- },- group 'Blocks' {- test('Strings are broken into words and wrapped in Plain', function ()- assert.are_equal(- pandoc.Div{- pandoc.Plain{pandoc.Str 'Nice,', pandoc.Space(), pandoc.Str 'init?'}- },- pandoc.Div{'Nice, init?'}- )- end)- }- }-}
binary file changed (3097 → absent bytes)
@@ -1,6 +0,0 @@-return {- { Plain = function (elem)- return pandoc.Para(elem.content)- end,- }-}
@@ -1,2 +0,0 @@-package.path = package.path .. ';lua/?.lua'-require 'script-name'
@@ -1,3 +0,0 @@-function Para (_)- return pandoc.Para{pandoc.Str(PANDOC_SCRIPT_FILE)}-end
@@ -1,10 +0,0 @@-return {- {- Quoted = function (elem)- if elem.quotetype == "SingleQuote" then- elem.quotetype = "DoubleQuote"- end- return elem- end,- }-}
@@ -1,12 +0,0 @@-return {- {- Meta = function(meta)- -- The call to `MetaInlines` is redundant and used for testing purposes- -- only. The explicit use of a MetaValue constructor is only useful when- -- used with an empty table: `MetaInlines{}` is read differently than- -- `MetaBlocks{}`.- meta.title = pandoc.MetaInlines{pandoc.SmallCaps(meta.title)}- return meta- end- }-}
@@ -1,10 +0,0 @@--- Test that constructors are "smart" in that they autoconvert--- types where sensible.-function Para (_)- return {- pandoc.BulletList{pandoc.Para "Hello", pandoc.Para "World"},- pandoc.DefinitionList{{"foo", pandoc.Para "placeholder"}},- pandoc.LineBlock{"Moin", "Welt"},- pandoc.OrderedList{pandoc.Plain{pandoc.Str "one"}, pandoc.Plain "two"}- }-end
@@ -1,11 +0,0 @@-return {- {- Str = function (elem)- if elem.text == "{{helloworld}}" then- return pandoc.Emph {pandoc.Str "Hello, World"}- else- return elem- end- end,- }-}
@@ -1,3 +0,0 @@-function Div(el)- return el.content-end
@@ -1,9 +0,0 @@-local text = require 'text'--local function str_to_uppercase (s)- return pandoc.Str(text.upper(s.text))-end--function Header (el)- return pandoc.walk_block(el, {Str = str_to_uppercase})-end
@@ -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@@ -46,11 +42,11 @@ , Space , Str "*" ]- , Header 1 ( "" , [] , [] ) [ Str "Headers" ]+ , Header 1 ( "headers" , [] , [] ) [ Str "Headers" ] , Header- 1 ( "" , [] , [] ) [ Str "Level" , Space , Str "1" ]+ 1 ( "level-1" , [] , [] ) [ Str "Level" , Space , Str "1" ] , Header- 2 ( "" , [] , [] ) [ Str "Level" , Space , Str "2" ]+ 2 ( "level-2" , [] , [] ) [ Str "Level" , Space , Str "2" ] , Para [ Str "*" , Space@@ -62,7 +58,7 @@ , Space , Str "*" ]- , Header 1 ( "" , [] , [] ) [ Str "Paragraphs" ]+ , Header 1 ( "paragraphs" , [] , [] ) [ Str "Paragraphs" ] , Para [ Str "Here's" , Space@@ -163,7 +159,9 @@ , Str "*" ] , Header- 1 ( "" , [] , [] ) [ Str "Block" , Space , Str "Quotes" ]+ 1+ ( "block-quotes" , [] , [] )+ [ Str "Block" , Space , Str "Quotes" ] , Para [ Str "Code" , Space@@ -186,7 +184,9 @@ , [ Para [ Str "item" , Space , Str "two" ] ] ] , Header- 1 ( "" , [] , [] ) [ Str "Code" , Space , Str "Blocks" ]+ 1+ ( "code-blocks" , [] , [] )+ [ Str "Code" , Space , Str "Blocks" ] , Para [ Str "Code:" ] , CodeBlock ( "" , [] , [] )@@ -205,22 +205,22 @@ , Space , Str "*" ]- , Header 1 ( "" , [] , [] ) [ Str "Lists" ]- , Header 2 ( "" , [] , [] ) [ Str "Unordered" ]+ , Header 1 ( "lists" , [] , [] ) [ Str "Lists" ]+ , Header 2 ( "unordered" , [] , [] ) [ Str "Unordered" ] , Para [ Str "Asterisks:" ] , BulletList [ [ Para [ Str "asterisk" , Space , Str "1" ] ] , [ Para [ Str "asterisk" , Space , Str "2" ] ] , [ Para [ Str "asterisk" , Space , Str "3" ] ] ]- , Header 2 ( "" , [] , [] ) [ Str "Ordered" ]+ , Header 2 ( "ordered" , [] , [] ) [ Str "Ordered" ] , OrderedList ( 1 , Decimal , Period ) [ [ Para [ Str "First" ] ] , [ Para [ Str "Second" ] ] , [ Para [ Str "Third" ] ] ]- , Header 2 ( "" , [] , [] ) [ Str "Nested" ]+ , Header 2 ( "nested" , [] , [] ) [ Str "Nested" ] , BulletList [ [ Para [ Str "Tab" ] , BulletList@@ -258,7 +258,7 @@ ] , Header 2- ( "" , [] , [] )+ ( "different-styles" , [] , [] ) [ Str "different" , Space , Str "styles:" ] , OrderedList ( 1 , UpperAlpha , Period )@@ -296,7 +296,7 @@ ] ] ]- , Header 2 ( "" , [] , [] ) [ Str "Ordered" ]+ , Header 2 ( "ordered-1" , [] , [] ) [ Str "Ordered" ] , Para [ Str "Definition" , Space , Str "lists" ] , DefinitionList [ ( [ Strong [ Str "term1" ] ]@@ -327,7 +327,7 @@ ] , Header 1- ( "" , [] , [] )+ ( "special-characters" , [] , [] ) [ Str "Special" , Space , Str "Characters" ] , Para [ Str "AT&T"@@ -368,7 +368,7 @@ , Para [ Str "Bang:" , Space , Str "!" ] , Para [ Str "Plus:" , Space , Str "+" ] , Para [ Str "Minus:" , Space , Str "-" ]- , Header 1 ( "" , [] , [] ) [ Str "Links" ]+ , Header 1 ( "links" , [] , [] ) [ Str "Links" ] , Para [ Link ( "" , [] , [] )@@ -383,7 +383,7 @@ ( "mailto:me@example.com" , "" ) , Str "." ]- , Header 1 ( "" , [] , [] ) [ Str "Macros" ]+ , Header 1 ( "macros" , [] , [] ) [ Str "Macros" ] , Para [ Strong [ Str "Me" , Space , Str "Myself" ] , Space@@ -410,7 +410,7 @@ , Strong [ Str "Author" ] , Str "." ]- , Header 1 ( "" , [] , [] ) [ Str "Tables" ]+ , Header 1 ( "tables" , [] , [] ) [ Str "Tables" ] , Table ( "" , [] , [] ) (Caption Nothing [])
@@ -200,12 +200,8 @@ , Str "item" ] , BulletList- [ [ Plain- [ Str "one"- , SoftBreak- , RawInline (Format "html") "<!--\n- two\n-->"- ]- ]+ [ [ Plain [ Str "one" , SoftBreak , Str "<!\8211" ] ]+ , [ Plain [ Str "two" , SoftBreak , Str "\8211>" ] ] , [ Plain [ Str "three" ] ] ] , Header@@ -316,8 +312,8 @@ 2 ( "curly-smart-quotes" , [] , [] ) [ Str "Curly" , Space , Str "smart" , Space , Str "quotes" ]- , Para [ Quoted DoubleQuote [ Str "Hi" ] ]- , Para [ Quoted SingleQuote [ Str "Hi" ] ]+ , Para [ Str "\8220Hi\8221" ]+ , Para [ Str "\8216Hi\8217" ] , Header 2 ( "consecutive-lists" , [] , [] )@@ -357,7 +353,7 @@ , Link ( "" , [] , [] ) [ Str "My" , Space , Str "header" ]- ( "#my-header-1" , "" )+ ( "#my-header" , "" ) , Str "." ] , Para@@ -367,7 +363,7 @@ , Space , Str "to" , Space- , Link ( "" , [] , [] ) [ Str "it" ] ( "#my-header-1" , "" )+ , Link ( "" , [] , [] ) [ Str "it" ] ( "#my-header" , "" ) , Str "." ] , Para@@ -378,7 +374,7 @@ , Link ( "" , [] , [] ) [ Str "case" , Space , Str "insensitive" ]- ( "#my-header-1" , "" )+ ( "#my-header" , "" ) , Str "." ] , Para
@@ -254,93 +254,125 @@ [ Str "internal" , Space , Str "links" ] , Para [ Link- ( "" , [] , [] ) [ Str "Help" ] ( "Help" , "wikilink" )+ ( "" , [ "wikilink" ] , [] )+ [ Str "Help" ]+ ( "Help" , "Help" ) ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "the" , Space , Str "help" , Space , Str "page" ]- ( "Help" , "wikilink" )+ ( "Help" , "the help page" ) ] , Para [ Link- ( "" , [] , [] ) [ Str "Helpers" ] ( "Help" , "wikilink" )+ ( "" , [ "wikilink" ] , [] )+ [ Str "Helpers" ]+ ( "Help" , "Help" ) ] , Para [ Link- ( "" , [] , [] ) [ Str "Help" ] ( "Help" , "wikilink" )+ ( "" , [ "wikilink" ] , [] )+ [ Str "Help" ]+ ( "Help" , "Help" ) , Str "ers" ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "Contents" ]- ( "Help:Contents" , "wikilink" )+ ( "Help:Contents" , "Contents" ) ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "#My" , Space , Str "anchor" ]- ( "#My_anchor" , "wikilink" )+ ( "#My_anchor" , "#My anchor" ) ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "and" , Space , Str "text" ]- ( "Page#with_anchor" , "wikilink" )+ ( "Page#with_anchor" , "and text" ) ] , Header 2 ( "images" , [] , [] ) [ Str "images" ]- , Para- [ Image- ( "" , [] , [] )- [ Str "caption" ]- ( "example.jpg" , "fig:caption" )+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "caption" ] ])+ [ Plain+ [ Image ( "" , [] , [] ) [] ( "example.jpg" , "caption" ) ] ]- , Para- [ Image- ( "" , [] , [] )- [ Str "the"- , Space- , Emph [ Str "caption" ]- , Space- , Str "with"- , Space- , Link+ , Figure+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "the"+ , Space+ , Emph [ Str "caption" ]+ , Space+ , Str "with"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "external" , Space , Str "link" ]+ ( "http://google.com" , "" )+ ]+ ])+ [ Plain+ [ Image ( "" , [] , [] )- [ Str "external" , Space , Str "link" ]- ( "http://google.com" , "" )+ []+ ( "example.jpg" , "the caption with external link" ) ]- ( "example.jpg" , "fig:the caption with external link" ) ]- , Para- [ Image- ( "" , [] , [ ( "width" , "30" ) , ( "height" , "40" ) ] )- [ Str "caption" ]- ( "example.jpg" , "fig:caption" )+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "caption" ] ])+ [ Plain+ [ Image+ ( "" , [] , [ ( "width" , "30" ) , ( "height" , "40" ) ] )+ []+ ( "example.jpg" , "caption" )+ ] ]- , Para- [ Image- ( "" , [] , [ ( "width" , "30" ) ] )- [ Str "caption" ]- ( "example.jpg" , "fig:caption" )+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "caption" ] ])+ [ Plain+ [ Image+ ( "" , [] , [ ( "width" , "30" ) ] )+ []+ ( "example.jpg" , "caption" )+ ] ]- , Para- [ Image- ( "" , [] , [ ( "width" , "30" ) ] )- [ Str "caption" ]- ( "example.jpg" , "fig:caption" )+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "caption" ] ])+ [ Plain+ [ Image+ ( "" , [] , [ ( "width" , "30" ) ] )+ []+ ( "example.jpg" , "caption" )+ ] ]- , Para- [ Image- ( "" , [] , [] )- [ Str "example.jpg" ]- ( "example.jpg" , "fig:example.jpg" )+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "example.jpg" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] ) [] ( "example.jpg" , "example.jpg" )+ ] ]- , Para- [ Image- ( "" , [] , [] )- [ Str "example_es.jpg" ]- ( "example_es.jpg" , "fig:example_es.jpg" )+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "example_es.jpg" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] )+ []+ ( "example_es.jpg" , "example_es.jpg" )+ ] ] , Header 2 ( "lists" , [] , [] ) [ Str "lists" ] , BulletList@@ -820,24 +852,7 @@ [ ( AlignDefault , ColWidthDefault ) , ( AlignDefault , ColWidthDefault ) ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- []- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- []- ]- ])+ (TableHead ( "" , [] , [] ) []) [ TableBody ( "" , [] , [] ) (RowHeadColumns 0)@@ -1016,30 +1031,7 @@ , ( AlignDefault , ColWidthDefault ) , ( AlignDefault , ColWidthDefault ) ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- []- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- []- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- []- ]- ])+ (TableHead ( "" , [] , [] ) []) [ TableBody ( "" , [] , [] ) (RowHeadColumns 0)@@ -1122,20 +1114,20 @@ [ Row ( "" , [] , [] ) [ Cell- ( "" , [] , [] )- AlignDefault+ ( "" , [] , [ ( "width" , "50%" ) ] )+ AlignLeft (RowSpan 1) (ColSpan 1) [ Para [ Str "Left" ] ] , Cell ( "" , [] , [] )- AlignDefault+ AlignRight (RowSpan 1) (ColSpan 1) [ Para [ Str "Right" ] ] , Cell ( "" , [] , [] )- AlignDefault+ AlignCenter (RowSpan 1) (ColSpan 1) [ Para [ Str "Center" ] ]@@ -1196,24 +1188,7 @@ [ ( AlignDefault , ColWidthDefault ) , ( AlignDefault , ColWidthDefault ) ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- []- , Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- []- ]- ])+ (TableHead ( "" , [] , [] ) []) [ TableBody ( "" , [] , [] ) (RowHeadColumns 0)@@ -1321,18 +1296,7 @@ ( "" , [] , [] ) (Caption Nothing []) [ ( AlignDefault , ColWidthDefault ) ]- (TableHead- ( "" , [] , [] )- [ Row- ( "" , [] , [] )- [ Cell- ( "" , [] , [] )- AlignDefault- (RowSpan 1)- (ColSpan 1)- []- ]- ])+ (TableHead ( "" , [] , [] ) []) [ TableBody ( "" , [] , [] ) (RowHeadColumns 0)
@@ -0,0 +1,3 @@+Paragraph++> A blockquote.
@@ -1,1 +1,28 @@-[Para [Image ("",[],[("width","5.292cm"),("height","5.292cm")]) [Str "Abbildung",Space,Str "1:",Space,Str "Image",Space,Str "caption"] ("Pictures/10000000000000FA000000FAD6A15225.jpg","fig:")]]+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "Image"+ , Space+ , Str "caption"+ ]+ ])+ [ Plain+ [ Image+ ( ""+ , []+ , [ ( "width" , "5.292cm" ) , ( "height" , "5.292cm" ) ]+ )+ [ Str "Abbildung"+ , Space+ , Str "1:"+ , Space+ , Str "Image"+ , Space+ , Str "caption"+ ]+ ( "Pictures/10000000000000FA000000FAD6A15225.jpg" , "" )+ ]+ ]+]
@@ -0,0 +1,10 @@+[ Para+ [ Image+ ( ""+ , []+ , [ ( "width" , "5.292cm" ) , ( "height" , "5.292cm" ) ]+ )+ []+ ( "../../lalune.jpg" , "" )+ ]+]
@@ -1,1 +1,28 @@-[Para [Image ("",[],[("width","5.292cm"),("height","5.292cm")]) [Str "Abbildung",Space,Str "1:",Space,Str "Image",Space,Str "caption"] ("Pictures/10000000000000FA000000FAD6A15225.jpg","fig:")]]+[ Figure+ ( "" , [] , [] )+ (Caption+ Nothing+ [ Plain+ [ Str "Image"+ , Space+ , Str "caption"+ ]+ ])+ [ Plain+ [ Image+ ( ""+ , []+ , [ ( "width" , "5.292cm" ) , ( "height" , "5.292cm" ) ]+ )+ [ Str "Abbildung"+ , Space+ , Str "1:"+ , Space+ , Str "Image"+ , Space+ , Str "caption"+ ]+ ( "Pictures/10000000000000FA000000FAD6A15225.jpg" , "" )+ ]+ ]+]
@@ -0,0 +1,89 @@+[ OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain+ [ Str "Some" , Space , Str "text" , Space , Str "(1.)" ]+ ]+ ]+, Para []+, Para+ [ Str "Some"+ , Space+ , Str "text"+ , Space+ , Str "in"+ , Space+ , Str "between."+ ]+, Para []+, OrderedList+ ( 2 , Decimal , Period )+ [ [ Plain+ [ Str "Some" , Space , Str "text" , Space , Str "(2.)" ]+ ]+ , [ Plain+ [ Str "Some" , Space , Str "text" , Space , Str "(3.)" ]+ ]+ ]+, Para []+, Para+ [ Str "Some"+ , Space+ , Str "text"+ , Space+ , Str "in"+ , Space+ , Str "between."+ ]+, Para []+, OrderedList+ ( 4 , Decimal , Period )+ [ [ Plain+ [ Str "Some" , Space , Str "text" , Space , Str "(4.)" ]+ ]+ ]+, Para []+, Para+ [ Str "Some"+ , Space+ , Str "text"+ , Space+ , Str "before"+ , Space+ , Str "starting"+ , Space+ , Str "new"+ , Space+ , Str "list"+ , Space+ , Str "from"+ , Space+ , Str "1."+ ]+, Para []+, OrderedList+ ( 1 , Decimal , Period )+ [ [ Plain+ [ Str "Some" , Space , Str "text" , Space , Str "(1.)" ]+ ]+ ]+, Para []+, Para+ [ Str "Some"+ , Space+ , Str "text"+ , Space+ , Str "in"+ , Space+ , Str "between."+ ]+, Para []+, OrderedList+ ( 2 , Decimal , Period )+ [ [ Plain+ [ Str "Some" , Space , Str "text" , Space , Str "(2.)" ]+ ]+ , [ Plain+ [ Str "Some" , Space , Str "text" , Space , Str "(3.)" ]+ ]+ ]+]
@@ -0,0 +1,95 @@+[ OrderedList+ ( 1 , Decimal , Period )+ [ [ Para [ Str "Top" , Space , Str "one" ]+ , OrderedList+ ( 1 , LowerAlpha , Period )+ [[ Plain+ [ Str "Sub"+ , Space+ , Str "item"+ , Space+ , Str "1.a"+ ]+ ]+ , [ Plain+ [ Str "Sub"+ , Space+ , Str "item"+ , Space+ , Str "1.b"+ ]+ ]+ ]+ ]+ ]+, Para []+, Para+ [ Str "Some"+ , Space+ , Str "text"+ , Space+ , Str "in"+ , Space+ , Str "between."+ ]+, Para []+, OrderedList+ ( 2 , Decimal , Period )+ [ [ Para [ Str "Top" , Space , Str "two" ]+ , OrderedList+ ( 1 , LowerAlpha , Period )+ [ [ Plain+ [ Str "Sub"+ , Space+ , Str "item"+ , Space+ , Str "2.a"+ ]+ ]+ , [ Plain+ [ Str "Sub"+ , Space+ , Str "item"+ , Space+ , Str "2.b"+ ]+ ]+ ]+ ]+ ]+, Para []+, Para+ [ Str "Some"+ , Space+ , Str "text"+ , Space+ , Str "in"+ , Space+ , Str "between."+ ]+, Para []+, OrderedList+ ( 3 , Decimal , Period )+ [ [ Para [ Str "Top" , Space , Str "three" ]+ , OrderedList+ ( 1 , LowerAlpha , Period )+ [ [ Plain+ [ Str "Sub"+ , Space+ , Str "item"+ , Space+ , Str "3.a"+ ]+ ]+ , [ Plain+ [ Str "Sub"+ , Space+ , Str "item"+ , Space+ , Str "3.b"+ ]+ ]+ ]+ ]+ ]+]
@@ -0,0 +1,4 @@+[ CodeBlock+ ( "" , [] , [] )+ "void main() {\n printf(\"Hello world\");\n}"+]
@@ -0,0 +1,4 @@+[ CodeBlock+ ( "" , [] , [] )+ "void main() {\n printf(\"Hello world\");\n}"+]
@@ -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 []+]+
@@ -0,0 +1,11 @@+[ Header+ 1+ ( "test-foo" , [] , [] )+ [ Span ( "anchor" , [] , [] ) []+ , Str "Test"+ , Space+ , Code ( "" , [] , [] ) "foo"+ ]+, Para+ [ Str "Hello" , Space , Code ( "" , [] , [] ) "world" ]+]
@@ -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 []]
@@ -0,0 +1,134 @@+[ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 1)+ [ Plain+ [ Str "H1"+ , Space+ , Str "Rowspan"+ , Space+ , Str "2"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "H1-2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "H1-3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "H2-2/3" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "B1-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "B1-2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 3)+ (ColSpan 1)+ [ Plain [ Str "Rowspan" , Space , Str "3" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "B2-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "B2-2" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 2)+ [ Plain [ Str "Columnspan" , Space , Str "2" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "B4-1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 2)+ (ColSpan 2)+ [ Plain+ [ Str "Columnspan"+ , Space+ , Str "&"+ , Space+ , Str "Rowspan"+ , Space+ , Str "2"+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "B5-1" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+, Para []+]
binary file changed (absent → 9024 bytes)
binary file changed (absent → 16213 bytes)
binary file changed (absent → 12263 bytes)
binary file changed (absent → 9300 bytes)
binary file changed (absent → 7342 bytes)
binary file changed (absent → 7150 bytes)
binary file changed (absent → 10377 bytes)
binary file changed (absent → 10173 bytes)
binary file changed (absent → 6805 bytes)
binary file changed (absent → 10695 bytes)
@@ -0,0 +1,393 @@+[ Header+ 1+ ( "" , [] , [] )+ [ Str "POD" , Space , Str "TEST" , Space , Str "SUITE" ]+, Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "test"+ , Space+ , Link+ ( "" , [] , [] )+ [ Str "Pod" ]+ ( "https://perldoc.pl/perlpod" , "" )+ , Space+ , Str "document"+ , Space+ , Str "for"+ , Space+ , Str "pandoc."+ ]+, Header 2 ( "" , [] , [] ) [ Str "Head" , Space , Str "2" ]+, Header+ 3+ ( "" , [] , [] )+ [ Str "Head"+ , Space+ , Str "3:"+ , Space+ , Emph [ Str "The>" , Space , Str "<Return" ]+ ]+, Header+ 4+ ( "" , [] , [] )+ [ Str "How"+ , Space+ , Str "to"+ , Space+ , Str "use"+ , Space+ , Str "the"+ , Space+ , Link+ ( "" , [] , [ ( "manual" , "ls(1)" ) ] )+ [ Str "ls(1)" ]+ ( "" , "" )+ , Space+ , Str "command,"+ , Space+ , Str "an"+ , Space+ , Str "introduction"+ ]+, Header+ 5+ ( "" , [] , [] )+ [ Code ( "" , [] , [] ) "Ricky Jay"+ , Space+ , Str "and"+ , Space+ , Str "his"+ , Space+ , Str "52"+ , Space+ , Str "assistants"+ ]+, Header+ 6+ ( "" , [] , [] )+ [ Str "The"+ , Space+ , Str "=head5"+ , Space+ , Str "and"+ , Space+ , Str "=head6"+ , Space+ , Str "commands"+ , Space+ , Str "are"+ , Space+ , Str "newer"+ , Space+ , Str "and"+ , Space+ , Str "my"+ , Space+ , Str "syntax"+ , Space+ , Str "highlighting"+ , Space+ , Str "doesn't"+ , Space+ , Str "recognize"+ , Space+ , Str "them."+ , Space+ , Str "In"+ , Space+ , Str "any"+ , Space+ , Str "case,"+ , Space+ , Str "it"+ , Space+ , Str "should"+ , Space+ , Str "be"+ , Space+ , Str "possible"+ , Space+ , Str "to"+ , Space+ , Str "have"+ , Space+ , Str "a"+ , Space+ , Str "very"+ , Space+ , Str "long"+ , Space+ , Str "paragraph"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "heading."+ ]+, Header+ 6+ ( "" , [] , [] )+ [ Str "It"+ , Space+ , Str "should"+ , Space+ , Str "also"+ , Space+ , Str "be"+ , Space+ , Str "possible"+ , Space+ , Str "to"+ , Space+ , Str "start"+ , Space+ , Str "the"+ , Space+ , Str "heading"+ , Space+ , Str "paragraph"+ , Space+ , Str "on"+ , Space+ , Str "the"+ , Space+ , Str "next"+ , Space+ , Str "line"+ ]+, RawBlock+ (Format "html")+ "<strong>This is a raw block destined for the HTML format</strong>\n\n"+, BulletList+ [ [ Para [ Str "Bulleted" , Space , Str "list" ] ]+ , [ Para [ Str "Ordered" , Space , Str "list" ]+ , OrderedList+ ( 1 , DefaultStyle , DefaultDelim )+ [ [ Para+ [ Str "Here's"+ , Space+ , Str "a"+ , Space+ , Str "verbatim"+ , Space+ , Str "paragraph"+ , Space+ , Str "in"+ , Space+ , Str "this"+ , Space+ , Str "list"+ , Space+ , Str "item:"+ ]+ , CodeBlock+ ( "" , [] , [] )+ " this is a code block\nthis is still part of the code block\n so is this.\nIt seems that the prefixed spaces in verbatim blocks in pod don't get stripped.\n\n This should continue the previous code block despite the intervening blank\n line, because the first line starts with a space\n\n\n\n the above blank lines with varying numbers of spaces should also be in\n the code block\n pod formatters should (but not must) expand tabs by default\nso we're not special casing pandoc's behavior there in any way\n"+ , Para+ [ Str "Wow,"+ , Space+ , Str "that"+ , Space+ , Str "was"+ , Space+ , Str "fun."+ ]+ ]+ , [ Para [ Str "Definition" , Space , Str "list" ]+ , DefinitionList+ [ ( [ Span+ ( "" , [] , [] )+ [ Str "Marvin"+ , Space+ , Str "the"+ , Space+ , Str "Martian"+ ]+ ]+ , [ [ Para+ [ Str "A"+ , Space+ , Str "cartoon"+ , Space+ , Str "alien"+ ]+ ]+ ]+ )+ , ( [ Span+ ( "" , [] , [] )+ [ Emph+ [ Str "The"+ , Space+ , Str "Sun"+ , Space+ , Str "Also"+ , Space+ , Str "Rises"+ ]+ ]+ ]+ , [ [ Para+ [ Str "A"+ , Space+ , Str "novel"+ , Space+ , Str "by"+ , Space+ , Str "Ernest"+ , Space+ , Str "Hemingway"+ ]+ ]+ ]+ )+ , ( [ Span+ ( "" , [] , [] )+ [ Code ( "" , [] , [] ) "undefined" ]+ ]+ , [ [] ]+ )+ , ( [ Span+ ( "" , [] , [] )+ [ Str "And"+ , Space+ , Str "now,"+ , Space+ , Str "a"+ , Space+ , Str "quotation"+ ]+ ]+ , [ [ BlockQuote+ [ Para+ [ Str "Where's"+ , Space+ , Str "my"+ , Space+ , Str "space"+ , Space+ , Str "modulator?"+ ]+ ]+ ]+ ]+ )+ ]+ ]+ , [ Para+ [ Str "And"+ , Space+ , Str "the"+ , Space+ , Str "list"+ , Space+ , Str "continues."+ ]+ ]+ ]+ ]+ , [ Para+ [ Str "And"+ , Space+ , Str "so"+ , Space+ , Str "does"+ , Space+ , Str "the"+ , Space+ , Str "other"+ , Space+ , Str "one,"+ , Space+ , Str "even"+ , Space+ , Str "if"+ , Space+ , Str "I"+ , Space+ , Str "forget"+ , Space+ , Str "the"+ , Space+ , Str "asterisk."+ ]+ ]+ ]+, Div+ ( "" , [ "neat" ] , [] )+ [ Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "div"+ , Space+ , Str "for"+ , Space+ , Str "our"+ , Space+ , Str "purposes."+ ]+ , Para+ [ Str "It"+ , Space+ , Str "should"+ , Space+ , Str "parse"+ , Space+ , Strong [ Str "content" ]+ , Space+ , Str "inside"+ , Space+ , Str "of"+ , Space+ , Str "it."+ ]+ , BulletList+ [ [ Para [ Str "Like" , Space , Str "this" ] ] ]+ ]+, Div+ ( "" , [ "excitement" ] , [] )+ [ Para+ [ Str "this"+ , Space+ , Str "is"+ , Space+ , Str "its"+ , Space+ , Str "own"+ , Space+ , Str "div"+ ]+ ]+, RawBlock+ (Format "html") " <p>and this is its own raw block</p>\n"+, RawBlock (Format "html") "\n<p>so is this</p>\n"+, Header+ 2+ ( "" , [] , [] )+ [ Code ( "" , [] , [] ) "=cut"+ , Space+ , Str "before"+ , Space+ , Str "any"+ , Space+ , Code ( "" , [] , [] ) "=item"+ , Space+ , Str "in"+ , Space+ , Code ( "" , [] , [] ) "=over"+ ]+, BulletList+ [ [ Para [ Str "a" ] , Para [ Str "b" ] ]+ , [ Para [ Str "c" ] ]+ ]+]
@@ -0,0 +1,155 @@+text before any Pod commands is not parsed, which is unusual for formats+supported by pandoc, but ++=head1 POD TEST SUITE++This is a test L<Pod|https://perldoc.pl/perlpod> document for pandoc.++=encoding utf8++=head2 Head 2++=head3 Head 3: I<< The> <Return >>++=head4 How to use the L<ls(1)> command,+an introduction++=head5 C<Ricky Jay> and his 52 assistants++=head6 The =head5 and =head6 commands are newer and my syntax highlighting+doesn't recognize them. In any case, it should be possible to have a very long+paragraph in the heading.++=head6+It should also be possible to start the heading paragraph on the next line++=cut++This doesn't get parsed at all.++=begin html++<strong>This is a raw block destined for the HTML format</strong>++=end html++=over++=item *++Bulleted list++=item *++Ordered list++=over++=item 1.++Here's a verbatim paragraph in this list item:++ this is a code block+this is still part of the code block+ so is this.+It seems that the prefixed spaces in verbatim blocks in pod don't get stripped.++ This should continue the previous code block despite the intervening blank+ line, because the first line starts with a space+ ++ + the above blank lines with varying numbers of spaces should also be in+ the code block+ pod formatters should (but not must) expand tabs by default+so we're not special casing pandoc's behavior there in any way++Wow, that was fun.++=item 2.++Definition list++=over++=item Marvin the MZ<>artian++A cartoon alien++=item I<The Sun+Also Rises>++A novel by Ernest Hemingway++=item C<undefined>++=item And now, a quotation++=over++Where's my space modulator?++=back++=back++=item 3.++And the list continues.++=back++=item++And so does the other one, even if I forget the asterisk.++=back++=begin :neat++This is a div for our purposes.++It should parse B<< content >> inside of it.++=over++=item++Like this++=back++=end :neat++=for :excitement this is its own div++=for html <p>and this is its own raw block</p>++=for html+<p>so is this</p>++=head2 C<=cut> before any C<=item> in C<=over>++=over++=cut++blah++=item *++a++=cut++blah blah++=pod++b++=item *++c++=back
@@ -0,0 +1,149 @@+[ Header 2 ( "slide-1" , [] , [] ) [ Str "LLMs" ]+, BulletList+ [ [ Plain+ [ Str+ "Provider \61664 Available LLMs \8211 who manages? How?"+ ]+ ]+ , [ Plain+ [ Str+ "EW maintained list of \8220approved\8221 LLMs for Universal workers"+ ]+ ]+ , [ Plain+ [ Str+ "Rebuilding of UWs to the \8220Newgen\8221 thing completely"+ ]+ ]+ , [ Plain [ Str "Streaming support" ] ]+ , [ Plain [ Str "Multimodal (voice streaming) models?" ] ]+ ]+, Header+ 2+ ( "slide-2" , [] , [] )+ [ Str "Everworker venn diagram" ]+, Para [ Str "SKILLS" ]+, Para [ Str "" ]+, Para [ Str "Specialized Workers / Workflows:" ]+, Para [ Str "" ]+, Para [ Str "n8n, UI Path, " ]+, Para [ Str "other RPA" ]+, Para [ Str "BRAINS" ]+, Para [ Str "" ]+, Para [ Str "Universal Workers / AI Agents:" ]+, Para [ Str "" ]+, Para [ Str "openai , anthropic," ]+, Para [ Str "Crew AI, other " ]+, Para [ Str "\8220AI natives\8221" ]+, Para [ Str "KNOWLEDGE " ]+, Para [ Str "" ]+, Para [ Str "Data / " ]+, Para [ Str "RAG Pipelines" ]+, Para [ Str "" ]+, Para+ [ Str "Vector DBs, specialized data prep vendors, \8230" ]+, Para [ Str "glean" ]+, Para [ Str "EW" ]+, Header 2 ( "slide-3" , [] , [] ) [ Str "Table" ]+, Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Col1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Col2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Col3" ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Name" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Anton" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Antich" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Age" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "23" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "years" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+, Para+ [ Image+ ( "" , [] , [] ) [] ( "ppt/media/image1.png" , "Picture 6" )+ ]+, Header 2 ( "slide-4" , [] , [] ) [ Str "Smart Art" ]+, Div+ ( ""+ , [ "smartart" , "chevron2" ]+ , [ ( "layout" , "chevron2" ) ]+ )+ [ Para [ Strong [ Str "First" ] ]+ , BulletList+ [ [ Plain [ Str "another" ] ]+ , [ Plain [ Str "subtitle" ] ]+ ]+ , Para [ Strong [ Str "Second" ] ]+ , BulletList+ [ [ Plain [ Str "and yet again" ] ]+ , [ Plain [ Str "yet more" ] ]+ ]+ ]+]
binary file changed (absent → 111674 bytes)
binary file changed (53335 → 53336 bytes)
binary file changed (66426 → 66427 bytes)
binary file changed (44543 → 44543 bytes)
binary file changed (57662 → 57666 bytes)
binary file changed (44571 → 44572 bytes)
binary file changed (57688 → 57693 bytes)
binary file changed (44543 → 44543 bytes)
binary file changed (57662 → 57666 bytes)
binary file changed (44458 → 44459 bytes)
binary file changed (57553 → 57553 bytes)
binary file changed (41000 → 41004 bytes)
binary file changed (44300 → 44302 bytes)
binary file changed (57390 → 57391 bytes)
binary file changed (44989 → 44999 bytes)
binary file changed (58079 → 58089 bytes)
binary file changed (44241 → 44244 bytes)
binary file changed (57330 → 57332 bytes)
binary file changed (28585 → 28579 bytes)
binary file changed (41671 → 41666 bytes)
binary file changed (52727 → 52718 bytes)
binary file changed (51354 → 51344 bytes)
binary file changed (52740 → 52729 bytes)
binary file changed (52314 → 52303 bytes)
binary file changed (46208 → 46224 bytes)
binary file changed (59299 → 59315 bytes)
binary file changed (77152 → 77156 bytes)
binary file changed (90277 → 90284 bytes)
binary file changed (75402 → 75406 bytes)
binary file changed (88522 → 88529 bytes)
binary file changed (55691 → 55633 bytes)
binary file changed (66426 → 66368 bytes)
@@ -0,0 +1,3 @@+Pandoc (Meta {unMeta = fromList [("author",MetaInlines [Str "Jesse",Space,Str "Rosenthal"]),("notes",MetaBlocks [Para [Str "These",Space,Str "are",Space,Str "speaker",Space,Str "notes",Space,Str "from",Space,Str "metadata."]]),("title",MetaInlines [Str "Testing"])]})+[Header 1 ("a-header",[],[]) [Str "A",Space,Str "header"]+,Para [Str "And",Space,Str "a",Space,Str "new",Space,Str "slide."]]
binary file changed (absent → 31689 bytes)
binary file changed (absent → 44773 bytes)
binary file changed (absent → 30988 bytes)
@@ -0,0 +1,14 @@+[ Header+ 2+ ( "first-slide" , [] , [] )+ [ Str "First" , Space , Str "Slide" ]+, Para [ Str "Title" ]+, Header+ 2+ ( "second-slide" , [] , [] )+ [ Str "Second" , Space , Str "Slide" ]+, BulletList+ [ [ Plain [ Str "First" , Space , Str "item" ] ]+ , [ Plain [ Str "Second" , Space , Str "item" ] ]+ ]+]
binary file changed (absent → 28888 bytes)
@@ -0,0 +1,70 @@+[ Header+ 2+ ( "first-slide" , [] , [] )+ [ Str "First" , Space , Str "Slide" ]+, Para+ [ Str "First"+ , Space+ , Str "slide"+ , Space+ , Str "with"+ , Space+ , Str "notes"+ ]+, Div+ ( "" , [ "notes" ] , [] )+ [ Para+ [ Str "Notes"+ , Space+ , Str "for"+ , Space+ , Str "the"+ , Space+ , Str "first"+ , Space+ , Str "slide"+ ]+ ]+, Header+ 2+ ( "second-slide" , [] , [] )+ [ Str "Second" , Space , Str "Slide" ]+, Para+ [ Str "Slide"+ , Space+ , Str "without"+ , Space+ , Str "notes"+ ]+, Header+ 2+ ( "third-slide" , [] , [] )+ [ Str "Third" , Space , Str "Slide" ]+, Para+ [ Str "Slide"+ , Space+ , Str "with"+ , Space+ , Str "notes"+ , Space+ , Str "again"+ ]+, BulletList+ [ [ Plain [ Str "First" , Space , Str "item" ] ]+ , [ Plain [ Str "Second" , Space , Str "item" ] ]+ ]+, Div+ ( "" , [ "notes" ] , [] )+ [ Para+ [ Str "Notes"+ , Space+ , Str "for"+ , Space+ , Str "the"+ , Space+ , Str "third"+ , Space+ , Str "slides"+ ]+ ]+]
binary file changed (absent → 33927 bytes)
@@ -0,0 +1,22 @@+[ Header+ 1+ ( "single-column" , [] , [] )+ [ Str "Single" , Space , Str "column" ]+, Div+ ( "" , [ "columns" ] , [] )+ [ Div+ ( "" , [ "column" ] , [] )+ [ Figure+ ( "" , [] , [] )+ (Caption+ Nothing [ Plain [ Str "an" , Space , Str "image" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] )+ [ Str "an" , Space , Str "image" ]+ ( "lalune.jpg" , "" )+ ]+ ]+ ]+ ]+]
binary file changed (absent → 44216 bytes)
binary file changed (absent → 57307 bytes)
@@ -0,0 +1,13 @@+[ Header+ 1+ ( "single-column" , [] , [] )+ [ Str "Single" , Space , Str "column" ]+, Div+ ( "" , [ "columns" ] , [] )+ [ Div+ ( "" , [ "column" ] , [] )+ [ Para [ Str "One" , Space , Str "paragraph." ]+ , Para [ Str "Another" , Space , Str "paragraph." ]+ ]+ ]+]
binary file changed (absent → 27619 bytes)
binary file changed (absent → 40714 bytes)
binary file changed (44212 → 44217 bytes)
binary file changed (57302 → 57307 bytes)
binary file changed (44212 → 44217 bytes)
binary file changed (57302 → 57307 bytes)
binary file changed (31580 → 31575 bytes)
binary file changed (44666 → 44659 bytes)
binary file changed (51455 → 51466 bytes)
binary file changed (64548 → 64559 bytes)
binary file changed (29134 → 29134 bytes)
binary file changed (42228 → 42229 bytes)
binary file changed (45489 → 45496 bytes)
binary file changed (58574 → 58582 bytes)
@@ -12,7 +12,7 @@ , MetaInlines [ Str "July" , Space , Str "17," , Space , Str "2006" ] )- , ( "revision" , MetaBlocks [ Para [ Str "3" ] ] )+ , ( "revision" , MetaInlines [ Str "3" ] ) , ( "subtitle" , MetaInlines [ Str "Subtitle" ] ) , ( "title" , MetaInlines@@ -598,11 +598,11 @@ , BlockQuote [ DefinitionList [ ( [ Str "address" ]- , [ [ Para [ Str "61" , Space , Str "Main" , Space , Str "St." ] ]+ , [ [ Plain [ Str "61" , Space , Str "Main" , Space , Str "St." ] ] ] ) , ( [ Str "city" ]- , [ [ Para+ , [ [ Plain [ Emph [ Str "Nowhere" ] , Str "," , Space@@ -613,16 +613,16 @@ ] ] )- , ( [ Str "phone" ] , [ [ Para [ Str "123-4567" ] ] ] )+ , ( [ Str "phone" ] , [ [ Plain [ Str "123-4567" ] ] ] ) ] ] , DefinitionList [ ( [ Str "address" ]- , [ [ Para [ Str "61" , Space , Str "Main" , Space , Str "St." ] ]+ , [ [ Plain [ Str "61" , Space , Str "Main" , Space , Str "St." ] ] ] ) , ( [ Str "city" ]- , [ [ Para+ , [ [ Plain [ Emph [ Str "Nowhere" ] , Str "," , Space@@ -633,7 +633,7 @@ ] ] )- , ( [ Str "phone" ] , [ [ Para [ Str "123-4567" ] ] ] )+ , ( [ Str "phone" ] , [ [ Plain [ Str "123-4567" ] ] ] ) ] , Header 1 ( "html-blocks" , [] , [] ) [ Str "HTML" , Space , Str "Blocks" ]
@@ -11,13 +11,22 @@ <meta name="date" content="2006-07-15" /> <title>My S5 Document</title> <style type="text/css">- code{white-space: pre-wrap;}+ /* Default styles provided by pandoc.+ ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+ */ span.smallcaps{font-variant: small-caps;}- div.columns{display: flex; gap: min(4vw, 1.5em);}- div.column{flex: auto; overflow-x: auto;}+ div.columns{display: flex; gap: 1.5em;}+ div.column{flex: auto;}+ @media screen {+ div.columns{gap: min(4vw, 1.5em);}+ div.column{overflow-x: auto;}+ } div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}- ul.task-list{list-style: none;}+ /* The extra [class] is a hack that increases specificity enough to+ override a similar rule in reveal.js */+ ul.task-list[class]{list-style: none;} ul.task-list li input[type="checkbox"] {+ font-size: inherit; width: 0.8em; margin: 0 0.8em 0.2em -1.6em; vertical-align: middle;
@@ -11,13 +11,22 @@ <meta name="date" content="2006-07-15" /> <title>My S5 Document</title> <style type="text/css">- code{white-space: pre-wrap;}+ /* Default styles provided by pandoc.+ ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+ */ span.smallcaps{font-variant: small-caps;}- div.columns{display: flex; gap: min(4vw, 1.5em);}- div.column{flex: auto; overflow-x: auto;}+ div.columns{display: flex; gap: 1.5em;}+ div.column{flex: auto;}+ @media screen {+ div.columns{gap: min(4vw, 1.5em);}+ div.column{overflow-x: auto;}+ } div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}- ul.task-list{list-style: none;}+ /* The extra [class] is a hack that increases specificity enough to+ override a similar rule in reveal.js */+ ul.task-list[class]{list-style: none;} ul.task-list li input[type="checkbox"] {+ font-size: inherit; width: 0.8em; margin: 0 0.8em 0.2em -1.6em; vertical-align: middle;@@ -33,8 +42,8 @@ <link rel="stylesheet" href="s5/default/opera.css" type="text/css" media="projection" id="operaFix" /> <!-- S5 JS --> <script src="s5/default/slides.js" type="text/javascript"></script>- <script- src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js"+ <script defer=""+ src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-chtml.js" type="text/javascript"></script> </head> <body>
@@ -3,19 +3,28 @@ <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" />- <meta name="generator" content="pandoc" />+ <meta name="generator" content="pandoc " /> <meta name="author" content="Sam Smith" /> <meta name="author" content="Jen Jones" /> <meta name="date" content="2006-07-15" /> <title>My S5 Document</title> <style type="text/css">- code{white-space: pre-wrap;}+ /* Default styles provided by pandoc.+ ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+ */ span.smallcaps{font-variant: small-caps;}- div.columns{display: flex; gap: min(4vw, 1.5em);}- div.column{flex: auto; overflow-x: auto;}+ div.columns{display: flex; gap: 1.5em;}+ div.column{flex: auto;}+ @media screen {+ div.columns{gap: min(4vw, 1.5em);}+ div.column{overflow-x: auto;}+ } div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}- ul.task-list{list-style: none;}+ /* The extra [class] is a hack that increases specificity enough to+ override a similar rule in reveal.js */+ ul.task-list[class]{list-style: none;} ul.task-list li input[type="checkbox"] {+ font-size: inherit; width: 0.8em; margin: 0 0.8em 0.2em -1.6em; vertical-align: middle;
@@ -0,0 +1,67 @@+Simple table with caption:++.Demonstration of simple table syntax.+[cols=">,<,^,",options="header",]+|===+|Right |Left |Center |Default+|12 |12 |12 |12+|123 |123 |123 |123+|1 |1 |1 |1+|===++Simple table without caption:++[cols=">,<,^,",options="header",]+|===+|Right |Left |Center |Default+|12 |12 |12 |12+|123 |123 |123 |123+|1 |1 |1 |1+|===++Simple table indented two spaces:++.Demonstration of simple table syntax.+[cols=">,<,^,",options="header",]+|===+|Right |Left |Center |Default+|12 |12 |12 |12+|123 |123 |123 |123+|1 |1 |1 |1+|===++Multiline table with caption:++.Here’s the caption. It may span multiple lines.+[width="80%",cols="^20%,<17%,>20%,<43%",options="header",]+|===+|Centered Header |Left Aligned |Right Aligned |Default aligned+|First |row |12.0 |Example of a row that spans multiple lines.+|Second |row |5.0 |Here’s another one. Note the blank line between rows.+|===++Multiline table without caption:++[width="80%",cols="^20%,<17%,>20%,<43%",options="header",]+|===+|Centered Header |Left Aligned |Right Aligned |Default aligned+|First |row |12.0 |Example of a row that spans multiple lines.+|Second |row |5.0 |Here’s another one. Note the blank line between rows.+|===++Table without column headers:++[cols=">,<,^,>",]+|===+|12 |12 |12 |12+|123 |123 |123 |123+|1 |1 |1 |1+|===++Multiline table without column headers:++[width="80%",cols="^20%,<17%,>20%,43%",]+|===+|First |row |12.0 |Example of a row that spans multiple lines.+|Second |row |5.0 |Here’s another one. Note the blank line between rows.+|===
@@ -1,67 +0,0 @@-Simple table with caption:--.Demonstration of simple table syntax.-[cols=">,<,^,",options="header",]-|===-|Right |Left |Center |Default-|12 |12 |12 |12-|123 |123 |123 |123-|1 |1 |1 |1-|===--Simple table without caption:--[cols=">,<,^,",options="header",]-|===-|Right |Left |Center |Default-|12 |12 |12 |12-|123 |123 |123 |123-|1 |1 |1 |1-|===--Simple table indented two spaces:--.Demonstration of simple table syntax.-[cols=">,<,^,",options="header",]-|===-|Right |Left |Center |Default-|12 |12 |12 |12-|123 |123 |123 |123-|1 |1 |1 |1-|===--Multiline table with caption:--.Here’s the caption. It may span multiple lines.-[width="80%",cols="^20%,<17%,>20%,<43%",options="header",]-|===-|Centered Header |Left Aligned |Right Aligned |Default aligned-|First |row |12.0 |Example of a row that spans multiple lines.-|Second |row |5.0 |Here’s another one. Note the blank line between rows.-|===--Multiline table without caption:--[width="80%",cols="^20%,<17%,>20%,<43%",options="header",]-|===-|Centered Header |Left Aligned |Right Aligned |Default aligned-|First |row |12.0 |Example of a row that spans multiple lines.-|Second |row |5.0 |Here’s another one. Note the blank line between rows.-|===--Table without column headers:--[cols=">,<,^,>",]-|===-|12 |12 |12 |12-|123 |123 |123 |123-|1 |1 |1 |1-|===--Multiline table without column headers:--[width="80%",cols="^20%,<17%,>20%,43%",]-|===-|First |row |12.0 |Example of a row that spans multiple lines.-|Second |row |5.0 |Here’s another one. Note the blank line between rows.-|===
@@ -0,0 +1,60 @@+Simple table with caption:++Demonstration of simple table syntax.+[table]+[tr][th]Right[/th][th]Left[/th][th]Center[/th][th]Default[/th][/tr]+[tr][td]12[/td][td]12[/td][td]12[/td][td]12[/td][/tr]+[tr][td]123[/td][td]123[/td][td]123[/td][td]123[/td][/tr]+[tr][td]1[/td][td]1[/td][td]1[/td][td]1[/td][/tr]+[/table]++Simple table without caption:++[table]+[tr][th]Right[/th][th]Left[/th][th]Center[/th][th]Default[/th][/tr]+[tr][td]12[/td][td]12[/td][td]12[/td][td]12[/td][/tr]+[tr][td]123[/td][td]123[/td][td]123[/td][td]123[/td][/tr]+[tr][td]1[/td][td]1[/td][td]1[/td][td]1[/td][/tr]+[/table]++Simple table indented two spaces:++Demonstration of simple table syntax.+[table]+[tr][th]Right[/th][th]Left[/th][th]Center[/th][th]Default[/th][/tr]+[tr][td]12[/td][td]12[/td][td]12[/td][td]12[/td][/tr]+[tr][td]123[/td][td]123[/td][td]123[/td][td]123[/td][/tr]+[tr][td]1[/td][td]1[/td][td]1[/td][td]1[/td][/tr]+[/table]++Multiline table with caption:++Here's the caption. It may span multiple lines.+[table]+[tr][th]Centered Header[/th][th]Left Aligned[/th][th]Right Aligned[/th][th]Default aligned[/th][/tr]+[tr][td]First[/td][td]row[/td][td]12.0[/td][td]Example of a row that spans multiple lines.[/td][/tr]+[tr][td]Second[/td][td]row[/td][td]5.0[/td][td]Here's another one. Note the blank line between rows.[/td][/tr]+[/table]++Multiline table without caption:++[table]+[tr][th]Centered Header[/th][th]Left Aligned[/th][th]Right Aligned[/th][th]Default aligned[/th][/tr]+[tr][td]First[/td][td]row[/td][td]12.0[/td][td]Example of a row that spans multiple lines.[/td][/tr]+[tr][td]Second[/td][td]row[/td][td]5.0[/td][td]Here's another one. Note the blank line between rows.[/td][/tr]+[/table]++Table without column headers:++[table]+[tr][td]12[/td][td]12[/td][td]12[/td][td]12[/td][/tr]+[tr][td]123[/td][td]123[/td][td]123[/td][td]123[/td][/tr]+[tr][td]1[/td][td]1[/td][td]1[/td][td]1[/td][/tr]+[/table]++Multiline table without column headers:++[table]+[tr][td]First[/td][td]row[/td][td]12.0[/td][td]Example of a row that spans multiple lines.[/td][/tr]+[tr][td]Second[/td][td]row[/td][td]5.0[/td][td]Here's another one. Note the blank line between rows.[/td][/tr]+[/table]
@@ -1,200 +0,0 @@-<p>Simple table with caption:</p>--<table>-<caption>Demonstration of simple table syntax.</caption>-<tr class="header">-<th align="right">Right</th>-<th align="left">Left</th>-<th align="center">Center</th>-<th align="left">Default</th>-</tr>-<tr class="odd">-<td align="right">12</td>-<td align="left">12</td>-<td align="center">12</td>-<td align="left">12</td>-</tr>-<tr class="even">-<td align="right">123</td>-<td align="left">123</td>-<td align="center">123</td>-<td align="left">123</td>-</tr>-<tr class="odd">-<td align="right">1</td>-<td align="left">1</td>-<td align="center">1</td>-<td align="left">1</td>-</tr>-</table>--<p>Simple table without caption:</p>--<table>-<tr class="header">-<th align="right">Right</th>-<th align="left">Left</th>-<th align="center">Center</th>-<th align="left">Default</th>-</tr>-<tr class="odd">-<td align="right">12</td>-<td align="left">12</td>-<td align="center">12</td>-<td align="left">12</td>-</tr>-<tr class="even">-<td align="right">123</td>-<td align="left">123</td>-<td align="center">123</td>-<td align="left">123</td>-</tr>-<tr class="odd">-<td align="right">1</td>-<td align="left">1</td>-<td align="center">1</td>-<td align="left">1</td>-</tr>-</table>--<p>Simple table indented two spaces:</p>--<table>-<caption>Demonstration of simple table syntax.</caption>-<tr class="header">-<th align="right">Right</th>-<th align="left">Left</th>-<th align="center">Center</th>-<th align="left">Default</th>-</tr>-<tr class="odd">-<td align="right">12</td>-<td align="left">12</td>-<td align="center">12</td>-<td align="left">12</td>-</tr>-<tr class="even">-<td align="right">123</td>-<td align="left">123</td>-<td align="center">123</td>-<td align="left">123</td>-</tr>-<tr class="odd">-<td align="right">1</td>-<td align="left">1</td>-<td align="center">1</td>-<td align="left">1</td>-</tr>-</table>--<p>Multiline table with caption:</p>--<table>-<caption>Here’s the caption.-It may span multiple lines.</caption>-<col width="15%" />-<col width="14%" />-<col width="16%" />-<col width="35%" />-<tr class="header">-<th align="center">Centered-Header</th>-<th align="left">Left-Aligned</th>-<th align="right">Right-Aligned</th>-<th align="left">Default aligned</th>-</tr>-<tr class="odd">-<td align="center">First</td>-<td align="left">row</td>-<td align="right">12.0</td>-<td align="left">Example of a row that spans-multiple lines.</td>-</tr>-<tr class="even">-<td align="center">Second</td>-<td align="left">row</td>-<td align="right">5.0</td>-<td align="left">Here’s another one. Note-the blank line between rows.</td>-</tr>-</table>--<p>Multiline table without caption:</p>--<table>-<col width="15%" />-<col width="14%" />-<col width="16%" />-<col width="35%" />-<tr class="header">-<th align="center">Centered-Header</th>-<th align="left">Left-Aligned</th>-<th align="right">Right-Aligned</th>-<th align="left">Default aligned</th>-</tr>-<tr class="odd">-<td align="center">First</td>-<td align="left">row</td>-<td align="right">12.0</td>-<td align="left">Example of a row that spans-multiple lines.</td>-</tr>-<tr class="even">-<td align="center">Second</td>-<td align="left">row</td>-<td align="right">5.0</td>-<td align="left">Here’s another one. Note-the blank line between rows.</td>-</tr>-</table>--<p>Table without column headers:</p>--<table>-<tr class="odd">-<td align="right">12</td>-<td align="left">12</td>-<td align="center">12</td>-<td align="right">12</td>-</tr>-<tr class="even">-<td align="right">123</td>-<td align="left">123</td>-<td align="center">123</td>-<td align="right">123</td>-</tr>-<tr class="odd">-<td align="right">1</td>-<td align="left">1</td>-<td align="center">1</td>-<td align="right">1</td>-</tr>-</table>--<p>Multiline table without column headers:</p>--<table>-<col width="15%" />-<col width="14%" />-<col width="16%" />-<col width="35%" />-<tr class="odd">-<td align="center">First</td>-<td align="left">row</td>-<td align="right">12.0</td>-<td align="left">Example of a row that spans-multiple lines.</td>-</tr>-<tr class="even">-<td align="center">Second</td>-<td align="left">row</td>-<td align="right">5.0</td>-<td align="left">Here’s another one. Note-the blank line between rows.</td>-</tr>-</table>
@@ -0,0 +1,56 @@+Simple table with caption:++| Right | Left | Center | Default |+|------:|:-----|:------:|-------|+| 12 | 12 | 12 | 12 |+| 123 | 123 | 123 | 123 |+| 1 | 1 | 1 | 1 |++^ Demonstration of simple table syntax.++Simple table without caption:++| Right | Left | Center | Default |+|------:|:-----|:------:|-------|+| 12 | 12 | 12 | 12 |+| 123 | 123 | 123 | 123 |+| 1 | 1 | 1 | 1 |++Simple table indented two spaces:++| Right | Left | Center | Default |+|------:|:-----|:------:|-------|+| 12 | 12 | 12 | 12 |+| 123 | 123 | 123 | 123 |+| 1 | 1 | 1 | 1 |++^ Demonstration of simple table syntax.++Multiline table with caption:++| Centered Header | Left Aligned | Right Aligned | Default aligned |+|:---------------:|:-------------|--------------:|:------------------------------------------------------|+| First | row | 12.0 | Example of a row that spans multiple lines. |+| Second | row | 5.0 | Here's another one. Note the blank line between rows. |++^ Here's the caption. It may span multiple lines.++Multiline table without caption:++| Centered Header | Left Aligned | Right Aligned | Default aligned |+|:---------------:|:-------------|--------------:|:------------------------------------------------------|+| First | row | 12.0 | Example of a row that spans multiple lines. |+| Second | row | 5.0 | Here's another one. Note the blank line between rows. |++Table without column headers:++|----:|:----|:---:|----:|+| 12 | 12 | 12 | 12 |+| 123 | 123 | 123 | 123 |+| 1 | 1 | 1 | 1 |++Multiline table without column headers:++|:------:|:----|-----:|-----------------------------------------------------|+| First | row | 12.0 | Example of a row that spans multiple lines. |+| Second | row | 5.0 | Here's another one. Note the blank line between rows. |
@@ -2,9 +2,7 @@ Simple table with caption: </para> <table>- <title>- Demonstration of simple table syntax.- </title>+ <title>Demonstration of simple table syntax.</title> <tgroup cols="4"> <colspec align="right" /> <colspec align="left" />@@ -147,9 +145,7 @@ Simple table indented two spaces: </para> <table>- <title>- Demonstration of simple table syntax.- </title>+ <title>Demonstration of simple table syntax.</title> <tgroup cols="4"> <colspec align="right" /> <colspec align="left" />@@ -221,9 +217,7 @@ Multiline table with caption: </para> <table>- <title>- Here’s the caption. It may span multiple lines.- </title>+ <title>Here’s the caption. It may span multiple lines.</title> <tgroup cols="4"> <colspec colwidth="15*" align="center" /> <colspec colwidth="13*" align="left" />
@@ -2,9 +2,7 @@ Simple table with caption: </para> <table>- <title>- Demonstration of simple table syntax.- </title>+ <title>Demonstration of simple table syntax.</title> <tgroup cols="4"> <colspec align="right" /> <colspec align="left" />@@ -147,9 +145,7 @@ Simple table indented two spaces: </para> <table>- <title>- Demonstration of simple table syntax.- </title>+ <title>Demonstration of simple table syntax.</title> <tgroup cols="4"> <colspec align="right" /> <colspec align="left" />@@ -221,9 +217,7 @@ Multiline table with caption: </para> <table>- <title>- Here’s the caption. It may span multiple lines.- </title>+ <title>Here’s the caption. It may span multiple lines.</title> <tgroup cols="4"> <colspec colwidth="15*" align="center" /> <colspec colwidth="13*" align="left" />
@@ -2,7 +2,7 @@ +-------+------+--------+---------+ | Right | Left | Center | Default |-+=======+======+========+=========+++======:+:=====+:======:+=========+ | 12 | 12 | 12 | 12 | +-------+------+--------+---------+ | 123 | 123 | 123 | 123 |@@ -16,7 +16,7 @@ +-------+------+--------+---------+ | Right | Left | Center | Default |-+=======+======+========+=========+++======:+:=====+:======:+=========+ | 12 | 12 | 12 | 12 | +-------+------+--------+---------+ | 123 | 123 | 123 | 123 |@@ -28,7 +28,7 @@ +-------+------+--------+---------+ | Right | Left | Center | Default |-+=======+======+========+=========+++======:+:=====+:======:+=========+ | 12 | 12 | 12 | 12 | +-------+------+--------+---------+ | 123 | 123 | 123 | 123 |@@ -43,7 +43,7 @@ +-----------+----------+------------+---------------------------+ | Centered | Left | Right | Default aligned | | Header | Aligned | Aligned | |-+===========+==========+============+===========================+++:=========:+:=========+===========:+:==========================+ | First | row | 12.0 | Example of a row that | | | | | spans multiple lines. | +-----------+----------+------------+---------------------------+@@ -59,7 +59,7 @@ +-----------+----------+------------+---------------------------+ | Centered | Left | Right | Default aligned | | Header | Aligned | Aligned | |-+===========+==========+============+===========================+++:=========:+:=========+===========:+:==========================+ | First | row | 12.0 | Example of a row that | | | | | spans multiple lines. | +-----------+----------+------------+---------------------------+@@ -70,7 +70,7 @@ Table without column headers: -+-----+-----+-----+-----+++----:+:----+:---:+----:+ | 12 | 12 | 12 | 12 | +-----+-----+-----+-----+ | 123 | 123 | 123 | 123 |@@ -80,7 +80,7 @@ Multiline table without column headers: -+-----------+----------+------------+---------------------------+++:---------:+:---------+-----------:+---------------------------+ | First | row | 12.0 | Example of a row that | | | | | spans multiple lines. | +-----------+----------+------------+---------------------------+
@@ -2,7 +2,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -10,19 +10,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -33,7 +33,7 @@ <p>Simple table without caption:</p> <table> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -41,19 +41,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -65,7 +65,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -73,19 +73,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -103,7 +103,7 @@ <col width="35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -111,13 +111,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -134,7 +134,7 @@ <col width="35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -142,13 +142,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -159,19 +159,19 @@ <p>Table without column headers:</p> <table> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td align="right">12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td align="right">123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -188,13 +188,13 @@ <col width="35%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td>Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>
@@ -2,7 +2,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th style="text-align: right;">Right</th> <th style="text-align: left;">Left</th> <th style="text-align: center;">Center</th>@@ -10,19 +10,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -33,7 +33,7 @@ <p>Simple table without caption:</p> <table> <thead>-<tr class="header">+<tr> <th style="text-align: right;">Right</th> <th style="text-align: left;">Left</th> <th style="text-align: center;">Center</th>@@ -41,19 +41,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -65,7 +65,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th style="text-align: right;">Right</th> <th style="text-align: left;">Left</th> <th style="text-align: center;">Center</th>@@ -73,19 +73,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td>12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td>123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -103,7 +103,7 @@ <col style="width: 35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Centered Header</th> <th style="text-align: left;">Left Aligned</th> <th style="text-align: right;">Right Aligned</th>@@ -111,13 +111,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">First</td> <td style="text-align: left;">row</td> <td style="text-align: right;">12.0</td> <td style="text-align: left;">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td style="text-align: center;">Second</td> <td style="text-align: left;">row</td> <td style="text-align: right;">5.0</td>@@ -135,7 +135,7 @@ <col style="width: 35%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Centered Header</th> <th style="text-align: left;">Left Aligned</th> <th style="text-align: right;">Right Aligned</th>@@ -143,13 +143,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">First</td> <td style="text-align: left;">row</td> <td style="text-align: right;">12.0</td> <td style="text-align: left;">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td style="text-align: center;">Second</td> <td style="text-align: left;">row</td> <td style="text-align: right;">5.0</td>@@ -161,19 +161,19 @@ <p>Table without column headers:</p> <table> <tbody>-<tr class="odd">+<tr> <td style="text-align: right;">12</td> <td style="text-align: left;">12</td> <td style="text-align: center;">12</td> <td style="text-align: right;">12</td> </tr>-<tr class="even">+<tr> <td style="text-align: right;">123</td> <td style="text-align: left;">123</td> <td style="text-align: center;">123</td> <td style="text-align: right;">123</td> </tr>-<tr class="odd">+<tr> <td style="text-align: right;">1</td> <td style="text-align: left;">1</td> <td style="text-align: center;">1</td>@@ -190,13 +190,13 @@ <col style="width: 35%" /> </colgroup> <tbody>-<tr class="odd">+<tr> <td style="text-align: center;">First</td> <td style="text-align: left;">row</td> <td style="text-align: right;">12.0</td> <td>Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td style="text-align: center;">Second</td> <td style="text-align: left;">row</td> <td style="text-align: right;">5.0</td>
@@ -2,60 +2,65 @@ \begin{longtable}[]{@{}rlcl@{}} \caption{Demonstration of simple table syntax.}\tabularnewline-\toprule()+\toprule\noalign{} Right & Left & Center & Default \\-\midrule()+\midrule\noalign{} \endfirsthead-\toprule()+\toprule\noalign{} Right & Left & Center & Default \\-\midrule()+\midrule\noalign{} \endhead+\bottomrule\noalign{}+\endlastfoot 12 & 12 & 12 & 12 \\ 123 & 123 & 123 & 123 \\ 1 & 1 & 1 & 1 \\-\bottomrule() \end{longtable} Simple table without caption: +{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}rlcl@{}}-\toprule()+\toprule\noalign{} Right & Left & Center & Default \\-\midrule()+\midrule\noalign{} \endhead+\bottomrule\noalign{}+\endlastfoot 12 & 12 & 12 & 12 \\ 123 & 123 & 123 & 123 \\ 1 & 1 & 1 & 1 \\-\bottomrule() \end{longtable}+} Simple table indented two spaces: \begin{longtable}[]{@{}rlcl@{}} \caption{Demonstration of simple table syntax.}\tabularnewline-\toprule()+\toprule\noalign{} Right & Left & Center & Default \\-\midrule()+\midrule\noalign{} \endfirsthead-\toprule()+\toprule\noalign{} Right & Left & Center & Default \\-\midrule()+\midrule\noalign{} \endhead+\bottomrule\noalign{}+\endlastfoot 12 & 12 & 12 & 12 \\ 123 & 123 & 123 & 123 \\ 1 & 1 & 1 & 1 \\-\bottomrule() \end{longtable} Multiline table with caption: \begin{longtable}[]{@{}- >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1500}}- >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1375}}- >{\raggedleft\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1625}}- >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3500}}@{}}+ >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}+ >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}+ >{\raggedleft\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1625}}+ >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3500}}@{}} \caption{Here's the caption. It may span multiple lines.}\tabularnewline-\toprule()+\toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering Centered Header \end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright@@ -65,9 +70,9 @@ \end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright Default aligned \end{minipage} \\-\midrule()+\midrule\noalign{} \endfirsthead-\toprule()+\toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering Centered Header \end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright@@ -77,21 +82,23 @@ \end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright Default aligned \end{minipage} \\-\midrule()+\midrule\noalign{} \endhead+\bottomrule\noalign{}+\endlastfoot First & row & 12.0 & Example of a row that spans multiple lines. \\ Second & row & 5.0 & Here's another one. Note the blank line between rows. \\-\bottomrule() \end{longtable} Multiline table without caption: +{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}- >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1500}}- >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1375}}- >{\raggedleft\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1625}}- >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3500}}@{}}-\toprule()+ >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}+ >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}+ >{\raggedleft\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1625}}+ >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3500}}@{}}+\toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering Centered Header \end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright@@ -101,34 +108,42 @@ \end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright Default aligned \end{minipage} \\-\midrule()+\midrule\noalign{} \endhead+\bottomrule\noalign{}+\endlastfoot First & row & 12.0 & Example of a row that spans multiple lines. \\ Second & row & 5.0 & Here's another one. Note the blank line between rows. \\-\bottomrule() \end{longtable}+} Table without column headers: +{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}rlcr@{}}-\toprule()+\toprule\noalign{} \endhead+\bottomrule\noalign{}+\endlastfoot 12 & 12 & 12 & 12 \\ 123 & 123 & 123 & 123 \\ 1 & 1 & 1 & 1 \\-\bottomrule() \end{longtable}+} Multiline table without column headers: +{\def\LTcaptype{none} % do not increment counter \begin{longtable}[]{@{}- >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1500}}- >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1375}}- >{\raggedleft\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.1625}}- >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3500}}@{}}-\toprule()+ >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1500}}+ >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1375}}+ >{\raggedleft\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1625}}+ >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3500}}@{}}+\toprule\noalign{} \endhead+\bottomrule\noalign{}+\endlastfoot First & row & 12.0 & Example of a row that spans multiple lines. \\ Second & row & 5.0 & Here's another one. Note the blank line between rows. \\-\bottomrule() \end{longtable}+}
@@ -135,7 +135,7 @@ .PP Multiline table with caption: .PP-Here\[cq]s the caption. It may span multiple lines.+Here\(cqs the caption. It may span multiple lines. .TS tab(@); cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).@@ -165,7 +165,7 @@ T}@T{ 5.0 T}@T{-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE@@ -201,7 +201,7 @@ T}@T{ 5.0 T}@T{-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE@@ -261,7 +261,7 @@ T}@T{ 5.0 T}@T{-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE
@@ -28,19 +28,19 @@ Multiline table with caption: -| Centered Header | Left Aligned | Right Aligned | Default aligned |-|:---------------:|:-------------|--------------:|:------------------------------------------------------|-| First | row | 12.0 | Example of a row that spans multiple lines. |-| Second | row | 5.0 | Here’s another one. Note the blank line between rows. |+| Centered Header | Left Aligned | Right Aligned | Default aligned |+|:--:|:---|---:|:---|+| First | row | 12.0 | Example of a row that spans multiple lines. |+| Second | row | 5.0 | Here’s another one. Note the blank line between rows. | Here’s the caption. It may span multiple lines. Multiline table without caption: -| Centered Header | Left Aligned | Right Aligned | Default aligned |-|:---------------:|:-------------|--------------:|:------------------------------------------------------|-| First | row | 12.0 | Example of a row that spans multiple lines. |-| Second | row | 5.0 | Here’s another one. Note the blank line between rows. |+| Centered Header | Left Aligned | Right Aligned | Default aligned |+|:--:|:---|---:|:---|+| First | row | 12.0 | Example of a row that spans multiple lines. |+| Second | row | 5.0 | Here’s another one. Note the blank line between rows. | Table without column headers:
@@ -1,145 +1,152 @@ Simple table with caption: -{|+{| class="wikitable" |+ Demonstration of simple table syntax.-!align="right"| Right-! Left-!align="center"| Center+|-+! style="text-align: right;"| Right+! style="text-align: left;"| Left+! style="text-align: center;"| Center ! Default |--|align="right"| 12-| 12-|align="center"| 12+| style="text-align: right;"| 12+| style="text-align: left;"| 12+| style="text-align: center;"| 12 | 12 |--|align="right"| 123-| 123-|align="center"| 123+| style="text-align: right;"| 123+| style="text-align: left;"| 123+| style="text-align: center;"| 123 | 123 |--|align="right"| 1-| 1-|align="center"| 1+| style="text-align: right;"| 1+| style="text-align: left;"| 1+| style="text-align: center;"| 1 | 1 |} Simple table without caption: -{|-!align="right"| Right-! Left-!align="center"| Center+{| class="wikitable"+|-+! style="text-align: right;"| Right+! style="text-align: left;"| Left+! style="text-align: center;"| Center ! Default |--|align="right"| 12-| 12-|align="center"| 12+| style="text-align: right;"| 12+| style="text-align: left;"| 12+| style="text-align: center;"| 12 | 12 |--|align="right"| 123-| 123-|align="center"| 123+| style="text-align: right;"| 123+| style="text-align: left;"| 123+| style="text-align: center;"| 123 | 123 |--|align="right"| 1-| 1-|align="center"| 1+| style="text-align: right;"| 1+| style="text-align: left;"| 1+| style="text-align: center;"| 1 | 1 |} Simple table indented two spaces: -{|+{| class="wikitable" |+ Demonstration of simple table syntax.-!align="right"| Right-! Left-!align="center"| Center+|-+! style="text-align: right;"| Right+! style="text-align: left;"| Left+! style="text-align: center;"| Center ! Default |--|align="right"| 12-| 12-|align="center"| 12+| style="text-align: right;"| 12+| style="text-align: left;"| 12+| style="text-align: center;"| 12 | 12 |--|align="right"| 123-| 123-|align="center"| 123+| style="text-align: right;"| 123+| style="text-align: left;"| 123+| style="text-align: center;"| 123 | 123 |--|align="right"| 1-| 1-|align="center"| 1+| style="text-align: right;"| 1+| style="text-align: left;"| 1+| style="text-align: center;"| 1 | 1 |} Multiline table with caption: -{|+{| class="wikitable" |+ Here’s the caption. It may span multiple lines.-!align="center" width="15%"| Centered Header-!width="13%"| Left Aligned-!align="right" width="16%"| Right Aligned-!width="35%"| Default aligned |--|align="center"| First-| row-|align="right"| 12.0-| Example of a row that spans multiple lines.+! style="text-align: center;"| Centered Header+! style="text-align: left;"| Left Aligned+! style="text-align: right;"| Right Aligned+! style="text-align: left;"| Default aligned |--|align="center"| Second-| row-|align="right"| 5.0-| Here’s another one. Note the blank line between rows.+| style="text-align: center;"| First+| style="text-align: left;"| row+| style="text-align: right;"| 12.0+| style="text-align: left;"| Example of a row that spans multiple lines.+|-+| style="text-align: center;"| Second+| style="text-align: left;"| row+| style="text-align: right;"| 5.0+| style="text-align: left;"| Here’s another one. Note the blank line between rows. |} Multiline table without caption: -{|-!align="center" width="15%"| Centered Header-!width="13%"| Left Aligned-!align="right" width="16%"| Right Aligned-!width="35%"| Default aligned+{| class="wikitable" |--|align="center"| First-| row-|align="right"| 12.0-| Example of a row that spans multiple lines.+! style="text-align: center;"| Centered Header+! style="text-align: left;"| Left Aligned+! style="text-align: right;"| Right Aligned+! style="text-align: left;"| Default aligned |--|align="center"| Second-| row-|align="right"| 5.0-| Here’s another one. Note the blank line between rows.+| style="text-align: center;"| First+| style="text-align: left;"| row+| style="text-align: right;"| 12.0+| style="text-align: left;"| Example of a row that spans multiple lines.+|-+| style="text-align: center;"| Second+| style="text-align: left;"| row+| style="text-align: right;"| 5.0+| style="text-align: left;"| Here’s another one. Note the blank line between rows. |} Table without column headers: -{|-|align="right"| 12-| 12-|align="center"| 12-|align="right"| 12+{| class="wikitable" |--|align="right"| 123-| 123-|align="center"| 123-|align="right"| 123+| style="text-align: right;"| 12+| style="text-align: left;"| 12+| style="text-align: center;"| 12+| style="text-align: right;"| 12 |--|align="right"| 1-| 1-|align="center"| 1-|align="right"| 1+| style="text-align: right;"| 123+| style="text-align: left;"| 123+| style="text-align: center;"| 123+| style="text-align: right;"| 123+|-+| style="text-align: right;"| 1+| style="text-align: left;"| 1+| style="text-align: center;"| 1+| style="text-align: right;"| 1 |} Multiline table without column headers: -{|-|align="center" width="15%"| First-|width="13%"| row-|align="right" width="16%"| 12.0-|width="35%"| Example of a row that spans multiple lines.+{| class="wikitable" |--|align="center"| Second-| row-|align="right"| 5.0+| style="text-align: center;"| First+| style="text-align: left;"| row+| style="text-align: right;"| 12.0+| Example of a row that spans multiple lines.+|-+| style="text-align: center;"| Second+| style="text-align: left;"| row+| style="text-align: right;"| 5.0 | Here’s another one. Note the blank line between rows. |}
@@ -141,7 +141,7 @@ .LP Multiline table with caption: .PP-Here\[cq]s the caption. It may span multiple lines.+Here\(cqs the caption. It may span multiple lines. .na .nr LLold \n[LL] .TS@@ -181,7 +181,7 @@ 5.0 T} T{ .nr LL 24.5n-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE@@ -229,7 +229,7 @@ 5.0 T} T{ .nr LL 24.5n-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE@@ -303,7 +303,7 @@ 5.0 T} T{ .nr LL 24.5n-Here\[cq]s another one.+Here\(cqs another one. Note the blank line between rows. T} .TE
@@ -23,6 +23,9 @@ Multiline table with caption: ++:---------:+:---------+-----------:+:--------------------------++| Centered | Left | Right | Default aligned |+| Header | Aligned | Aligned | | +-----------+----------+------------+---------------------------+ | First | row | 12.0 | Example of a row that | | | | | spans multiple lines. |@@ -33,6 +36,9 @@ +-----------+----------+------------+---------------------------+ Multiline table without caption: ++:---------:+:---------+-----------:+:--------------------------++| Centered | Left | Right | Default aligned |+| Header | Aligned | Aligned | | +-----------+----------+------------+---------------------------+ | First | row | 12.0 | Example of a row that | | | | | spans multiple lines. |@@ -49,7 +55,7 @@ Multiline table without column headers: -+-----------+----------+------------+---------------------------+++:---------:+:---------+-----------:+---------------------------+ | First | row | 12.0 | Example of a row that | | | | | spans multiple lines. | +-----------+----------+------------+---------------------------+
@@ -3,7 +3,7 @@ Simple table with caption: -@float+@float Table @multitable {Right} {Left} {Center} {Default} @headitem Right@@ -55,7 +55,7 @@ Simple table indented two spaces: -@float+@float Table @multitable {Right} {Left} {Center} {Default} @headitem Right@@ -82,7 +82,7 @@ @end float Multiline table with caption: -@float+@float Table @multitable @columnfractions 0.15 0.14 0.16 0.35 @headitem Centered Header
@@ -3,7 +3,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -11,19 +11,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td align="left">12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td align="left">123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -44,7 +44,7 @@ <table> <caption>Demonstration of simple table syntax.</caption> <thead>-<tr class="header">+<tr> <th align="right">Right</th> <th align="left">Left</th> <th align="center">Center</th>@@ -52,19 +52,19 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="right">12</td> <td align="left">12</td> <td align="center">12</td> <td align="left">12</td> </tr>-<tr class="even">+<tr> <td align="right">123</td> <td align="left">123</td> <td align="center">123</td> <td align="left">123</td> </tr>-<tr class="odd">+<tr> <td align="right">1</td> <td align="left">1</td> <td align="center">1</td>@@ -82,7 +82,7 @@ <col width="16%" /> <col width="35%" /> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -90,13 +90,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -113,7 +113,7 @@ <col width="16%" /> <col width="35%" /> <thead>-<tr class="header">+<tr> <th align="center">Centered Header</th> <th align="left">Left Aligned</th> <th align="right">Right Aligned</th>@@ -121,13 +121,13 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>@@ -150,13 +150,13 @@ <col width="16%" /> <col width="35%" /> <tbody>-<tr class="odd">+<tr> <td align="center">First</td> <td align="left">row</td> <td align="right">12.0</td> <td align="left">Example of a row that spans multiple lines.</td> </tr>-<tr class="even">+<tr> <td align="center">Second</td> <td align="left">row</td> <td align="right">5.0</td>
@@ -0,0 +1,105 @@+Simple table with caption:++#figure(+ align(center)[#table(+ columns: 4,+ align: (right,left,center,auto,),+ table.header([Right], [Left], [Center], [Default],),+ table.hline(),+ [12], [12], [12], [12],+ [123], [123], [123], [123],+ [1], [1], [1], [1],+ )]+ , caption: [Demonstration of simple table syntax.]+ , kind: table+ )++Simple table without caption:++#figure(+ align(center)[#table(+ columns: 4,+ align: (right,left,center,auto,),+ table.header([Right], [Left], [Center], [Default],),+ table.hline(),+ [12], [12], [12], [12],+ [123], [123], [123], [123],+ [1], [1], [1], [1],+ )]+ , kind: table+ )++Simple table indented two spaces:++#figure(+ align(center)[#table(+ columns: 4,+ align: (right,left,center,auto,),+ table.header([Right], [Left], [Center], [Default],),+ table.hline(),+ [12], [12], [12], [12],+ [123], [123], [123], [123],+ [1], [1], [1], [1],+ )]+ , caption: [Demonstration of simple table syntax.]+ , kind: table+ )++Multiline table with caption:++#figure(+ align(center)[#table(+ columns: (15%, 13.75%, 16.25%, 35%),+ align: (center,left,right,left,),+ table.header([Centered Header], [Left Aligned], [Right Aligned], [Default+ aligned],),+ table.hline(),+ [First], [row], [12.0], [Example of a row that spans multiple lines.],+ [Second], [row], [5.0], [Here's another one. Note the blank line between+ rows.],+ )]+ , caption: [Here's the caption. It may span multiple lines.]+ , kind: table+ )++Multiline table without caption:++#figure(+ align(center)[#table(+ columns: (15%, 13.75%, 16.25%, 35%),+ align: (center,left,right,left,),+ table.header([Centered Header], [Left Aligned], [Right Aligned], [Default+ aligned],),+ table.hline(),+ [First], [row], [12.0], [Example of a row that spans multiple lines.],+ [Second], [row], [5.0], [Here's another one. Note the blank line between+ rows.],+ )]+ , kind: table+ )++Table without column headers:++#figure(+ align(center)[#table(+ columns: 4,+ align: (right,left,center,right,),+ [12], [12], [12], [12],+ [123], [123], [123], [123],+ [1], [1], [1], [1],+ )]+ , kind: table+ )++Multiline table without column headers:++#figure(+ align(center)[#table(+ columns: (15%, 13.75%, 16.25%, 35%),+ align: (center,left,right,auto,),+ [First], [row], [12.0], [Example of a row that spans multiple lines.],+ [Second], [row], [5.0], [Here's another one. Note the blank line between+ rows.],+ )]+ , kind: table+ )
@@ -0,0 +1,65 @@+Simple table with caption:++ Right Left Center Default ~+ 12 12 12 12+ 123 123 123 123+ 1 1 1 1++ Demonstration of simple table syntax.++Simple table without caption:++ Right Left Center Default ~+ 12 12 12 12+ 123 123 123 123+ 1 1 1 1++Simple table indented two spaces:++ Right Left Center Default ~+ 12 12 12 12+ 123 123 123 123+ 1 1 1 1++ Demonstration of simple table syntax.++Multiline table with caption:++ Centered Left Right Default aligned+ Header Aligned Aligned ~++ First row 12.0 Example of a row that+ spans multiple lines.++ Second row 5.0 Here's another one.+ Note the blank line+ between rows.++ Here's the caption. It may span multiple lines.++Multiline table without caption:++ Centered Left Right Default aligned+ Header Aligned Aligned ~++ First row 12.0 Example of a row that+ spans multiple lines.++ Second row 5.0 Here's another one.+ Note the blank line+ between rows.++Table without column headers:++ 12 12 12 12+ 123 123 123 123+ 1 1 1 1++Multiline table without column headers:++ First row 12.0 Example of a row that+ spans multiple lines.++ Second row 5.0 Here's another one.+ Note the blank line+ between rows.
@@ -7,7 +7,7 @@ <col width="20%" /> </colgroup> <thead class="simple-head">-<tr class="header">+<tr> <th align="center">Name</th> <th align="center">Capital</th> <th align="center">Population<br />@@ -17,38 +17,38 @@ </tr> </thead> <tbody class="souvereign-states">-<tr class="odd country">+<tr class="country"> <th align="center">Denmark</th> <td align="left">Copenhagen</td> <td align="left">5,809,502</td> <td align="left">43,094</td> </tr>-<tr class="even country">+<tr class="country"> <th align="center">Finland</th> <td align="left">Helsinki</td> <td align="left">5,537,364</td> <td align="left">338,145</td> </tr>-<tr class="odd country">+<tr class="country"> <th align="center">Iceland</th> <td align="left">Reykjavik</td> <td align="left">343,518</td> <td align="left">103,000</td> </tr>-<tr class="even country">+<tr class="country"> <th align="center">Norway</th> <td align="left">Oslo</td> <td align="left">5,372,191</td> <td align="left">323,802</td> </tr>-<tr class="odd country">+<tr class="country"> <th align="center">Sweden</th> <td align="left">Stockholm</td> <td align="left">10,313,447</td> <td align="left">450,295</td> </tr> </tbody><tfoot>-<tr id="summary" class="even">+<tr id="summary"> <td align="center">Total</td> <td align="left"></td> <td id="total-population" align="left">27,376,022</td>
@@ -7,7 +7,7 @@ <col style="width: 20%" /> </colgroup> <thead class="simple-head">-<tr class="header">+<tr> <th style="text-align: center;">Name</th> <th style="text-align: center;">Capital</th> <th style="text-align: center;">Population<br />@@ -17,38 +17,38 @@ </tr> </thead> <tbody class="souvereign-states">-<tr class="odd country">+<tr class="country"> <th style="text-align: center;">Denmark</th> <td style="text-align: left;">Copenhagen</td> <td style="text-align: left;">5,809,502</td> <td style="text-align: left;">43,094</td> </tr>-<tr class="even country">+<tr class="country"> <th style="text-align: center;">Finland</th> <td style="text-align: left;">Helsinki</td> <td style="text-align: left;">5,537,364</td> <td style="text-align: left;">338,145</td> </tr>-<tr class="odd country">+<tr class="country"> <th style="text-align: center;">Iceland</th> <td style="text-align: left;">Reykjavik</td> <td style="text-align: left;">343,518</td> <td style="text-align: left;">103,000</td> </tr>-<tr class="even country">+<tr class="country"> <th style="text-align: center;">Norway</th> <td style="text-align: left;">Oslo</td> <td style="text-align: left;">5,372,191</td> <td style="text-align: left;">323,802</td> </tr>-<tr class="odd country">+<tr class="country"> <th style="text-align: center;">Sweden</th> <td style="text-align: left;">Stockholm</td> <td style="text-align: left;">10,313,447</td> <td style="text-align: left;">450,295</td> </tr> </tbody><tfoot>-<tr id="summary" class="even">+<tr id="summary"> <td style="text-align: center;">Total</td> <td style="text-align: left;"></td> <td id="total-population" style="text-align: left;">27,376,022</td>
@@ -13,10 +13,8 @@ <tr> <th align="center">Name</th> <th align="center">Capital</th>- <th align="center">Population- (in 2018)</th>- <th align="center">Area- (in km<sup>2</sup>)</th>+ <th align="center">Population<break/>(in 2018)</th>+ <th align="center">Area<break/>(in km<sup>2</sup>)</th> </tr> </thead> <tfoot>
@@ -1,10 +1,11 @@ \begin{longtable}[]{@{}- >{\centering\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3000}}- >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.3000}}- >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.2000}}- >{\raggedright\arraybackslash}p{(\columnwidth - 6\tabcolsep) * \real{0.2000}}@{}}-\caption{States belonging to the \emph{Nordics.}}\label{nordics}\tabularnewline-\toprule()+ >{\centering\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3000}}+ >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3000}}+ >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2000}}+ >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2000}}@{}}+\caption[Nordic countries]{States belonging to the+\emph{Nordics.}}\label{nordics}\tabularnewline+\toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering Name \end{minipage} & \begin{minipage}[b]{\linewidth}\centering@@ -16,9 +17,9 @@ Area\\ (in km\textsuperscript{2})\strut \end{minipage} \\-\midrule()+\midrule\noalign{} \endfirsthead-\toprule()+\toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering Name \end{minipage} & \begin{minipage}[b]{\linewidth}\centering@@ -30,13 +31,15 @@ Area\\ (in km\textsuperscript{2})\strut \end{minipage} \\-\midrule()+\midrule\noalign{} \endhead+\midrule\noalign{}+Total & & 27,376,022 & 1,258,336 \\+\bottomrule\noalign{}+\endlastfoot Denmark & Copenhagen & 5,809,502 & 43,094 \\ Finland & Helsinki & 5,537,364 & 338,145 \\ Iceland & Reykjavik & 343,518 & 103,000 \\ Norway & Oslo & 5,372,191 & 323,802 \\ Sweden & Stockholm & 10,313,447 & 450,295 \\-Total & & 27,376,022 & 1,258,336 \\-\bottomrule() \end{longtable}
@@ -0,0 +1,18 @@++-----------------------+-----------------------+---------------+---------------++| Name | Capital | Population\ | Area\ |+| | | (in 2018) | (in km^2^) |++:=====================:+:======================+:==============+:==============++| Denmark | Copenhagen | 5,809,502 | 43,094 |++-----------------------+-----------------------+---------------+---------------++| Finland | Helsinki | 5,537,364 | 338,145 |++-----------------------+-----------------------+---------------+---------------++| Iceland | Reykjavik | 343,518 | 103,000 |++-----------------------+-----------------------+---------------+---------------++| Norway | Oslo | 5,372,191 | 323,802 |++-----------------------+-----------------------+---------------+---------------++| Sweden | Stockholm | 10,313,447 | 450,295 |++=======================+=======================+===============+===============++| Total | | 27,376,022 | 1,258,336 |++=======================+=======================+===============+===============+++: States belonging to the *Nordics.* {#nordics source="wikipedia"}
@@ -0,0 +1,40 @@+{| id="nordics" class="wikitable" data-source="wikipedia"+|+ States belonging to the ''Nordics.''+|-+! style="text-align: center;"| Name+! style="text-align: center;"| Capital+! style="text-align: center;"| Population<br />+(in 2018)+! style="text-align: center;"| Area<br />+(in km<sup>2</sup>)+|- class="country"+! style="text-align: center;"| Denmark+| style="text-align: left;"| Copenhagen+| style="text-align: left;"| 5,809,502+| style="text-align: left;"| 43,094+|- class="country"+! style="text-align: center;"| Finland+| style="text-align: left;"| Helsinki+| style="text-align: left;"| 5,537,364+| style="text-align: left;"| 338,145+|- class="country"+! style="text-align: center;"| Iceland+| style="text-align: left;"| Reykjavik+| style="text-align: left;"| 343,518+| style="text-align: left;"| 103,000+|- class="country"+! style="text-align: center;"| Norway+| style="text-align: left;"| Oslo+| style="text-align: left;"| 5,372,191+| style="text-align: left;"| 323,802+|- class="country"+! style="text-align: center;"| Sweden+| style="text-align: left;"| Stockholm+| style="text-align: left;"| 10,313,447+| style="text-align: left;"| 450,295+|- id="summary"+! style="text-align: center;"| Total+! style="text-align: left;"|+! id="total-population" style="text-align: left;"| 27,376,022+! id="total-area" style="text-align: left;"| 1,258,336+|}
@@ -0,0 +1,21 @@+#figure(+ align(center)[#table(+ columns: (30%, 30%, 20%, 20%),+ align: (center,left,left,left,),+ table.header(table.cell(align: center)[Name], table.cell(align: center)[Capital], table.cell(align: center)[Population+ \ (in 2018)], table.cell(align: center)[Area \ (in km#super[2])],),+ table.hline(),+ [Denmark], [Copenhagen], [5,809,502], [43,094],+ [Finland], [Helsinki], [5,537,364], [338,145],+ [Iceland], [Reykjavik], [343,518], [103,000],+ [Norway], [Oslo], [5,372,191], [323,802],+ [Sweden], [Stockholm], [10,313,447], [450,295],+ table.hline(),+ table.footer([Total], [], [27,376,022], [1,258,336],),+ )]+ , caption: [States belonging to the #emph[Nordics.]++ ]+ , kind: table+ )+<nordics>
@@ -1,7 +1,7 @@ <table> <caption><p>Data about the planets of our solar system.</p></caption> <thead>-<tr class="header">+<tr> <th colspan="2" align="center"></th> <th>Name</th> <th align="right">Mass (10^24kg)</th>@@ -16,7 +16,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <th colspan="2" rowspan="4" align="center">Terrestrial planets</th> <th>Mercury</th> <td align="right">0.330</td>@@ -29,7 +29,7 @@ <td align="right">0</td> <td>Closest to the Sun</td> </tr>-<tr class="even">+<tr> <th>Venus</th> <td align="right">4.87</td> <td align="right">12,104</td>@@ -41,7 +41,7 @@ <td align="right">0</td> <td></td> </tr>-<tr class="odd">+<tr> <th>Earth</th> <td align="right">5.97</td> <td align="right">12,756</td>@@ -53,7 +53,7 @@ <td align="right">1</td> <td>Our world</td> </tr>-<tr class="even">+<tr> <th>Mars</th> <td align="right">0.642</td> <td align="right">6,792</td>@@ -65,7 +65,7 @@ <td align="right">2</td> <td>The red planet</td> </tr>-<tr class="odd">+<tr> <th rowspan="4" align="center">Jovian planets</th> <th rowspan="2" align="center">Gas giants</th> <th>Jupiter</th>@@ -79,7 +79,7 @@ <td align="right">67</td> <td>The largest planet</td> </tr>-<tr class="even">+<tr> <th>Saturn</th> <td align="right">568</td> <td align="right">120,536</td>@@ -91,7 +91,7 @@ <td align="right">62</td> <td></td> </tr>-<tr class="odd">+<tr> <th rowspan="2" align="center">Ice giants</th> <th>Uranus</th> <td align="right">86.8</td>@@ -104,7 +104,7 @@ <td align="right">27</td> <td></td> </tr>-<tr class="even">+<tr> <th>Neptune</th> <td align="right">102</td> <td align="right">49,528</td>@@ -116,7 +116,7 @@ <td align="right">14</td> <td></td> </tr>-<tr class="odd">+<tr> <th colspan="2" align="center">Dwarf planets</th> <th>Pluto</th> <td align="right">0.0146</td>
@@ -1,7 +1,7 @@ <table> <caption><p>Data about the planets of our solar system.</p></caption> <thead>-<tr class="header">+<tr> <th colspan="2" style="text-align: center;"></th> <th>Name</th> <th style="text-align: right;">Mass (10^24kg)</th>@@ -16,7 +16,7 @@ </tr> </thead> <tbody>-<tr class="odd">+<tr> <th colspan="2" rowspan="4" style="text-align: center;">Terrestrial planets</th> <th>Mercury</th> <td style="text-align: right;">0.330</td>@@ -29,7 +29,7 @@ <td style="text-align: right;">0</td> <td>Closest to the Sun</td> </tr>-<tr class="even">+<tr> <th>Venus</th> <td style="text-align: right;">4.87</td> <td style="text-align: right;">12,104</td>@@ -41,7 +41,7 @@ <td style="text-align: right;">0</td> <td></td> </tr>-<tr class="odd">+<tr> <th>Earth</th> <td style="text-align: right;">5.97</td> <td style="text-align: right;">12,756</td>@@ -53,7 +53,7 @@ <td style="text-align: right;">1</td> <td>Our world</td> </tr>-<tr class="even">+<tr> <th>Mars</th> <td style="text-align: right;">0.642</td> <td style="text-align: right;">6,792</td>@@ -65,7 +65,7 @@ <td style="text-align: right;">2</td> <td>The red planet</td> </tr>-<tr class="odd">+<tr> <th rowspan="4" style="text-align: center;">Jovian planets</th> <th rowspan="2" style="text-align: center;">Gas giants</th> <th>Jupiter</th>@@ -79,7 +79,7 @@ <td style="text-align: right;">67</td> <td>The largest planet</td> </tr>-<tr class="even">+<tr> <th>Saturn</th> <td style="text-align: right;">568</td> <td style="text-align: right;">120,536</td>@@ -91,7 +91,7 @@ <td style="text-align: right;">62</td> <td></td> </tr>-<tr class="odd">+<tr> <th rowspan="2" style="text-align: center;">Ice giants</th> <th>Uranus</th> <td style="text-align: right;">86.8</td>@@ -104,7 +104,7 @@ <td style="text-align: right;">27</td> <td></td> </tr>-<tr class="even">+<tr> <th>Neptune</th> <td style="text-align: right;">102</td> <td style="text-align: right;">49,528</td>@@ -116,7 +116,7 @@ <td style="text-align: right;">14</td> <td></td> </tr>-<tr class="odd">+<tr> <th colspan="2" style="text-align: center;">Dwarf planets</th> <th>Pluto</th> <td style="text-align: right;">0.0146</td>
@@ -1,34 +1,36 @@ \begin{longtable}[]{@{}cclrrrrrrrrl@{}} \caption{Data about the planets of our solar system.}\tabularnewline-\toprule()-\multicolumn{2}{@{}>{\centering\arraybackslash}p{(\columnwidth - 22\tabcolsep) * \real{0.0000} + 2\tabcolsep}}{%+\toprule\noalign{}+\multicolumn{2}{@{}c}{% } & Name & Mass (10\^{}24kg) & Diameter (km) & Density (kg/m\^{}3) & Gravity (m/s\^{}2) & Length of day (hours) & Distance from Sun (10\^{}6km) & Mean temperature (C) & Number of moons & Notes \\-\midrule()+\midrule\noalign{} \endfirsthead-\toprule()-\multicolumn{2}{@{}>{\centering\arraybackslash}p{(\columnwidth - 22\tabcolsep) * \real{0.0000} + 2\tabcolsep}}{%+\toprule\noalign{}+\multicolumn{2}{@{}c}{% } & Name & Mass (10\^{}24kg) & Diameter (km) & Density (kg/m\^{}3) & Gravity (m/s\^{}2) & Length of day (hours) & Distance from Sun (10\^{}6km) & Mean temperature (C) & Number of moons & Notes \\-\midrule()+\midrule\noalign{} \endhead-\multicolumn{2}{@{}>{\centering\arraybackslash}p{(\columnwidth - 22\tabcolsep) * \real{0.0000} + 2\tabcolsep}}{%-\multirow{4}{*}{Terrestrial planets}} & Mercury & 0.330 & 4,879 & 5427 & 3.7 &-4222.6 & 57.9 & 167 & 0 & Closest to the Sun \\+\bottomrule\noalign{}+\endlastfoot+\multicolumn{2}{@{}c}{%+\multirow{4}{*}{\centering\arraybackslash Terrestrial planets}} & Mercury &+0.330 & 4,879 & 5427 & 3.7 & 4222.6 & 57.9 & 167 & 0 & Closest to the Sun \\ & & Venus & 4.87 & 12,104 & 5243 & 8.9 & 2802.0 & 108.2 & 464 & 0 & \\ & & Earth & 5.97 & 12,756 & 5514 & 9.8 & 24.0 & 149.6 & 15 & 1 & Our world \\ & & Mars & 0.642 & 6,792 & 3933 & 3.7 & 24.7 & 227.9 & -65 & 2 & The red planet \\-\multirow{4}{*}{Jovian planets} & \multirow{2}{*}{Gas giants} & Jupiter & 1898 &-142,984 & 1326 & 23.1 & 9.9 & 778.6 & -110 & 67 & The largest planet \\+\multirow{4}{*}{\centering\arraybackslash Jovian planets} &+\multirow{2}{*}{\centering\arraybackslash Gas giants} & Jupiter & 1898 & 142,984+& 1326 & 23.1 & 9.9 & 778.6 & -110 & 67 & The largest planet \\ & & Saturn & 568 & 120,536 & 687 & 9.0 & 10.7 & 1433.5 & -140 & 62 & \\-& \multirow{2}{*}{Ice giants} & Uranus & 86.8 & 51,118 & 1271 & 8.7 & 17.2 &-2872.5 & -195 & 27 & \\+& \multirow{2}{*}{\centering\arraybackslash Ice giants} & Uranus & 86.8 & 51,118+& 1271 & 8.7 & 17.2 & 2872.5 & -195 & 27 & \\ & & Neptune & 102 & 49,528 & 1638 & 11.0 & 16.1 & 4495.1 & -200 & 14 & \\-\multicolumn{2}{@{}>{\centering\arraybackslash}p{(\columnwidth - 22\tabcolsep) * \real{0.0000} + 2\tabcolsep}}{%+\multicolumn{2}{@{}c}{% Dwarf planets} & Pluto & 0.0146 & 2,370 & 2095 & 0.7 & 153.3 & 5906.4 & -225 & 5 & Declassified as a planet in 2006. \\-\bottomrule() \end{longtable}
@@ -0,0 +1,31 @@++------------------+---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++| | Name | Mass | Diameter | Density | Gravity | Length | Distance | Mean | Number | Notes |+| | | (10\^24kg) | (km) | (kg/m\^3) | (m/s\^2) | of day | from Sun | temperature | of | |+| | | | | | | (hours) | (10\^6km) | (C) | moons | |++:=======:+:======:+=========+===========:+=========:+==========:+=========:+========:+==========:+============:+=======:+==============++| Terrestrial | Mercury | 0.330 | 4,879 | 5427 | 3.7 | 4222.6 | 57.9 | 167 | 0 | Closest to |+| planets | | | | | | | | | | the Sun |+| +---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++| | Venus | 4.87 | 12,104 | 5243 | 8.9 | 2802.0 | 108.2 | 464 | 0 | |+| +---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++| | Earth | 5.97 | 12,756 | 5514 | 9.8 | 24.0 | 149.6 | 15 | 1 | Our world |+| +---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++| | Mars | 0.642 | 6,792 | 3933 | 3.7 | 24.7 | 227.9 | -65 | 2 | The red |+| | | | | | | | | | | planet |++---------+--------+---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++| Jovian | Gas | Jupiter | 1898 | 142,984 | 1326 | 23.1 | 9.9 | 778.6 | -110 | 67 | The largest |+| planets | giants | | | | | | | | | | planet |+| | +---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++| | | Saturn | 568 | 120,536 | 687 | 9.0 | 10.7 | 1433.5 | -140 | 62 | |+| +--------+---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++| | Ice | Uranus | 86.8 | 51,118 | 1271 | 8.7 | 17.2 | 2872.5 | -195 | 27 | |+| | giants | | | | | | | | | | |+| | +---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++| | | Neptune | 102 | 49,528 | 1638 | 11.0 | 16.1 | 4495.1 | -200 | 14 | |++---------+--------+---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------++| Dwarf planets | Pluto | 0.0146 | 2,370 | 2095 | 0.7 | 153.3 | 5906.4 | -225 | 5 | Declassified |+| | | | | | | | | | | as a planet |+| | | | | | | | | | | in 2006. |++------------------+---------+------------+----------+-----------+----------+---------+-----------+-------------+--------+--------------+++: Data about the planets of our solar system.
@@ -0,0 +1,119 @@+{| class="wikitable"+|+ Data about the planets of our solar system.+|-+! colspan="2" style="text-align: center;"|+! Name+! style="text-align: right;"| Mass (10^24kg)+! style="text-align: right;"| Diameter (km)+! style="text-align: right;"| Density (kg/m^3)+! style="text-align: right;"| Gravity (m/s^2)+! style="text-align: right;"| Length of day (hours)+! style="text-align: right;"| Distance from Sun (10^6km)+! style="text-align: right;"| Mean temperature (C)+! style="text-align: right;"| Number of moons+! Notes+|-+! rowspan="4" colspan="2" style="text-align: center;"| Terrestrial planets+! Mercury+| style="text-align: right;"| 0.330+| style="text-align: right;"| 4,879+| style="text-align: right;"| 5427+| style="text-align: right;"| 3.7+| style="text-align: right;"| 4222.6+| style="text-align: right;"| 57.9+| style="text-align: right;"| 167+| style="text-align: right;"| 0+| Closest to the Sun+|-+! Venus+| style="text-align: right;"| 4.87+| style="text-align: right;"| 12,104+| style="text-align: right;"| 5243+| style="text-align: right;"| 8.9+| style="text-align: right;"| 2802.0+| style="text-align: right;"| 108.2+| style="text-align: right;"| 464+| style="text-align: right;"| 0+|+|-+! Earth+| style="text-align: right;"| 5.97+| style="text-align: right;"| 12,756+| style="text-align: right;"| 5514+| style="text-align: right;"| 9.8+| style="text-align: right;"| 24.0+| style="text-align: right;"| 149.6+| style="text-align: right;"| 15+| style="text-align: right;"| 1+| Our world+|-+! Mars+| style="text-align: right;"| 0.642+| style="text-align: right;"| 6,792+| style="text-align: right;"| 3933+| style="text-align: right;"| 3.7+| style="text-align: right;"| 24.7+| style="text-align: right;"| 227.9+| style="text-align: right;"| -65+| style="text-align: right;"| 2+| The red planet+|-+! rowspan="4" style="text-align: center;"| Jovian planets+! rowspan="2" style="text-align: center;"| Gas giants+! Jupiter+| style="text-align: right;"| 1898+| style="text-align: right;"| 142,984+| style="text-align: right;"| 1326+| style="text-align: right;"| 23.1+| style="text-align: right;"| 9.9+| style="text-align: right;"| 778.6+| style="text-align: right;"| -110+| style="text-align: right;"| 67+| The largest planet+|-+! Saturn+| style="text-align: right;"| 568+| style="text-align: right;"| 120,536+| style="text-align: right;"| 687+| style="text-align: right;"| 9.0+| style="text-align: right;"| 10.7+| style="text-align: right;"| 1433.5+| style="text-align: right;"| -140+| style="text-align: right;"| 62+|+|-+! rowspan="2" style="text-align: center;"| Ice giants+! Uranus+| style="text-align: right;"| 86.8+| style="text-align: right;"| 51,118+| style="text-align: right;"| 1271+| style="text-align: right;"| 8.7+| style="text-align: right;"| 17.2+| style="text-align: right;"| 2872.5+| style="text-align: right;"| -195+| style="text-align: right;"| 27+|+|-+! Neptune+| style="text-align: right;"| 102+| style="text-align: right;"| 49,528+| style="text-align: right;"| 1638+| style="text-align: right;"| 11.0+| style="text-align: right;"| 16.1+| style="text-align: right;"| 4495.1+| style="text-align: right;"| -200+| style="text-align: right;"| 14+|+|-+! colspan="2" style="text-align: center;"| Dwarf planets+! Pluto+| style="text-align: right;"| 0.0146+| style="text-align: right;"| 2,370+| style="text-align: right;"| 2095+| style="text-align: right;"| 0.7+| style="text-align: right;"| 153.3+| style="text-align: right;"| 5906.4+| style="text-align: right;"| -225+| style="text-align: right;"| 5+| Declassified as a planet in 2006.+|}
@@ -0,0 +1,33 @@+#figure(+ align(center)[#table(+ columns: 12,+ align: (center,center,auto,right,right,right,right,right,right,right,right,auto,),+ table.header(table.cell(colspan: 2)[], [Name], [Mass (10^24kg)], [Diameter+ (km)], [Density (kg/m^3)], [Gravity (m/s^2)], [Length of day+ (hours)], [Distance from Sun (10^6km)], [Mean temperature (C)], [Number of+ moons], [Notes],),+ table.hline(),+ table.cell(rowspan: 4, colspan: 2)[Terrestrial+ planets], [Mercury], [0.330], [4,879], [5427], [3.7], [4222.6], [57.9], [167], [0], [Closest+ to the Sun],+ [Venus], [4.87], [12,104], [5243], [8.9], [2802.0], [108.2], [464], [0], [],+ [Earth], [5.97], [12,756], [5514], [9.8], [24.0], [149.6], [15], [1], [Our+ world],+ [Mars], [0.642], [6,792], [3933], [3.7], [24.7], [227.9], [-65], [2], [The+ red planet],+ table.cell(rowspan: 4)[Jovian planets], table.cell(rowspan: 2)[Gas+ giants], [Jupiter], [1898], [142,984], [1326], [23.1], [9.9], [778.6], [-110], [67], [The+ largest planet],+ [Saturn], [568], [120,536], [687], [9.0], [10.7], [1433.5], [-140], [62], [],+ table.cell(rowspan: 2)[Ice+ giants], [Uranus], [86.8], [51,118], [1271], [8.7], [17.2], [2872.5], [-195], [27], [],+ [Neptune], [102], [49,528], [1638], [11.0], [16.1], [4495.1], [-200], [14], [],+ table.cell(colspan: 2)[Dwarf+ planets], [Pluto], [0.0146], [2,370], [2095], [0.7], [153.3], [5906.4], [-225], [5], [Declassified+ as a planet in 2006.],+ )]+ , caption: [Data about the planets of our solar system.++ ]+ , kind: table+ )
@@ -5,49 +5,49 @@ <col width="50%" /> </colgroup> <thead>-<tr class="header">+<tr> <th align="center">Student ID</th> <th align="center">Name</th> </tr> </thead> <tbody class="souvereign-states">-<tr class="odd">+<tr> <th colspan="2" align="left">Computer Science</th> </tr> -<tr class="odd">+<tr> <td align="left">3741255</td> <td align="left">Jones, Martha</td> </tr>-<tr class="even">+<tr> <td align="left">4077830</td> <td align="left">Pierce, Benjamin</td> </tr>-<tr class="odd">+<tr> <td align="left">5151701</td> <td align="left">Kirk, James</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" align="left">Russian Literature</th> </tr> -<tr class="odd">+<tr> <td align="left">3971244</td> <td align="left">Nim, Victor</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" align="left">Astrophysics</th> </tr> -<tr class="odd">+<tr> <td align="left">4100332</td> <td align="left">Petrov, Alexandra</td> </tr>-<tr class="even">+<tr> <td align="left">4100332</td> <td align="left">Toyota, Hiroko</td> </tr>
@@ -5,49 +5,49 @@ <col style="width: 50%" /> </colgroup> <thead>-<tr class="header">+<tr> <th style="text-align: center;">Student ID</th> <th style="text-align: center;">Name</th> </tr> </thead> <tbody class="souvereign-states">-<tr class="odd">+<tr> <th colspan="2" style="text-align: left;">Computer Science</th> </tr> -<tr class="odd">+<tr> <td style="text-align: left;">3741255</td> <td style="text-align: left;">Jones, Martha</td> </tr>-<tr class="even">+<tr> <td style="text-align: left;">4077830</td> <td style="text-align: left;">Pierce, Benjamin</td> </tr>-<tr class="odd">+<tr> <td style="text-align: left;">5151701</td> <td style="text-align: left;">Kirk, James</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" style="text-align: left;">Russian Literature</th> </tr> -<tr class="odd">+<tr> <td style="text-align: left;">3971244</td> <td style="text-align: left;">Nim, Victor</td> </tr> </tbody> <tbody>-<tr class="odd">+<tr> <th colspan="2" style="text-align: left;">Astrophysics</th> </tr> -<tr class="odd">+<tr> <td style="text-align: left;">4100332</td> <td style="text-align: left;">Petrov, Alexandra</td> </tr>-<tr class="even">+<tr> <td style="text-align: left;">4100332</td> <td style="text-align: left;">Toyota, Hiroko</td> </tr>
@@ -1,34 +1,35 @@ \begin{longtable}[]{@{}- >{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{0.5000}}- >{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{0.5000}}@{}}+ >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.5000}}+ >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.5000}}@{}} \caption{List of Students}\label{students}\tabularnewline-\toprule()+\toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering Student ID \end{minipage} & \begin{minipage}[b]{\linewidth}\centering Name \end{minipage} \\-\midrule()+\midrule\noalign{} \endfirsthead-\toprule()+\toprule\noalign{} \begin{minipage}[b]{\linewidth}\centering Student ID \end{minipage} & \begin{minipage}[b]{\linewidth}\centering Name \end{minipage} \\-\midrule()+\midrule\noalign{} \endhead-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{%+\bottomrule\noalign{}+\endlastfoot+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Computer Science} \\ 3741255 & Jones, Martha \\ 4077830 & Pierce, Benjamin \\ 5151701 & Kirk, James \\-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{%+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Russian Literature} \\ 3971244 & Nim, Victor \\-\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{%+\multicolumn{2}{@{}>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{1.0000} + 2\tabcolsep}@{}}{% Astrophysics} \\ 4100332 & Petrov, Alexandra \\ 4100332 & Toyota, Hiroko \\-\bottomrule() \end{longtable}
@@ -0,0 +1,23 @@++-----------------------------------------+-----------------------------------------++| Student ID | Name |++:========================================+:========================================++| Computer Science |++-----------------------------------------+-----------------------------------------++| 3741255 | Jones, Martha |++-----------------------------------------+-----------------------------------------++| 4077830 | Pierce, Benjamin |++-----------------------------------------+-----------------------------------------++| 5151701 | Kirk, James |++-----------------------------------------+-----------------------------------------++| Russian Literature |++-----------------------------------------+-----------------------------------------++| 3971244 | Nim, Victor |++-----------------------------------------+-----------------------------------------++| Astrophysics |++-----------------------------------------+-----------------------------------------++| 4100332 | Petrov, Alexandra |++-----------------------------------------+-----------------------------------------++| 4100332 | Toyota, Hiroko |++-----------------------------------------+-----------------------------------------+++: List of Students {#students source="mdn"}
@@ -0,0 +1,30 @@+{| id="students" class="wikitable" data-source="mdn"+|+ List of Students+|-+! style="text-align: center;"| Student ID+! style="text-align: center;"| Name+|-+! colspan="2" style="text-align: left;"| Computer Science+|-+| style="text-align: left;"| 3741255+| style="text-align: left;"| Jones, Martha+|-+| style="text-align: left;"| 4077830+| style="text-align: left;"| Pierce, Benjamin+|-+| style="text-align: left;"| 5151701+| style="text-align: left;"| Kirk, James+|-+! colspan="2" style="text-align: left;"| Russian Literature+|-+| style="text-align: left;"| 3971244+| style="text-align: left;"| Nim, Victor+|-+! colspan="2" style="text-align: left;"| Astrophysics+|-+| style="text-align: left;"| 4100332+| style="text-align: left;"| Petrov, Alexandra+|-+| style="text-align: left;"| 4100332+| style="text-align: left;"| Toyota, Hiroko+|}
@@ -0,0 +1,26 @@+#figure(+ align(center)[#table(+ columns: (50%, 50%),+ align: (left,left,),+ table.header(table.cell(align: center)[Student+ ID], table.cell(align: center)[Name],),+ table.hline(),+ table.cell(colspan: 2)[Computer Science],+ table.hline(),+ [3741255], [Jones, Martha],+ [4077830], [Pierce, Benjamin],+ [5151701], [Kirk, James],+ table.cell(colspan: 2)[Russian Literature],+ table.hline(),+ [3971244], [Nim, Victor],+ table.cell(colspan: 2)[Astrophysics],+ table.hline(),+ [4100332], [Petrov, Alexandra],+ [4100332], [Toyota, Hiroko],+ )]+ , caption: [List of Students++ ]+ , kind: table+ )+<students>
@@ -1,20 +1,19 @@-{-# OPTIONS_GHC -Wall #-}--module Main where+module Main (main) where import System.Environment (getArgs, getExecutablePath) import qualified Control.Exception as E-import Text.Pandoc.App (convertWithOpts, defaultOpts, options,+import Text.Pandoc.App (convertWithOpts, handleOptInfo, defaultOpts, options, parseOptionsFromArgs) import Text.Pandoc.Error (handleError)+import Text.Pandoc.Scripting (noEngine) import GHC.IO.Encoding import Test.Tasty import qualified Tests.Command-import qualified Tests.Lua-import qualified Tests.Lua.Module import qualified Tests.Old import qualified Tests.Readers.Creole import qualified Tests.Readers.Docx+import qualified Tests.Readers.Pptx+import qualified Tests.Readers.Xlsx import qualified Tests.Readers.DokuWiki import qualified Tests.Readers.EPUB import qualified Tests.Readers.FB2@@ -24,16 +23,18 @@ import qualified Tests.Readers.LaTeX import qualified Tests.Readers.Markdown import qualified Tests.Readers.Muse-import qualified Tests.Readers.Odt+import qualified Tests.Readers.ODT import qualified Tests.Readers.Org import qualified Tests.Readers.RST import qualified Tests.Readers.RTF import qualified Tests.Readers.Txt2Tags import qualified Tests.Readers.Man+import qualified Tests.Readers.Mdoc+import qualified Tests.Readers.Pod import qualified Tests.Shared import qualified Tests.Writers.AsciiDoc import qualified Tests.Writers.ConTeXt-import qualified Tests.Writers.Docbook+import qualified Tests.Writers.DocBook import qualified Tests.Writers.Docx import qualified Tests.Writers.FB2 import qualified Tests.Writers.HTML@@ -51,6 +52,9 @@ import qualified Tests.Writers.AnnotatedTable import qualified Tests.Writers.TEI import qualified Tests.Writers.Markua+import qualified Tests.Writers.BBCode+import qualified Tests.XML+import qualified Tests.MediaBag import Text.Pandoc.Shared (inDirectory) tests :: FilePath -> TestTree@@ -58,6 +62,8 @@ [ Tests.Command.tests , 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@@ -65,7 +71,7 @@ , testGroup "HTML" Tests.Writers.HTML.tests , testGroup "JATS" Tests.Writers.JATS.tests , testGroup "Jira" Tests.Writers.Jira.tests- , testGroup "Docbook" Tests.Writers.Docbook.tests+ , testGroup "Docbook" Tests.Writers.DocBook.tests , testGroup "Markdown" Tests.Writers.Markdown.tests , testGroup "Org" Tests.Writers.Org.tests , testGroup "Plain" Tests.Writers.Plain.tests@@ -79,6 +85,7 @@ , testGroup "PowerPoint" Tests.Writers.Powerpoint.tests , testGroup "Ms" Tests.Writers.Ms.tests , testGroup "AnnotatedTable" Tests.Writers.AnnotatedTable.tests+ , testGroup "BBCode" Tests.Writers.BBCode.tests ] , testGroup "Readers" [ testGroup "LaTeX" Tests.Readers.LaTeX.tests@@ -90,18 +97,18 @@ , testGroup "RST" Tests.Readers.RST.tests , testGroup "RTF" Tests.Readers.RTF.tests , testGroup "Docx" Tests.Readers.Docx.tests- , testGroup "Odt" Tests.Readers.Odt.tests+ , testGroup "Pptx" Tests.Readers.Pptx.tests+ , testGroup "Xlsx" Tests.Readers.Xlsx.tests+ , testGroup "ODT" Tests.Readers.ODT.tests , testGroup "Txt2Tags" Tests.Readers.Txt2Tags.tests , testGroup "EPUB" Tests.Readers.EPUB.tests , testGroup "Muse" Tests.Readers.Muse.tests , testGroup "Creole" Tests.Readers.Creole.tests , testGroup "Man" Tests.Readers.Man.tests+ , testGroup "Mdoc" Tests.Readers.Mdoc.tests , testGroup "FB2" Tests.Readers.FB2.tests , testGroup "DokuWiki" Tests.Readers.DokuWiki.tests- ]- , testGroup "Lua"- [ testGroup "Lua filters" Tests.Lua.tests- , testGroup "Lua modules" Tests.Lua.Module.tests+ , testGroup "Pod" Tests.Readers.Pod.tests ] ] @@ -112,11 +119,13 @@ case args of "--emulate":args' -> -- emulate pandoc executable E.catch- (parseOptionsFromArgs options defaultOpts "pandoc" args' >>=- convertWithOpts)+ (do+ res <- parseOptionsFromArgs options defaultOpts "pandoc" args'+ case res of+ Left e -> handleOptInfo noEngine e+ Right opts -> convertWithOpts noEngine opts) (handleError . Left) _ -> inDirectory "test" $ do fp <- getExecutablePath -- putStrLn $ "Using pandoc executable at " ++ fp defaultMain $ tests fp-
@@ -1906,11 +1906,15 @@ , Space , Str "(1902):" ]- , Para- [ Image- ( "" , [] , [] )- [ Str "lalune" ]- ( "lalune.jpg" , "fig:Voyage dans la Lune" )+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "lalune" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] )+ [ Str "lalune" ]+ ( "lalune.jpg" , "Voyage dans la Lune" )+ ] ] , Para [ Str "Here"
@@ -522,8 +522,7 @@ - $p$-Tree - Here's some display math: $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$-- Here's one that has a line break in it: $\alpha + \omega \times-x^2$. +- Here's one that has a line break in it: $\alpha + \omega \times x^2$. These shouldn't be math:
@@ -749,6 +749,33 @@ , Space , Str "spaces." ]+ , Para+ [ Str "A"+ , Space+ , Link+ ( "" , [] , [] ) [ Str "link" ] ( "ftp://example.com" , "" )+ , Space+ , Str "to"+ , Space+ , Str "a"+ , Space+ , Str "named"+ , Space+ , Str "target"+ ]+ , Para+ [ Str "A"+ , Space+ , Link ( "" , [] , [] ) [ Str "link" ] ( "missing" , "" )+ , Space+ , Str "to"+ , Space+ , Str "a"+ , Space+ , Str "missing"+ , Space+ , Str "target"+ ] , Header 1 ( "tables" , [] , [] ) [ Str "Tables" ] , Para [ Str "Textile"@@ -1072,18 +1099,21 @@ ( "" , [] , [ ( "style" , "color:red;" ) ] ) [ Str "all" , Space , Str "kind" ] ]- , Para- [ Str "and"- , Space- , Str "paragraph"- , Space- , Str "attributes,"- , Space- , Str "and"- , Space- , Str "table"- , Space- , Str "attributes."+ , Div+ ( "" , [] , [ ( "style" , "color:green;" ) ] )+ [ Para+ [ Str "and"+ , Space+ , Str "paragraph"+ , Space+ , Str "attributes,"+ , Space+ , Str "and"+ , Space+ , Str "table"+ , Space+ , Str "attributes."+ ] ] , Table ( "" , [] , [] )
@@ -183,6 +183,10 @@ A link["with brackets":http://www.example.com]and no spaces. +A "link":link-target to a named target++A "link":missing to a missing target+ h1. Tables Textile allows tables with and without headers :@@ -269,7 +273,7 @@ fn1. The note is here! -fn2. Other note.+fn2^. Other note. h1. Comment blocks @@ -277,3 +281,5 @@ is here. not a comment.++[link-target]ftp://example.com
@@ -149,6 +149,22 @@ , Para [ Str "Nother" , Space , Str "paragraph." ] , Header 1+ ( "internal-links" , [] , [] )+ [ Str "internal" , Space , Str "links" ]+ , Para+ [ Link+ ( "" , [ "wikilink" ] , [] )+ [ Str "MySimplePage" ]+ ( "MySimplePage" , "" )+ ]+ , Para+ [ Link+ ( "" , [ "wikilink" ] , [] )+ [ Str "My23Page23" ]+ ( "My23Page23" , "" )+ ]+ , Header+ 1 ( "external-links" , [] , [] ) [ Str "external" , Space , Str "links" ] , Para
@@ -93,6 +93,12 @@ </blockquote> Nother paragraph. +---+ internal links++MySimplePage++My23Page23+ ---+ external links [[http://google.com][<i>Google</i> search engine]]
@@ -0,0 +1,5349 @@+Pandoc+ Meta { unMeta = fromList [] }+ [ Header+ 1+ ( "" , [] , [] )+ [ Str "Fibonacci" , Space , Str "sequence" ]+ , Para+ [ Str "The"+ , Space+ , Str "Fibonacci"+ , Space+ , Str "sequence"+ , Space+ , Str "is"+ , Space+ , Str "defined"+ , Space+ , Str "through"+ , Space+ , Str "the"+ , SoftBreak+ , Str "recurrence"+ , Space+ , Str "relation"+ , Space+ , Math InlineMath "F_{n} = F_{n - 1} + F_{n - 2}"+ , Str "."+ , SoftBreak+ , Str "It"+ , Space+ , Str "can"+ , Space+ , Str "also"+ , Space+ , Str "be"+ , Space+ , Str "expressed"+ , Space+ , Str "in"+ , Space+ , Emph [ Str "closed" , Space , Str "form:" ]+ ]+ , Para+ [ Math+ DisplayMath+ "F_{n} = \\left\\lfloor {\\frac{1}{\\sqrt{5}}\\phi^{n}} \\right\\rceil,\\quad\\phi = \\frac{1 + \\sqrt{5}}{2}"+ ]+ , Para+ [ Str "The"+ , Space+ , Str "first"+ , Space+ , Str "8"+ , Space+ , Str "numbers"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "sequence"+ , Space+ , Str "are:"+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Math InlineMath "F_{1}" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Math InlineMath "F_{2}" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Math InlineMath "F_{3}" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Math InlineMath "F_{4}" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Math InlineMath "F_{5}" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Math InlineMath "F_{6}" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Math InlineMath "F_{7}" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Math InlineMath "F_{8}" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "1" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "2" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "3" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "5" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "8" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "13" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para [ Str "21" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Div+ ( "" , [ "columns-flow" ] , [ ( "count" , "2" ) ] )+ [ Para+ [ Span+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Link+ ( "" , [] , [] )+ [ SoftBreak+ , Strong+ [ Str "Typst"+ , Space+ , Str "Math"+ , Space+ , Str "for"+ , Space+ , Str "Undergrads"+ ]+ , SoftBreak+ ]+ ( "https://github.com/johanvx/typst-undergradmath"+ , ""+ )+ ]+ ]+ , Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "Typst"+ , Space+ , Str "port"+ , Space+ , Str "of"+ , Space+ , Emph+ [ Span+ ( "" , [ "box" ] , [] )+ [ Str "L\8202A\8202"+ , Span ( "" , [ "box" ] , [] ) [ Str "T\8202E\8202X" ]+ ]+ , Space+ , Str "Math"+ , Space+ , Str "for"+ , Space+ , Str "Undergrads"+ ]+ , Space+ , Str "by"+ , Space+ , Str "Jim"+ , Space+ , Str "Hefferon."+ , SoftBreak+ , Str "The"+ , Space+ , Str "original"+ , Space+ , Str "version"+ , Space+ , Str "is"+ , Space+ , Str "available"+ , Space+ , Str "at"+ , Space+ , Underline+ [ Link+ ( "" , [] , [] )+ [ Str "https://gitlab.com/jim.hefferon/undergradmath"+ ]+ ( "https://gitlab.com/jim.hefferon/undergradmath"+ , ""+ )+ ]+ , Str "."+ ]+ , Para+ [ Strong+ [ Str "Meaning"+ , Space+ , Str "of"+ , Space+ , Str "annotations\8192\160"+ ]+ ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidth 0.3333333333333333 )+ , ( AlignLeft , ColWidth 0.6666666666666666 )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Str "2023-05-22"+ , Space+ , Str "\10060"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "This"+ , Space+ , Str "is"+ , Space+ , Str "unavailable."+ , Space+ , Str "Last"+ , Space+ , Str "check"+ , Space+ , Str "date"+ , Space+ , Str "is"+ , Space+ , Str "2023-05-22."+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ , Para [ Span ( "unavailable" , [] , [] ) [] ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidth 0.3333333333333333 )+ , ( AlignLeft , ColWidth 0.6666666666666666 )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] ) [ Str "\128166" ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Get"+ , Space+ , Str "this"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "tricky"+ , Space+ , Str "way."+ , Space+ , Str "Need"+ , Space+ , Str "a"+ , Space+ , Str "simpler"+ , Space+ , Str "method."+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ , Para [ Span ( "tricky" , [] , [] ) [] ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidth 0.3333333333333333 )+ , ( AlignLeft , ColWidth 0.6666666666666666 )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Str "No"+ , Space+ , Str "idea"+ , Space+ , Str "\128533"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Str "Don\8217t"+ , Space+ , Str "know"+ , Space+ , Str "how"+ , Space+ , Str "to"+ , Space+ , Str "get"+ , Space+ , Str "this."+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ , Para [ Span ( "noidea" , [] , [] ) [] ]+ , Para+ [ Strong [ Str "Rule" , Space , Str "One\8192\160" ]+ , Str "Any"+ , Space+ , Str "mathematics"+ , Space+ , Str "at"+ , Space+ , Str "all,"+ , Space+ , Str "even"+ , Space+ , Str "a"+ , Space+ , Str "single"+ , Space+ , Str "character,"+ , Space+ , Str "gets"+ , Space+ , Str "a"+ , Space+ , Str "mathematical"+ , Space+ , Str "setting."+ , SoftBreak+ , Str "Thus,"+ , Space+ , Str "for"+ , Space+ , Str "\8220the"+ , Space+ , Str "value"+ , Space+ , Str "of"+ , Space+ , Math InlineMath "x"+ , Space+ , Str "is"+ , Space+ , Math InlineMath "7"+ , Str "\8221"+ , Space+ , Str "enter"+ , Space+ , Code ( "" , [] , [] ) "the value of $x$ is $7$"+ , Str "."+ ]+ , Para+ [ Strong [ Str "Template\8192\160" ]+ , Str "Your"+ , Space+ , Str "document"+ , Space+ , Str "should"+ , Space+ , Str "contain"+ , Space+ , Str "at"+ , Space+ , Str "least"+ , Space+ , Str "this."+ ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] ) "-- document body here --"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ , Para+ [ Strong+ [ Str "Common" , Space , Str "constructs\8192\160" ]+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "x^{2}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "x^2"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\sqrt{2}"+ , Str ","+ , Space+ , Math InlineMath "\\sqrt[n]{3}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "sqrt(2)"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "root(n, 3)"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "x_{i,j}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "x_(i, j)"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\frac{2}{3}"+ , Str ","+ , Space+ , Math InlineMath "2/3"+ , Str "\8192"+ , Code ( "" , [] , [] ) "2 / 3"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "2 \\/ 3"+ , Space+ , Str "or"+ , Space+ , Code ( "" , [] , [] ) "2 slash 3"+ ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Strong+ [ Str "Calligraphic" , Space , Str "letters\8192\160" ]+ , Str "Use"+ , Space+ , Str "as"+ , Space+ , Str "in"+ , Space+ , Code ( "" , [] , [] ) "$cal(A)$"+ , Str "."+ ]+ , Para+ [ Math DisplayMath "\\mathcal{ABCDEFGHIJKLMNOPQRSTUVWXYZ}" ]+ , Para+ [ Str "Getting"+ , Space+ , Str "script"+ , Space+ , Str "letters"+ , Space+ , Str "is"+ , Space+ , Link+ ( "" , [ "ref" ] , [] )+ [ Str "[unavailable]" ]+ ( "#unavailable" , "" )+ , Str "."+ ]+ , Para [ Strong [ Str "Greek\8192\160" ] ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\alpha"+ , Str "\8192"+ , Code ( "" , [] , [] ) "alpha"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\xi"+ , Str ","+ , Space+ , Math InlineMath "\\Xi"+ , Str "\8192"+ , Code ( "" , [] , [] ) "xi"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "Xi"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\beta"+ , Str "\8192"+ , Code ( "" , [] , [] ) "beta"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\959"+ , Str "\8192"+ , Code ( "" , [] , [] ) "omicron"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\gamma"+ , Str ","+ , Space+ , Math InlineMath "\\Gamma"+ , Str "\8192"+ , Code ( "" , [] , [] ) "gamma"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "Gamma"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\pi"+ , Str ","+ , Space+ , Math InlineMath "\\Pi"+ , Str "\8192"+ , Code ( "" , [] , [] ) "pi"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "Pi"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\delta"+ , Str ","+ , Space+ , Math InlineMath "\\Delta"+ , Str "\8192"+ , Code ( "" , [] , [] ) "delta"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "Delta"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\varpi"+ , Str "\8192"+ , Code ( "" , [] , [] ) "pi.alt"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\epsilon"+ , Str "\8192"+ , Code ( "" , [] , [] ) "epsilon.alt"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\rho"+ , Str "\8192"+ , Code ( "" , [] , [] ) "rho"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\varepsilon"+ , Str "\8192"+ , Code ( "" , [] , [] ) "epsilon"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\varrho"+ , Str "\8192"+ , Code ( "" , [] , [] ) "rho.alt"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\zeta"+ , Str "\8192"+ , Code ( "" , [] , [] ) "zeta"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\sigma"+ , Str ","+ , Space+ , Math InlineMath "\\Sigma"+ , Str "\8192"+ , Code ( "" , [] , [] ) "sigma"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "Sigma"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\eta"+ , Str "\8192"+ , Code ( "" , [] , [] ) "eta"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\varsigma"+ , Str "\8192"+ , Code ( "" , [] , [] ) "\\u{03C2}"+ , Space+ , Link+ ( "" , [ "ref" ] , [] )+ [ Str "[tricky]" ]+ ( "#tricky" , "" )+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\theta"+ , Str ","+ , Space+ , Math InlineMath "\\Theta"+ , Str "\8192"+ , Code ( "" , [] , [] ) "theta"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "Theta"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\tau"+ , Str "\8192"+ , Code ( "" , [] , [] ) "tau"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\vartheta"+ , Str "\8192"+ , Code ( "" , [] , [] ) "theta.alt"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\upsilon"+ , Str ","+ , Space+ , Math InlineMath "\\Upsilon"+ , Str "\8192"+ , Code ( "" , [] , [] ) "upsilon"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "Upsilon"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\iota"+ , Str "\8192"+ , Code ( "" , [] , [] ) "iota"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\phi"+ , Str ","+ , Space+ , Math InlineMath "\\Phi"+ , Str "\8192"+ , Code ( "" , [] , [] ) "phi.alt"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "Phi"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\kappa"+ , Str "\8192"+ , Math InlineMath "\922"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\varphi"+ , Str "\8192"+ , Code ( "" , [] , [] ) "phi"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\lambda"+ , Str ","+ , Space+ , Math InlineMath "\\Lambda"+ , Str "\8192"+ , Code ( "" , [] , [] ) "lambda"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "Lambda"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\chi"+ , Str "\8192"+ , Code ( "" , [] , [] ) "chi"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\mu"+ , Str "\8192"+ , Code ( "" , [] , [] ) "mu"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\psi"+ , Str ","+ , Space+ , Math InlineMath "\\Psi"+ , Str "\8192"+ , Code ( "" , [] , [] ) "psi"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "Psi"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\nu"+ , Str "\8192"+ , Code ( "" , [] , [] ) "nu"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\omega"+ , Str ","+ , Space+ , Math InlineMath "\\Omega"+ , Str "\8192"+ , Code ( "" , [] , [] ) "omega"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "Omega"+ ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Strong+ [ Str "Sets"+ , Space+ , Str "and"+ , Space+ , Str "logic\8192\160"+ ]+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\cup"+ , Str "\8192"+ , Code ( "" , [] , [] ) "union"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\mathbb{R}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "RR"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "bb(R)"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\forall"+ , Str "\8192"+ , Code ( "" , [] , [] ) "forall"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\cap"+ , Str "\8192"+ , Code ( "" , [] , [] ) "sect"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\mathbb{Z}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "ZZ"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "bb(Z)"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\exists"+ , Str "\8192"+ , Code ( "" , [] , [] ) "exists"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\subset"+ , Str "\8192"+ , Code ( "" , [] , [] ) "subset"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\mathbb{Q}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "QQ"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "bb(Q)"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\neg"+ , Str "\8192"+ , Code ( "" , [] , [] ) "not"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\subseteq"+ , Str "\8192"+ , Code ( "" , [] , [] ) "subset.eq"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\mathbb{N}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "NN"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "bb(N)"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\vee"+ , Str "\8192"+ , Code ( "" , [] , [] ) "or"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\supset"+ , Str "\8192"+ , Code ( "" , [] , [] ) "supset"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\mathbb{C}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "CC"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "bb(C)"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\land"+ , Str "\8192"+ , Code ( "" , [] , [] ) "and"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\supseteq"+ , Str "\8192"+ , Code ( "" , [] , [] ) "supset.eq"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\varnothing"+ , Str "\8192"+ , Code ( "" , [] , [] ) "diameter"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\vdash"+ , Str "\8192"+ , Code ( "" , [] , [] ) "tack.r"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\in"+ , Str "\8192"+ , Code ( "" , [] , [] ) "in"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\varnothing"+ , Str "\8192"+ , Code ( "" , [] , [] ) "nothing"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\models"+ , Str "\8192"+ , Code ( "" , [] , [] ) "models"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\notin"+ , Str "\8192"+ , Code ( "" , [] , [] ) "in.not"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\1488"+ , Str "\8192"+ , Code ( "" , [] , [] ) "alef"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\smallsetminus"+ , Str "\8192"+ , Code ( "" , [] , [] ) "without"+ ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "Negate"+ , Space+ , Str "an"+ , Space+ , Str "operator,"+ , Space+ , Str "as"+ , Space+ , Str "in"+ , Space+ , Math InlineMath "\8836"+ , Str ","+ , Space+ , Str "with"+ , Space+ , Code ( "" , [] , [] ) "subset.not"+ , Str "."+ , SoftBreak+ , Str "Get"+ , Space+ , Str "the"+ , Space+ , Str "set"+ , Space+ , Str "complement"+ , Space+ , Math InlineMath "A^{\\mathsf{c}}"+ , Space+ , Str "with"+ , Space+ , Code ( "" , [] , [] ) "A^(sans(c))"+ , Space+ , Str "(or"+ , Space+ , Math InlineMath "A^{\\complement}"+ , Space+ , Str "with"+ , Space+ , Code ( "" , [] , [] ) "A^(complement)"+ , Str ","+ , Space+ , Str "or"+ , Space+ , Math InlineMath "\\overline{A}"+ , Space+ , Str "with"+ , Space+ , Code ( "" , [] , [] ) "overline(A)"+ , Str ")."+ ]+ , DefinitionList+ [ ( [ Str "Remark" ]+ , [ [ Para+ [ Str "Using"+ , Space+ , Code ( "" , [] , [] ) "diameter"+ , Space+ , Str "for"+ , Space+ , Code ( "" , [] , [] ) "\\varnothing"+ , Space+ , Str "may"+ , Space+ , Str "cause"+ , Space+ , Str "some"+ , Space+ , Str "confusion."+ , Space+ , Str "However,"+ , Space+ , Span+ ( "" , [ "box" ] , [] )+ [ Str "L\8202A\8202"+ , Span+ ( "" , [ "box" ] , [] )+ [ Str "T\8202E\8202X" ]+ ]+ , Space+ , Str "also"+ , Space+ , Str "uses"+ , Space+ , Math InlineMath "\\varnothing"+ , Space+ , Str "("+ , Code ( "" , [] , [] ) "\\u{2300}"+ , Str ")"+ , Space+ , Str "instead"+ , Space+ , Str "of"+ , Space+ , Math InlineMath "\\varnothing"+ , Space+ , Str "("+ , Code ( "" , [] , [] ) "\\u{2205}"+ , Str "),"+ , Space+ , Str "see"+ , Space+ , Underline+ [ Link+ ( "" , [] , [] )+ [ Str "newcm"+ , Space+ , Math InlineMath "\167"+ , Str "13.3"+ ]+ ( "https://mirrors.sustech.edu.cn/CTAN/fonts/newcomputermodern/doc/newcm-doc.pdf"+ , ""+ )+ ]+ , Str "."+ , SoftBreak+ , Str "Another"+ , Space+ , Str "solution"+ , Space+ , Str "is"+ , Space+ , Str "to"+ , Space+ , Str "use"+ , Space+ , Code+ ( "" , [] , [] )+ "text(font: \"Fira Sans\", nothing)"+ , Str ","+ , Space+ , Str "but"+ , Space+ , Str "the"+ , Space+ , Str "resultant"+ , Space+ , Str "glyph"+ , Space+ , Math InlineMath "\\varnothing"+ , Space+ , Str "is"+ , Space+ , Str "subtly"+ , Space+ , Str "different"+ , Space+ , Str "from"+ , Space+ , Str "the"+ , Space+ , Str "widely"+ , Space+ , Str "used"+ , Space+ , Str "one."+ , SoftBreak+ , Str "Ultimately,"+ , Space+ , Str "the"+ , Space+ , Str "choice"+ , Space+ , Str "is"+ , Space+ , Str "always"+ , Space+ , Strong [ Str "your" , Space , Str "decision" ]+ , Str "."+ ]+ ]+ ]+ )+ ]+ , Para [ Strong [ Str "Decorations\8192\160" ] ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "f'"+ , Str "\8192"+ , Code ( "" , [] , [] ) "f'"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "f prime"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\dot{a}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "dot(a)"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\widetilde{a}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "tilde(a)"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "f''"+ , Str "\8192"+ , Code+ ( "" , [] , [] ) "f prime.double"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\ddot{a}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "diaer(a)"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\overline{a}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "macron(a)"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\Sigma^{\\ast}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "Sigma^*"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\hat{a}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "hat(a)"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math+ InlineMath+ "\\overset{\\rightarrow}{a}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "arrow(a)"+ ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "If"+ , Space+ , Str "the"+ , Space+ , Str "decorated"+ , Space+ , Str "letter"+ , Space+ , Str "is"+ , Space+ , Math InlineMath "i"+ , Space+ , Str "or"+ , Space+ , Math InlineMath "j"+ , Space+ , Str "then"+ , Space+ , Str "some"+ , Space+ , Str "decorations"+ , Space+ , Str "need"+ , Space+ , Code ( "" , [] , [] ) "\\u{1D6A4}"+ , Space+ , Link+ ( "" , [ "ref" ] , [] )+ [ Str "[tricky]" ]+ ( "#tricky" , "" )+ , Space+ , Str "and"+ , Space+ , Code ( "" , [] , [] ) "\\u{1D6A5}"+ , Space+ , Link+ ( "" , [ "ref" ] , [] )+ [ Str "[tricky]" ]+ ( "#tricky" , "" )+ , Str ","+ , Space+ , Str "as"+ , Space+ , Str "in"+ , Space+ , Math InlineMath "\\overset{\\rightarrow}{\\imath}"+ , Space+ , Str "with"+ , Space+ , Code ( "" , [] , [] ) "arrow(\\u{1D6A4})"+ , Str "."+ , SoftBreak+ , Str "Some"+ , Space+ , Str "authors"+ , Space+ , Str "use"+ , Space+ , Str "boldface"+ , Space+ , Str "for"+ , Space+ , Str "vectors:"+ , Space+ , Code ( "" , [] , [] ) "bold(x)"+ , Str "."+ ]+ , Para+ [ Str "Entering"+ , Space+ , Code ( "" , [] , [] ) "overline(x + y)"+ , Space+ , Str "produces"+ , Space+ , Math InlineMath "\\overline{x + y}"+ , Str ","+ , Space+ , Str "and"+ , Space+ , Code ( "" , [] , [] ) "hat(x + y)"+ , Space+ , Str "gives"+ , Space+ , Math InlineMath "\\hat{x + y}"+ , Str "."+ , SoftBreak+ , Str "Comment"+ , Space+ , Str "on"+ , Space+ , Str "an"+ , Space+ , Str "expression"+ , Space+ , Str "as"+ , Space+ , Str "here"+ , Space+ , Str "(there"+ , Space+ , Str "is"+ , Space+ , Str "also"+ , Space+ , Code ( "" , [] , [] ) "overbrace(..)"+ , Str ")."+ ]+ , Para+ [ Span+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math+ InlineMath "\\underset{|A|}{\\underbrace{x + y}}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "underbrace(x + y, |A|)"+ ]+ ]+ ]+ , Para+ [ Strong [ Str "Dots\8192\160" ]+ , Str "Use"+ , Space+ , Str "low"+ , Space+ , Str "dots"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "list"+ , Space+ , Math InlineMath "\\left\\{ 0,1,2,\\ldots \\right\\}"+ , Str ","+ , Space+ , Str "entered"+ , Space+ , Str "as"+ , Space+ , Code ( "" , [] , [] ) "{0, 1, 2, ...}"+ , Str "."+ , SoftBreak+ , Str "Use"+ , Space+ , Str "centered"+ , Space+ , Str "dots"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "sum"+ , Space+ , Str "or"+ , Space+ , Str "product"+ , Space+ , Math InlineMath "1 + \\cdots + 100"+ , Str ","+ , Space+ , Str "entered"+ , Space+ , Str "as"+ , Space+ , Code ( "" , [] , [] ) "1 + dots.h.c + 100"+ , Str "."+ , SoftBreak+ , Str "You"+ , Space+ , Str "can"+ , Space+ , Str "also"+ , Space+ , Str "get"+ , Space+ , Str "vertical"+ , Space+ , Str "dots"+ , Space+ , Code ( "" , [] , [] ) "dots.v"+ , Str ","+ , Space+ , Str "diagonal"+ , Space+ , Str "dots"+ , Space+ , Code ( "" , [] , [] ) "dots.down"+ , Space+ , Str "and"+ , Space+ , Str "anti-diagonal"+ , Space+ , Str "dots"+ , Space+ , Code ( "" , [] , [] ) "dots.up"+ , Str "."+ ]+ , Para+ [ Strong [ Str "Roman" , Space , Str "names\8192\160" ]+ , Str "Just"+ , Space+ , Str "type"+ , Space+ , Str "them!"+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\sin"+ , Str "\8192"+ , Code ( "" , [] , [] ) "sin"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\sinh"+ , Str "\8192"+ , Code ( "" , [] , [] ) "sinh"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\arcsin"+ , Str "\8192"+ , Code ( "" , [] , [] ) "arcsin"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\cos"+ , Str "\8192"+ , Code ( "" , [] , [] ) "cos"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\cosh"+ , Str "\8192"+ , Code ( "" , [] , [] ) "cosh"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\arccos"+ , Str "\8192"+ , Code ( "" , [] , [] ) "arccos"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\tan"+ , Str "\8192"+ , Code ( "" , [] , [] ) "tan"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\tanh"+ , Str "\8192"+ , Code ( "" , [] , [] ) "tanh"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\arctan"+ , Str "\8192"+ , Code ( "" , [] , [] ) "arctan"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\sec"+ , Str "\8192"+ , Code ( "" , [] , [] ) "sec"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\coth"+ , Str "\8192"+ , Code ( "" , [] , [] ) "coth"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\min"+ , Str "\8192"+ , Code ( "" , [] , [] ) "min"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\csc"+ , Str "\8192"+ , Code ( "" , [] , [] ) "csc"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\det"+ , Str "\8192"+ , Code ( "" , [] , [] ) "det"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\max"+ , Str "\8192"+ , Code ( "" , [] , [] ) "max"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\cot"+ , Str "\8192"+ , Code ( "" , [] , [] ) "cot"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\dim"+ , Str "\8192"+ , Code ( "" , [] , [] ) "dim"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\inf"+ , Str "\8192"+ , Code ( "" , [] , [] ) "inf"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\exp"+ , Str "\8192"+ , Code ( "" , [] , [] ) "exp"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\ker"+ , Str "\8192"+ , Code ( "" , [] , [] ) "ker"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\sup"+ , Str "\8192"+ , Code ( "" , [] , [] ) "sup"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\log"+ , Str "\8192"+ , Code ( "" , [] , [] ) "log"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\deg"+ , Str "\8192"+ , Code ( "" , [] , [] ) "deg"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\liminf"+ , Str "\8192"+ , Code ( "" , [] , [] ) "liminf"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\ln"+ , Str "\8192"+ , Code ( "" , [] , [] ) "ln"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\arg"+ , Str "\8192"+ , Code ( "" , [] , [] ) "arg"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\limsup"+ , Str "\8192"+ , Code ( "" , [] , [] ) "limsup"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\lg"+ , Str "\8192"+ , Code ( "" , [] , [] ) "lg"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\gcd"+ , Str "\8192"+ , Code ( "" , [] , [] ) "gcd"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\lim"+ , Str "\8192"+ , Code ( "" , [] , [] ) "lim"+ ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Strong [ Str "Other" , Space , Str "symbols\8192\160" ] ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "<"+ , Str "\8192"+ , Code ( "" , [] , [] ) "<"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "lt"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\angle"+ , Str "\8192"+ , Code ( "" , [] , [] ) "angle"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\cdot"+ , Str "\8192"+ , Code ( "" , [] , [] ) "dot"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\leq"+ , Str "\8192"+ , Code ( "" , [] , [] ) "<="+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "lt.eq"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\measuredangle"+ , Str "\8192"+ , Code ( "" , [] , [] ) "angle.arc"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\pm"+ , Str "\8192"+ , Code ( "" , [] , [] ) "plus.minus"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath ">"+ , Str "\8192"+ , Code ( "" , [] , [] ) ">"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "gt"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\ell"+ , Str "\8192"+ , Code ( "" , [] , [] ) "ell"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\mp"+ , Str "\8192"+ , Code ( "" , [] , [] ) "minus.plus"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\geq"+ , Str "\8192"+ , Code ( "" , [] , [] ) ">="+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "gt.eq"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\parallel"+ , Str "\8192"+ , Code ( "" , [] , [] ) "parallel"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\times"+ , Str "\8192"+ , Code ( "" , [] , [] ) "times"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\neq"+ , Str "\8192"+ , Code ( "" , [] , [] ) "!="+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "eq.not"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "45{^\\circ}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "45 degree"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\div"+ , Str "\8192"+ , Code ( "" , [] , [] ) "div"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\ll"+ , Str "\8192"+ , Code ( "" , [] , [] ) "<<"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "lt.double"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\cong"+ , Str "\8192"+ , Code ( "" , [] , [] ) "tilde.equiv"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\ast"+ , Str "\8192"+ , Code ( "" , [] , [] ) "*"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "ast"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\gg"+ , Str "\8192"+ , Code ( "" , [] , [] ) ">>"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "gt.double"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\ncong"+ , Str "\8192"+ , Code+ ( "" , [] , [] ) "tilde.equiv.not"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\mid"+ , Str "\8192"+ , Code ( "" , [] , [] ) "divides"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\approx"+ , Str "\8192"+ , Code ( "" , [] , [] ) "approx"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\sim"+ , Str "\8192"+ , Code ( "" , [] , [] ) "tilde"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\nmid"+ , Str "\8192"+ , Code ( "" , [] , [] ) "divides.not"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\asymp"+ , Str "\8192"+ , Code ( "" , [] , [] ) "\\u{224D}"+ , Space+ , Link+ ( "" , [ "ref" ] , [] )+ [ Str "[tricky]" ]+ ( "#tricky" , "" )+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\simeq"+ , Str "\8192"+ , Code ( "" , [] , [] ) "tilde.eq"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "n!"+ , Str "\8192"+ , Code ( "" , [] , [] ) "n!"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\equiv"+ , Str "\8192"+ , Code ( "" , [] , [] ) "equiv"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\nsim"+ , Str "\8192"+ , Code ( "" , [] , [] ) "tilde.not"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\partial"+ , Str "\8192"+ , Code ( "" , [] , [] ) "diff"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\prec"+ , Str "\8192"+ , Code ( "" , [] , [] ) "prec"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\oplus"+ , Str "\8192"+ , Code ( "" , [] , [] ) "plus.circle"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\nabla"+ , Str "\8192"+ , Code ( "" , [] , [] ) "nabla"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\preceq"+ , Str "\8192"+ , Code ( "" , [] , [] ) "prec.eq"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\ominus"+ , Str "\8192"+ , Code ( "" , [] , [] ) "minus.circle"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\295"+ , Str "\8192"+ , Code+ ( "" , [] , [] ) "planck.reduce"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\succ"+ , Str "\8192"+ , Code ( "" , [] , [] ) "succ"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\odot"+ , Str "\8192"+ , Code ( "" , [] , [] ) "dot.circle"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\circ"+ , Str "\8192"+ , Code+ ( "" , [] , [] )+ "circle.stroked.tiny"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\succeq"+ , Str "\8192"+ , Code ( "" , [] , [] ) "succ.eq"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\otimes"+ , Str "\8192"+ , Code ( "" , [] , [] ) "times.circle"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\star"+ , Str "\8192"+ , Code ( "" , [] , [] ) "star"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\propto"+ , Str "\8192"+ , Code ( "" , [] , [] ) "prop"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\oslash"+ , Str "\8192"+ , Code ( "" , [] , [] ) "\\u{2298}"+ , Space+ , Link+ ( "" , [ "ref" ] , [] )+ [ Str "[tricky]" ]+ ( "#tricky" , "" )+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\sqrt{}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "sqrt(\"\")"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\doteq"+ , Str "\8192"+ , Code ( "" , [] , [] ) "\\u{2250}"+ , Space+ , Link+ ( "" , [ "ref" ] , [] )+ [ Str "[tricky]" ]+ ( "#tricky" , "" )+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\upharpoonright"+ , Str "\8192"+ , Code ( "" , [] , [] ) "harpoon.tr"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\10003"+ , Str "\8192"+ , Code ( "" , [] , [] ) "checkmark"+ ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "Use"+ , Space+ , Code ( "" , [] , [] ) "a divides b"+ , Space+ , Str "for"+ , Space+ , Str "the"+ , Space+ , Str "divides"+ , Space+ , Str "relation,"+ , Space+ , Math InlineMath "a \\mid b"+ , Str ","+ , Space+ , Str "and"+ , Space+ , Code ( "" , [] , [] ) "a divides.not b"+ , Space+ , Str "for"+ , Space+ , Str "the"+ , Space+ , Str "negation,"+ , Space+ , Math InlineMath "a \\nmid b"+ , Str "."+ , SoftBreak+ , Str "Use"+ , Space+ , Code ( "" , [] , [] ) "|"+ , Space+ , Str "to"+ , Space+ , Str "get"+ , Space+ , Str "set"+ , Space+ , Str "builder"+ , Space+ , Str "notation"+ , Space+ , Math+ InlineMath+ "\\left\\{ a \\in S~|~a\\text{ is odd} \\right\\}"+ , Space+ , Str "with"+ , Space+ , Code ( "" , [] , [] ) "{a in S | a \"is odd\"}"+ , Str "."+ ]+ , Para [ Strong [ Str "Arrows\8192\160" ] ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\rightarrow"+ , Str "\8192"+ , Code ( "" , [] , [] ) "->"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "arrow.r"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\mapsto"+ , Str "\8192"+ , Code ( "" , [] , [] ) "|->"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "arrow.r.bar"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\nrightarrow"+ , Str "\8192"+ , Code ( "" , [] , [] ) "arrow.r.not"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\longmapsto"+ , Str "\8192"+ , Code+ ( "" , [] , [] )+ "arrow.r.long.bar"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\longrightarrow"+ , Str "\8192"+ , Code ( "" , [] , [] ) "arrow.r.long"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\leftarrow"+ , Str "\8192"+ , Code ( "" , [] , [] ) "<-"+ , Str ","+ , Space+ , Code ( "" , [] , [] ) "arrow.l"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\Rightarrow"+ , Str "\8192"+ , Code ( "" , [] , [] ) "=>"+ , Str ","+ , Space+ , Code+ ( "" , [] , [] ) "arrow.r.double"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math+ InlineMath "\\longleftrightarrow"+ , Str "\8192"+ , Code ( "" , [] , [] ) "<-->"+ , Str ","+ , Space+ , Code+ ( "" , [] , [] ) "arrow.l.r.long"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\nRightarrow"+ , Str "\8192"+ , Code+ ( "" , [] , [] )+ "arrow.r.double.not"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\downarrow"+ , Str "\8192"+ , Code ( "" , [] , [] ) "arrow.b"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\Longrightarrow"+ , Str "\8192"+ , Code+ ( "" , [] , [] )+ "arrow.r.double.long"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\uparrow"+ , Str "\8192"+ , Code ( "" , [] , [] ) "arrow.t"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\rightsquigarrow"+ , Str "\8192"+ , Code+ ( "" , [] , [] ) "arrow.squiggly"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\updownarrow"+ , Str "\8192"+ , Code ( "" , [] , [] ) "arrow.t.b"+ ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "The"+ , Space+ , Str "right"+ , Space+ , Str "arrows"+ , Space+ , Str "in"+ , Space+ , Str "the"+ , Space+ , Str "first"+ , Space+ , Str "column"+ , Space+ , Str "have"+ , Space+ , Str "matching"+ , Space+ , Str "left"+ , Space+ , Str "arrows,"+ , Space+ , Str "such"+ , Space+ , Str "as"+ , Space+ , Code ( "" , [] , [] ) "arrow.l.not"+ , Str ","+ , Space+ , Str "and"+ , Space+ , Str "there"+ , Space+ , Str "are"+ , Space+ , Str "some"+ , Space+ , Str "other"+ , Space+ , Str "matches"+ , Space+ , Str "for"+ , Space+ , Str "down"+ , Space+ , Str "arrows,"+ , Space+ , Str "etc."+ ]+ , Para+ [ Strong+ [ Str "Variable-sized"+ , Space+ , Str "operators\8192\160"+ ]+ , Str "The"+ , Space+ , Str "summation"+ , Space+ , Math InlineMath "\\sum_{j = 0}^{3}j^{2}"+ , Space+ , Code ( "" , [] , [] ) "sum_(j = 0)^3 j^2"+ , Space+ , Str "and"+ , Space+ , Str "the"+ , Space+ , Str "integral"+ , Space+ , Math InlineMath "\\int_{x = 0}^{3}x^{2}dx"+ , Space+ , Code ( "" , [] , [] ) "integral_(x = 0)^3 x^2 dif x"+ , Space+ , Str "expand"+ , Space+ , Str "when"+ , Space+ , Str "displayed."+ ]+ , Para+ [ Math+ DisplayMath+ "\\sum_{j = 0}^{3}j^{2}\\qquad\\int_{x = 0}^{3}x^{2}dx"+ ]+ , Para+ [ Str "These"+ , Space+ , Str "do"+ , Space+ , Str "the"+ , Space+ , Str "same."+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\int"+ , Str "\8192"+ , Code ( "" , [] , [] ) "integral"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\iiint"+ , Str "\8192"+ , Code+ ( "" , [] , [] ) "integral.triple"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\bigcup"+ , Str "\8192"+ , Code ( "" , [] , [] ) "union.big"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\iint"+ , Str "\8192"+ , Code+ ( "" , [] , [] ) "integral.double"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\oint"+ , Str "\8192"+ , Code+ ( "" , [] , [] ) "integral.cont"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\bigcap"+ , Str "\8192"+ , Code ( "" , [] , [] ) "sect.big"+ ]+ ]+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para [ Strong [ Str "Fences\8192\160" ] ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "()"+ , Str "\8192"+ , Code ( "" , [] , [] ) "()"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\langle\\rangle"+ , Str "\8192"+ , Code+ ( "" , [] , [] ) "angle.l angle.r"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math+ InlineMath "\\left| {} \\right|"+ , Str "\8192"+ , Code ( "" , [] , [] ) "abs(\"\")"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math InlineMath "\\lbrack\\rbrack"+ , Str "\8192"+ , Code ( "" , [] , [] ) "[]"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math+ InlineMath+ "\\left\\lfloor {} \\right\\rfloor"+ , Str "\8192"+ , Code ( "" , [] , [] ) "floor(\"\")"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math+ InlineMath+ "\\left\\| {} \\right\\|"+ , Str "\8192"+ , Code ( "" , [] , [] ) "norm(\"\")"+ ]+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math+ InlineMath "\\left\\{ \\right\\}"+ , Str "\8192"+ , Code ( "" , [] , [] ) "{}"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Span+ ( "" , [ "box" ] , [] )+ [ Math+ InlineMath+ "\\left\\lceil {} \\right\\rceil"+ , Str "\8192"+ , Code ( "" , [] , [] ) "ceil(\"\")"+ ]+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ []+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "Fix"+ , Space+ , Str "the"+ , Space+ , Str "size"+ , Space+ , Str "with"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "lr"+ , Space+ , Str "function."+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath+ "\\left. \\left\\lbrack \\sum_{k = 0}^{n}e^{k^{2}} \\right\\rbrack \\right."+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "lr([sum_(k = 0)^n e^(k^2)], size: #50%)"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "To"+ , Space+ , Str "have"+ , Space+ , Str "them"+ , Space+ , Str "grow"+ , Space+ , Str "with"+ , Space+ , Str "the"+ , Space+ , Str "enclosed"+ , Space+ , Str "formula,"+ , Space+ , Str "also"+ , Space+ , Str "use"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "lr"+ , Space+ , Str "function."+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath+ "\\left\\langle i,2^{2^{i}} \\right\\rangle"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "lr(angle.l i, 2^(2^i) angle.r)"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "Fences"+ , Space+ , Str "scale"+ , Space+ , Str "by"+ , Space+ , Str "default"+ , Space+ , Str "if"+ , Space+ , Str "entered"+ , Space+ , Str "directly"+ , Space+ , Str "as"+ , Space+ , Str "codepoints,"+ , Space+ , Str "and"+ , Space+ , Str "don\8217t"+ , Space+ , Str "scale"+ , Space+ , Str "automatically"+ , Space+ , Str "if"+ , Space+ , Str "entered"+ , Space+ , Str "as"+ , Space+ , Str "symbol"+ , Space+ , Str "notation."+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath+ "\\left( \\frac{1}{n^{\\alpha}} \\right)"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock ( "" , [] , [] ) "(1 / n^(alpha))"+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath "(\\frac{1}{n^{\\alpha}})"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "paren.l 1 / n^(alpha) paren.r"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "The"+ , Space+ , Code ( "" , [] , [] ) "lr"+ , Space+ , Str "function"+ , Space+ , Str "also"+ , Space+ , Str "allows"+ , Space+ , Str "to"+ , Space+ , Str "scale"+ , Space+ , Str "unmatched"+ , Space+ , Str "delimiters"+ , Space+ , Str "and"+ , Space+ , Str "one-side"+ , Space+ , Str "fences."+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath+ "\\left. \\frac{df}{dx} \\right|_{x_{0}}"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "lr(frac(dif f, dif x) |)_(x_0)"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Strong [ Str "Arrays," , Space , Str "Matrices\8192\160" ]+ , Str "Get"+ , Space+ , Str "a"+ , Space+ , Str "matrix"+ , Space+ , Str "with"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "mat"+ , Space+ , Str "function."+ , Space+ , Str "You"+ , Space+ , Str "can"+ , Space+ , Str "pass"+ , Space+ , Str "an"+ , Space+ , Str "array"+ , Space+ , Str "to"+ , Space+ , Str "it."+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath+ "\\begin{pmatrix}\na & b \\\\\nc & d\n\\end{pmatrix}"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] ) "$ mat(a, b; c, d) $"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "In"+ , Space+ , Str "Typst,"+ , Space+ , Underline+ [ Link+ ( "" , [] , [] )+ [ Str "array" ]+ ( "https://typst.app/docs/reference/typst/array"+ , ""+ )+ ]+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "sequence"+ , Space+ , Str "of"+ , Space+ , Str "values,"+ , SoftBreak+ , Str "while"+ , Space+ , Str "in"+ , Space+ , Span+ ( "" , [ "box" ] , [] )+ [ Str "L\8202A\8202"+ , Span ( "" , [ "box" ] , [] ) [ Str "T\8202E\8202X" ]+ ]+ , Str ","+ , Space+ , Str "array"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "matrix"+ , Space+ , Str "without"+ , Space+ , Str "fences,"+ , Space+ , Str "which"+ , Space+ , Str "is"+ , Space+ , Code ( "" , [] , [] ) "$mat(delim: #none, ..)$"+ , Space+ , Str "in"+ , Space+ , Str "Typst."+ ]+ , Para+ [ Str "For"+ , Space+ , Str "the"+ , Space+ , Str "determinant"+ , Space+ , Str "use"+ , Space+ , Code ( "" , [] , [] ) "|A|"+ , Str ","+ , Space+ , Str "text"+ , Space+ , Str "operator"+ , Space+ , Math InlineMath "\\det"+ , Space+ , Code ( "" , [] , [] ) "det"+ , Space+ , Str "or"+ , Space+ , Code ( "" , [] , [] ) "mat(delim: \"|\", ..)"+ , Str "."+ ]+ , Para+ [ Str "Definition"+ , Space+ , Str "by"+ , Space+ , Str "cases"+ , Space+ , Str "can"+ , Space+ , Str "be"+ , Space+ , Str "easily"+ , Space+ , Str "obtained"+ , Space+ , Str "with"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "cases"+ , Space+ , Str "function."+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath+ "f_{n} = \\begin{cases}\na & \\text{if }n = 0 \\\\\nr \\cdot f_{n - 1} & \\text{else }\n\\end{cases}"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "$ f_n = cases(\n a &\"if\" n = 0,\n r dot f_(n - 1) &\"else\"\n) $"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Strong+ [ Str "Spacing"+ , Space+ , Str "in"+ , Space+ , Str "mathematics\8192\160"+ ]+ , Str "Improve"+ , Space+ , Math InlineMath "\\sqrt{2}x"+ , Space+ , Str "to"+ , Space+ , Math InlineMath "\\sqrt{2}\\, x"+ , Space+ , Str "with"+ , Space+ , Str "a"+ , Space+ , Str "thin"+ , Space+ , Str "space,"+ , Space+ , Str "as"+ , Space+ , Str "in"+ , Space+ , Code ( "" , [] , [] ) "sqrt(2) thin x"+ , Str "."+ , SoftBreak+ , Str "Slightly"+ , Space+ , Str "wider"+ , Space+ , Str "are"+ , Space+ , Code ( "" , [] , [] ) "medium"+ , Space+ , Str "and"+ , Space+ , Code ( "" , [] , [] ) "thick"+ , Space+ , Str "(the"+ , Space+ , Str "three"+ , Space+ , Str "are"+ , Space+ , Str "in"+ , Space+ , Str "ratio"+ , Space+ , Math InlineMath "3:4:5"+ , Str ")."+ , SoftBreak+ , Str "Bigger"+ , Space+ , Str "space"+ , Space+ , Str "is"+ , Space+ , Code ( "" , [] , [] ) "quad"+ , Space+ , Str "for"+ , Space+ , Math InlineMath "\\rightarrow \\quad \\leftarrow"+ , Str ","+ , Space+ , Str "which"+ , Space+ , Str "is"+ , Space+ , Str "useful"+ , Space+ , Str "between"+ , Space+ , Str "parts"+ , Space+ , Str "of"+ , Space+ , Str "a"+ , Space+ , Str "display."+ , SoftBreak+ , Str "Get"+ , Space+ , Str "arbitrary"+ , Space+ , Str "space"+ , Space+ , Str "with"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "h"+ , Space+ , Str "function."+ , SoftBreak+ , Str "For"+ , Space+ , Str "example,"+ , Space+ , Str "use"+ , Space+ , Code ( "" , [] , [] ) "#h(2em)"+ , Space+ , Str "for"+ , Space+ , Code ( "" , [] , [] ) "\\qquad"+ , Space+ , Str "in"+ , Space+ , Span+ ( "" , [ "box" ] , [] )+ [ Str "L\8202A\8202"+ , Span ( "" , [ "box" ] , [] ) [ Str "T\8202E\8202X" ]+ ]+ , Space+ , Str "and"+ , Space+ , Code ( "" , [] , [] ) "#h(-0.1667em)"+ , Space+ , Str "for"+ , Space+ , Code ( "" , [] , [] ) "\\!"+ , Str "."+ ]+ , Para+ [ Strong+ [ Str "Displayed" , Space , Str "equations\8192\160" ]+ , Str "Display"+ , Space+ , Str "equations"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "block"+ , Space+ , Str "level"+ , Space+ , Str "using"+ , Space+ , Code ( "" , [] , [] ) "$ ... $"+ , Space+ , Str "with"+ , Space+ , Str "at"+ , Space+ , Str "least"+ , Space+ , Str "one"+ , Space+ , Str "space"+ , Space+ , Str "separating"+ , Space+ , Str "the"+ , Space+ , Str "math"+ , Space+ , Str "content"+ , Space+ , Str "and"+ , Space+ , Str "the"+ , Space+ , Code ( "" , [] , [] ) "$"+ , Str "."+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math DisplayMath "S = k \\cdot \\lg W" ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] ) "$ S = k dot lg W $"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "You"+ , Space+ , Str "can"+ , Space+ , Str "break"+ , Space+ , Str "into"+ , Space+ , Str "multiple"+ , Space+ , Str "lines."+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath+ "\\begin{array}{r}\n\\sin(x) = x - \\frac{x^{3}}{3!} \\\\\n + \\frac{x^{5}}{5!} - \\cdots\n\\end{array}"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "$ sin(x) = x - x^3 / 3! \\\n + x^5 / 5! - dots.h.c $"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "Align"+ , Space+ , Str "equations"+ , Space+ , Str "using"+ , Space+ , Code ( "" , [] , [] ) "&"+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignLeft , ColWidthDefault )+ , ( AlignLeft , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath+ "\\begin{aligned}\n\\nabla \\cdot \\mathbf{D} & = \\rho \\\\\n\\nabla \\cdot \\mathbf{B} & = 0\n\\end{aligned}"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "$ nabla dot bold(D) &= rho \\\n nabla dot bold(B) &= 0 $"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "(the"+ , Space+ , Str "left"+ , Space+ , Str "or"+ , Space+ , Str "right"+ , Space+ , Str "side"+ , Space+ , Str "of"+ , Space+ , Str "an"+ , Space+ , Str "alignment"+ , Space+ , Str "can"+ , Space+ , Str "be"+ , Space+ , Str "empty)."+ , SoftBreak+ , Str "Get"+ , Space+ , Str "a"+ , Space+ , Str "numbered"+ , Space+ , Str "version"+ , Space+ , Str "by"+ , Space+ , Code ( "" , [] , [] ) "#set math.equation(numbering: ..)"+ , Str "."+ ]+ , Para+ [ Strong+ [ Str "Calculus" , Space , Str "examples\8192\160" ]+ , Str "The"+ , Space+ , Str "last"+ , Space+ , Str "three"+ , Space+ , Str "here"+ , Space+ , Str "are"+ , Space+ , Str "display"+ , Space+ , Str "style."+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ InlineMath+ "f:{\\mathbb{R}} \\rightarrow {\\mathbb{R}}"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock ( "" , [] , [] ) "f: RR -> RR" ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math InlineMath "9.8\\ \\text{ m/s}^{2}"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Code+ ( "" , [] , [] ) "\"9.8\" \"m/s\"^2"+ , Space+ , Link+ ( "" , [ "ref" ] , [] )+ [ Str "[tricky]" ]+ ( "#tricky" , "" )+ ]+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath+ "\\lim\\limits_{h \\rightarrow 0}\\frac{f(x + h) - f(x)}{h}"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "lim_(h -> 0) (f(x + h) - f(x)) / h"+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath+ "\\int x^{2}dx = x^{3}/3 + C"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "integral x^2 dif x = x^3 \\/ 3 + C"+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ DisplayMath+ "\\nabla = \\mathbf{i}\\frac{d}{dx} + \\mathbf{j}\\frac{d}{dy} + \\mathbf{k}\\frac{d}{dz}"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "nabla = bold(i) dif / (dif x) + bold(j) dif / (dif y) + bold(k) dif / (dif z)"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Strong+ [ Str "Discrete"+ , Space+ , Str "mathematics"+ , Space+ , Str "examples\8192\160"+ ]+ , Str "For"+ , Space+ , Str "modulo,"+ , Space+ , Str "there"+ , Space+ , Str "is"+ , Space+ , Str "a"+ , Space+ , Str "symbol"+ , Space+ , Math InlineMath "\\equiv"+ , Space+ , Str "from"+ , Space+ , Code ( "" , [] , [] ) "equiv"+ , Space+ , Str "and"+ , Space+ , Str "a"+ , Space+ , Str "text"+ , Space+ , Str "operator"+ , Space+ , Math InlineMath "\\operatorname{mod}"+ , Space+ , Str "from"+ , Space+ , Code ( "" , [] , [] ) "mod"+ , Str "."+ ]+ , Para+ [ Str "For"+ , Space+ , Str "combinations"+ , Space+ , Str "the"+ , Space+ , Str "binomial"+ , Space+ , Str "symbol"+ , Space+ , Math InlineMath "\\binom{n}{k}"+ , Space+ , Str "is"+ , Space+ , Str "from"+ , Space+ , Code ( "" , [] , [] ) "binom(n, k)"+ , Str "."+ , SoftBreak+ , Str "This"+ , Space+ , Str "resizes"+ , Space+ , Str "to"+ , Space+ , Str "be"+ , Space+ , Str "bigger"+ , Space+ , Str "in"+ , Space+ , Str "a"+ , Space+ , Str "display."+ ]+ , Para+ [ Str "For"+ , Space+ , Str "permutations"+ , Space+ , Str "use"+ , Space+ , Math InlineMath "n^{\\underline{r}}"+ , Space+ , Str "from"+ , Space+ , Code ( "" , [] , [] ) "n^(underline(r))"+ , Space+ , Str "(some"+ , Space+ , Str "authors"+ , Space+ , Str "use"+ , Space+ , Math InlineMath "P(n,r)"+ , Str ","+ , Space+ , Str "or"+ , Space+ , Math InlineMath "{}_{n}P_{r}"+ , Space+ , Str "from"+ , Space+ , Code ( "" , [] , [] ) "\"\"_n P_r"+ , Str ")."+ ]+ , Para+ [ Strong+ [ Str "Statistics" , Space , Str "examples\8192\160" ]+ ]+ , Div+ ( "" , [] , [ ( "align" , "center" ) ] )+ [ Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ InlineMath+ "\\sigma^{2} = \\sqrt{{\\sum(x_{i} - \\mu)}^{2}/N}"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "sigma^2 = sqrt(sum(x_i - mu)^2 \\/ N)"+ ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Para+ [ Math+ InlineMath+ "E(X) = \\mu_{X} = \\sum(x_{i} - P\\left( x_{i} \\right))"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "E(X) = mu_X = sum(x_i - P(x_i))"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]+ , Para+ [ Str "The"+ , Space+ , Str "probability"+ , Space+ , Str "density"+ , Space+ , Str "of"+ , Space+ , Str "the"+ , Space+ , Str "normal"+ , Space+ , Str "distribution"+ ]+ , Para+ [ Math+ DisplayMath+ "\\frac{1}{\\sqrt{2\\sigma^{2}\\pi}}e^{- \\frac{(x - \\mu)^{2}}{2\\sigma^{2}}}"+ ]+ , Para+ [ Str "comes" , Space , Str "from" , Space , Str "this." ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead ( "" , [] , [] ) [])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ []+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ CodeBlock+ ( "" , [] , [] )+ "1 / sqrt(2 sigma^2 pi)\n e^(- (x - mu)^2 / (2 sigma^2))"+ ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ , Para+ [ Strong [ Str "For" , Space , Str "more\8192\160" ]+ , Str "See"+ , Space+ , Str "also"+ , Space+ , Str "the"+ , Space+ , Str "Typst"+ , Space+ , Str "Documentation"+ , Space+ , Str "at"+ , Space+ , Underline+ [ Link+ ( "" , [] , [] )+ [ Str "https://typst.app/docs" ]+ ( "https://typst.app/docs" , "" )+ ]+ , Str "."+ ]+ , HorizontalRule+ , Para+ [ Str "johanvx"+ , Space+ , Str "("+ , Underline+ [ Link+ ( "" , [] , [] )+ [ Str "https://github.com/johanvx" ]+ ( "https://github.com/johanvx" , "" )+ ]+ , Str ")"+ , Space+ , Str "\8202\8193"+ , Space+ , Str "2023-05-22"+ ]+ ]+ ]
@@ -0,0 +1,28 @@+#set page(width: 10cm, height: auto)+#set heading(numbering: "1.")++= Fibonacci sequence+The Fibonacci sequence is defined through the+recurrence relation $F_n = F_(n-1) + F_(n-2)$.+It can also be expressed in _closed form:_++$ F_n = round(1 / sqrt(5) phi.alt^n), quad+ phi.alt = (1 + sqrt(5)) / 2 $++#let count = 8+#let nums = range(1, count + 1)+#let fib(n) = (+ if n <= 2 { 1 }+ else { fib(n - 1) + fib(n - 2) }+)++The first #count numbers of the sequence are:++#align(center, table(+ columns: count,+ ..nums.map(n => $F_#n$),+ ..nums.map(n => str(fib(n))),+))++#include "undergradmath.typ"+
@@ -0,0 +1,510 @@+// Licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.+// https://creativecommons.org/licenses/by-sa/4.0/++// Meta data+#set document(title: "Typst Math for Undergrads", author: "johanvx")++// Margin+#set page(margin: 0.5in)++// Font size+#let scriptsize = 7pt+#let normalsize = 10pt+#let large = 12pt+#set text(size: normalsize, lang: "en")++// Some horizontal spacing+#let kern(length) = h(length, weak: true)+#let enspace = kern(0.5em)+#let qquad = h(2em)++// For table/grid, something like "lhs \enspace rhs"+#let cell(lhs, rhs) = box(lhs + enspace + rhs)+// Grid for code blocks+#set grid(columns: (2em, auto))+// Table for math-code listing+#set table(stroke: none, align: horizon + left, inset: 0pt, row-gutter: 0.45em)++// LaTeX and TeX logos+#let TeX = style(styles => {+ let e = measure(text(normalsize, "E"), styles)+ let T = "T"+ let E = text(normalsize, baseline: e.height / 2, "E")+ let X = "X"+ box(T + kern(-0.1667em) + E + kern(-0.125em) + X)+})+#let LaTeX = style(styles => {+ let l = measure(text(10pt, "L"), styles)+ let a = measure(text(7pt, "A"), styles)+ let L = "L"+ let A = text(7pt, baseline: a.height - l.height, "A")+ box(L + kern(-0.36em) + A + kern(-0.15em) + TeX)+})++// Update date+#let date = "2023-05-22"++// Unavailable (last check date)+#show "??": box(text(red, [#date #emoji.crossmark]))+// Tricky+#show "!!": box(text(blue, emoji.drops))+// No idea+#show "?!": box(text(orange, [No idea #emoji.face.unhappy]))+// Tricky figure numbering+#set figure(numbering: n => {+ ([??], [!!], [?!]).at(n - 1)+})+// No prefix+#set ref(supplement: "")++// Justified paragraphs+#set par(justify: true)++// Two-column body+#show: rest => columns(2, rest)++// headcolor+#let headcolor = rgb("004225")++// Run-in sections, like LaTeX \paragraph+#show heading.where(+ level: 1+): it => text(+ size: normalsize,+ weight: "bold",+ fill: headcolor,+ it.body + h(0.67em)+)++// Black raw code+// #show raw.where(block: false): it => { it.text }++// Title+#align(center, link("https://github.com/johanvx/typst-undergradmath")[+ #text(large, headcolor)[*Typst Math for Undergrads*]+])++// Put this here to avoid affecting the title+#show link: underline++This is a Typst port of _#LaTeX Math for Undergrads_ by Jim Hefferon.+The original version is available at #link("https://gitlab.com/jim.hefferon/undergradmath").++= Meaning of annotations+#figure(+ table(+ columns: (1fr, 2fr),+ [??], [This is unavailable. Last check date is #date.],+ )+) <unavailable>+#figure(+ table(+ columns: (1fr, 2fr),+ [!!], [Get this in a tricky way. Need a simpler method.],+ )+) <tricky>+#figure(+ table(+ columns: (1fr, 2fr),+ [?!], [Don't know how to get this.],+ )+) <noidea>++= Rule One+Any mathematics at all, even a single character, gets a mathematical setting.+Thus, for "the value of $x$ is $7$" enter `the value of $x$ is $7$`.++= Template+Your document should contain at least this.++#grid(+ "",+ ```+ -- document body here --+ ```+)++= Common constructs+#align(center, table(+ columns: 2,+ column-gutter: 1.5em,+ cell($x^2$, `x^2`),+ cell([$sqrt(2)$, $root(n, 3)$], [`sqrt(2)`, `root(n, 3)`]),+ cell($x_(i, j)$, `x_(i, j)`),+ cell([$2 / 3$, $2 \/ 3$], [`2 / 3`, `2 \/ 3` or `2 slash 3`]), // Maybe use `slash`?+))++= Calligraphic letters+Use as in `$cal(A)$`.++$ cal(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) $++Getting script letters is @unavailable.++= Greek+#align(center, table(+ columns: 2,+ column-gutter: 1em,+ cell($alpha$, `alpha`), cell([$xi$, $Xi$], [`xi`, `Xi`]),+ cell($beta$, `beta`), cell($omicron$, `omicron`),+ cell([$gamma$, $Gamma$], [`gamma`, `Gamma`]), cell([$pi$, $Pi$], [`pi`, `Pi`]),+ cell([$delta$, $Delta$], [`delta`, `Delta`]), cell($pi.alt$, `pi.alt`),+ cell($epsilon.alt$, `epsilon.alt`), cell($rho$, `rho`),+ cell($epsilon$, `epsilon`), cell($rho.alt$, `rho.alt`),+ cell($zeta$, `zeta`), cell([$sigma$, $Sigma$], [`sigma`, `Sigma`]),+ cell($eta$, `eta`), cell($\u{03C2}$, [`\u{03C2}` @tricky]),+ cell([$theta$, $Theta$], [`theta`, `Theta`]), cell($tau$, `tau`),+ cell($theta.alt$, `theta.alt`), cell([$upsilon$, $Upsilon$], [`upsilon`, `Upsilon`]),+ cell($iota$, `iota`), cell([$phi.alt$, $Phi$], [`phi.alt`, `Phi`]),+ cell($kappa$, $Kappa$), cell($phi$, `phi`),+ cell([$lambda$, $Lambda$], [`lambda`, `Lambda`]), cell($chi$, `chi`),+ cell($mu$, `mu`), cell([$psi$, $Psi$], [`psi`, `Psi`]),+ cell($nu$, `nu`), cell([$omega$, $Omega$], [`omega`, `Omega`]),+))++= Sets and logic+#align(center, table(+ columns: 3,+ column-gutter: 1em,+ cell($union$, `union`), cell($RR$, [`RR`, `bb(R)`]), cell($forall$, `forall`),+ cell($sect$, `sect`), cell($bb(Z)$, [`ZZ`, `bb(Z)`]), cell($exists$, `exists`),+ cell($subset$, `subset`), cell($bb(Q)$, [`QQ`, `bb(Q)`]), cell($not$, `not`),+ cell($subset.eq$, `subset.eq`), cell($bb(N)$, [`NN`, `bb(N)`]), cell($or$, `or`),+ cell($supset$, `supset`), cell($bb(C)$, [`CC`, `bb(C)`]), cell($and$, `and`),+ cell($supset.eq$, `supset.eq`), cell($diameter$, [`diameter`]), cell($tack.r$, `tack.r`),+ cell($in$, `in`), cell($nothing$, `nothing`), cell($models$, `models`),+ cell($in.not$, `in.not`), cell($alef$, `alef`), cell($without$, `without`),+))++Negate an operator, as in $subset.not$, with `subset.not`.+Get the set complement $A^(sans(c))$ with `A^(sans(c))` (or $A^(complement)$ with `A^(complement)`, or $overline(A)$ with `overline(A)`).++// https://www.ctan.org/tex-archive/fonts/newcomputermodern+//+// README+//+// Version 3.93+//+// Provides access to Russian and Greek guillemotleft and guillemotright+// using the character variant tables cv3 and cv4 respectively.+//+// The Math fonts provide the character \varnothing, an alternative to \emptyset,+// through Character Variant cv01. The fontsetup package provides the option+// 'varnothing' to easily switch to the alternative character.++// https://mirrors.sustech.edu.cn/CTAN/fonts/newcomputermodern/doc/newcm-doc.pdf+// The NewComputerModern FontFamily §13.3+// The Math fonts provide the character \varnothing (⌀, U+2300), as an alternative to \emptyset (a slashed zero), through Character Variant cv01.+// The fontsetup package provides the option ‘varnothing’ to easily switch to the alternative character.++/ Remark: Using `diameter` for `\varnothing` may cause some confusion. However, #LaTeX also uses $diameter$ (`\u{2300}`) instead of $\u{2205}$ (`\u{2205}`), see #link("https://mirrors.sustech.edu.cn/CTAN/fonts/newcomputermodern/doc/newcm-doc.pdf")[newcm $section$13.3].+ Another solution is to use `text(font: "Fira Sans", nothing)`, but the resultant glyph $text(font: "Fira Sans", nothing)$ is subtly different from the widely used one.+ Ultimately, the choice is always *your decision*.++= Decorations+#align(center, table(+ columns: 3,+ column-gutter: 1em,+ cell($f'$, [`f'`, `f prime`]), cell($dot(a)$, `dot(a)`), cell($tilde(a)$, `tilde(a)`),+ cell($f prime.double$, `f prime.double`), cell($diaer(a)$, `diaer(a)`), cell($macron(a)$, `macron(a)`),+ cell($Sigma^*$, `Sigma^*`), cell($hat(a)$, `hat(a)`), cell($arrow(a)$, `arrow(a)`),+))++If the decorated letter is $i$ or $j$ then some decorations need `\u{1D6A4}` @tricky and `\u{1D6A5}` @tricky, as in $arrow(\u{1D6A4})$ with `arrow(\u{1D6A4})`.+Some authors use boldface for vectors: `bold(x)`.++Entering `overline(x + y)` produces $overline(x + y)$, and `hat(x + y)` gives $hat(x + y)$.+Comment on an expression as here (there is also `overbrace(..)`).++#align(center, cell(+ $underbrace(x + y, |A|)$,+ `underbrace(x + y, |A|)`,+))++= Dots+Use low dots in a list ${0, 1, 2, ...}$, entered as `{0, 1, 2, ...}`.+Use centered dots in a sum or product $1 + dots.h.c + 100$, entered as `1 + dots.h.c + 100`.+You can also get vertical dots `dots.v`, diagonal dots `dots.down` and anti-diagonal dots `dots.up`.++= Roman names+Just type them!++#align(center, table(+ columns: 3,+ column-gutter: 1.5em,+ cell($sin$, `sin`), cell($sinh$, `sinh`), cell($arcsin$, `arcsin`),+ cell($cos$, `cos`), cell($cosh$, `cosh`), cell($arccos$, `arccos`),+ cell($tan$, `tan`), cell($tanh$, `tanh`), cell($arctan$, `arctan`),+ cell($sec$, `sec`), cell($coth$, `coth`), cell($min$, `min`),+ cell($csc$, `csc`), cell($det$, `det`), cell($max$, `max`),+ cell($cot$, `cot`), cell($dim$, `dim`), cell($inf$, `inf`),+ cell($exp$, `exp`), cell($ker$, `ker`), cell($sup$, `sup`),+ cell($log$, `log`), cell($deg$, `deg`), cell($liminf$, `liminf`),+ cell($ln$, `ln`), cell($arg$, `arg`), cell($limsup$, `limsup`),+ cell($lg$, `lg`), cell($gcd$, `gcd`), cell($lim$, `lim`),+))++= Other symbols+#align(center, table(+ columns: 3,+ column-gutter: 1.2em,+ cell($<$, [`<`, `lt`]), cell($angle$, `angle`), cell($dot$, [`dot`]),+ cell($<=$, [`<=`, `lt.eq`]), cell($angle.arc$, `angle.arc`), cell($plus.minus$, `plus.minus`),+ cell($>$, [`>`, `gt`]), cell($ell$, `ell`), cell($minus.plus$, `minus.plus`),+ cell($>=$, [`>=`, `gt.eq`]), cell($parallel$, `parallel`), cell($times$, `times`),+ cell($!=$, [`!=`, `eq.not`]), cell($45 degree$, `45 degree`), cell($div$, `div`),+ cell($<<$, [`<<`, `lt.double`]), cell($tilde.equiv$, `tilde.equiv`), cell($*$, [`*`, `ast`]),+ cell($>>$, [`>>`, `gt.double`]), cell($tilde.equiv.not$, `tilde.equiv.not`), cell($divides$, `divides`),+ cell($approx$, `approx`), cell($tilde$, `tilde`), cell($divides.not$, `divides.not`),+ cell($\u{224D}$, [`\u{224D}` @tricky]), cell($tilde.eq$, `tilde.eq`), cell($n!$, `n!`),+ cell($equiv$, `equiv`), cell($tilde.not$, `tilde.not`), cell($diff$, `diff`),+ cell($prec$, `prec`), cell($plus.circle$, `plus.circle`), cell($nabla$, `nabla`),+ cell($prec.eq$, `prec.eq`), cell($minus.circle$, `minus.circle`), cell($planck.reduce$, `planck.reduce`),+ cell($succ$, `succ`), cell($dot.circle$, `dot.circle`), cell($circle.stroked.tiny$, `circle.stroked.tiny`),+ cell($succ.eq$, `succ.eq`), cell($times.circle$, `times.circle`), cell($star$, `star`),+ cell($prop$, `prop`), cell($\u{2298}$, [`\u{2298}` @tricky]), cell($sqrt("")$, `sqrt("")`),+ cell($\u{2250}$, [`\u{2250}` @tricky]), cell($harpoon.tr$, `harpoon.tr`), cell($checkmark$, `checkmark`),+))++Use `a divides b` for the divides relation, $a divides b$, and `a divides.not b` for the negation, $a divides.not b$.+Use `|` to get set builder notation ${a in S | a "is odd"}$ with `{a in S | a "is odd"}`.++= Arrows+#align(center, table(+ columns: 2,+ column-gutter: 1.5em,+ cell($->$, [`->`, `arrow.r`]), cell($|->$, [`|->`, `arrow.r.bar`]),+ cell($arrow.r.not$, `arrow.r.not`), cell($arrow.r.long.bar$, `arrow.r.long.bar`),+ cell($arrow.r.long$, `arrow.r.long`), cell($<-$, [`<-`, `arrow.l`]),+ cell($=>$, [`=>`, `arrow.r.double`]), cell($<-->$, [`<-->`, `arrow.l.r.long`]),+ cell($arrow.r.double.not$, `arrow.r.double.not`), cell($arrow.b$, `arrow.b`),+ cell($arrow.r.double.long$, `arrow.r.double.long`), cell($arrow.t$, `arrow.t`),+ cell($arrow.squiggly$, `arrow.squiggly`), cell($arrow.t.b$, `arrow.t.b`),+))++The right arrows in the first column have matching left arrows, such as `arrow.l.not`, and there are some other matches for down arrows, etc.++= Variable-sized operators+The summation $sum_(j = 0)^3 j^2$ `sum_(j = 0)^3 j^2` and the integral $integral_(x = 0)^3 x^2 dif x$ `integral_(x = 0)^3 x^2 dif x` expand when displayed.++$ sum_(j = 0)^3 j^2 qquad integral_(x = 0)^3 x^2 dif x $++These do the same.++#align(center, table(+ columns: 3,+ cell($integral$, `integral`), cell($integral.triple$, `integral.triple`), cell($union.big$, `union.big`),+ cell($integral.double$, `integral.double`), cell($integral.cont$, `integral.cont`), cell($sect.big$, `sect.big`),+))++= Fences+#align(center, table(+ columns: 3,+ column-gutter: 1.5em,+ cell($()$, `()`), cell($angle.l angle.r$, `angle.l angle.r`), cell($abs("")$, `abs("")`),+ cell($[]$, `[]`), cell($floor("")$, `floor("")`), cell($norm("")$, `norm("")`),+ cell(${}$, `{}`), cell($ceil("")$, `ceil("")`),+))++Fix the size with the `lr` function.++#align(center, table(+ columns: 2,+ column-gutter: 0.5em,+ $ lr([sum_(k = 0)^n e^(k^2)], size: #50%) $,+ ```+ lr([sum_(k = 0)^n e^(k^2)], size: #50%)+ ```,+))++To have them grow with the enclosed formula, also use the `lr` function.++#align(center, table(+ columns: 2,+ column-gutter: 1em,+ $ lr(angle.l i, 2^(2^i) angle.r) $,+ ```+ lr(angle.l i, 2^(2^i) angle.r)+ ```,+))++Fences scale by default if entered directly as codepoints, and don't scale automatically if entered as symbol notation.++#align(center, table(+ columns: 2,+ column-gutter: 1em,+ $ (1 / n^(alpha)) $,+ ```+ (1 / n^(alpha))+ ```,+ $ paren.l 1 / n^(alpha) paren.r $,+ ```+ paren.l 1 / n^(alpha) paren.r+ ```,+))++The `lr` function also allows to scale unmatched delimiters and one-side fences.++#align(center, table(+ columns: 2,+ column-gutter: 1em,+ $ lr(frac(dif f, dif x) |)_(x_0) $,+ ```+ lr(frac(dif f, dif x) |)_(x_0)+ ```,+))++= Arrays, Matrices+Get a matrix with the `mat` function. You can pass an array to it.++#align(center, table(+ columns: 2,+ column-gutter: 1em,+ $ mat(a, b; c, d) $,+ ```+ $ mat(a, b; c, d) $+ ```+))++In Typst, #link("https://typst.app/docs/reference/typst/array")[array] is a sequence of values,+while in #LaTeX, array is a matrix without fences, which is `$mat(delim: #none, ..)$` in Typst.++For the determinant use `|A|`, text operator $det$ `det` or `mat(delim: "|", ..)`.++Definition by cases can be easily obtained with the `cases` function.++#align(center, table(+ columns: 2,+ column-gutter: 1em,+ $ f_n = cases(+ a &"if" n = 0,+ r dot f_(n - 1) &"else"+ ) $,+ ```+ $ f_n = cases(+ a &"if" n = 0,+ r dot f_(n - 1) &"else"+ ) $+ ```+))++= Spacing in mathematics+Improve $sqrt(2) x$ to $sqrt(2) thin x$ with a thin space, as in `sqrt(2) thin x`.+Slightly wider are `medium` and `thick` (the three are in ratio $3 : 4 : 5$).+Bigger space is `quad` for $arrow.r quad arrow.l$, which is useful between parts of a display.+Get arbitrary space with the `h` function.+For example, use `#h(2em)` for `\qquad` in #LaTeX and `#h(-0.1667em)` for `\!`.++= Displayed equations+Display equations in a block level using `$ ... $` with at least one space separating the math content and the `$`.++#align(center, table(+ columns: 2,+ column-gutter: 1em,+ $ S = k dot lg W $,+ ```+ $ S = k dot lg W $+ ```,+))++You can break into multiple lines.++#align(center, table(+ columns: 2,+ column-gutter: 1em,+ $ sin(x) = x - x^3 / 3! \+ + x^5 / 5! - dots.h.c $,+ ```+ $ sin(x) = x - x^3 / 3! \+ + x^5 / 5! - dots.h.c $+ ```,+))++Align equations using `&`++#align(center, table(+ columns: 2,+ column-gutter: 1em,+ $ nabla dot bold(D) &= rho \+ nabla dot bold(B) &= 0 $,+ ```+ $ nabla dot bold(D) &= rho \+ nabla dot bold(B) &= 0 $+ ```,+))++(the left or right side of an alignment can be empty).+Get a numbered version by `#set math.equation(numbering: ..)`.++= Calculus examples+The last three here are display style.++#align(center, table(+ align: horizon,+ columns: 2,+ column-gutter: 1em,+ block($f: RR -> RR$),+ ```+ f: RR -> RR+ ```,+ block($"9.8" "m/s"^2$),+ block([`"9.8" "m/s"^2` @tricky]),+ $ lim_(h->0) (f(x+h)-f(x))/h $,+ ```+ lim_(h -> 0) (f(x + h) - f(x)) / h+ ```,+ $ integral x^2 dif x = x^3 \/ 3 + C $,+ ```+ integral x^2 dif x = x^3 \/ 3 + C+ ```,+ $ nabla = bold(i) dif / (dif x) + bold(j) dif / (dif y) + bold(k) dif / (dif z) $,+ ```+ nabla = bold(i) dif / (dif x) + bold(j) dif / (dif y) + bold(k) dif / (dif z)+ ```,+))++= Discrete mathematics examples+For modulo, there is a symbol $equiv$ from `equiv` and a text operator $mod$ from `mod`.++For combinations the binomial symbol $binom(n, k)$ is from `binom(n, k)`.+This resizes to be bigger in a display.++For permutations use $n^(underline(r))$ from `n^(underline(r))` (some authors use $P(n, r)$, or $""_n P_r$ from `""_n P_r`).++= Statistics examples+#align(center, table(+ align: horizon,+ columns: 2,+ block($sigma^2 = sqrt(sum(x_i - mu)^2 \/ N)$),+ ```+ sigma^2 = sqrt(sum(x_i - mu)^2 \/ N)+ ```,+ block($E(X) = mu_X = sum(x_i - P(x_i))$),+ ```+ E(X) = mu_X = sum(x_i - P(x_i))+ ```,+))++The probability density of the normal distribution++$ 1 / sqrt(2 sigma^2 pi) e^(- (x - mu)^2 / (2 sigma^2)) $++comes from this.++#grid(+ "",+ ```+ 1 / sqrt(2 sigma^2 pi)+ e^(- (x - mu)^2 / (2 sigma^2))+ ```+)++= For more+See also the Typst Documentation at #link("https://typst.app/docs").++#v(1fr)++#block(+ line(length: 100%, stroke: headcolor) ++ text(headcolor)[johanvx (https://github.com/johanvx) #h(1fr) #date]+)
@@ -0,0 +1,70 @@+---+vimdoc-prefix: pandoc+abstract: "A short description"+filename: "definition-lists.txt"+author: Author+title: Title+---++## Basic++Term 1+: Definition I++Term 2+: Definition II++Term 3+: Definition III++## Code++<!-- Source: <https://github.com/ggandor/leap.nvim/blob/c4a215acef90749851d85ddba08bc282867b50eb/doc/leap.txt#L283-L294> -->++`leap.opts.keys.next_target`+: Jump to the next available target (use the previous search pattern if no input+ has been given). `:h leap-repeat`++`leap.opts.keys.prev_target`+: Jump to the previous target (revert `next_target`).++`leap.opts.keys.next_group`+: Shift to the next group of labeled targets.++`leap.opts.keys.prev_group`+: Shift to the previous group of labeled targets (revert `next_group`).++## Span++[Important concept]{#important-concept}+: Definition++[I am too long to fit on the same line as a reference, so reference is put above me!]{#i-am-too-long}+: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod+ tempor incididunt ut labore et dolore magna aliqua.++## Commands++In markdown vim commands are represented as inline code starting with colon (ie.+`:MyCommand`), but writer strips the backticks++`:FnlCompileBuffer`{#:FnlCompileBuffer}++: Compiles current active fennel buffer++`:FnlCompile[!]`{#:FnlCompile}++: Diff compiles all indexed fennel files+ If bang! is present then forcefully compiles all `source` files++`:[range]Fnl {expr}`{#:Fnl}++: Evaluates {expr} or range++ ```+ :'<,'>Fnl++ :Fnl (print "Hello World")++ :Fnl (values some_var)+ ```
@@ -0,0 +1,71 @@+*definition-lists.txt* A short description++ Title by Author+++ Type |gO| to see the table of contents.++Basic ........................................................... |pandoc-basic|+Code ............................................................. |pandoc-code|+Span ............................................................. |pandoc-span|+Commands ..................................................... |pandoc-commands|++------------------------------------------------------------------------------+Basic *pandoc-basic*++Term 1+ Definition I+Term 2+ Definition II+Term 3+ Definition III++------------------------------------------------------------------------------+Code *pandoc-code*++`leap.opts.keys.next_target`+ Jump to the next available target (use the previous search pattern if no+ input has been given). |leap-repeat|+`leap.opts.keys.prev_target`+ Jump to the previous target (revert `next_target`).+`leap.opts.keys.next_group`+ Shift to the next group of labeled targets.+`leap.opts.keys.prev_group`+ Shift to the previous group of labeled targets (revert `next_group`).++------------------------------------------------------------------------------+Span *pandoc-span*++Important concept *pandoc-important-concept*+ Definition+ *pandoc-i-am-too-long*+I am too long to fit on the same line as a reference, so reference is put+above me!+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod+ tempor incididunt ut labore et dolore magna aliqua.++------------------------------------------------------------------------------+Commands *pandoc-commands*++In markdown vim commands are represented as inline code starting with colon+(ie. `:MyCommand`), but writer strips the backticks++:FnlCompileBuffer *:FnlCompileBuffer*+ Compiles current active fennel buffer++:FnlCompile[!] *:FnlCompile*+ Diff compiles all indexed fennel files If bang! is present then forcefully+ compiles all `source` files++:[range]Fnl {expr} *:Fnl*+ Evaluates {expr} or range++ >+ :'<,'>Fnl++ :Fnl (print "Hello World")++ :Fnl (values some_var)+<++ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
@@ -0,0 +1,108 @@+ Type |gO| to see the table of contents.++1. unremarkable header 1 ............................... |unremarkable-header-1|+ 1.1 unremarkable header 2 ............................ |unremarkable-header-2|+ 1.1.1 unremarkable header 3 ...................... |unremarkable-header-3|+ 1.1.2 unremarkable header 3 .................... |unremarkable-header-3-1|+ unremarkable header 2 .............................. |unremarkable-header-2-1|+ unremarkable header 3 ............................ |unremarkable-header-3-2|+ unremarkable header 3 ............................ |unremarkable-header-3-3|+2. bold italic underline strikethrough ............................... |short11|+ 2.1 superscript2 subscript3 ........................................ |short21|+ 2.1.1 smallcaps code inline math display math .................. |short31|+ 2.1.2 link image ............................................... |short32|+3. Long header 1 long header 1 long header 1 long header 1 long heade... |long1|+ 3.1 Long header 2 long header 2 long header 2 long header 2 long h... |long21|+ 3.1.1 Long header 3 long header 3 long header 3 long header 3.... |long31|+ 3.1.2 Long header 3 long header 3 long header 3 long header 3.... |long32|+ 3.2 Long header 2 long header 2 long header 2 long header 2 long h... |long22|+ 3.2.1 Long header 3 long header 3 long header 3 long header 3.... |long33|+ 3.2.2 Long header 3 long header 3 long header 3 long header 3.... |long34|+4. ... |long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1|+ 4.1 ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2|+ 4.1.1 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3|+ 4.1.2 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-1|+ 4.2 ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1|+ 4.2.1 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-2|+ 4.2.2 ... |long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-3|+++Headers with a short title and implicit ref. Last 3 headers are unnumbered.++==============================================================================+unremarkable header 1 *unremarkable-header-1*++------------------------------------------------------------------------------+unremarkable header 2 *unremarkable-header-2*++UNREMARKABLE HEADER 3 *unremarkable-header-3*++UNREMARKABLE HEADER 3 *unremarkable-header-3-1*++------------------------------------------------------------------------------+unremarkable header 2 *unremarkable-header-2-1*++UNREMARKABLE HEADER 3 *unremarkable-header-3-2*++UNREMARKABLE HEADER 3 *unremarkable-header-3-3*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with various inline elements++==============================================================================+bold italic underline strikethrough *short11*++------------------------------------------------------------------------------+superscript2 subscript3 *short21*++SMALLCAPS `code` `$inline math$` `$display math$` *short31*++LINK example.com *short32*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with a long name and explicit short ref++==============================================================================+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long21*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long31*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long32*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long22*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long33*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long34*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with a long name and implicit ref.++Since implicit ref is very lengthy, there is no way to fit it. Therefore title+is not rendered and the references exceed the columns (textwidth) limit++==============================================================================+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-2*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-3*++ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
@@ -0,0 +1,45 @@+Headers with a short title and implicit ref. Last 3 headers are unnumbered.++# unremarkable header 1+## unremarkable header 2+### unremarkable header 3+### unremarkable header 3+## unremarkable header 2 {.unnumbered}+### unremarkable header 3 {.unnumbered}+### unremarkable header 3 {.unnumbered}++---++Headers with various inline elements++# **bold** *italic* [underline]{.underline} ~strikethrough~ {#short11}+## superscript^2^ subscript~3~ {#short21}+### [smallcaps]{.smallcaps} `code` $inline math$ $$display math$$ {#short31}+### [link](example.com)  {#short32}++---++Headers with a long name and explicit short ref++# Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 {#long1}+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 {#long21}+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long31}+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long32}+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 {#long22}+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long33}+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 {#long34}++---++Headers with a long name and implicit ref.++Since implicit ref is very lengthy, there is no way to fit it. Therefore title+is not rendered and the references exceed the columns (textwidth) limit++# Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3+## Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3+### Long header 3 long header 3 long header 3 long header 3 long header 3 long header 3 long header 3
@@ -0,0 +1,94 @@+ Type |gO| to see the table of contents.++unremarkable header 1 .................................. |unremarkable-header-1|+ unremarkable header 2 ................................ |unremarkable-header-2|+ unremarkable header 2 .............................. |unremarkable-header-2-1|+bold italic underline strikethrough .................................. |short11|+ superscript2 subscript3 ............................................ |short21|+Long header 1 long header 1 long header 1 long header 1 long header 1... |long1|+ Long header 2 long header 2 long header 2 long header 2 long heade... |long21|+ Long header 2 long header 2 long header 2 long header 2 long heade... |long22|+... |long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1|+ ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2|+ ... |long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1|+++Headers with a short title and implicit ref. Last 3 headers are unnumbered.++==============================================================================+unremarkable header 1 *unremarkable-header-1*++------------------------------------------------------------------------------+unremarkable header 2 *unremarkable-header-2*++UNREMARKABLE HEADER 3 *unremarkable-header-3*++UNREMARKABLE HEADER 3 *unremarkable-header-3-1*++------------------------------------------------------------------------------+unremarkable header 2 *unremarkable-header-2-1*++UNREMARKABLE HEADER 3 *unremarkable-header-3-2*++UNREMARKABLE HEADER 3 *unremarkable-header-3-3*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with various inline elements++==============================================================================+bold italic underline strikethrough *short11*++------------------------------------------------------------------------------+superscript2 subscript3 *short21*++SMALLCAPS `code` `$inline math$` `$display math$` *short31*++LINK example.com *short32*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with a long name and explicit short ref++==============================================================================+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long21*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long31*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long32*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long22*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long33*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long34*++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++Headers with a long name and implicit ref.++Since implicit ref is very lengthy, there is no way to fit it. Therefore title+is not rendered and the references exceed the columns (textwidth) limit++==============================================================================+Long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 long header 1 *long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1-long-header-1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-1*++------------------------------------------------------------------------------+Long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 long header 2 *long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-long-header-2-1*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-2*++LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 LONG HEADER 3 *long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-long-header-3-3*++ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
@@ -0,0 +1,42 @@+# Online vim documentation++While vim documentation can be accessed with `:help`, it may be beneficial to+link to the websites inside readme/markdown docs. Two most common websites are:++- <https://vimhelp.org/> and+- <https://neovim.io/doc/user>++Also it is not uncommon to reference documentation as `:h <topic>`++## Links to vimhelp.org {#vimhelp-links}++For introduction to writing help files see+<https://vimhelp.org/helphelp.txt.html#help-writing>++Named link: [vimhelp link](https://vimhelp.org/helphelp.txt.html#help-writing)++## Links to neo.vimhelp.org {#neo-vimhelp-links}++For introduction to writing help files see+<https://neo.vimhelp.org/helphelp.txt.html#help-writing>++Named link: [vimhelp link](https://neo.vimhelp.org/helphelp.txt.html#help-writing)++## Links to neovim.io {#neovim-io-links}++For introduction to writing help files see+<https://neovim.io/doc/user/helphelp.html#help-writing>++Named link: [neovim.io link](https://neovim.io/doc/user/helphelp.html#help-writing)++You can also reference whole files with topic omitted:+<https://neovim.io/doc/user/vim_diff.html>++## :h-style documentation {#colon-h-docs}++For introduction to writing help files see+`:h help-writing`++Long name for `:help` is also supported: `:help help-writing`++This is malformed: `:help help-writing `, but this is not: `:help help-writing`
@@ -0,0 +1,53 @@+ Type |gO| to see the table of contents.++Online vim documentation ............................ |online-vim-documentation|+ Links to vimhelp.org ......................................... |vimhelp-links|+ Links to neo.vimhelp.org ................................. |neo-vimhelp-links|+ Links to neovim.io ......................................... |neovim-io-links|+ :h-style documentation ........................................ |colon-h-docs|++==============================================================================+Online vim documentation *online-vim-documentation*++While vim documentation can be accessed with `:help`, it may be beneficial to+link to the websites inside readme/markdown docs. Two most common websites+are:++- https://vimhelp.org/ and+- https://neovim.io/doc/user++Also it is not uncommon to reference documentation as |<topic>|++------------------------------------------------------------------------------+Links to vimhelp.org *vimhelp-links*++For introduction to writing help files see |help-writing|++Named link: vimhelp link |help-writing|++------------------------------------------------------------------------------+Links to neo.vimhelp.org *neo-vimhelp-links*++For introduction to writing help files see |help-writing|++Named link: vimhelp link |help-writing|++------------------------------------------------------------------------------+Links to neovim.io *neovim-io-links*++For introduction to writing help files see |help-writing|++Named link: neovim.io link |help-writing|++You can also reference whole files with topic omitted: |vim_diff.txt|++------------------------------------------------------------------------------+:h-style documentation *colon-h-docs*++For introduction to writing help files see |help-writing|++Long name for `:help` is also supported: |help-writing|++This is malformed: |help-writing|, but this is not: |help-writing|++ vim:tw=78:sw=4:ts=4:ft=help:norl:et:
@@ -559,13 +559,13 @@ [ Str "internal" , Space , Str "links" ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "This is a link" ]- ( "This is a link" , "wikilink" )+ ( "This is a link" , "" ) ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "Description" , Space , Str "of"@@ -574,27 +574,27 @@ , Space , Str "link" ]- ( "This is a link source" , "wikilink" )+ ( "This is a link source" , "" ) ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "projects/Important Project 1" ]- ( "projects/Important Project 1" , "wikilink" )+ ( "projects/Important Project 1" , "" ) , SoftBreak , Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "../index" ]- ( "../index" , "wikilink" )+ ( "../index" , "" ) , SoftBreak , Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "Other" , Space , Str "files" ]- ( "a subdirectory/" , "wikilink" )+ ( "a subdirectory/" , "" ) ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "try" , Space , Str "me"@@ -607,11 +607,11 @@ , Space , Str "anchors" ]- ( "#tag-one" , "wikilink" )+ ( "#tag-one" , "" ) ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "try" , Space , Str "me"@@ -624,11 +624,11 @@ , Space , Str "anchors" ]- ( "#block quotes" , "wikilink" )+ ( "#block quotes" , "" ) ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "try" , Space , Str "me"@@ -641,19 +641,19 @@ , Space , Str "anchors" ]- ( "#strong" , "wikilink" )+ ( "#strong" , "" ) ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "Tasks" , Space , Str "for" , Space , Str "tomorrow" ]- ( "Todo List#Tomorrow" , "wikilink" )+ ( "Todo List#Tomorrow" , "" ) ] , Para [ Link- ( "" , [] , [] )+ ( "" , [ "wikilink" ] , [] ) [ Str "diary:2017-05-01" ]- ( "diary/2017-05-01" , "wikilink" )+ ( "diary/2017-05-01" , "" ) ] , Para [ Link
@@ -1,6 +1,7 @@ = Pandoc Test Suite John MacFarlane; Anonymous July 17, 2006+:stem: latexmath This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite.@@ -39,7 +40,7 @@ Because a hard-wrapped line in the middle of a paragraph looked like a list item. -Here’s one with a bullet. * criminey.+Here’s one with a bullet. ++*++ criminey. There should be a hard line break + here.@@ -83,7 +84,7 @@ -- ____ -This should not be a block quote: 2 > 1.+This should not be a block quote: 2 ++>++ 1. And a following paragraph. @@ -423,9 +424,9 @@ So is *_this_* word. -This is code: `>`, `$`, `\`, `\$`, `<html>`.+This is code: `++>++`, `$`, `++\++`, `++\++$`, `++<++html++>++`. -[line-through]*This is _strikeout_.*+[line-through]#This is _strikeout_.# Superscripts: a^bc^d a^_hello_^ a^hello there^. @@ -438,16 +439,16 @@ == Smart quotes, ellipses, dashes -``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. @@ -460,24 +461,24 @@ == LaTeX * -* latexmath:[$2+2=4$]-* latexmath:[$x \in y$]-* latexmath:[$\alpha \wedge \omega$]-* latexmath:[$223$]-* latexmath:[$p$]-Tree+* latexmath:[2+2=4]+* latexmath:[x \in y]+* latexmath:[\alpha \wedge \omega]+* latexmath:[223]+* latexmath:[p]-Tree * Here’s some display math: + [latexmath] ++++-\[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}\]+\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h} ++++ * Here’s one that has a line break in it:-latexmath:[$\alpha + \omega \times x^2$].+latexmath:[\alpha + \omega \times x^2]. These shouldn’t be math: * To get the famous equation, write `$e = mc^2$`.-* $22,000 is a _lot_ of money. So is $34,000. (It worked if ``lot'' is+* $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$.@@ -502,39 +503,39 @@ This & that. -4 < 5.+4 ++<++ 5. -6 > 5.+6 ++>++ 5. -Backslash: \+Backslash: ++\++ -Backtick: `+Backtick: ++`++ -Asterisk: *+Asterisk: ++*++ -Underscore: _+Underscore: ++_++ -Left brace: \{+Left brace: ++{++ Right brace: } -Left bracket: [+Left bracket: ++[++ -Right bracket: ]+Right bracket: ++]++ Left paren: ( Right paren: ) -Greater-than: >+Greater-than: ++>++ -Hash: #+Hash: ++#++ Period: . Bang: ! -Plus: ++Plus: {plus} Minus: - @@ -556,7 +557,7 @@ link:/url/[URL and title] -link:/url/with_underscore[with_underscore]+link:/url/with_underscore[with++_++underscore] mailto:nobody@nowhere.net[Email link] @@ -566,7 +567,7 @@ Foo link:/url/[bar]. -With link:/url/[embedded [brackets]].+With link:/url/[embedded ++[++brackets++]++]. link:/url/[b] by itself should be a link. @@ -576,7 +577,7 @@ Indented link:/url[thrice]. -This should [not][] be a link.+This should ++[++not++][]++ be a link. .... [not]: /url@@ -610,7 +611,7 @@ Blockquoted: http://example.com/ ____ -Auto-links should not occur here: `<http://example.com/>`+Auto-links should not occur here: `++<++http://example.com/++>++` .... or here: <http://example.com/>@@ -620,8 +621,9 @@ == Images -From ``Voyage dans la Lune'' by Georges Melies (1902):+From "`Voyage dans la Lune`" by Georges Melies (1902): +.lalune image::lalune.jpg[lalune,title="Voyage dans la Lune"] Here is a movie image:movie.jpg[movie] icon.@@ -633,10 +635,10 @@ Here is a footnote reference,footnote:[Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.] and another.[multiblock footnote omitted] This should _not_ be a footnote-reference, because it contains a space.[^my note] Here is an inline+reference, because it contains a space.++[++^my note++]++ Here is an inline note.footnote:[This is _easier_ to type. Inline notes may contain-http://google.com[links] and `]` verbatim characters, as well as [bracketed-text].]+http://google.com[links] and `++]++` verbatim characters, as well as+++[++bracketed text++]++.] ____ Notes can go in quotes.footnote:[In quote.]
@@ -0,0 +1,649 @@+= Pandoc Test Suite+John MacFarlane; Anonymous+July 17, 2006++This is a set of tests for pandoc. Most of them are adapted from John Gruber’s+markdown test suite.++'''''++== Headers++=== Level 2 with an link:/url[embedded link]++==== Level 3 with _emphasis_++===== Level 4++====== Level 5++== Level 1++=== Level 2 with _emphasis_++==== Level 3++with no blank line++=== Level 2++with no blank line++'''''++== Paragraphs++Here’s a regular paragraph.++In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.+Because a hard-wrapped line in the middle of a paragraph looked like a list+item.++Here’s one with a bullet. ++*++ criminey.++There should be a hard line break ++here.++'''''++== Block Quotes++E-mail style:++____+This is a block quote. It is pretty short.+____++____+--+Code in a block quote:++....+sub status {+ print "working";+}+....++A list:++[arabic]+. item one+. item two++Nested block quotes:++____+nested+____++____+nested+____++--+____++This should not be a block quote: 2 ++>++ 1.++And a following paragraph.++'''''++== Code Blocks++Code:++....+---- (should be four hyphens)++sub status {+ print "working";+}++this code block is indented by one tab+....++And:++....+ this code block is indented by two tabs++These should not be escaped: \$ \\ \> \[ \{+....++'''''++== Lists++=== Unordered++Asterisks tight:++* asterisk 1+* asterisk 2+* asterisk 3++Asterisks loose:++* asterisk 1+* asterisk 2+* asterisk 3++Pluses tight:++* Plus 1+* Plus 2+* Plus 3++Pluses loose:++* Plus 1+* Plus 2+* Plus 3++Minuses tight:++* Minus 1+* Minus 2+* Minus 3++Minuses loose:++* Minus 1+* Minus 2+* Minus 3++=== Ordered++Tight:++[arabic]+. First+. Second+. Third++and:++[arabic]+. One+. Two+. Three++Loose using tabs:++[arabic]+. First+. Second+. Third++and using spaces:++[arabic]+. One+. Two+. Three++Multiple paragraphs:++[arabic]+. Item 1, graf one.+++Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.+. Item 2.+. Item 3.++=== Nested++* Tab+** Tab+*** Tab++Here’s another:++[arabic]+. First+. Second:+* Fee+* Fie+* Foe+. Third++Same thing but with paragraphs:++[arabic]+. First+. Second:+* Fee+* Fie+* Foe+. Third++=== Tabs and spaces++* this is a list item indented with tabs+* this is a list item indented with spaces+** this is an example list item indented with tabs+** this is an example list item indented with spaces++=== Fancy list markers++[arabic, start=2]+. begins with 2+. and now 3+++with a continuation+[lowerroman, start=4]+.. sublist with roman numerals, starting with 4+.. more items+[upperalpha]+... a subsublist+... a subsublist++Nesting:++[upperalpha]+. Upper Alpha+[upperroman]+.. Upper Roman.+[arabic, start=6]+... Decimal start with 6+[loweralpha, start=3]+.... Lower alpha with paren++Autonumbering:++. Autonumber.+. More.+.. Nested.++Should not be a list item:++M.A. 2007++B. Williams++'''''++== Definition Lists++Tight using spaces:++apple::+ red fruit+orange::+ orange fruit+banana::+ yellow fruit++Tight using tabs:++apple::+ red fruit+orange::+ orange fruit+banana::+ yellow fruit++Loose:++apple::+ red fruit+orange::+ orange fruit+banana::+ yellow fruit++Multiple blocks with italics:++_apple_::+ red fruit+ ++ contains seeds, crisp, pleasant to taste+_orange_::+ orange fruit+ ++....+{ orange code block }+....+ ++ ____+ orange block quote+ ____++Multiple definitions, tight:++apple::+ red fruit+ ++ computer+orange::+ orange fruit+ ++ bank++Multiple definitions, loose:++apple::+ red fruit+ ++ computer+orange::+ orange fruit+ ++ bank++Blank line after term, indented marker, alternate markers:++apple::+ red fruit+ ++ computer+orange::+ orange fruit+ ++ [arabic]+ . sublist+ . sublist++== HTML Blocks++Simple block on one line:++foo++And nested without indentation:++foo++bar++Interpreted markdown in a table:++This is _emphasized_++And this is *strong*++Here’s a simple block:++foo++This should be a code block, though:++....+<div>+ foo+</div>+....++As should this:++....+<div>foo</div>+....++Now, nested:++foo++This should just be an HTML comment:++Multiline:++Code block:++....+<!-- Comment -->+....++Just plain comment, with trailing spaces on the line:++Code:++....+<hr />+....++Hr’s:++'''''++== Inline Markup++This is _emphasized_, and so _is this_.++This is *strong*, and so *is this*.++An _link:/url[emphasized link]_.++*_This is strong and em._*++So is *_this_* word.++*_This is strong and em._*++So is *_this_* word.++This is code: `>`, `$`, `\`, `\$`, `<html>`.++[line-through]#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.++'''''++== Smart quotes, ellipses, dashes++``Hello,'' said the spider. ```Shelob' is my name.''++`A', `B', and `C' are letters.++`Oak,' `elm,' and `beech' are names of trees. So is `pine.'++`He said, ``I want to go.''' Were you alive in the 70’s?++Here is some quoted ``code`' and a ``http://example.com/?foo=1&bar=2[quoted+link]''.++Some dashes: one—two — three—four — five.++Dashes between numbers: 5–7, 255–66, 1987–1999.++Ellipses…and…and….++'''''++== LaTeX++* +* latexmath:[$2+2=4$]+* latexmath:[$x \in y$]+* latexmath:[$\alpha \wedge \omega$]+* latexmath:[$223$]+* latexmath:[$p$]-Tree+* Here’s some display math:+++[latexmath]++++++\[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}\]++++++* Here’s one that has a line break in it:+latexmath:[$\alpha + \omega \times x^2$].++These shouldn’t be math:++* To get the famous equation, write `$e = mc^2$`.+* $22,000 is a _lot_ of money. So is $34,000. (It worked if ``lot'' is+emphasized.)+* Shoes ($20) and socks ($5).+* Escaped `$`: $73 _this should be emphasized_ 23$.++Here’s a LaTeX table:++'''''++== Special Characters++Here is some unicode:++* I hat: Î+* o umlaut: ö+* section: §+* set membership: ∈+* copyright: ©++AT&T has an ampersand in their name.++AT&T is another way to write it.++This & that.++4 ++<++ 5.++6 ++>++ 5.++Backslash: ++\++++Backtick: ++`++++Asterisk: ++*++++Underscore: ++_++++Left brace: ++{++++Right brace: }++Left bracket: ++[++++Right bracket: ++]++++Left paren: (++Right paren: )++Greater-than: ++>++++Hash: ++#++++Period: .++Bang: !++Plus: {plus}++Minus: -++'''''++== Links++=== Explicit++Just a link:/url/[URL].++link:/url/[URL and title].++link:/url/[URL and title].++link:/url/[URL and title].++link:/url/[URL and title]++link:/url/[URL and title]++link:/url/with_underscore[with++_++underscore]++mailto:nobody@nowhere.net[Email link]++link:[Empty].++=== Reference++Foo link:/url/[bar].++With link:/url/[embedded ++[++brackets++]++].++link:/url/[b] by itself should be a link.++Indented link:/url[once].++Indented link:/url[twice].++Indented link:/url[thrice].++This should ++[++not++][]++ be a link.++....+[not]: /url+....++Foo link:/url/[bar].++Foo link:/url/[biz].++=== With ampersands++Here’s a http://example.com/?foo=1&bar=2[link with an ampersand in the URL].++Here’s a link with an amersand in the link text: http://att.com/[AT&T].++Here’s an link:/script?foo=1&bar=2[inline link].++Here’s an link:/script?foo=1&bar=2[inline link in pointy braces].++=== Autolinks++With an ampersand: http://example.com/?foo=1&bar=2++* In a list?+* http://example.com/+* It should.++An e-mail address: nobody@nowhere.net++____+Blockquoted: http://example.com/+____++Auto-links should not occur here: `<http://example.com/>`++....+or here: <http://example.com/>+....++'''''++== Images++From ``Voyage dans la Lune'' by Georges Melies (1902):++.lalune+image::lalune.jpg[lalune,title="Voyage dans la Lune"]++Here is a movie image:movie.jpg[movie] icon.++'''''++== Footnotes++Here is a footnote reference,footnote:[Here is the footnote. It can go anywhere+after the footnote reference. It need not be placed at the end of the document.]+and another.[multiblock footnote omitted] This should _not_ be a footnote+reference, because it contains a space.++[++^my note++]++ Here is an inline+note.footnote:[This is _easier_ to type. Inline notes may contain+http://google.com[links] and `]` verbatim characters, as well as ++[++bracketed+text++]++.]++____+Notes can go in quotes.footnote:[In quote.]+____++[arabic]+. And in list items.footnote:[In list.]++This paragraph should not be part of the note, as it is not indented.
@@ -1,649 +0,0 @@-= Pandoc Test Suite-John MacFarlane; Anonymous-July 17, 2006-:stem: latexmath--This is a set of tests for pandoc. Most of them are adapted from John Gruber’s-markdown test suite.--'''''--== Headers--=== Level 2 with an link:/url[embedded link]--==== Level 3 with _emphasis_--===== Level 4--====== Level 5--== Level 1--=== Level 2 with _emphasis_--==== Level 3--with no blank line--=== Level 2--with no blank line--'''''--== Paragraphs--Here’s a regular paragraph.--In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.-Because a hard-wrapped line in the middle of a paragraph looked like a list-item.--Here’s one with a bullet. * criminey.--There should be a hard line break +-here.--'''''--== Block Quotes--E-mail style:--____-This is a block quote. It is pretty short.-____--____----Code in a block quote:--....-sub status {- print "working";-}-....--A list:--[arabic]-. item one-. item two--Nested block quotes:--____-nested-____--____-nested-____-----____--This should not be a block quote: 2 > 1.--And a following paragraph.--'''''--== Code Blocks--Code:--....----- (should be four hyphens)--sub status {- print "working";-}--this code block is indented by one tab-....--And:--....- this code block is indented by two tabs--These should not be escaped: \$ \\ \> \[ \{-....--'''''--== Lists--=== Unordered--Asterisks tight:--* asterisk 1-* asterisk 2-* asterisk 3--Asterisks loose:--* asterisk 1-* asterisk 2-* asterisk 3--Pluses tight:--* Plus 1-* Plus 2-* Plus 3--Pluses loose:--* Plus 1-* Plus 2-* Plus 3--Minuses tight:--* Minus 1-* Minus 2-* Minus 3--Minuses loose:--* Minus 1-* Minus 2-* Minus 3--=== Ordered--Tight:--[arabic]-. First-. Second-. Third--and:--[arabic]-. One-. Two-. Three--Loose using tabs:--[arabic]-. First-. Second-. Third--and using spaces:--[arabic]-. One-. Two-. Three--Multiple paragraphs:--[arabic]-. Item 1, graf one.-+-Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.-. Item 2.-. Item 3.--=== Nested--* Tab-** Tab-*** Tab--Here’s another:--[arabic]-. First-. Second:-* Fee-* Fie-* Foe-. Third--Same thing but with paragraphs:--[arabic]-. First-. Second:-* Fee-* Fie-* Foe-. Third--=== Tabs and spaces--* this is a list item indented with tabs-* this is a list item indented with spaces-** this is an example list item indented with tabs-** this is an example list item indented with spaces--=== Fancy list markers--[arabic, start=2]-. begins with 2-. and now 3-+-with a continuation-[lowerroman, start=4]-.. sublist with roman numerals, starting with 4-.. more items-[upperalpha]-... a subsublist-... a subsublist--Nesting:--[upperalpha]-. Upper Alpha-[upperroman]-.. Upper Roman.-[arabic, start=6]-... Decimal start with 6-[loweralpha, start=3]-.... Lower alpha with paren--Autonumbering:--. Autonumber.-. More.-.. Nested.--Should not be a list item:--M.A. 2007--B. Williams--'''''--== Definition Lists--Tight using spaces:--apple::- red fruit-orange::- orange fruit-banana::- yellow fruit--Tight using tabs:--apple::- red fruit-orange::- orange fruit-banana::- yellow fruit--Loose:--apple::- red fruit-orange::- orange fruit-banana::- yellow fruit--Multiple blocks with italics:--_apple_::- red fruit- +- contains seeds, crisp, pleasant to taste-_orange_::- orange fruit- +-....-{ orange code block }-....- +- ____- orange block quote- ____--Multiple definitions, tight:--apple::- red fruit- +- computer-orange::- orange fruit- +- bank--Multiple definitions, loose:--apple::- red fruit- +- computer-orange::- orange fruit- +- bank--Blank line after term, indented marker, alternate markers:--apple::- red fruit- +- computer-orange::- orange fruit- +- [arabic]- . sublist- . sublist--== HTML Blocks--Simple block on one line:--foo--And nested without indentation:--foo--bar--Interpreted markdown in a table:--This is _emphasized_--And this is *strong*--Here’s a simple block:--foo--This should be a code block, though:--....-<div>- foo-</div>-....--As should this:--....-<div>foo</div>-....--Now, nested:--foo--This should just be an HTML comment:--Multiline:--Code block:--....-<!-- Comment -->-....--Just plain comment, with trailing spaces on the line:--Code:--....-<hr />-....--Hr’s:--'''''--== Inline Markup--This is _emphasized_, and so _is this_.--This is *strong*, and so *is this*.--An _link:/url[emphasized link]_.--*_This is strong and em._*--So is *_this_* word.--*_This is strong and em._*--So is *_this_* word.--This is code: `+>+`, `+$+`, `+\+`, `+\$+`, `+<html>+`.--[line-through]*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.--'''''--== Smart quotes, ellipses, dashes--"`Hello,`" said the spider. "`'`Shelob`' is my name.`"--'`A`', '`B`', and '`C`' are letters.--'`Oak,`' '`elm,`' and '`beech`' are names of trees. So is '`pine.`'--'`He said, "`I want to go.`"`' Were you alive in the 70’s?--Here is some quoted '``+code+``' and a "`http://example.com/?foo=1&bar=2[quoted-link]`".--Some dashes: one—two — three—four — five.--Dashes between numbers: 5–7, 255–66, 1987–1999.--Ellipses…and…and….--'''''--== LaTeX--* -* latexmath:[2+2=4]-* latexmath:[x \in y]-* latexmath:[\alpha \wedge \omega]-* latexmath:[223]-* latexmath:[p]-Tree-* Here’s some display math:-+-[latexmath]-++++-\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}-++++-* Here’s one that has a line break in it:-latexmath:[\alpha + \omega \times x^2].--These shouldn’t be math:--* To get the famous equation, write `+$e = mc^2$+`.-* $22,000 is a _lot_ of money. So is $34,000. (It worked if "`lot`" is-emphasized.)-* Shoes ($20) and socks ($5).-* Escaped `+$+`: $73 _this should be emphasized_ 23$.--Here’s a LaTeX table:--'''''--== Special Characters--Here is some unicode:--* I hat: Î-* o umlaut: ö-* section: §-* set membership: ∈-* copyright: ©--AT&T has an ampersand in their name.--AT&T is another way to write it.--This & that.--4 < 5.--6 > 5.--Backslash: \--Backtick: `--Asterisk: *--Underscore: _--Left brace: \{--Right brace: }--Left bracket: [--Right bracket: ]--Left paren: (--Right paren: )--Greater-than: >--Hash: #--Period: .--Bang: !--Plus: +--Minus: ---'''''--== Links--=== Explicit--Just a link:/url/[URL].--link:/url/[URL and title].--link:/url/[URL and title].--link:/url/[URL and title].--link:/url/[URL and title]--link:/url/[URL and title]--link:/url/with_underscore[with_underscore]--mailto:nobody@nowhere.net[Email link]--link:[Empty].--=== Reference--Foo link:/url/[bar].--With link:/url/[embedded [brackets]].--link:/url/[b] by itself should be a link.--Indented link:/url[once].--Indented link:/url[twice].--Indented link:/url[thrice].--This should [not][] be a link.--....-[not]: /url-....--Foo link:/url/[bar].--Foo link:/url/[biz].--=== With ampersands--Here’s a http://example.com/?foo=1&bar=2[link with an ampersand in the URL].--Here’s a link with an amersand in the link text: http://att.com/[AT&T].--Here’s an link:/script?foo=1&bar=2[inline link].--Here’s an link:/script?foo=1&bar=2[inline link in pointy braces].--=== Autolinks--With an ampersand: http://example.com/?foo=1&bar=2--* In a list?-* http://example.com/-* It should.--An e-mail address: nobody@nowhere.net--____-Blockquoted: http://example.com/-____--Auto-links should not occur here: `+<http://example.com/>+`--....-or here: <http://example.com/>-....--'''''--== Images--From "`Voyage dans la Lune`" by Georges Melies (1902):--image::lalune.jpg[lalune,title="Voyage dans la Lune"]--Here is a movie image:movie.jpg[movie] icon.--'''''--== Footnotes--Here is a footnote reference,footnote:[Here is the footnote. It can go anywhere-after the footnote reference. It need not be placed at the end of the document.]-and another.[multiblock footnote omitted] This should _not_ be a footnote-reference, because it contains a space.[^my note] Here is an inline-note.footnote:[This is _easier_ to type. Inline notes may contain-http://google.com[links] and `+]+` verbatim characters, as well as [bracketed-text].]--____-Notes can go in quotes.footnote:[In quote.]-____--[arabic]-. And in list items.footnote:[In list.]--This paragraph should not be part of the note, as it is not indented.
@@ -0,0 +1,729 @@+This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite.++* * *++[u][b]Headers[/b][/u]++[b]Level 2 with an [url=/url]embedded link[/url][/b]++[u]Level 3 with [i]emphasis[/i][/u]++Level 4++Level 5++[u][b]Level 1[/b][/u]++[b]Level 2 with [i]emphasis[/i][/b]++[u]Level 3[/u]++with no blank line++[b]Level 2[/b]++with no blank line++* * *++[u][b]Paragraphs[/b][/u]++Here's a regular paragraph.++In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item.++Here's one with a bullet. * criminey.++There should be a hard line break+here.++* * *++[u][b]Block Quotes[/b][/u]++E-mail style:++[quote]+This is a block quote. It is pretty short.+[/quote]++[quote]+Code in a block quote:++[code]sub status {+ print "working";+}+[/code]++A list:++[list=1]+[*]item one+[*]item two+[/list]++Nested block quotes:++[quote]+nested+[/quote]++[quote]+nested+[/quote]+[/quote]++This should not be a block quote: 2 > 1.++And a following paragraph.++* * *++[u][b]Code Blocks[/b][/u]++Code:++[code]---- (should be four hyphens)++sub status {+ print "working";+}++this code block is indented by one tab+[/code]++And:++[code] this code block is indented by two tabs++These should not be escaped: \$ \\ \> \[ \{+[/code]++* * *++[u][b]Lists[/b][/u]++[b]Unordered[/b]++Asterisks tight:++[list]+[*]asterisk 1+[*]asterisk 2+[*]asterisk 3+[/list]++Asterisks loose:++[list]+[*]asterisk 1+[*]asterisk 2+[*]asterisk 3+[/list]++Pluses tight:++[list]+[*]Plus 1+[*]Plus 2+[*]Plus 3+[/list]++Pluses loose:++[list]+[*]Plus 1+[*]Plus 2+[*]Plus 3+[/list]++Minuses tight:++[list]+[*]Minus 1+[*]Minus 2+[*]Minus 3+[/list]++Minuses loose:++[list]+[*]Minus 1+[*]Minus 2+[*]Minus 3+[/list]++[b]Ordered[/b]++Tight:++[list=1]+[*]First+[*]Second+[*]Third+[/list]++and:++[list=1]+[*]One+[*]Two+[*]Three+[/list]++Loose using tabs:++[list=1]+[*]First+[*]Second+[*]Third+[/list]++and using spaces:++[list=1]+[*]One+[*]Two+[*]Three+[/list]++Multiple paragraphs:++[list=1]+[*]Item 1, graf one.++Item 1. graf two. The quick brown fox jumped over the lazy dog's back.+[*]Item 2.+[*]Item 3.+[/list]++[b]Nested[/b]++[list]+[*]Tab++[list]+[*]Tab++[list]+[*]Tab+[/list]+[/list]+[/list]++Here's another:++[list=1]+[*]First+[*]Second:++[list]+[*]Fee+[*]Fie+[*]Foe+[/list]+[*]Third+[/list]++Same thing but with paragraphs:++[list=1]+[*]First+[*]Second:++[list]+[*]Fee+[*]Fie+[*]Foe+[/list]+[*]Third+[/list]++[b]Tabs and spaces[/b]++[list]+[*]this is a list item indented with tabs+[*]this is a list item indented with spaces++[list]+[*]this is an example list item indented with tabs+[*]this is an example list item indented with spaces+[/list]+[/list]++[b]Fancy list markers[/b]++[list=1]+[*]begins with 2+[*]and now 3++with a continuation++[list=i]+[*]sublist with roman numerals, starting with 4+[*]more items++[list=A]+[*]a subsublist+[*]a subsublist+[/list]+[/list]+[/list]++Nesting:++[list=A]+[*]Upper Alpha++[list=I]+[*]Upper Roman.++[list=1]+[*]Decimal start with 6++[list=a]+[*]Lower alpha with paren+[/list]+[/list]+[/list]+[/list]++Autonumbering:++[list=1]+[*]Autonumber.+[*]More.++[list=1]+[*]Nested.+[/list]+[/list]++Should not be a list item:++M.A. 2007++B. Williams++* * *++[u][b]Definition Lists[/b][/u]++Tight using spaces:++apple+[list]+[*]red fruit+[/list]+orange+[list]+[*]orange fruit+[/list]+banana+[list]+[*]yellow fruit+[/list]++Tight using tabs:++apple+[list]+[*]red fruit+[/list]+orange+[list]+[*]orange fruit+[/list]+banana+[list]+[*]yellow fruit+[/list]++Loose:++apple+[list]+[*]red fruit+[/list]+orange+[list]+[*]orange fruit+[/list]+banana+[list]+[*]yellow fruit+[/list]++Multiple blocks with italics:++[i]apple[/i]+[list]+[*]red fruit++contains seeds, crisp, pleasant to taste+[/list]+[i]orange[/i]+[list]+[*]orange fruit++[code]{ orange code block }+[/code]++[quote]+orange block quote+[/quote]+[/list]++Multiple definitions, tight:++apple+[list]+[*]red fruit+[*]computer+[/list]+orange+[list]+[*]orange fruit+[*]bank+[/list]++Multiple definitions, loose:++apple+[list]+[*]red fruit+[*]computer+[/list]+orange+[list]+[*]orange fruit+[*]bank+[/list]++Blank line after term, indented marker, alternate markers:++apple+[list]+[*]red fruit+[*]computer+[/list]+orange+[list]+[*]orange fruit++[list=1]+[*]sublist+[*]sublist+[/list]+[/list]++[u][b]HTML Blocks[/b][/u]++Simple block on one line:++foo++And nested without indentation:++foo++bar++Interpreted markdown in a table:++This is [i]emphasized[/i]++And this is [b]strong[/b]++Here's a simple block:++foo++This should be a code block, though:++[code]<div>+ foo+</div>+[/code]++As should this:++[code]<div>foo</div>+[/code]++Now, nested:++foo++This should just be an HTML comment:++Multiline:++Code block:++[code]<!-- Comment -->+[/code]++Just plain comment, with trailing spaces on the line:++Code:++[code]<hr />+[/code]++Hr's:++* * *++[u][b]Inline Markup[/b][/u]++This is [i]emphasized[/i], and so [i]is this[/i].++This is [b]strong[/b], and so [b]is this[/b].++An [i][url=/url]emphasized link[/url][/i].++[b][i]This is strong and em.[/i][/b]++So is [b][i]this[/i][/b] word.++[b][i]This is strong and em.[/i][/b]++So is [b][i]this[/i][/b] word.++This is code: >, $, \, \$, <html>.++[s]This is [i]strikeout[/i].[/s]++Superscripts: abcd a[i]hello[/i] ahello there.++Subscripts: H2O, H23O, Hmany of themO.++These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.++* * *++[u][b]Smart quotes, ellipses, dashes[/b][/u]++"Hello," said the spider. "'Shelob' is my name."++'A', 'B', and 'C' are letters.++'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'++'He said, "I want to go."' Were you alive in the 70's?++Here is some quoted 'code' and a "[url=http://example.com/?foo=1&bar=2]quoted link[/url]".++Some dashes: one---two --- three---four --- five.++Dashes between numbers: 5--7, 255--66, 1987--1999.++Ellipses...and...and....++* * *++[u][b]LaTeX[/b][/u]++[list]+[*]+[*]$2+2=4$+[*]$x \in y$+[*]$\alpha \wedge \omega$+[*]$223$+[*]$p$-Tree+[*]Here's some display math: [code=latex]$$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$+[/code]+[*]Here's one that has a line break in it: $\alpha + \omega \times x^2$.+[/list]++These shouldn't be math:++[list]+[*]To get the famous equation, write $e = mc^2$.+[*]$22,000 is a [i]lot[/i] of money. So is $34,000. (It worked if "lot" is emphasized.)+[*]Shoes ($20) and socks ($5).+[*]Escaped $: $73 [i]this should be emphasized[/i] 23$.+[/list]++Here's a LaTeX table:++* * *++[u][b]Special Characters[/b][/u]++Here is some unicode:++[list]+[*]I hat: Î+[*]o umlaut: ö+[*]section: §+[*]set membership: ∈+[*]copyright: ©+[/list]++AT&T has an ampersand in their name.++AT&T is another way to write it.++This & that.++4 < 5.++6 > 5.++Backslash: \++Backtick: `++Asterisk: *++Underscore: _++Left brace: {++Right brace: }++Left bracket: [++Right bracket: ]++Left paren: (++Right paren: )++Greater-than: >++Hash: #++Period: .++Bang: !++Plus: +++Minus: -++* * *++[u][b]Links[/b][/u]++[b]Explicit[/b]++Just a [url=/url/]URL[/url].++[url=/url/]URL and title[/url].++[url=/url/]URL and title[/url].++[url=/url/]URL and title[/url].++[url=/url/]URL and title[/url]++[url=/url/]URL and title[/url]++[url=/url/with_underscore]with_underscore[/url]++[email=nobody@nowhere.net]Email link[/email]++[url]Empty[/url].++[b]Reference[/b]++Foo [url=/url/]bar[/url].++With [url=/url/]embedded [brackets][/url].++[url=/url/]b[/url] by itself should be a link.++Indented [url=/url]once[/url].++Indented [url=/url]twice[/url].++Indented [url=/url]thrice[/url].++This should [not][] be a link.++[code][not]: /url+[/code]++Foo [url=/url/]bar[/url].++Foo [url=/url/]biz[/url].++[b]With ampersands[/b]++Here's a [url=http://example.com/?foo=1&bar=2]link with an ampersand in the URL[/url].++Here's a link with an amersand in the link text: [url=http://att.com/]AT&T[/url].++Here's an [url=/script?foo=1&bar=2]inline link[/url].++Here's an [url=/script?foo=1&bar=2]inline link in pointy braces[/url].++[b]Autolinks[/b]++With an ampersand: [url]http://example.com/?foo=1&bar=2[/url]++[list]+[*]In a list?+[*][url]http://example.com/[/url]+[*]It should.+[/list]++An e-mail address: [email]nobody@nowhere.net[/email]++[quote]+Blockquoted: [url]http://example.com/[/url]+[/quote]++Auto-links should not occur here: <http://example.com/>++[code]or here: <http://example.com/>+[/code]++* * *++[u][b]Images[/b][/u]++From "Voyage dans la Lune" by Georges Melies (1902):++[img alt="lalune" title="Voyage dans la Lune"]lalune.jpg[/img]+lalune++Here is a movie [img alt="movie"]movie.jpg[/img] icon.++* * *++[u][b]Footnotes[/b][/u]++Here is a footnote reference,(1) and another.(2) This should [i]not[/i] be a footnote reference, because it contains a space.[^my note] Here is an inline note.(3)++[quote]+Notes can go in quotes.(4)+[/quote]++[list=1]+[*]And in list items.(5)+[/list]++This paragraph should not be part of the note, as it is not indented.++* * *++(1) Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.++(2) Here's the long note. This one contains multiple blocks.++Subsequent blocks are indented to show that they belong to the footnote (as with list items).++[code] { <code> }+[/code]++If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.++(3) This is [i]easier[/i] to type. Inline notes may contain [url=http://google.com]links[/url] and ] verbatim characters, as well as [bracketed text].++(4) In quote.++(5) In list.
@@ -6,13 +6,13 @@ style=, color=, contrastcolor=]+\setupurl[style=] % make chapter, section bookmarks visible when opening document \placebookmarks[chapter, section, subsection, subsubsection, subsubsubsection, subsubsubsubsection][chapter, section] \setupinteractionscreen[option={bookmark,title}] \setuppagenumbering[location={footer,middle}]-\setupbackend[export=yes] \setupstructure[state=start,method=auto] % use microtypography@@ -86,8 +86,8 @@ \startsectionlevel[title={Level 2 with an \goto{embedded link}[url(/url)]},reference={level-2-with-an-embedded-link}] -\startsectionlevel[title={Level 3 with-{\em emphasis}},reference={level-3-with-emphasis}]+\startsectionlevel[title={Level 3 with {\em+emphasis}},reference={level-3-with-emphasis}] \startsectionlevel[title={Level 4},reference={level-4}] @@ -105,8 +105,8 @@ \startsectionlevel[title={Level 1},reference={level-1}] -\startsectionlevel[title={Level 2 with-{\em emphasis}},reference={level-2-with-emphasis}]+\startsectionlevel[title={Level 2 with {\em+emphasis}},reference={level-2-with-emphasis}] \startsectionlevel[title={Level 3},reference={level-3}] @@ -930,7 +930,9 @@ From \quotation{Voyage dans la Lune} by Georges Melies (1902): -\placefigure{lalune}{\externalfigure[lalune.jpg]}+\startplacefigure[title={lalune}]+{\externalfigure[lalune.jpg]}+\stopplacefigure Here is a movie {\externalfigure[movie.jpg]} icon.
@@ -1,781 +0,0 @@-<p>This is a set of tests for pandoc. Most of them are adapted from-John Gruber’s markdown test suite.</p>--<hr/>--<h1 id="headers">Headers</h1>--<h2 id="level-2-with-an-embedded-link">Level 2 with an <a href="/url" title="">embedded link</a></h2>--<h3 id="level-3-with-emphasis">Level 3 with <em>emphasis</em></h3>--<h4 id="level-4">Level 4</h4>--<h5 id="level-5">Level 5</h5>--<h1 id="level-1">Level 1</h1>--<h2 id="level-2-with-emphasis">Level 2 with <em>emphasis</em></h2>--<h3 id="level-3">Level 3</h3>--<p>with no blank line</p>--<h2 id="level-2">Level 2</h2>--<p>with no blank line</p>--<hr/>--<h1 id="paragraphs">Paragraphs</h1>--<p>Here’s a regular paragraph.</p>--<p>In Markdown 1.0.0 and earlier. Version-8. This line turns into a list item.-Because a hard-wrapped line in the-middle of a paragraph looked like a-list item.</p>--<p>Here’s one with a bullet.-* criminey.</p>--<p>There should be a hard line break<br/>here.</p>--<hr/>--<h1 id="block-quotes">Block Quotes</h1>--<p>E-mail style:</p>--<blockquote>-<p>This is a block quote.-It is pretty short.</p>-</blockquote>--<blockquote>-<p>Code in a block quote:</p>--<pre><code>sub status {- print "working";-}</code></pre>--<p>A list:</p>--<ol>-<li>item one</li>-<li>item two</li>-</ol>--<p>Nested block quotes:</p>--<blockquote>-<p>nested</p>-</blockquote>--<blockquote>-<p>nested</p>-</blockquote>-</blockquote>--<p>This should not be a block quote: 2-> 1.</p>--<p>And a following paragraph.</p>--<hr/>--<h1 id="code-blocks">Code Blocks</h1>--<p>Code:</p>--<pre><code>---- (should be four hyphens)--sub status {- print "working";-}--this code block is indented by one tab</code></pre>--<p>And:</p>--<pre><code> this code block is indented by two tabs--These should not be escaped: \$ \\ \> \[ \{</code></pre>--<hr/>--<h1 id="lists">Lists</h1>--<h2 id="unordered">Unordered</h2>--<p>Asterisks tight:</p>--<ul>-<li>asterisk 1</li>-<li>asterisk 2</li>-<li>asterisk 3</li>-</ul>--<p>Asterisks loose:</p>--<ul>-<li><p>asterisk 1</p></li>-<li><p>asterisk 2</p></li>-<li><p>asterisk 3</p></li>-</ul>--<p>Pluses tight:</p>--<ul>-<li>Plus 1</li>-<li>Plus 2</li>-<li>Plus 3</li>-</ul>--<p>Pluses loose:</p>--<ul>-<li><p>Plus 1</p></li>-<li><p>Plus 2</p></li>-<li><p>Plus 3</p></li>-</ul>--<p>Minuses tight:</p>--<ul>-<li>Minus 1</li>-<li>Minus 2</li>-<li>Minus 3</li>-</ul>--<p>Minuses loose:</p>--<ul>-<li><p>Minus 1</p></li>-<li><p>Minus 2</p></li>-<li><p>Minus 3</p></li>-</ul>--<h2 id="ordered">Ordered</h2>--<p>Tight:</p>--<ol>-<li>First</li>-<li>Second</li>-<li>Third</li>-</ol>--<p>and:</p>--<ol>-<li>One</li>-<li>Two</li>-<li>Three</li>-</ol>--<p>Loose using tabs:</p>--<ol>-<li><p>First</p></li>-<li><p>Second</p></li>-<li><p>Third</p></li>-</ol>--<p>and using spaces:</p>--<ol>-<li><p>One</p></li>-<li><p>Two</p></li>-<li><p>Three</p></li>-</ol>--<p>Multiple paragraphs:</p>--<ol>-<li><p>Item 1, graf one.</p>--<p>Item 1. graf two. The quick brown fox jumped over the lazy dog’s-back.</p></li>-<li><p>Item 2.</p></li>-<li><p>Item 3.</p></li>-</ol>--<h2 id="nested">Nested</h2>--<ul>-<li>Tab--<ul>-<li>Tab--<ul>-<li>Tab</li>-</ul></li>-</ul></li>-</ul>--<p>Here’s another:</p>--<ol>-<li>First</li>-<li>Second:--<ul>-<li>Fee</li>-<li>Fie</li>-<li>Foe</li>-</ul></li>-<li>Third</li>-</ol>--<p>Same thing but with paragraphs:</p>--<ol>-<li><p>First</p></li>-<li><p>Second:</p>--<ul>-<li>Fee</li>-<li>Fie</li>-<li>Foe</li>-</ul></li>-<li><p>Third</p></li>-</ol>--<h2 id="tabs-and-spaces">Tabs and spaces</h2>--<ul>-<li><p>this is a list item-indented with tabs</p></li>-<li><p>this is a list item-indented with spaces</p>--<ul>-<li><p>this is an example list item-indented with tabs</p></li>-<li><p>this is an example list item-indented with spaces</p></li>-</ul></li>-</ul>--<h2 id="fancy-list-markers">Fancy list markers</h2>--<ol>-<li><p>begins with 2</p></li>-<li><p>and now 3</p>--<p>with a continuation</p>--<ol>-<li>sublist with roman numerals,-starting with 4</li>-<li>more items--<ol>-<li>a subsublist</li>-<li>a subsublist</li>-</ol></li>-</ol></li>-</ol>--<p>Nesting:</p>--<ol>-<li>Upper Alpha--<ol>-<li>Upper Roman.--<ol>-<li>Decimal start with 6--<ol>-<li>Lower alpha with paren</li>-</ol></li>-</ol></li>-</ol></li>-</ol>--<p>Autonumbering:</p>--<ol>-<li>Autonumber.</li>-<li>More.--<ol>-<li>Nested.</li>-</ol></li>-</ol>--<p>Should not be a list item:</p>--<p>M.A. 2007</p>--<p>B. Williams</p>--<hr/>--<h1 id="definition-lists">Definition Lists</h1>--<p>Tight using spaces:</p>--<dl>-<dt>apple</dt>-<dd>red fruit</dd>-<dt>orange</dt>-<dd>orange fruit</dd>-<dt>banana</dt>-<dd>yellow fruit</dd>-</dl>--<p>Tight using tabs:</p>--<dl>-<dt>apple</dt>-<dd>red fruit</dd>-<dt>orange</dt>-<dd>orange fruit</dd>-<dt>banana</dt>-<dd>yellow fruit</dd>-</dl>--<p>Loose:</p>--<dl>-<dt>apple</dt>-<dd><p>red fruit</p></dd>-<dt>orange</dt>-<dd><p>orange fruit</p></dd>-<dt>banana</dt>-<dd><p>yellow fruit</p></dd>-</dl>--<p>Multiple blocks with italics:</p>--<dl>-<dt><em>apple</em></dt>-<dd><p>red fruit</p>--<p>contains seeds,-crisp, pleasant to taste</p></dd>-<dt><em>orange</em></dt>-<dd><p>orange fruit</p>--<pre><code>{ orange code block }</code></pre>--<blockquote>-<p>orange block quote</p>-</blockquote></dd>-</dl>--<p>Multiple definitions, tight:</p>--<dl>-<dt>apple</dt>-<dd>red fruit</dd>-<dd>computer</dd>-<dt>orange</dt>-<dd>orange fruit</dd>-<dd>bank</dd>-</dl>--<p>Multiple definitions, loose:</p>--<dl>-<dt>apple</dt>-<dd><p>red fruit</p></dd>-<dd><p>computer</p></dd>-<dt>orange</dt>-<dd><p>orange fruit</p></dd>-<dd><p>bank</p></dd>-</dl>--<p>Blank line after term, indented marker, alternate markers:</p>--<dl>-<dt>apple</dt>-<dd><p>red fruit</p></dd>-<dd><p>computer</p></dd>-<dt>orange</dt>-<dd><p>orange fruit</p>--<ol>-<li>sublist</li>-<li>sublist</li>-</ol></dd>-</dl>--<h1 id="html-blocks">HTML Blocks</h1>--<p>Simple block on one line:</p>--<div>-foo</div>--<p>And nested without indentation:</p>--<div>-<div>-<div>-<p>foo</p></div></div>--<div>-bar</div></div>--<p>Interpreted markdown in a table:</p>--<table>--<tr>--<td>--This is <em>emphasized</em>--</td>--<td>--And this is <strong>strong</strong>--</td>--</tr>--</table>--<script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script>--<p>Here’s a simple block:</p>--<div>-<p>foo</p></div>--<p>This should be a code block, though:</p>--<pre><code><div>- foo-</div></code></pre>--<p>As should this:</p>--<pre><code><div>foo</div></code></pre>--<p>Now, nested:</p>--<div>-<div>-<div>-foo</div></div></div>--<p>This should just be an HTML comment:</p>--<!-- Comment -->--<p>Multiline:</p>--<!---Blah-Blah--->--<!--- This is another comment.--->--<p>Code block:</p>--<pre><code><!-- Comment --></code></pre>--<p>Just plain comment, with trailing spaces on the line:</p>--<!-- foo -->--<p>Code:</p>--<pre><code><hr /></code></pre>--<p>Hr’s:</p>--<hr>--<hr />--<hr />--<hr>--<hr />--<hr />--<hr class="foo" id="bar" />--<hr class="foo" id="bar" />--<hr class="foo" id="bar">--<hr/>--<h1 id="inline-markup">Inline Markup</h1>--<p>This is <em>emphasized</em>, and so <em>is this</em>.</p>--<p>This is <strong>strong</strong>, and so <strong>is this</strong>.</p>--<p>An <em><a href="/url" title="">emphasized link</a></em>.</p>--<p><strong><em>This is strong and em.</em></strong></p>--<p>So is <strong><em>this</em></strong> word.</p>--<p><strong><em>This is strong and em.</em></strong></p>--<p>So is <strong><em>this</em></strong> word.</p>--<p>This is code: <code>></code>, <code>$</code>, <code>\</code>, <code>\$</code>, <code><html></code>.</p>--<p><del>This is <em>strikeout</em>.</del></p>--<p>Superscripts: a<sup>bc</sup>d a<sup><em>hello</em></sup> a<sup>hello there</sup>.</p>--<p>Subscripts: H<sub>2</sub>O, H<sub>23</sub>O, H<sub>many of them</sub>O.</p>--<p>These should not be superscripts or subscripts,-because of the unescaped spaces: a^b c^d, a~b c~d.</p>--<hr/>--<h1 id="smart-quotes-ellipses-dashes">Smart quotes, ellipses, dashes</h1>--<p>“Hello,” said the spider. “‘Shelob’ is my name.”</p>--<p>‘A’, ‘B’, and ‘C’ are letters.</p>--<p>‘Oak,’ ‘elm,’ and ‘beech’ are names of trees.-So is ‘pine.’</p>--<p>‘He said, “I want to go.”’ Were you alive in the-70’s?</p>--<p>Here is some quoted ‘<code>code</code>’ and a “<a href="http://example.com/?foo=1&bar=2" title="">quoted link</a>”.</p>--<p>Some dashes: one—two — three—four — five.</p>--<p>Dashes between numbers: 5–7, 255–66, 1987–1999.</p>--<p>Ellipses…and…and….</p>--<hr/>--<h1 id="latex">LaTeX</h1>--<ul>-<li></li>-<li>\(2+2=4\)</li>-<li>\(x \in y\)</li>-<li>\(\alpha \wedge \omega\)</li>-<li>\(223\)</li>-<li>\(p\)-Tree</li>-<li>Here’s some display math:-\[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}\]</li>-<li>Here’s one that has a line break in it: \(\alpha + \omega \times x^2\).</li>-</ul>--<p>These shouldn’t be math:</p>--<ul>-<li>To get the famous equation, write <code>$e = mc^2$</code>.</li>-<li>$22,000 is a <em>lot</em> of money. So is $34,000.-(It worked if “lot” is emphasized.)</li>-<li>Shoes ($20) and socks ($5).</li>-<li>Escaped <code>$</code>: $73 <em>this should be emphasized</em> 23$.</li>-</ul>--<p>Here’s a LaTeX table:</p>----<hr/>--<h1 id="special-characters">Special Characters</h1>--<p>Here is some unicode:</p>--<ul>-<li>I hat: Î</li>-<li>o umlaut: ö</li>-<li>section: §</li>-<li>set membership: ∈</li>-<li>copyright: ©</li>-</ul>--<p>AT&T has an ampersand in their name.</p>--<p>AT&T is another way to write it.</p>--<p>This & that.</p>--<p>4 < 5.</p>--<p>6 > 5.</p>--<p>Backslash: \</p>--<p>Backtick: `</p>--<p>Asterisk: *</p>--<p>Underscore: _</p>--<p>Left brace: {</p>--<p>Right brace: }</p>--<p>Left bracket: [</p>--<p>Right bracket: ]</p>--<p>Left paren: (</p>--<p>Right paren: )</p>--<p>Greater-than: ></p>--<p>Hash: #</p>--<p>Period: .</p>--<p>Bang: !</p>--<p>Plus: +</p>--<p>Minus: -</p>--<hr/>--<h1 id="links">Links</h1>--<h2 id="explicit">Explicit</h2>--<p>Just a <a href="/url/" title="">URL</a>.</p>--<p><a href="/url/" title="title">URL and title</a>.</p>--<p><a href="/url/" title="title preceded by two spaces">URL and title</a>.</p>--<p><a href="/url/" title="title preceded by a tab">URL and title</a>.</p>--<p><a href="/url/" title="title with "quotes" in it">URL and title</a></p>--<p><a href="/url/" title="title with single quotes">URL and title</a></p>--<p><a href="/url/with_underscore" title="">with_underscore</a></p>--<p><a href="mailto:nobody@nowhere.net" title="">Email link</a></p>--<p><a href="" title="">Empty</a>.</p>--<h2 id="reference">Reference</h2>--<p>Foo <a href="/url/" title="">bar</a>.</p>--<p>With <a href="/url/" title="">embedded [brackets]</a>.</p>--<p><a href="/url/" title="">b</a> by itself should be a link.</p>--<p>Indented <a href="/url" title="">once</a>.</p>--<p>Indented <a href="/url" title="">twice</a>.</p>--<p>Indented <a href="/url" title="">thrice</a>.</p>--<p>This should [not][] be a link.</p>--<pre><code>[not]: /url</code></pre>--<p>Foo <a href="/url/" title="Title with "quotes" inside">bar</a>.</p>--<p>Foo <a href="/url/" title="Title with "quote" inside">biz</a>.</p>--<h2 id="with-ampersands">With ampersands</h2>--<p>Here’s a <a href="http://example.com/?foo=1&bar=2" title="">link with an ampersand in the URL</a>.</p>--<p>Here’s a link with an amersand in the link text: <a href="http://att.com/" title="AT&T">AT&T</a>.</p>--<p>Here’s an <a href="/script?foo=1&bar=2" title="">inline link</a>.</p>--<p>Here’s an <a href="/script?foo=1&bar=2" title="">inline link in pointy braces</a>.</p>--<h2 id="autolinks">Autolinks</h2>--<p>With an ampersand: <a href="http://example.com/?foo=1&bar=2" title="" class="uri">http://example.com/?foo=1&bar=2</a></p>--<ul>-<li>In a list?</li>-<li><a href="http://example.com/" title="" class="uri">http://example.com/</a></li>-<li>It should.</li>-</ul>--<p>An e-mail address: <a href="mailto:nobody@nowhere.net" title="" class="email">nobody@nowhere.net</a></p>--<blockquote>-<p>Blockquoted: <a href="http://example.com/" title="" class="uri">http://example.com/</a></p>-</blockquote>--<p>Auto-links should not occur here: <code><http://example.com/></code></p>--<pre><code>or here: <http://example.com/></code></pre>--<hr/>--<h1 id="images">Images</h1>--<p>From “Voyage dans la Lune” by Georges Melies (1902):</p>--<figure>-<img src="lalune.jpg" id="" alt="lalune"/><figcaption>lalune</figcaption>-</figure>--<p>Here is a movie <img src="movie.jpg" title=""/> icon.</p>--<hr/>--<h1 id="footnotes">Footnotes</h1>--<p>Here is a footnote reference,<a id="fnref1" href="#fn1"><sup>1</sup></a> and another.<a id="fnref2" href="#fn2"><sup>2</sup></a>-This should <em>not</em> be a footnote reference, because it-contains a space.[^my note] Here is an inline note.<a id="fnref3" href="#fn3"><sup>3</sup></a></p>--<blockquote>-<p>Notes can go in quotes.<a id="fnref4" href="#fn4"><sup>4</sup></a></p>-</blockquote>--<ol>-<li>And in list items.<a id="fnref5" href="#fn5"><sup>5</sup></a></li>-</ol>--<p>This paragraph should not be part of the note, as it is not indented.</p>-<ol class="footnotes">-<li id="fn1"><p>Here is the footnote. It can go anywhere after the footnote-reference. It need not be placed at the end of the document. <a href="#fnref1">↩</a></p></li>-<li id="fn2"><p>Here’s the long note. This one contains multiple-blocks.</p>--<p>Subsequent blocks are indented to show that they belong to the-footnote (as with list items).</p>--<pre><code> { <code> }</code></pre>--<p>If you want, you can indent every line, but you can also be-lazy and just indent the first line of each block. <a href="#fnref2">↩</a></p></li>-<li id="fn3"><p>This-is <em>easier</em> to type. Inline notes may contain-<a href="http://google.com" title="">links</a> and <code>]</code> verbatim characters,-as well as [bracketed text]. <a href="#fnref3">↩</a></p></li>-<li id="fn4"><p>In quote. <a href="#fnref4">↩</a></p></li>-<li id="fn5"><p>In list. <a href="#fnref5">↩</a></p></li>-</ol>
@@ -0,0 +1,749 @@+# Pandoc Test Suite++John MacFarlane+Anonymous++July 17, 2006++This is a set of tests for pandoc. Most of them are adapted from John Gruber's+markdown test suite.++* * * *++{#headers}+# Headers++{#level-2-with-an-embedded-link}+## Level 2 with an [embedded link](/url)++{#level-3-with-emphasis}+### Level 3 with _emphasis_++{#level-4}+#### Level 4++{#level-5}+##### Level 5++{#level-1}+# Level 1++{#level-2-with-emphasis}+## Level 2 with _emphasis_++{#level-3}+### Level 3++with no blank line++{#level-2}+## Level 2++with no blank line++* * * *++{#paragraphs}+# Paragraphs++Here's a regular paragraph.++In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.+Because a hard-wrapped line in the middle of a paragraph looked like a list+item.++Here's one with a bullet. \* criminey.++There should be a hard line break\+here.++* * * *++{#block-quotes}+# Block Quotes++E-mail style:++> This is a block quote. It is pretty short.++> Code in a block quote:+>+> ```+> sub status {+> print "working";+> }+> ```+>+> A list:+>+> 1. item one+> 2. item two+>+> Nested block quotes:+>+> > nested+>+> > nested++This should not be a block quote: 2 \> 1.++And a following paragraph.++* * * *++{#code-blocks}+# Code Blocks++Code:++```+---- (should be four hyphens)++sub status {+ print "working";+}++this code block is indented by one tab+```++And:++```+ this code block is indented by two tabs++These should not be escaped: \$ \\ \> \[ \{+```++* * * *++{#lists}+# Lists++{#unordered}+## Unordered++Asterisks tight:++- asterisk 1+- asterisk 2+- asterisk 3++Asterisks loose:++- asterisk 1++- asterisk 2++- asterisk 3++Pluses tight:++- Plus 1+- Plus 2+- Plus 3++Pluses loose:++- Plus 1++- Plus 2++- Plus 3++Minuses tight:++- Minus 1+- Minus 2+- Minus 3++Minuses loose:++- Minus 1++- Minus 2++- Minus 3++{#ordered}+## Ordered++Tight:++1. First+2. Second+3. Third++and:++1. One+2. Two+3. Three++Loose using tabs:++1. First++2. Second++3. Third++and using spaces:++1. One++2. Two++3. Three++Multiple paragraphs:++1. Item 1, graf one.++ Item 1. graf two. The quick brown fox jumped over the lazy dog's back.++2. Item 2.++3. Item 3.++{#nested}+## Nested++- Tab++ - Tab++ - Tab++Here's another:++1. First+2. Second:++ - Fee+ - Fie+ - Foe+3. Third++Same thing but with paragraphs:++1. First++2. Second:++ - Fee+ - Fie+ - Foe++3. Third++{#tabs-and-spaces}+## Tabs and spaces++- this is a list item indented with tabs++- this is a list item indented with spaces++ - this is an example list item indented with tabs++ - this is an example list item indented with spaces++{#fancy-list-markers}+## Fancy list markers++(2) begins with 2++(3) and now 3++ with a continuation++ iv. sublist with roman numerals, starting with 4+ v. more items++ (A) a subsublist+ (B) a subsublist++Nesting:++A. Upper Alpha++ I. Upper Roman.++ (6) Decimal start with 6++ c) Lower alpha with paren++Autonumbering:++1. Autonumber.+2. More.++ 1. Nested.++Should not be a list item:++M.A. 2007++B. Williams++* * * *++{#definition-lists}+# Definition Lists++Tight using spaces:++: apple++ red fruit+: orange++ orange fruit+: banana++ yellow fruit++Tight using tabs:++: apple++ red fruit+: orange++ orange fruit+: banana++ yellow fruit++Loose:++: apple++ red fruit++: orange++ orange fruit++: banana++ yellow fruit++Multiple blocks with italics:++: _apple_++ red fruit++ contains seeds, crisp, pleasant to taste++: _orange_++ orange fruit++ ```+ { orange code block }+ ```++ > orange block quote++Multiple definitions, tight:++: apple++ red fruit++ computer+: orange++ orange fruit++ bank++Multiple definitions, loose:++: apple++ red fruit++ computer++: orange++ orange fruit++ bank++Blank line after term, indented marker, alternate markers:++: apple++ red fruit++ computer++: orange++ orange fruit++ 1. sublist+ 2. sublist++{#html-blocks}+# HTML Blocks++Simple block on one line:++:::+foo++:::++And nested without indentation:++::::::+::::+:::+foo++:::++::::++:::+bar++:::++::::::++Interpreted markdown in a table:++This is _emphasized_++And this is *strong*++Here's a simple block:++:::+foo++:::++This should be a code block, though:++```+<div>+ foo+</div>+```++As should this:++```+<div>foo</div>+```++Now, nested:++:::::+::::+:::+foo++:::++::::++:::::++This should just be an HTML comment:++Multiline:++Code block:++```+<!-- Comment -->+```++Just plain comment, with trailing spaces on the line:++Code:++```+<hr />+```++Hr's:++* * * *++{#inline-markup}+# Inline Markup++This is _emphasized_, and so _is this_.++This is *strong*, and so *is this*.++An _[emphasized link](/url)_.++*_This is strong and em._*++So is *_this_* word.++*_This is strong and em._*++So is *_this_* word.++This is code: `>`, `$`, `\`, `\$`, `<html>`.++{-This is _strikeout_.-}++Superscripts: 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.++* * * *++{#smart-quotes-ellipses-dashes}+# Smart quotes, ellipses, dashes++"Hello," said the spider. "'Shelob' is my name."++'A', 'B', and 'C' are letters.++'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'++'He said, "I want to go."' Were you alive in the 70's?++Here is some quoted '`code`' and a "[quoted+link](http://example.com/?foo=1&bar=2)".++Some dashes: one---two --- three---four --- five.++Dashes between numbers: 5--7, 255--66, 1987--1999.++Ellipses...and...and....++* * * *++{#latex}+# LaTeX++-+- $`2+2=4`+- $`x \in y`+- $`\alpha \wedge \omega`+- $`223`+- $`p`-Tree+- Here's some display math:+ $$`\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}`+- Here's one that has a line break in it: $`\alpha + \omega \times x^2`.++These shouldn't be math:++- To get the famous equation, write `$e = mc^2$`.+- $22,000 is a _lot_ of money. So is $34,000. (It worked if "lot" is+ emphasized.)+- Shoes ($20) and socks ($5).+- Escaped `$`\: $73 _this should be emphasized_ 23$.++Here's a LaTeX table:++* * * *++{#special-characters}+# Special Characters++Here is some unicode:++- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: ©++AT&T has an ampersand in their name.++AT&T is another way to write it.++This & that.++4 \< 5.++6 \> 5.++Backslash: \\++Backtick: \`++Asterisk: \*++Underscore: \_++Left brace: \{++Right brace: \}++Left bracket: \[++Right bracket: \]++Left paren: (++Right paren: )++Greater-than: \>++Hash: #++Period: .++Bang: \!++Plus: +++Minus: -++* * * *++{#links}+# Links++{#explicit}+## Explicit++Just a [URL](/url/).++[URL and title](/url/){title="title"}.++[URL and title](/url/){title="title preceded by two spaces"}.++[URL and title](/url/){title="title preceded by a tab"}.++[URL and title](/url/){title="title with \"quotes\" in it"}++[URL and title](/url/){title="title with single quotes"}++[with\_underscore](/url/with_underscore)++[Email link](mailto:nobody@nowhere.net)++[Empty]().++{#reference}+## Reference++Foo [bar](/url/).++With [embedded \[brackets\]](/url/).++[b](/url/) by itself should be a link.++Indented [once](/url).++Indented [twice](/url).++Indented [thrice](/url).++This should \[not\]\[\] be a link.++```+[not]: /url+```++Foo [bar](/url/){title="Title with \"quotes\" inside"}.++Foo [biz](/url/){title="Title with \"quote\" inside"}.++{#with-ampersands}+## With ampersands++Here's a [link with an ampersand in the URL](http://example.com/?foo=1&bar=2).++Here's a link with an amersand in the link text:+[AT&T](http://att.com/){title="AT&T"}.++Here's an [inline link](/script?foo=1&bar=2).++Here's an [inline link in pointy braces](/script?foo=1&bar=2).++{#autolinks}+## Autolinks++With an ampersand: <http://example.com/?foo=1&bar=2>++- In a list?+- <http://example.com/>+- It should.++An e-mail address: <nobody@nowhere.net>++> Blockquoted: <http://example.com/>++Auto-links should not occur here: `<http://example.com/>`++```+or here: <http://example.com/>+```++* * * *++{#images}+# Images++From "Voyage dans la Lune" by Georges Melies (1902):++::::+{title="Voyage dans la Lune"}++{.caption}+:::+lalune++:::++::::++Here is a movie  icon.++* * * *++{#footnotes}+# Footnotes++Here is a footnote reference,[^1] and another.[^2] This should _not_ be a+footnote reference, because it contains a space.\[\^my note\] Here is an inline+note.[^3]++> Notes can go in quotes.[^4]++1. And in list items.[^5]++This paragraph should not be part of the note, as it is not indented.++[^1]: Here is the footnote. It can go anywhere after the footnote reference. It+ need not be placed at the end of the document.++[^2]: Here's the long note. This one contains multiple blocks.++ Subsequent blocks are indented to show that they belong to the footnote (as+ with list items).++ ```+ { <code> }+ ```++ If you want, you can indent every line, but you can also be lazy and just+ indent the first line of each block.++[^3]: This is _easier_ to type. Inline notes may contain+ [links](http://google.com) and `]` verbatim characters, as well as+ \[bracketed text\].++[^4]: In quote.++[^5]: In list.
@@ -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>@@ -1358,6 +1358,9 @@ <imageobject> <imagedata fileref="movie.jpg" /> </imageobject>+ <textobject>+ <phrase>movie</phrase>+ </textobject> </inlinemediaobject> icon. </para> </sect1>
@@ -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>@@ -1333,6 +1333,9 @@ <imageobject> <imagedata fileref="movie.jpg" /> </imageobject>+ <textobject>+ <phrase>movie</phrase>+ </textobject> </inlinemediaobject> icon. </para> </section>
@@ -48,26 +48,25 @@ > This is a block quote. It is pretty short. -<HTML><blockquote>-Code in a block quote:+> Code in a block quote: -<code>+> <code> sub status { print "working"; } </code> -A list:+> A list: - - item one- - item two+> - item one+> - item two -Nested block quotes:+> Nested block quotes: -> nested+>> nested -> nested-</blockquote></HTML>+>> nested+ This should not be a block quote: 2 > 1. And a following paragraph.@@ -168,11 +167,12 @@ Multiple paragraphs: -<HTML><ol style="list-style-type: decimal;"></HTML>-<HTML><li></HTML><HTML><p></HTML>Item 1, graf one.<HTML></p></HTML>-<HTML><p></HTML>Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.<HTML></p></HTML><HTML></li></HTML>-<HTML><li></HTML><HTML><p></HTML>Item 2.<HTML></p></HTML><HTML></li></HTML>-<HTML><li></HTML><HTML><p></HTML>Item 3.<HTML></p></HTML><HTML></li></HTML><HTML></ol></HTML>+ - <WRAP>+Item 1, graf one.+Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.+</WRAP>+ - Item 2.+ - Item 3. ===== Nested ===== @@ -207,32 +207,28 @@ ===== Fancy list markers ===== -<HTML><ol start="2" style="list-style-type: decimal;"></HTML>-<HTML><li></HTML><HTML><p></HTML>begins with 2<HTML></p></HTML><HTML></li></HTML>-<HTML><li></HTML><HTML><p></HTML>and now 3<HTML></p></HTML>-<HTML><p></HTML>with a continuation<HTML></p></HTML>-<HTML><ol start="4" style="list-style-type: lower-roman;"></HTML>-<HTML><li></HTML>sublist with roman numerals, starting with 4<HTML></li></HTML>-<HTML><li></HTML>more items-<HTML><ol style="list-style-type: upper-alpha;"></HTML>-<HTML><li></HTML>a subsublist<HTML></li></HTML>-<HTML><li></HTML>a subsublist<HTML></li></HTML><HTML></ol></HTML>-<HTML></li></HTML><HTML></ol></HTML>-<HTML></li></HTML><HTML></ol></HTML>+ - begins with 2+ - <WRAP>+and now 3+with a continuation+ - sublist with roman numerals, starting with 4+ - more items+ - a subsublist+ - a subsublist+</WRAP> Nesting: -<HTML><ol style="list-style-type: upper-alpha;"></HTML>-<HTML><li></HTML>Upper Alpha-<HTML><ol style="list-style-type: upper-roman;"></HTML>-<HTML><li></HTML>Upper Roman.-<HTML><ol start="6" style="list-style-type: decimal;"></HTML>-<HTML><li></HTML>Decimal start with 6-<HTML><ol start="3" style="list-style-type: lower-alpha;"></HTML>-<HTML><li></HTML>Lower alpha with paren<HTML></li></HTML><HTML></ol></HTML>-<HTML></li></HTML><HTML></ol></HTML>-<HTML></li></HTML><HTML></ol></HTML>-<HTML></li></HTML><HTML></ol></HTML>+ - <WRAP>+Upper Alpha+ - <WRAP>+Upper Roman.+ - <WRAP>+Decimal start with 6+ - Lower alpha with paren+</WRAP>+</WRAP>+</WRAP> Autonumbering: @@ -271,32 +267,32 @@ Multiple blocks with italics: -<HTML><dl></HTML>-<HTML><dt></HTML>//apple//<HTML></dt></HTML>-<HTML><dd></HTML><HTML><p></HTML>red fruit<HTML></p></HTML>-<HTML><p></HTML>contains seeds, crisp, pleasant to taste<HTML></p></HTML><HTML></dd></HTML>-<HTML><dt></HTML>//orange//<HTML></dt></HTML>-<HTML><dd></HTML><HTML><p></HTML>orange fruit<HTML></p></HTML>+ * **//apple//** <WRAP>+red fruit+contains seeds, crisp, pleasant to taste+</WRAP>+ * **//orange//** <WRAP>+orange fruit <code> { orange code block } </code> -> <HTML><p></HTML>orange block quote<HTML></p></HTML>-<HTML></dd></HTML><HTML></dl></HTML>+> orange block quote+</WRAP> Multiple definitions, tight: - * **apple** red fruitcomputer- * **orange** orange fruitbank+ * **apple** red fruit; computer+ * **orange** orange fruit; bank Multiple definitions, loose: - * **apple** red fruitcomputer- * **orange** orange fruitbank+ * **apple** red fruit; computer+ * **orange** orange fruit; bank Blank line after term, indented marker, alternate markers: - * **apple** red fruitcomputer+ * **apple** red fruit; computer * **orange** orange fruit - sublist - sublist@@ -318,23 +314,11 @@ Interpreted markdown in a table: -<HTML>-<table>-<tr>-<td>-</HTML>+ This is //emphasized//-<HTML>-</td>-<td>-</HTML>+ And this is **strong**-<HTML>-</td>-</tr>-</table>-<script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script>-</HTML>+ Here’s a simple block: foo@@ -362,20 +346,10 @@ This should just be an HTML comment: -<HTML>-<!-- Comment -->-</HTML>+ Multiline: -<HTML>-<!---Blah-Blah--->-<!--- This is another comment.--->-</HTML>+ Code block: <code>@@ -384,9 +358,7 @@ Just plain comment, with trailing spaces on the line: -<HTML>-<!-- foo -->-</HTML>+ Code: <code>@@ -395,18 +367,8 @@ Hr’s: -<HTML>-<hr>-<hr />-<hr />-<hr>-<hr />-<hr />-<hr class="foo" id="bar" />-<hr class="foo" id="bar" />-<hr class="foo" id="bar">-</HTML> + ---- ====== Inline Markup ======@@ -619,8 +581,10 @@ From “Voyage dans la Lune” by Georges Melies (1902): -{{lalune.jpg|Voyage dans la Lune lalune}}+{{lalune.jpg|Voyage dans la Lune}}+lalune + Here is a movie {{movie.jpg|movie}} icon. @@ -642,7 +606,7 @@ )) > Notes can go in quotes.((In quote.-> ))+)) - And in list items.((In list.))
@@ -614,6 +614,7 @@ From “Voyage dans la Lune” by Georges Melies (1902): <<lalune.jpg lalune>>+lalune Here is a movie <<movie.jpg movie>> icon.
@@ -3,16 +3,16 @@ <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" />- <meta name="generator" content="pandoc" />+ <meta name="generator" content="pandoc " /> <meta name="author" content="John MacFarlane" /> <meta name="author" content="Anonymous" /> <meta name="date" content="2006-07-17" /> <title>Pandoc Test Suite</title> <style type="text/css">+ /* Default styles provided by pandoc.+ ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+ */ html {- line-height: 1.5;- font-family: Georgia, serif;- font-size: 20px; color: #1a1a1a; background-color: #fdfdfd; }@@ -31,13 +31,16 @@ @media (max-width: 600px) { body { font-size: 0.9em;- padding: 1em;+ padding: 12px; } h1 { font-size: 1.8em; } } @media print {+ html {+ background-color: white;+ } body { background-color: transparent; color: black;@@ -63,6 +66,10 @@ img { max-width: 100%; }+ svg {+ height: auto;+ max-width: 100%;+ } h1, h2, h3, h4, h5, h6 { margin-top: 1.4em; }@@ -87,9 +94,11 @@ color: #606060; } code {- font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;+ white-space: pre-wrap;+ font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace; font-size: 85%; margin: 0;+ hyphens: manual; } pre { margin: 1em 0;@@ -105,8 +114,8 @@ overflow: visible; } hr {- background-color: #1a1a1a; border: none;+ border-top: 1px solid #1a1a1a; height: 1px; margin: 1em 0; }@@ -149,13 +158,19 @@ #TOC a:not(:hover) { text-decoration: none; }- code{white-space: pre-wrap;} span.smallcaps{font-variant: small-caps;}- div.columns{display: flex; gap: min(4vw, 1.5em);}- div.column{flex: auto; overflow-x: auto;}+ div.columns{display: flex; gap: 1.5em;}+ div.column{flex: auto;}+ @media screen {+ div.columns{gap: min(4vw, 1.5em);}+ div.column{overflow-x: auto;}+ } div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}- ul.task-list{list-style: none;}+ /* The extra [class] is a hack that increases specificity enough to+ override a similar rule in reveal.js */+ ul.task-list[class]{list-style: none;} ul.task-list li input[type="checkbox"] {+ font-size: inherit; width: 0.8em; margin: 0 0.8em 0.2em -1.6em; vertical-align: middle;@@ -707,9 +722,9 @@ <hr /> <h1 id="images">Images</h1> <p>From “Voyage dans la Lune” by Georges Melies (1902):</p>-<div class="figure">-<img src="lalune.jpg" title="Voyage dans la Lune" alt="" />-<p class="caption">lalune</p>+<div class="float">+<img src="lalune.jpg" title="Voyage dans la Lune" alt="lalune" />+<div class="figcaption">lalune</div> </div> <p>Here is a movie <img src="movie.jpg" alt="movie" /> icon.</p> <hr />
@@ -1,18 +1,18 @@ <!DOCTYPE html>-<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">+<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" />- <meta name="generator" content="pandoc" />+ <meta name="generator" content="pandoc " /> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> <meta name="author" content="John MacFarlane" /> <meta name="author" content="Anonymous" /> <meta name="dcterms.date" content="2006-07-17" /> <title>Pandoc Test Suite</title> <style>+ /* Default styles provided by pandoc.+ ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.+ */ html {- line-height: 1.5;- font-family: Georgia, serif;- font-size: 20px; color: #1a1a1a; background-color: #fdfdfd; }@@ -31,13 +31,16 @@ @media (max-width: 600px) { body { font-size: 0.9em;- padding: 1em;+ padding: 12px; } h1 { font-size: 1.8em; } } @media print {+ html {+ background-color: white;+ } body { background-color: transparent; color: black;@@ -63,6 +66,10 @@ img { max-width: 100%; }+ svg {+ height: auto;+ max-width: 100%;+ } h1, h2, h3, h4, h5, h6 { margin-top: 1.4em; }@@ -87,9 +94,11 @@ color: #606060; } code {- font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;+ white-space: pre-wrap;+ font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace; font-size: 85%; margin: 0;+ hyphens: manual; } pre { margin: 1em 0;@@ -105,8 +114,8 @@ overflow: visible; } hr {- background-color: #1a1a1a; border: none;+ border-top: 1px solid #1a1a1a; height: 1px; margin: 1em 0; }@@ -149,22 +158,25 @@ #TOC a:not(:hover) { text-decoration: none; }- code{white-space: pre-wrap;} span.smallcaps{font-variant: small-caps;}- div.columns{display: flex; gap: min(4vw, 1.5em);}- div.column{flex: auto; overflow-x: auto;}+ div.columns{display: flex; gap: 1.5em;}+ div.column{flex: auto;}+ @media screen {+ div.columns{gap: min(4vw, 1.5em);}+ div.column{overflow-x: auto;}+ } div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}- ul.task-list{list-style: none;}+ /* The extra [class] is a hack that increases specificity enough to+ override a similar rule in reveal.js */+ ul.task-list[class]{list-style: none;} ul.task-list li input[type="checkbox"] {+ font-size: inherit; width: 0.8em; margin: 0 0.8em 0.2em -1.6em; vertical-align: middle; } .display.math{display: block; text-align: center; margin: 0.5rem auto;} </style>- <!--[if lt IE 9]>- <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>- <![endif]--> </head> <body> <header id="title-block-header">
@@ -576,27 +576,15 @@ <sec id="html-blocks"> <title>HTML Blocks</title> <p>Simple block on one line:</p>- <boxed-text>- <p>foo</p>- </boxed-text>+ <p>foo</p> <p>And nested without indentation:</p>- <boxed-text>- <boxed-text>- <boxed-text>- <p>foo</p>- </boxed-text>- </boxed-text>- <boxed-text>- <p>bar</p>- </boxed-text>- </boxed-text>+ <p>foo</p>+ <p>bar</p> <p>Interpreted markdown in a table:</p> <p>This is <italic>emphasized</italic></p> <p>And this is <bold>strong</bold></p> <p>Here’s a simple block:</p>- <boxed-text>- <p>foo</p>- </boxed-text>+ <p>foo</p> <p>This should be a code block, though:</p> <preformat><div> foo@@ -604,13 +592,7 @@ <p>As should this:</p> <preformat><div>foo</div></preformat> <p>Now, nested:</p>- <boxed-text>- <boxed-text>- <boxed-text>- <p>foo</p>- </boxed-text>- </boxed-text>- </boxed-text>+ <p>foo</p> <p>This should just be an HTML comment:</p> <p>Multiline:</p> <p>Code block:</p>@@ -687,7 +669,7 @@ <list-item> <p>Here’s some display math: <disp-formula><alternatives> <tex-math><![CDATA[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}]]></tex-math>- <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>=</mml:mo><mml:munder><mml:mo>lim</mml:mo><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:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow></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>@@ -845,8 +827,9 @@ <graphic mimetype="image" mime-subtype="jpeg" xlink:href="lalune.jpg" xlink:title="Voyage dans la Lune" /> </fig> <p>Here is a movie- <inline-graphic mimetype="image" mime-subtype="jpeg" xlink:href="movie.jpg" />- icon.</p>+ <inline-graphic mimetype="image" mime-subtype="jpeg" xlink:href="movie.jpg">+ <alt-text>movie</alt-text>+ </inline-graphic> icon.</p> </sec> <sec id="footnotes"> <title>Footnotes</title>
@@ -573,27 +573,15 @@ <sec id="html-blocks"> <title>HTML Blocks</title> <p>Simple block on one line:</p>- <boxed-text>- <p>foo</p>- </boxed-text>+ <p>foo</p> <p>And nested without indentation:</p>- <boxed-text>- <boxed-text>- <boxed-text>- <p>foo</p>- </boxed-text>- </boxed-text>- <boxed-text>- <p>bar</p>- </boxed-text>- </boxed-text>+ <p>foo</p>+ <p>bar</p> <p>Interpreted markdown in a table:</p> <p>This is <italic>emphasized</italic></p> <p>And this is <bold>strong</bold></p> <p>Here’s a simple block:</p>- <boxed-text>- <p>foo</p>- </boxed-text>+ <p>foo</p> <p>This should be a code block, though:</p> <preformat><div> foo@@ -601,13 +589,7 @@ <p>As should this:</p> <preformat><div>foo</div></preformat> <p>Now, nested:</p>- <boxed-text>- <boxed-text>- <boxed-text>- <p>foo</p>- </boxed-text>- </boxed-text>- </boxed-text>+ <p>foo</p> <p>This should just be an HTML comment:</p> <p>Multiline:</p> <p>Code block:</p>@@ -673,7 +655,7 @@ </list-item> <list-item> <p>Here’s some display math:- <disp-formula><mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>=</mml:mo><mml:munder><mml:mo>lim</mml:mo><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:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow></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:@@ -830,8 +812,9 @@ <graphic mimetype="image" mime-subtype="jpeg" xlink:href="lalune.jpg" xlink:title="Voyage dans la Lune" /> </fig> <p>Here is a movie- <inline-graphic mimetype="image" mime-subtype="jpeg" xlink:href="movie.jpg" />- icon.</p>+ <inline-graphic mimetype="image" mime-subtype="jpeg" xlink:href="movie.jpg">+ <alt-text>movie</alt-text>+ </inline-graphic> icon.</p> </sec> <sec id="footnotes"> <title>Footnotes</title>
@@ -576,27 +576,15 @@ <sec id="html-blocks"> <title>HTML Blocks</title> <p>Simple block on one line:</p>- <boxed-text>- <p>foo</p>- </boxed-text>+ <p>foo</p> <p>And nested without indentation:</p>- <boxed-text>- <boxed-text>- <boxed-text>- <p>foo</p>- </boxed-text>- </boxed-text>- <boxed-text>- <p>bar</p>- </boxed-text>- </boxed-text>+ <p>foo</p>+ <p>bar</p> <p>Interpreted markdown in a table:</p> <p>This is <italic>emphasized</italic></p> <p>And this is <bold>strong</bold></p> <p>Here’s a simple block:</p>- <boxed-text>- <p>foo</p>- </boxed-text>+ <p>foo</p> <p>This should be a code block, though:</p> <preformat><div> foo@@ -604,13 +592,7 @@ <p>As should this:</p> <preformat><div>foo</div></preformat> <p>Now, nested:</p>- <boxed-text>- <boxed-text>- <boxed-text>- <p>foo</p>- </boxed-text>- </boxed-text>- </boxed-text>+ <p>foo</p> <p>This should just be an HTML comment:</p> <p>Multiline:</p> <p>Code block:</p>@@ -687,7 +669,7 @@ <list-item> <p>Here’s some display math: <disp-formula><alternatives> <tex-math><![CDATA[\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}]]></tex-math>- <mml:math display="block" xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mrow><mml:mfrac><mml:mi>d</mml:mi><mml:mrow><mml:mi>d</mml:mi><mml:mi>x</mml:mi></mml:mrow></mml:mfrac><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>=</mml:mo><mml:munder><mml:mo>lim</mml:mo><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:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo>+</mml:mo><mml:mi>h</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow><mml:mo>−</mml:mo><mml:mi>f</mml:mi><mml:mrow><mml:mo stretchy="true" form="prefix">(</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy="true" form="postfix">)</mml:mo></mml:mrow></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>@@ -845,8 +827,9 @@ <graphic mimetype="image" mime-subtype="jpeg" xlink:href="lalune.jpg" xlink:title="Voyage dans la Lune" /> </fig> <p>Here is a movie- <inline-graphic mimetype="image" mime-subtype="jpeg" xlink:href="movie.jpg" />- icon.</p>+ <inline-graphic mimetype="image" mime-subtype="jpeg" xlink:href="movie.jpg">+ <alt-text>movie</alt-text>+ </inline-graphic> icon.</p> </sec> <sec id="footnotes"> <title>Footnotes</title>
@@ -502,7 +502,7 @@ h1. {anchor:images}Images From "Voyage dans la Lune" by Georges Melies \(1902): -!lalune.jpg|title=fig:Voyage dans la Lune, alt=lalune!+!lalune.jpg|title=Voyage dans la Lune, alt=lalune! Here is a movie !movie.jpg|alt=movie! icon.
@@ -1,21 +1,25 @@ % Options for packages loaded elsewhere \PassOptionsToPackage{unicode}{hyperref} \PassOptionsToPackage{hyphens}{url}-% \documentclass[ ]{article}+\usepackage{xcolor} \usepackage{amsmath,amssymb}-\usepackage{lmodern}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering \usepackage{iftex} \ifPDFTeX \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage{textcomp} % provide euro and other symbols \else % if luatex or xetex- \usepackage{unicode-math}+ \usepackage{unicode-math} % this also loads fontspec \defaultfontfeatures{Scale=MatchLowercase} \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1} \fi+\usepackage{lmodern}+\ifPDFTeX\else+ % xetex/luatex font selection+\fi % Use upquote if available, for straight quotes in verbatim environments \IfFileExists{upquote.sty}{\usepackage{upquote}}{} \IfFileExists{microtype.sty}{% use microtype if available@@ -33,32 +37,38 @@ \KOMAoptions{parskip=half}} \makeatother \usepackage{fancyvrb}-\usepackage{xcolor} \usepackage{graphicx} \makeatletter-\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}-\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}-\makeatother-% Scale images if necessary, so that they will not overflow the page-% margins by default, and it is still possible to overwrite the defaults-% using explicit options in \includegraphics[width, height, ...]{}-\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}+\newsavebox\pandoc@box+\newcommand*\pandocbounded[1]{% scales image to fit in text height/width+ \sbox\pandoc@box{#1}%+ \Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}%+ \Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}%+ \ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both+ \ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}%+ \else\usebox{\pandoc@box}%+ \fi%+} % Set default figure placement to htbp-\makeatletter \def\fps@figure{htbp} \makeatother-\usepackage[normalem]{ulem}+\ifLuaTeX+ \usepackage{luacolor}+ \usepackage[soul]{lua-ul}+\else+ \usepackage{soul}+\fi \setlength{\emergencystretch}{3em} % prevent overfull lines \providecommand{\tightlist}{% \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}-\setcounter{secnumdepth}{-\maxdimen} % remove section numbering-\ifLuaTeX- \usepackage{selnolig} % disable illegal ligatures-\fi-\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}}+\usepackage{bookmark} \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available-\urlstyle{same} % disable monospaced font for URLs+\urlstyle{same} \VerbatimFootnotes % allow verbatim text in footnotes+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother \hypersetup{ pdftitle={Pandoc Test Suite}, pdfauthor={John MacFarlane; Anonymous},@@ -77,44 +87,34 @@ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{headers}{%-\section{Headers}\label{headers}}+\section{Headers}\label{headers} -\hypertarget{level-2-with-an-embedded-link}{% \subsection{\texorpdfstring{Level 2 with an \href{/url}{embedded-link}}{Level 2 with an embedded link}}\label{level-2-with-an-embedded-link}}+link}}{Level 2 with an embedded link}}\label{level-2-with-an-embedded-link} -\hypertarget{level-3-with-emphasis}{% \subsubsection{\texorpdfstring{Level 3 with-\emph{emphasis}}{Level 3 with emphasis}}\label{level-3-with-emphasis}}+\emph{emphasis}}{Level 3 with emphasis}}\label{level-3-with-emphasis} -\hypertarget{level-4}{%-\paragraph{Level 4}\label{level-4}}+\paragraph{Level 4}\label{level-4} -\hypertarget{level-5}{%-\subparagraph{Level 5}\label{level-5}}+\subparagraph{Level 5}\label{level-5} -\hypertarget{level-1}{%-\section{Level 1}\label{level-1}}+\section{Level 1}\label{level-1} -\hypertarget{level-2-with-emphasis}{% \subsection{\texorpdfstring{Level 2 with-\emph{emphasis}}{Level 2 with emphasis}}\label{level-2-with-emphasis}}+\emph{emphasis}}{Level 2 with emphasis}}\label{level-2-with-emphasis} -\hypertarget{level-3}{%-\subsubsection{Level 3}\label{level-3}}+\subsubsection{Level 3}\label{level-3} with no blank line -\hypertarget{level-2}{%-\subsection{Level 2}\label{level-2}}+\subsection{Level 2}\label{level-2} with no blank line \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{paragraphs}{%-\section{Paragraphs}\label{paragraphs}}+\section{Paragraphs}\label{paragraphs} Here's a regular paragraph. @@ -129,8 +129,7 @@ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{block-quotes}{%-\section{Block Quotes}\label{block-quotes}}+\section{Block Quotes}\label{block-quotes} E-mail style: @@ -175,8 +174,7 @@ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{code-blocks}{%-\section{Code Blocks}\label{code-blocks}}+\section{Code Blocks}\label{code-blocks} Code: @@ -200,11 +198,9 @@ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{lists}{%-\section{Lists}\label{lists}}+\section{Lists}\label{lists} -\hypertarget{unordered}{%-\subsection{Unordered}\label{unordered}}+\subsection{Unordered}\label{unordered} Asterisks tight: @@ -275,8 +271,7 @@ Minus 3 \end{itemize} -\hypertarget{ordered}{%-\subsection{Ordered}\label{ordered}}+\subsection{Ordered}\label{ordered} Tight: @@ -342,8 +337,7 @@ Item 3. \end{enumerate} -\hypertarget{nested}{%-\subsection{Nested}\label{nested}}+\subsection{Nested}\label{nested} \begin{itemize} \tightlist@@ -408,8 +402,7 @@ Third \end{enumerate} -\hypertarget{tabs-and-spaces}{%-\subsection{Tabs and spaces}\label{tabs-and-spaces}}+\subsection{Tabs and spaces}\label{tabs-and-spaces} \begin{itemize} \item@@ -425,8 +418,7 @@ \end{itemize} \end{itemize} -\hypertarget{fancy-list-markers}{%-\subsection{Fancy list markers}\label{fancy-list-markers}}+\subsection{Fancy list markers}\label{fancy-list-markers} \begin{enumerate} \def\labelenumi{(\arabic{enumi})}@@ -514,8 +506,7 @@ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{definition-lists}{%-\section{Definition Lists}\label{definition-lists}}+\section{Definition Lists}\label{definition-lists} Tight using spaces: @@ -618,8 +609,7 @@ \end{enumerate} \end{description} -\hypertarget{html-blocks}{%-\section{HTML Blocks}\label{html-blocks}}+\section{HTML Blocks}\label{html-blocks} Simple block on one line: @@ -681,8 +671,7 @@ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{inline-markup}{%-\section{Inline Markup}\label{inline-markup}}+\section{Inline Markup}\label{inline-markup} This is \emph{emphasized}, and so \emph{is this}. @@ -701,7 +690,7 @@ This is code: \texttt{\textgreater{}}, \texttt{\$}, \texttt{\textbackslash{}}, \texttt{\textbackslash{}\$}, \texttt{\textless{}html\textgreater{}}. -\sout{This is \emph{strikeout}.}+\st{This is \emph{strikeout}.} Superscripts: a\textsuperscript{bc}d a\textsuperscript{\emph{hello}} a\textsuperscript{hello~there}.@@ -714,8 +703,7 @@ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{smart-quotes-ellipses-dashes}{%-\section{Smart quotes, ellipses, dashes}\label{smart-quotes-ellipses-dashes}}+\section{Smart quotes, ellipses, dashes}\label{smart-quotes-ellipses-dashes} ``Hello,'' said the spider. ``\,`Shelob' is my name.'' @@ -726,7 +714,7 @@ `He said, ``I want to go.''\,' Were you alive in the 70's? Here is some quoted `\texttt{code}' and a-``\href{http://example.com/?foo=1\&bar=2}{quoted link}''.+``\href{http://example.com/?foo=1&bar=2}{quoted link}''. Some dashes: one---two --- three---four --- five. @@ -736,8 +724,7 @@ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{latex}{%-\section{LaTeX}\label{latex}}+\section{LaTeX}\label{latex} \begin{itemize} \tightlist@@ -785,8 +772,7 @@ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{special-characters}{%-\section{Special Characters}\label{special-characters}}+\section{Special Characters}\label{special-characters} Here is some unicode: @@ -848,11 +834,9 @@ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{links}{%-\section{Links}\label{links}}+\section{Links}\label{links} -\hypertarget{explicit}{%-\subsection{Explicit}\label{explicit}}+\subsection{Explicit}\label{explicit} Just a \href{/url/}{URL}. @@ -872,8 +856,7 @@ \href{}{Empty}. -\hypertarget{reference}{%-\subsection{Reference}\label{reference}}+\subsection{Reference}\label{reference} Foo \href{/url/}{bar}. @@ -897,22 +880,20 @@ Foo \href{/url/}{biz}. -\hypertarget{with-ampersands}{%-\subsection{With ampersands}\label{with-ampersands}}+\subsection{With ampersands}\label{with-ampersands} -Here's a \href{http://example.com/?foo=1\&bar=2}{link with an ampersand in the+Here's a \href{http://example.com/?foo=1&bar=2}{link with an ampersand in the URL}. Here's a link with an amersand in the link text: \href{http://att.com/}{AT\&T}. -Here's an \href{/script?foo=1\&bar=2}{inline link}.+Here's an \href{/script?foo=1&bar=2}{inline link}. -Here's an \href{/script?foo=1\&bar=2}{inline link in pointy braces}.+Here's an \href{/script?foo=1&bar=2}{inline link in pointy braces}. -\hypertarget{autolinks}{%-\subsection{Autolinks}\label{autolinks}}+\subsection{Autolinks}\label{autolinks} -With an ampersand: \url{http://example.com/?foo=1\&bar=2}+With an ampersand: \url{http://example.com/?foo=1&bar=2} \begin{itemize} \tightlist@@ -940,23 +921,22 @@ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{images}{%-\section{Images}\label{images}}+\section{Images}\label{images} From ``Voyage dans la Lune'' by Georges Melies (1902): \begin{figure} \centering-\includegraphics{lalune.jpg}+\pandocbounded{\includegraphics[keepaspectratio,alt={lalune}]{lalune.jpg}} \caption{lalune} \end{figure} -Here is a movie \includegraphics{movie.jpg} icon.+Here is a movie+\pandocbounded{\includegraphics[keepaspectratio,alt={movie}]{movie.jpg}} icon. \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\hypertarget{footnotes}{%-\section{Footnotes}\label{footnotes}}+\section{Footnotes}\label{footnotes} Here is a footnote reference,\footnote{Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the
@@ -1,22 +1,7 @@-.\" Define V font for inline verbatim, using C font in formats-.\" that render this, and otherwise B font.-.ie "\f[CB]x\f[]"x" \{\-. ftr V B-. ftr VI BI-. ftr VB B-. ftr VBI BI-.\}-.el \{\-. ftr V CR-. ftr VI CI-. ftr VB CB-. ftr VBI CBI-.\}-.TH "Pandoc Test Suite" "" "July 17, 2006" "" ""-.hy+.TH "Pandoc Test Suite" "" "July 17, 2006" "" .PP This is a set of tests for pandoc.-Most of them are adapted from John Gruber\[cq]s markdown test suite.+Most of them are adapted from John Gruber\(cqs markdown test suite. .PP * * * * * .SH Headers@@ -27,24 +12,21 @@ .SH Level 1 .SS Level 2 with \f[I]emphasis\f[R] .SS Level 3-.PP with no blank line .SS Level 2-.PP with no blank line .PP * * * * * .SH Paragraphs-.PP-Here\[cq]s a regular paragraph.+Here\(cqs a regular paragraph. .PP In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.-Because a hard-wrapped line in the middle of a paragraph looked like a list+Because a hard\-wrapped line in the middle of a paragraph looked like a list item. .PP-Here\[cq]s one with a bullet.+Here\(cqs one with a bullet. * criminey. .PP There should be a hard line break@@ -55,8 +37,7 @@ .PP * * * * * .SH Block Quotes-.PP-E-mail style:+E\-mail style: .RS .PP This is a block quote.@@ -66,13 +47,11 @@ .PP Code in a block quote: .IP-.nf-\f[C]+.EX sub status {- print \[dq]working\[dq];+ print \(dqworking\(dq; }-\f[R]-.fi+.EE .PP A list: .IP "1." 3@@ -97,84 +76,77 @@ .PP * * * * * .SH Code Blocks-.PP Code: .IP-.nf-\f[C]----- (should be four hyphens)+.EX+\-\-\-\- (should be four hyphens) sub status {- print \[dq]working\[dq];+ print \(dqworking\(dq; } this code block is indented by one tab-\f[R]-.fi+.EE .PP And: .IP-.nf-\f[C]+.EX this code block is indented by two tabs -These should not be escaped: \[rs]$ \[rs]\[rs] \[rs]> \[rs][ \[rs]{-\f[R]-.fi+These should not be escaped: \(rs$ \(rs\(rs \(rs> \(rs[ \(rs{+.EE .PP * * * * * .SH Lists .SS Unordered-.PP Asterisks tight:-.IP \[bu] 2+.IP \(bu 2 asterisk 1-.IP \[bu] 2+.IP \(bu 2 asterisk 2-.IP \[bu] 2+.IP \(bu 2 asterisk 3 .PP Asterisks loose:-.IP \[bu] 2+.IP \(bu 2 asterisk 1-.IP \[bu] 2+.IP \(bu 2 asterisk 2-.IP \[bu] 2+.IP \(bu 2 asterisk 3 .PP Pluses tight:-.IP \[bu] 2+.IP \(bu 2 Plus 1-.IP \[bu] 2+.IP \(bu 2 Plus 2-.IP \[bu] 2+.IP \(bu 2 Plus 3 .PP Pluses loose:-.IP \[bu] 2+.IP \(bu 2 Plus 1-.IP \[bu] 2+.IP \(bu 2 Plus 2-.IP \[bu] 2+.IP \(bu 2 Plus 3 .PP Minuses tight:-.IP \[bu] 2+.IP \(bu 2 Minus 1-.IP \[bu] 2+.IP \(bu 2 Minus 2-.IP \[bu] 2+.IP \(bu 2 Minus 3 .PP Minuses loose:-.IP \[bu] 2+.IP \(bu 2 Minus 1-.IP \[bu] 2+.IP \(bu 2 Minus 2-.IP \[bu] 2+.IP \(bu 2 Minus 3 .SS Ordered-.PP Tight: .IP "1." 3 First@@ -214,35 +186,35 @@ .PP Item 1. graf two.-The quick brown fox jumped over the lazy dog\[cq]s back.+The quick brown fox jumped over the lazy dog\(cqs back. .RE .IP "2." 3 Item 2. .IP "3." 3 Item 3. .SS Nested-.IP \[bu] 2+.IP \(bu 2 Tab .RS 2-.IP \[bu] 2+.IP \(bu 2 Tab .RS 2-.IP \[bu] 2+.IP \(bu 2 Tab .RE .RE .PP-Here\[cq]s another:+Here\(cqs another: .IP "1." 3 First .IP "2." 3 Second: .RS 4-.IP \[bu] 2+.IP \(bu 2 Fee-.IP \[bu] 2+.IP \(bu 2 Fie-.IP \[bu] 2+.IP \(bu 2 Foe .RE .IP "3." 3@@ -254,24 +226,24 @@ .IP "2." 3 Second: .RS 4-.IP \[bu] 2+.IP \(bu 2 Fee-.IP \[bu] 2+.IP \(bu 2 Fie-.IP \[bu] 2+.IP \(bu 2 Foe .RE .IP "3." 3 Third .SS Tabs and spaces-.IP \[bu] 2+.IP \(bu 2 this is a list item indented with tabs-.IP \[bu] 2+.IP \(bu 2 this is a list item indented with spaces .RS 2-.IP \[bu] 2+.IP \(bu 2 this is an example list item indented with tabs-.IP \[bu] 2+.IP \(bu 2 this is an example list item indented with spaces .RE .SS Fancy list markers@@ -324,12 +296,10 @@ .PP M.A.\ 2007 .PP-B.-Williams+B. Williams .PP * * * * * .SH Definition Lists-.PP Tight using spaces: .TP apple@@ -376,11 +346,9 @@ orange fruit .RS .IP-.nf-\f[C]+.EX { orange code block }-\f[R]-.fi+.EE .RS .PP orange block quote@@ -391,27 +359,40 @@ .TP apple red fruit+.RS computer+.RE .TP orange orange fruit+.RS bank+.RE .PP Multiple definitions, loose: .TP apple red fruit+.RS+.PP computer+.RE .TP orange orange fruit+.RS+.PP bank+.RE .PP Blank line after term, indented marker, alternate markers: .TP apple red fruit+.RS+.PP computer+.RE .TP orange orange fruit@@ -422,7 +403,6 @@ sublist .RE .SH HTML Blocks-.PP Simple block on one line: foo .PP@@ -435,27 +415,23 @@ This is \f[I]emphasized\f[R] And this is \f[B]strong\f[R] .PP-Here\[cq]s a simple block:+Here\(cqs a simple block: .PP foo .PP This should be a code block, though: .IP-.nf-\f[C]+.EX <div> foo </div>-\f[R]-.fi+.EE .PP As should this: .IP-.nf-\f[C]+.EX <div>foo</div>-\f[R]-.fi+.EE .PP Now, nested: foo@@ -466,27 +442,22 @@ .PP Code block: .IP-.nf-\f[C]-<!-- Comment -->-\f[R]-.fi+.EX+<!\-\- Comment \-\->+.EE .PP Just plain comment, with trailing spaces on the line: .PP Code: .IP-.nf-\f[C]+.EX <hr />-\f[R]-.fi+.EE .PP-Hr\[cq]s:+Hr\(cqs: .PP * * * * * .SH Inline Markup-.PP This is \f[I]emphasized\f[R], and so \f[I]is this\f[R]. .PP This is \f[B]strong\f[R], and so \f[B]is this\f[R].@@ -501,8 +472,8 @@ .PP So is \f[B]\f[BI]this\f[B]\f[R] word. .PP-This is code: \f[V]>\f[R], \f[V]$\f[R], \f[V]\[rs]\f[R], \f[V]\[rs]$\f[R],-\f[V]<html>\f[R].+This is code: \f[CR]>\f[R], \f[CR]$\f[R], \f[CR]\(rs\f[R], \f[CR]\(rs$\f[R],+\f[CR]<html>\f[R]. .PP [STRIKEOUT:This is \f[I]strikeout\f[R].] .PP@@ -511,80 +482,81 @@ Subscripts: H~2~O, H~23~O, H~many\ of\ them~O. .PP These should not be superscripts or subscripts, because of the unescaped spaces:-a\[ha]b c\[ha]d, a\[ti]b c\[ti]d.+a\(hab c\(had, a\(tib c\(tid. .PP * * * * * .SH Smart quotes, ellipses, dashes-.PP-\[lq]Hello,\[rq] said the spider.-\[lq]`Shelob' is my name.\[rq]+\(lqHello,\(rq said the spider.+\(lq`Shelob' is my name.\(rq .PP `A', `B', and `C' are letters. .PP `Oak,' `elm,' and `beech' are names of trees. So is `pine.' .PP-`He said, \[lq]I want to go.\[rq]' Were you alive in the 70\[cq]s?+`He said, \(lqI want to go.\(rq' Were you alive in the 70\(cqs? .PP-Here is some quoted `\f[V]code\f[R]' and a \[lq]quoted-link (http://example.com/?foo=1&bar=2)\[rq].+Here is some quoted `\f[CR]code\f[R]' and a \(lq\c+.UR http://example.com/?foo=1&bar=2+quoted link+.UE \c+\(rq. .PP-Some dashes: one\[em]two \[em] three\[em]four \[em] five.+Some dashes: one\(emtwo \(em three\(emfour \(em five. .PP-Dashes between numbers: 5\[en]7, 255\[en]66, 1987\[en]1999.+Dashes between numbers: 5\(en7, 255\(en66, 1987\(en1999. .PP Ellipses\&...and\&...and\&.... .PP * * * * * .SH LaTeX-.IP \[bu] 2-.IP \[bu] 2-2\[u2005]+\[u2005]2\[u2004]=\[u2004]4-.IP \[bu] 2-\f[I]x\f[R]\[u2004]\[mo]\[u2004]\f[I]y\f[R]-.IP \[bu] 2-\f[I]\[*a]\f[R]\[u2005]\[AN]\[u2005]\f[I]\[*w]\f[R]-.IP \[bu] 2+.IP \(bu 2+.IP \(bu 2+2 + 2 = 4+.IP \(bu 2+\f[I]x\f[R] ∈ \f[I]y\f[R]+.IP \(bu 2+\f[I]α\f[R] ∧ \f[I]ω\f[R]+.IP \(bu 2 223-.IP \[bu] 2-\f[I]p\f[R]-Tree-.IP \[bu] 2-Here\[cq]s some display math:+.IP \(bu 2+\f[I]p\f[R]\-Tree+.IP \(bu 2+Here\(cqs some display math: .RS-$$\[rs]frac{d}{dx}f(x)=\[rs]lim_{h\[rs]to 0}\[rs]frac{f(x+h)-f(x)}{h}$$+$$\(rsfrac{d}{dx}f(x)=\(rslim_{h\(rsto 0}\(rsfrac{f(x+h)\-f(x)}{h}$$ .RE-.IP \[bu] 2-Here\[cq]s one that has a line break in it:-\f[I]\[*a]\f[R]\[u2005]+\[u2005]\f[I]\[*w]\f[R]\[u2005]\[tmu]\[u2005]\f[I]x\f[R]^2^.+.IP \(bu 2+Here\(cqs one that has a line break in it:+\f[I]α\f[R] + \f[I]ω\f[R] × \f[I]x\f[R]^2^. .PP-These shouldn\[cq]t be math:-.IP \[bu] 2-To get the famous equation, write \f[V]$e = mc\[ha]2$\f[R].-.IP \[bu] 2+These shouldn\(cqt be math:+.IP \(bu 2+To get the famous equation, write \f[CR]$e = mc\(ha2$\f[R].+.IP \(bu 2 $22,000 is a \f[I]lot\f[R] of money. So is $34,000.-(It worked if \[lq]lot\[rq] is emphasized.)-.IP \[bu] 2+(It worked if \(lqlot\(rq is emphasized.)+.IP \(bu 2 Shoes ($20) and socks ($5).-.IP \[bu] 2-Escaped \f[V]$\f[R]: $73 \f[I]this should be emphasized\f[R] 23$.+.IP \(bu 2+Escaped \f[CR]$\f[R]: $73 \f[I]this should be emphasized\f[R] 23$. .PP-Here\[cq]s a LaTeX table:+Here\(cqs a LaTeX table: .PP * * * * * .SH Special Characters-.PP Here is some unicode:-.IP \[bu] 2-I hat: \[^I]-.IP \[bu] 2-o umlaut: \[:o]-.IP \[bu] 2-section: \[sc]-.IP \[bu] 2-set membership: \[mo]-.IP \[bu] 2-copyright: \[co]+.IP \(bu 2+I hat: Î+.IP \(bu 2+o umlaut: ö+.IP \(bu 2+section: §+.IP \(bu 2+set membership: ∈+.IP \(bu 2+copyright: © .PP AT&T has an ampersand in their name. .PP@@ -596,9 +568,9 @@ .PP 6 > 5. .PP-Backslash: \[rs]+Backslash: \(rs .PP-Backtick: \[ga]+Backtick: \(ga .PP Asterisk: * .PP@@ -616,7 +588,7 @@ .PP Right paren: ) .PP-Greater-than: >+Greater\-than: > .PP Hash: # .PP@@ -626,12 +598,11 @@ .PP Plus: + .PP-Minus: -+Minus: \- .PP * * * * * .SH Links .SS Explicit-.PP Just a URL. .PP URL and title.@@ -646,11 +617,13 @@ .PP with_underscore .PP-Email link (mailto:nobody@nowhere.net)+\c+.MT nobody@nowhere.net+Email link+.ME \c .PP Empty. .SS Reference-.PP Foo bar. .PP With embedded [brackets].@@ -665,63 +638,70 @@ .PP This should [not][] be a link. .IP-.nf-\f[C]+.EX [not]: /url-\f[R]-.fi+.EE .PP Foo bar. .PP Foo biz. .SS With ampersands-.PP-Here\[cq]s a link with an ampersand in the-URL (http://example.com/?foo=1&bar=2).+Here\(cqs a \c+.UR http://example.com/?foo=1&bar=2+link with an ampersand in the URL+.UE \c+\&. .PP-Here\[cq]s a link with an amersand in the link text: AT&T (http://att.com/).+Here\(cqs a link with an amersand in the link text: \c+.UR http://att.com/+AT&T+.UE \c+\&. .PP-Here\[cq]s an inline link.+Here\(cqs an inline link. .PP-Here\[cq]s an inline link in pointy braces.+Here\(cqs an inline link in pointy braces. .SS Autolinks-.PP-With an ampersand: <http://example.com/?foo=1&bar=2>-.IP \[bu] 2+With an ampersand: \c+.UR http://example.com/?foo=1&bar=2+.UE \c+.IP \(bu 2 In a list?-.IP \[bu] 2-<http://example.com/>-.IP \[bu] 2+.IP \(bu 2+\c+.UR http://example.com/+.UE \c+.IP \(bu 2 It should. .PP-An e-mail address: <nobody@nowhere.net>+An e\-mail address: \c+.MT nobody@nowhere.net+.ME \c .RS .PP-Blockquoted: <http://example.com/>+Blockquoted: \c+.UR http://example.com/+.UE \c .RE .PP-Auto-links should not occur here: \f[V]<http://example.com/>\f[R]+Auto\-links should not occur here: \f[CR]<http://example.com/>\f[R] .IP-.nf-\f[C]+.EX or here: <http://example.com/>-\f[R]-.fi+.EE .PP * * * * * .SH Images-.PP-From \[lq]Voyage dans la Lune\[rq] by Georges Melies (1902):-.PP+From \(lqVoyage dans la Lune\(rq by Georges Melies (1902): [IMAGE: lalune]+lalune .PP Here is a movie [IMAGE: movie] icon. .PP * * * * * .SH Footnotes-.PP Here is a footnote reference,[1] and another.[2] This should \f[I]not\f[R] be a-footnote reference, because it contains a space.[\[ha]my note] Here is an inline+footnote reference, because it contains a space.[\(hamy note] Here is an inline note.[3] .RS .PP@@ -739,25 +719,26 @@ It need not be placed at the end of the document. .SS [2] .PP-Here\[cq]s the long note.+Here\(cqs the long note. This one contains multiple blocks. .PP Subsequent blocks are indented to show that they belong to the footnote (as with list items). .IP-.nf-\f[C]+.EX { <code> }-\f[R]-.fi+.EE .PP If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. .SS [3] .PP This is \f[I]easier\f[R] to type.-Inline notes may contain links (http://google.com) and \f[V]]\f[R] verbatim-characters, as well as [bracketed text].+Inline notes may contain \c+.UR http://google.com+links+.UE \c+\ and \f[CR]]\f[R] verbatim characters, as well as [bracketed text]. .SS [4] .PP In quote.
@@ -105,45 +105,45 @@ Asterisks tight: -- asterisk 1-- asterisk 2-- asterisk 3+- asterisk 1+- asterisk 2+- asterisk 3 Asterisks loose: -- asterisk 1+- asterisk 1 -- asterisk 2+- asterisk 2 -- asterisk 3+- asterisk 3 Pluses tight: -- Plus 1-- Plus 2-- Plus 3+- Plus 1+- Plus 2+- Plus 3 Pluses loose: -- Plus 1+- Plus 1 -- Plus 2+- Plus 2 -- Plus 3+- Plus 3 Minuses tight: -- Minus 1-- Minus 2-- Minus 3+- Minus 1+- Minus 2+- Minus 3 Minuses loose: -- Minus 1+- Minus 1 -- Minus 2+- Minus 2 -- Minus 3+- Minus 3 ## Ordered @@ -187,17 +187,17 @@ ## Nested -- Tab- - Tab- - Tab+- Tab+ - Tab+ - Tab Here's another: 1. First 2. Second:- - Fee- - Fie- - Foe+ - Fee+ - Fie+ - Foe 3. Third Same thing but with paragraphs:@@ -206,21 +206,21 @@ 2. Second: - - Fee- - Fie- - Foe+ - Fee+ - Fie+ - Foe 3. Third ## Tabs and spaces -- this is a list item indented with tabs+- this is a list item indented with tabs -- this is a list item indented with spaces+- this is a list item indented with spaces - - this is an example list item indented with tabs+ - this is an example list item indented with tabs - - this is an example list item indented with spaces+ - this is an example list item indented with spaces ## Fancy list markers @@ -261,164 +261,135 @@ Tight using spaces: apple-: red fruit+: red fruit orange-: orange fruit+: orange fruit banana-: yellow fruit+: yellow fruit Tight using tabs: apple-: red fruit+: red fruit orange-: orange fruit+: orange fruit banana-: yellow fruit+: yellow fruit Loose: apple -: red fruit+: red fruit orange -: orange fruit+: orange fruit banana -: yellow fruit+: yellow fruit Multiple blocks with italics: *apple* -: red fruit+: red fruit - contains seeds, crisp, pleasant to taste+ contains seeds, crisp, pleasant to taste *orange* -: orange fruit+: orange fruit - { orange code block }+ { orange code block } - > orange block quote+ > orange block quote Multiple definitions, tight: apple-: red fruit-: computer+: red fruit+: computer orange-: orange fruit-: bank+: orange fruit+: bank Multiple definitions, loose: apple -: red fruit+: red fruit -: computer+: computer orange -: orange fruit+: orange fruit -: bank+: bank Blank line after term, indented marker, alternate markers: apple -: red fruit+: red fruit -: computer+: computer orange -: orange fruit+: orange fruit - 1. sublist- 2. sublist+ 1. sublist+ 2. sublist # HTML Blocks Simple block on one line: -<div>-+::: {} foo--</div>+::: And nested without indentation: -<div>--<div>--<div>-+:::::: {}+:::: {}+::: {} foo--</div>--</div>--<div>+:::+:::: +::: {} bar--</div>--</div>+:::+:::::: Interpreted markdown in a table: -```{=html} <table>-```-```{=html} <tr>-```-```{=html} <td>-``` This is *emphasized*-```{=html} </td>-```-```{=html} <td>-``` And this is **strong**-```{=html} </td>-```-```{=html} </tr>-```-```{=html} </table>-```-```{=html} <script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script>-```-Here's a simple block: -<div>+Here's a simple block: +::: {} foo--</div>+::: This should be a code block, though: @@ -432,80 +403,51 @@ Now, nested: -<div>--<div>--<div>-+::::: {}+:::: {}+::: {} foo--</div>--</div>--</div>+:::+::::+::::: This should just be an HTML comment: -```{=html} <!-- Comment -->-```+ Multiline: -```{=html} <!-- Blah Blah -->-```-```{=html} <!-- This is another comment. -->-```+ Code block: <!-- Comment --> Just plain comment, with trailing spaces on the line: -```{=html} <!-- foo -->-```+ Code: <hr /> Hr's: -```{=html} <hr>-```-```{=html} <hr />-```-```{=html} <hr />-```-```{=html} <hr>-```-```{=html} <hr />-```-```{=html} <hr />-```-```{=html} <hr class="foo" id="bar" />-```-```{=html} <hr class="foo" id="bar" />-```-```{=html} <hr class="foo" id="bar">-``` -------------------------------------------------------------------------------- @@ -561,33 +503,31 @@ # LaTeX -- `\cite[22-23]{smith.1899}`{=tex}-- $2+2=4$-- $x \in y$-- $\alpha \wedge \omega$-- $223$-- $p$-Tree-- Here's some display math:- $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$-- Here's one that has a line break in it: $\alpha + \omega \times x^2$.+- `\cite[22-23]{smith.1899}`{=tex}+- $2+2=4$+- $x \in y$+- $\alpha \wedge \omega$+- $223$+- $p$-Tree+- Here's some display math:+ $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$+- Here's one that has a line break in it: $\alpha + \omega \times x^2$. These shouldn't be math: -- To get the famous equation, write `$e = mc^2$`.-- \$22,000 is a *lot* of money. So is \$34,000. (It worked if "lot" is- emphasized.)-- Shoes (\$20) and socks (\$5).-- Escaped `$`: \$73 *this should be emphasized* 23\$.+- To get the famous equation, write `$e = mc^2$`.+- \$22,000 is a *lot* of money. So is \$34,000. (It worked if "lot" is+ emphasized.)+- Shoes (\$20) and socks (\$5).+- Escaped `$`: \$73 *this should be emphasized* 23\$. Here's a LaTeX table: -```{=tex} \begin{tabular}{|l|l|}\hline Animal & Number \\ \hline Dog & 2 \\ Cat & 1 \\ \hline \end{tabular}-``` -------------------------------------------------------------------------------- @@ -595,11 +535,11 @@ Here is some unicode: -- I hat: Î-- o umlaut: ö-- section: §-- set membership: ∈-- copyright: ©+- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: © AT&T has an ampersand in their name. @@ -703,9 +643,9 @@ With an ampersand: <http://example.com/?foo=1&bar=2> -- In a list?-- <http://example.com/>-- It should.+- In a list?+- <http://example.com/>+- It should. An e-mail address: <nobody@nowhere.net>
@@ -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@@ -655,6 +655,8 @@ {alt: "lalune", title: "Voyage dans la Lune"} ++lalune Here is a movie {alt: "movie"}
@@ -1,6 +1,5 @@ This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite. - ----- <span id="headers"></span>@@ -34,7 +33,6 @@ with no blank line - ----- <span id="paragraphs"></span>@@ -49,7 +47,6 @@ There should be a hard line break<br /> here. - ----- <span id="block-quotes"></span>@@ -74,12 +71,12 @@ <blockquote>nested </blockquote> <blockquote>nested-</blockquote></blockquote>+</blockquote>+</blockquote> This should not be a block quote: 2 > 1. And a following paragraph. - ----- <span id="code-blocks"></span>@@ -224,9 +221,7 @@ <li>more items <ol style="list-style-type: upper-alpha;"> <li>a subsublist</li>-<li>a subsublist</li></ol>-</li></ol>-</li></ol>+<li>a subsublist</li></ol></li></ol></li></ol> Nesting: @@ -237,10 +232,7 @@ <ol start="6" style="list-style-type: decimal;"> <li>Decimal start with 6 <ol start="3" style="list-style-type: lower-alpha;">-<li>Lower alpha with paren</li></ol>-</li></ol>-</li></ol>-</li></ol>+<li>Lower alpha with paren</li></ol></li></ol></li></ol></li></ol> Autonumbering: @@ -254,7 +246,6 @@ B. Williams - ----- <span id="definition-lists"></span>@@ -296,7 +287,8 @@ <dt>''orange''</dt> <dd><p>orange fruit</p> <pre>{ orange code block }</pre>-<blockquote><p>orange block quote</p></blockquote></dd></dl>+<blockquote><p>orange block quote</p>+</blockquote></dd></dl> Multiple definitions, tight: @@ -332,31 +324,26 @@ Simple block on one line: <div>- foo- </div>+ And nested without indentation: <div>- <div>- <div>- foo - </div> </div>-<div> +<div> bar- </div> </div>+ Interpreted markdown in a table: <table>@@ -373,11 +360,10 @@ Here’s a simple block: <div>- foo - </div>+ This should be a code block, though: <pre><div>@@ -389,18 +375,15 @@ Now, nested: <div>- <div>- <div>- foo- </div> </div> </div>+ This should just be an HTML comment: <!-- Comment -->@@ -463,7 +446,6 @@ These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d. - ----- <span id="smart-quotes-ellipses-dashes"></span>@@ -485,13 +467,12 @@ Ellipses…and…and…. - ----- <span id="latex"></span> = LaTeX = -* +* * <math display="inline">2+2=4</math> * <math display="inline">x \in y</math> * <math display="inline">\alpha \wedge \omega</math>@@ -509,8 +490,6 @@ Here’s a LaTeX table: -- ----- <span id="special-characters"></span>@@ -566,7 +545,6 @@ Minus: - - ----- <span id="links"></span>@@ -650,10 +628,11 @@ From “Voyage dans la Lune” by Georges Melies (1902): -[[File:lalune.jpg|thumb|none|alt=Voyage dans la Lune|lalune]]+<div class="figure">+[[File:lalune.jpg|lalune]]+</div> Here is a movie [[File:movie.jpg|movie]] icon.- -----
@@ -27,7 +27,7 @@ .\" line height .nr VS 12p .\" font family: A, BM, H, HN, N, P, T, ZCM-.fam P+.fam T .\" paragraph indent .nr PI 0m .\" interparagraph space@@ -38,10 +38,6 @@ .nr FPS (\n[PS] - 2000) .\" color used for strikeout .defcolor strikecolor rgb 0.7 0.7 0.7-.\" color for links (rgb)-.ds PDFHREF.COLOUR 0.35 0.00 0.60-.\" border for links (default none)-.ds PDFHREF.BORDER 0 0 0 .\" point size difference between heading levels .nr PSINCR 1p .\" heading level above which point size no longer changes@@ -52,6 +48,14 @@ .\" page numbers in footer, centered .ds CH .ds CF %+.hy+.EQ+delim @@+.EN+.\" color for links (rgb)+.ds PDFHREF.COLOUR 0.35 0.00 0.60+.\" border for links (default none)+.ds PDFHREF.BORDER 0 0 0 .\" pdf outline fold level .nr PDFOUTLINE.FOLDLEVEL 3 .\" start out in outline view@@ -60,10 +64,6 @@ .\" PDF metadata .pdfinfo /Title "Pandoc Test Suite" .pdfinfo /Author "John MacFarlane; Anonymous"-.hy-.EQ-delim @@-.EN .TL Pandoc Test Suite .AU@@ -78,7 +78,7 @@ .1C .LP This is a set of tests for pandoc.-Most of them are adapted from John Gruber\[cq]s markdown test suite.+Most of them are adapted from John Gruber\(cqs markdown test suite. .HLINE .SH 1 Headers@@ -129,7 +129,7 @@ .pdfhref O 1 "Paragraphs" .pdfhref M "paragraphs" .LP-Here\[cq]s a regular paragraph.+Here\(cqs a regular paragraph. .PP In Markdown 1.0.0 and earlier. Version 8.@@ -137,7 +137,7 @@ Because a hard-wrapped line in the middle of a paragraph looked like a list item. .PP-Here\[cq]s one with a bullet.+Here\(cqs one with a bullet. * criminey. .PP There should be a hard line break@@ -162,7 +162,7 @@ .nf \f[C] sub status {- print \[dq]working\[dq];+ print \(dqworking\(dq; } \f[] .fi@@ -200,7 +200,7 @@ ---- (should be four hyphens) sub status {- print \[dq]working\[dq];+ print \(dqworking\(dq; } this code block is indented by one tab@@ -213,7 +213,7 @@ \f[C] this code block is indented by two tabs -These should not be escaped: \[rs]$ \[rs]\[rs] \[rs]> \[rs][ \[rs]{+These should not be escaped: \(rs$ \(rs\(rs \(rs> \(rs[ \(rs{ \f[] .fi .HLINE@@ -227,51 +227,51 @@ .pdfhref M "unordered" .LP Asterisks tight:-.IP \[bu] 3+.IP \(bu 3 asterisk 1-.IP \[bu] 3+.IP \(bu 3 asterisk 2-.IP \[bu] 3+.IP \(bu 3 asterisk 3 .LP Asterisks loose:-.IP \[bu] 3+.IP \(bu 3 asterisk 1-.IP \[bu] 3+.IP \(bu 3 asterisk 2-.IP \[bu] 3+.IP \(bu 3 asterisk 3 .LP Pluses tight:-.IP \[bu] 3+.IP \(bu 3 Plus 1-.IP \[bu] 3+.IP \(bu 3 Plus 2-.IP \[bu] 3+.IP \(bu 3 Plus 3 .LP Pluses loose:-.IP \[bu] 3+.IP \(bu 3 Plus 1-.IP \[bu] 3+.IP \(bu 3 Plus 2-.IP \[bu] 3+.IP \(bu 3 Plus 3 .LP Minuses tight:-.IP \[bu] 3+.IP \(bu 3 Minus 1-.IP \[bu] 3+.IP \(bu 3 Minus 2-.IP \[bu] 3+.IP \(bu 3 Minus 3 .LP Minuses loose:-.IP \[bu] 3+.IP \(bu 3 Minus 1-.IP \[bu] 3+.IP \(bu 3 Minus 2-.IP \[bu] 3+.IP \(bu 3 Minus 3 .SH 2 Ordered@@ -317,7 +317,7 @@ .PP Item 1. graf two.-The quick brown fox jumped over the lazy dog\[cq]s back.+The quick brown fox jumped over the lazy dog\(cqs back. .RE .IP " 2." 4 Item 2.@@ -327,28 +327,28 @@ Nested .pdfhref O 2 "Nested" .pdfhref M "nested"-.IP \[bu] 3+.IP \(bu 3 Tab .RS 3-.IP \[bu] 3+.IP \(bu 3 Tab .RS 3-.IP \[bu] 3+.IP \(bu 3 Tab .RE .RE .LP-Here\[cq]s another:+Here\(cqs another: .IP " 1." 4 First .IP " 2." 4 Second: .RS 4-.IP \[bu] 3+.IP \(bu 3 Fee-.IP \[bu] 3+.IP \(bu 3 Fie-.IP \[bu] 3+.IP \(bu 3 Foe .RE .IP " 3." 4@@ -360,11 +360,11 @@ .IP " 2." 4 Second: .RS 4-.IP \[bu] 3+.IP \(bu 3 Fee-.IP \[bu] 3+.IP \(bu 3 Fie-.IP \[bu] 3+.IP \(bu 3 Foe .RE .IP " 3." 4@@ -373,14 +373,14 @@ Tabs and spaces .pdfhref O 2 "Tabs and spaces" .pdfhref M "tabs-and-spaces"-.IP \[bu] 3+.IP \(bu 3 this is a list item indented with tabs-.IP \[bu] 3+.IP \(bu 3 this is a list item indented with spaces .RS 3-.IP \[bu] 3+.IP \(bu 3 this is an example list item indented with tabs-.IP \[bu] 3+.IP \(bu 3 this is an example list item indented with spaces .RE .SH 2@@ -436,8 +436,7 @@ .PP M.A.\ 2007 .PP-B.-Williams+B. Williams .HLINE .SH 1 Definition Lists@@ -573,7 +572,7 @@ This is \f[I]emphasized\f[R] And this is \f[B]strong\f[R] .PP-Here\[cq]s a simple block:+Here\(cqs a simple block: .LP foo .LP@@ -620,7 +619,7 @@ \f[] .fi .LP-Hr\[cq]s:+Hr\(cqs: .HLINE .SH 1 Inline Markup@@ -644,8 +643,8 @@ .PP So is \f[B]\f[BI]this\f[B]\f[R] word. .PP-This is code: \f[C]>\f[R], \f[C]$\f[R], \f[C]\[rs]\f[R], \f[C]\[rs]$\f[R],-\f[C]<html>\f[R].+This is code: \f[CR]>\f[R], \f[CR]$\f[R], \f[CR]\(rs\f[R], \f[CR]\(rs$\f[R],+\f[CR]<html>\f[R]. .PP \m[strikecolor]This is \f[I]strikeout\f[R].\m[] .PP@@ -654,31 +653,31 @@ Subscripts: H\*<2\*>O, H\*<23\*>O, H\*<many\ of\ them\*>O. .PP These should not be superscripts or subscripts, because of the unescaped spaces:-a\[ha]b c\[ha]d, a\[ti]b c\[ti]d.+a\(hab c\(had, a\(tib c\(tid. .HLINE .SH 1 Smart quotes, ellipses, dashes .pdfhref O 1 "Smart quotes, ellipses, dashes" .pdfhref M "smart-quotes-ellipses-dashes" .LP-\[lq]Hello,\[rq] said the spider.-\[lq]`Shelob' is my name.\[rq]+\(lqHello,\(rq said the spider.+\(lq`Shelob' is my name.\(rq .PP `A', `B', and `C' are letters. .PP `Oak,' `elm,' and `beech' are names of trees. So is `pine.' .PP-`He said, \[lq]I want to go.\[rq]' Were you alive in the 70\[cq]s?+`He said, \(lqI want to go.\(rq' Were you alive in the 70\(cqs? .PP-Here is some quoted `\f[C]code\f[R]' and a \[lq]\c+Here is some quoted `\f[CR]code\f[R]' and a \(lq\c .pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \ -- "quoted link"-\&\[rq].+\&\(rq. .PP-Some dashes: one\[em]two \[em] three\[em]four \[em] five.+Some dashes: one\(emtwo \(em three\(emfour \(em five. .PP-Dashes between numbers: 5\[en]7, 255\[en]66, 1987\[en]1999.+Dashes between numbers: 5\(en7, 255\(en66, 1987\(en1999. .PP Ellipses\&...and\&...and\&.... .HLINE@@ -686,38 +685,38 @@ LaTeX .pdfhref O 1 "LaTeX" .pdfhref M "latex"-.IP \[bu] 3-.IP \[bu] 3+.IP \(bu 3+.IP \(bu 3 @2 + 2 = 4@-.IP \[bu] 3+.IP \(bu 3 @x \[u2208] y@-.IP \[bu] 3+.IP \(bu 3 @alpha \[u2227] omega@-.IP \[bu] 3+.IP \(bu 3 @223@-.IP \[bu] 3+.IP \(bu 3 @p@-Tree-.IP \[bu] 3-Here\[cq]s some display math:+.IP \(bu 3+Here\(cqs some display math: .EQ-d over {d x} f left ( x right ) = lim sub {h -> 0} {f left ( x + h right ) \[u2212] f left ( x right )} over h+d over {d x} f ( x ) = lim from {h -> 0} {f ( x + h ) - f ( x )} over h .EN-.IP \[bu] 3-Here\[cq]s one that has a line break in it: @alpha + omega times x sup 2@.+.IP \(bu 3+Here\(cqs one that has a line break in it: @alpha + omega times x sup 2@. .LP-These shouldn\[cq]t be math:-.IP \[bu] 3-To get the famous equation, write \f[C]$e = mc\[ha]2$\f[R].-.IP \[bu] 3+These shouldn\(cqt be math:+.IP \(bu 3+To get the famous equation, write \f[CR]$e = mc\(ha2$\f[R].+.IP \(bu 3 $22,000 is a \f[I]lot\f[R] of money. So is $34,000.-(It worked if \[lq]lot\[rq] is emphasized.)-.IP \[bu] 3+(It worked if \(lqlot\(rq is emphasized.)+.IP \(bu 3 Shoes ($20) and socks ($5).-.IP \[bu] 3-Escaped \f[C]$\f[R]: $73 \f[I]this should be emphasized\f[R] 23$.+.IP \(bu 3+Escaped \f[CR]$\f[R]: $73 \f[I]this should be emphasized\f[R] 23$. .LP-Here\[cq]s a LaTeX table:+Here\(cqs a LaTeX table: .HLINE .SH 1 Special Characters@@ -725,15 +724,15 @@ .pdfhref M "special-characters" .LP Here is some unicode:-.IP \[bu] 3+.IP \(bu 3 I hat: Î-.IP \[bu] 3+.IP \(bu 3 o umlaut: ö-.IP \[bu] 3+.IP \(bu 3 section: §-.IP \[bu] 3+.IP \(bu 3 set membership: ∈-.IP \[bu] 3+.IP \(bu 3 copyright: © .LP AT&T has an ampersand in their name.@@ -746,9 +745,9 @@ .PP 6 > 5. .PP-Backslash: \[rs]+Backslash: \(rs .PP-Backtick: \[ga]+Backtick: \(ga .PP Asterisk: * .PP@@ -888,22 +887,22 @@ .pdfhref O 2 "With ampersands" .pdfhref M "with-ampersands" .LP-Here\[cq]s a \c+Here\(cqs a \c .pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \ -- "link with an ampersand in the URL" \&. .PP-Here\[cq]s a link with an amersand in the link text: \c+Here\(cqs a link with an amersand in the link text: \c .pdfhref W -D "http://att.com/" -A "\c" \ -- "AT&T" \&. .PP-Here\[cq]s an \c+Here\(cqs an \c .pdfhref W -D "/script?foo=1&bar=2" -A "\c" \ -- "inline link" \&. .PP-Here\[cq]s an \c+Here\(cqs an \c .pdfhref W -D "/script?foo=1&bar=2" -A "\c" \ -- "inline link in pointy braces" \&.@@ -916,19 +915,19 @@ .pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \ -- "http://example.com/?foo=1&bar=2" \&-.IP \[bu] 3+.IP \(bu 3 In a list?-.IP \[bu] 3+.IP \(bu 3 \c .pdfhref W -D "http://example.com/" -A "\c" \ -- "http://example.com/" \&-.IP \[bu] 3+.IP \(bu 3 It should. .LP An e-mail address: \c .pdfhref W -D "mailto:nobody%40nowhere.net" -A "\c" \- -- "nobody\[at]nowhere.net"+ -- "nobody\(atnowhere.net" \& .QS .LP@@ -938,7 +937,7 @@ \& .QE .LP-Auto-links should not occur here: \f[C]<http://example.com/>\f[R]+Auto-links should not occur here: \f[CR]<http://example.com/>\f[R] .IP .nf \f[C]@@ -951,11 +950,15 @@ .pdfhref O 1 "Images" .pdfhref M "images" .LP-From \[lq]Voyage dans la Lune\[rq] by Georges Melies (1902):-.PP-[IMAGE: lalune]-.PP-Here is a movie [IMAGE: movie] icon.+From \(lqVoyage dans la Lune\(rq by Georges Melies (1902):+\" .IMAGE "lalune.jpg"+.ce 1+lalune+.sp 1+.LP+Here is a movie+[IMAGE: movie] \" "movie.jpg"+icon. .HLINE .SH 1 Footnotes@@ -970,7 +973,7 @@ .FE and another.\** .FS-Here\[cq]s the long note.+Here\(cqs the long note. This one contains multiple blocks. .PP Subsequent blocks are indented to show that they belong to the footnote (as with@@ -986,13 +989,13 @@ the first line of each block. .FE This should \f[I]not\f[R] be a footnote reference, because it contains a-space.[\[ha]my note] Here is an inline note.\**+space.[\(hamy note] Here is an inline note.\** .FS This is \f[I]easier\f[R] to type. Inline notes may contain \c .pdfhref W -D "http://google.com" -A "\c" \ -- "links"-\& and \f[C]]\f[R] verbatim characters, as well as [bracketed text].+\& and \f[CR]]\f[R] verbatim characters, as well as [bracketed text]. .FE .QS .LP
@@ -678,7 +678,7 @@ From “Voyage dans la Lune” by Georges Melies (1902): [[lalune.jpg][Voyage dans la Lune]]-+lalune Here is a movie [[movie.jpg][movie]] icon. ----
@@ -1841,11 +1841,15 @@ , Space , Str "(1902):" ]- , Para- [ Image- ( "" , [] , [] )- [ Str "lalune" ]- ( "lalune.jpg" , "fig:Voyage dans la Lune" )+ , Figure+ ( "" , [] , [] )+ (Caption Nothing [ Plain [ Str "lalune" ] ])+ [ Plain+ [ Image+ ( "" , [] , [] )+ [ Str "lalune" ]+ ( "lalune.jpg" , "Voyage dans la Lune" )+ ] ] , Para [ Str "Here"
@@ -1,1911 +1,961 @@ <?xml version="1.0" encoding="utf-8" ?>-<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.2">- <office:font-face-decls>- <style:font-face style:name="Courier New" style:font-family-generic="modern" style:font-pitch="fixed" svg:font-family="'Courier New'" />- </office:font-face-decls>- <office:automatic-styles>- <text:list-style style:name="L1">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L2">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L3">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L4">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L5">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L6">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L7">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L8">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L9">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L10">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L11">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L12">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L13">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L14">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L15">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L16">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L17">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L18">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L19">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L20">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L21">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L22">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="2" style:num-prefix="(" style:num-suffix=")">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="i" text:start-value="4" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-number>- <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="A" text:start-value="1" style:num-prefix="(" style:num-suffix=")">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L23">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="A" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="I" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-number>- <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="6" style:num-prefix="(" style:num-suffix=")">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-number>- <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="a" text:start-value="3" style:num-suffix=")">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L24">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L25">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <text:list-style style:name="L26">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L27">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L28">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L29">- <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.75in" fo:text-indent="-0.25in" fo:margin-left="0.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.0in" fo:text-indent="-0.25in" fo:margin-left="1.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.25in" fo:text-indent="-0.25in" fo:margin-left="1.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.5in" fo:text-indent="-0.25in" fo:margin-left="1.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.75in" fo:text-indent="-0.25in" fo:margin-left="1.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.0in" fo:text-indent="-0.25in" fo:margin-left="2.0in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="◦">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.25in" fo:text-indent="-0.25in" fo:margin-left="2.25in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="▪">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.5in" fo:text-indent="-0.25in" fo:margin-left="2.5in" />- </style:list-level-properties>- </text:list-level-style-bullet>- <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" style:num-suffix="." text:bullet-char="•">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.75in" fo:text-indent="-0.25in" fo:margin-left="2.75in" />- </style:list-level-properties>- </text:list-level-style-bullet>- </text:list-style>- <text:list-style style:name="L30">- <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" text:start-value="1" style:num-suffix=".">- <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="right">- <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.25in" fo:margin-left="0.5in" />- </style:list-level-properties>- </text:list-level-style-number>- </text:list-style>- <style:style style:name="T1" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" /></style:style>- <style:style style:name="T2" style:family="text"><style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style>- <style:style style:name="T3" style:family="text"><style:text-properties fo:font-style="italic" fo:font-weight="bold" style:font-style-asian="italic" style:font-style-complex="italic" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style>- <style:style style:name="T4" style:family="text"><style:text-properties style:text-line-through-style="solid" /></style:style>- <style:style style:name="T5" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-line-through-style="solid" /></style:style>- <style:style style:name="T6" style:family="text"><style:text-properties style:text-position="super 58%" /></style:style>- <style:style style:name="T7" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-position="super 58%" /></style:style>- <style:style style:name="T8" style:family="text"><style:text-properties style:text-position="sub 58%" /></style:style>- <style:style style:name="fr2" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" style:wrap="none" /></style:style>- <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" /></style:style>- <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Quotations">- <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />- </style:style>- <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Quotations">- <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />- </style:style>- <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />- </style:style>- <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />- </style:style>- <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />- </style:style>- <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1">- <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Quotations">- <style:paragraph-properties fo:margin-left="1.0in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />- </style:style>- <style:style style:name="P8" style:family="paragraph" style:parent-style-name="Quotations">- <style:paragraph-properties fo:margin-left="1.0in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />- </style:style>- <style:style style:name="P9" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P10" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P11" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P12" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P13" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P14" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P15" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P16" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P17" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P18" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P19" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L2">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P20" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L3">- </style:style>- <style:style style:name="P21" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L4">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P22" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L5">- </style:style>- <style:style style:name="P23" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L6">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P24" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L7">- </style:style>- <style:style style:name="P25" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L8">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P26" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L9">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P27" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L10">- </style:style>- <style:style style:name="P28" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L11">- </style:style>- <style:style style:name="P29" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L12">- </style:style>- <style:style style:name="P30" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L13">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P31" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L14">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P32" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L15">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P33" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L16">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P34" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L17">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P35" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L18">- </style:style>- <style:style style:name="P36" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L19">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P37" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L20">- </style:style>- <style:style style:name="P38" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L21">- </style:style>- <style:style style:name="P39" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L22">- </style:style>- <style:style style:name="P40" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L23">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P41" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L24">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P42" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />- </style:style>- <style:style style:name="P43" style:family="paragraph" style:parent-style-name="Quotations">- <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />- </style:style>- <style:style style:name="P44" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L25">- <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P45" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P46" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P47" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P48" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P49" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P50" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P51" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L26">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P52" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L27">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P53" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L28">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P54" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P55" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L29">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- <style:style style:name="P56" style:family="paragraph" style:parent-style-name="Quotations">- <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />- </style:style>- <style:style style:name="P57" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P58" style:family="paragraph" style:parent-style-name="Preformatted_20_Text">- </style:style>- <style:style style:name="P59" style:family="paragraph" style:parent-style-name="Quotations">- <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />- </style:style>- <style:style style:name="P60" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L30">- <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0in" />- </style:style>- </office:automatic-styles>-<office:body>-<office:text>-<text:p text:style-name="Title">Pandoc Test Suite</text:p>-<text:p text:style-name="Author">John MacFarlane</text:p>-<text:p text:style-name="Author">Anonymous</text:p>-<text:p text:style-name="Date">July 17, 2006</text:p>-<text:p text:style-name="Text_20_body">This is a set of tests for pandoc. Most-of them are adapted from John Gruber’s markdown test suite.</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="headers" />Headers<text:bookmark-end text:name="headers" /></text:h>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2-with-an-embedded-link" />Level-2 with an-<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">embedded-link</text:span></text:a><text:bookmark-end text:name="level-2-with-an-embedded-link" /></text:h>-<text:h text:style-name="Heading_20_3" text:outline-level="3"><text:bookmark-start text:name="level-3-with-emphasis" />Level-3 with-<text:span text:style-name="T1">emphasis</text:span><text:bookmark-end text:name="level-3-with-emphasis" /></text:h>-<text:h text:style-name="Heading_20_4" text:outline-level="4"><text:bookmark-start text:name="level-4" />Level-4<text:bookmark-end text:name="level-4" /></text:h>-<text:h text:style-name="Heading_20_5" text:outline-level="5"><text:bookmark-start text:name="level-5" />Level-5<text:bookmark-end text:name="level-5" /></text:h>-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="level-1" />Level-1<text:bookmark-end text:name="level-1" /></text:h>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2-with-emphasis" />Level-2 with-<text:span text:style-name="T1">emphasis</text:span><text:bookmark-end text:name="level-2-with-emphasis" /></text:h>-<text:h text:style-name="Heading_20_3" text:outline-level="3"><text:bookmark-start text:name="level-3" />Level-3<text:bookmark-end text:name="level-3" /></text:h>-<text:p text:style-name="First_20_paragraph">with no blank line</text:p>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2" />Level-2<text:bookmark-end text:name="level-2" /></text:h>-<text:p text:style-name="First_20_paragraph">with no blank line</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="paragraphs" />Paragraphs<text:bookmark-end text:name="paragraphs" /></text:h>-<text:p text:style-name="First_20_paragraph">Here’s a regular-paragraph.</text:p>-<text:p text:style-name="Text_20_body">In Markdown 1.0.0 and earlier. Version 8.-This line turns into a list item. Because a hard-wrapped line in the middle of a-paragraph looked like a list item.</text:p>-<text:p text:style-name="Text_20_body">Here’s one with a bullet. *-criminey.</text:p>-<text:p text:style-name="Text_20_body">There should be a hard line-break<text:line-break />here.</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="block-quotes" />Block-Quotes<text:bookmark-end text:name="block-quotes" /></text:h>-<text:p text:style-name="First_20_paragraph">E-mail style:</text:p>-<text:p text:style-name="P1">This is a block quote. It is pretty short.</text:p>-<text:p text:style-name="P2">Code in a block quote:</text:p>-<text:p text:style-name="P3">sub status {</text:p>-<text:p text:style-name="P4"><text:s text:c="4" />print "working";</text:p>-<text:p text:style-name="P5">}</text:p>-<text:p text:style-name="P2">A list:</text:p>-<text:list text:style-name="L1">- <text:list-item>- <text:p text:style-name="P6">item one</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P6">item two</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="P2">Nested block quotes:</text:p>-<text:p text:style-name="P7">nested</text:p>-<text:p text:style-name="P8">nested</text:p>-<text:p text:style-name="First_20_paragraph">This should not be a block quote: 2-> 1.</text:p>-<text:p text:style-name="Text_20_body">And a following paragraph.</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="code-blocks" />Code-Blocks<text:bookmark-end text:name="code-blocks" /></text:h>-<text:p text:style-name="First_20_paragraph">Code:</text:p>-<text:p text:style-name="P9">---- (should be four hyphens)</text:p>-<text:p text:style-name="P10"></text:p>-<text:p text:style-name="P11">sub status {</text:p>-<text:p text:style-name="P12"><text:s text:c="4" />print "working";</text:p>-<text:p text:style-name="P13">}</text:p>-<text:p text:style-name="P14"></text:p>-<text:p text:style-name="P15">this code block is indented by one tab</text:p>-<text:p text:style-name="First_20_paragraph">And:</text:p>-<text:p text:style-name="P16"><text:s text:c="4" />this code block is indented by two tabs</text:p>-<text:p text:style-name="P17"></text:p>-<text:p text:style-name="P18">These should not be escaped: <text:s text:c="1" />\$ \\ \> \[ \{</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="lists" />Lists<text:bookmark-end text:name="lists" /></text:h>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="unordered" />Unordered<text:bookmark-end text:name="unordered" /></text:h>-<text:p text:style-name="First_20_paragraph">Asterisks tight:</text:p>-<text:list text:style-name="L2">- <text:list-item>- <text:p text:style-name="P19">asterisk 1</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P19">asterisk 2</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P19">asterisk 3</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Asterisks loose:</text:p>-<text:list text:style-name="L3">- <text:list-item>- <text:p text:style-name="P20">asterisk 1</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P20">asterisk 2</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P20">asterisk 3</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Pluses tight:</text:p>-<text:list text:style-name="L4">- <text:list-item>- <text:p text:style-name="P21">Plus 1</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P21">Plus 2</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P21">Plus 3</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Pluses loose:</text:p>-<text:list text:style-name="L5">- <text:list-item>- <text:p text:style-name="P22">Plus 1</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P22">Plus 2</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P22">Plus 3</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Minuses tight:</text:p>-<text:list text:style-name="L6">- <text:list-item>- <text:p text:style-name="P23">Minus 1</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P23">Minus 2</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P23">Minus 3</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Minuses loose:</text:p>-<text:list text:style-name="L7">- <text:list-item>- <text:p text:style-name="P24">Minus 1</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P24">Minus 2</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P24">Minus 3</text:p>- </text:list-item>-</text:list>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="ordered" />Ordered<text:bookmark-end text:name="ordered" /></text:h>-<text:p text:style-name="First_20_paragraph">Tight:</text:p>-<text:list text:style-name="L8">- <text:list-item>- <text:p text:style-name="P25">First</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P25">Second</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P25">Third</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">and:</text:p>-<text:list text:style-name="L9">- <text:list-item>- <text:p text:style-name="P26">One</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P26">Two</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P26">Three</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Loose using tabs:</text:p>-<text:list text:style-name="L10">- <text:list-item>- <text:p text:style-name="P27">First</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P27">Second</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P27">Third</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">and using spaces:</text:p>-<text:list text:style-name="L11">- <text:list-item>- <text:p text:style-name="P28">One</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P28">Two</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P28">Three</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Multiple paragraphs:</text:p>-<text:list text:style-name="L12">- <text:list-item>- <text:p text:style-name="P29">Item 1, graf one.</text:p>- <text:p text:style-name="P29">Item 1. graf two. The quick brown fox jumped- over the lazy dog’s back.</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P29">Item 2.</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P29">Item 3.</text:p>- </text:list-item>-</text:list>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="nested" />Nested<text:bookmark-end text:name="nested" /></text:h>-<text:list text:style-name="L13">- <text:list-item>- <text:p text:style-name="P30">Tab</text:p><text:list text:style-name="L14">- <text:list-item>- <text:p text:style-name="P31">Tab</text:p><text:list text:style-name="L15">- <text:list-item>- <text:p text:style-name="P32">Tab</text:p>- </text:list-item>- </text:list>- </text:list-item>- </text:list>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Here’s another:</text:p>-<text:list text:style-name="L16">- <text:list-item>- <text:p text:style-name="P33">First</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P33">Second:</text:p>- <text:list text:style-name="L17">- <text:list-item>- <text:p text:style-name="P34">Fee</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P34">Fie</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P34">Foe</text:p>- </text:list-item>- </text:list>- </text:list-item>- <text:list-item>- <text:p text:style-name="P33">Third</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Same thing but with-paragraphs:</text:p>-<text:list text:style-name="L18">- <text:list-item>- <text:p text:style-name="P35">First</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P35">Second:</text:p>- <text:list text:style-name="L19">- <text:list-item>- <text:p text:style-name="P36">Fee</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P36">Fie</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P36">Foe</text:p>- </text:list-item>- </text:list>- </text:list-item>- <text:list-item>- <text:p text:style-name="P35">Third</text:p>- </text:list-item>-</text:list>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="tabs-and-spaces" />Tabs-and spaces<text:bookmark-end text:name="tabs-and-spaces" /></text:h>-<text:list text:style-name="L20">- <text:list-item>- <text:p text:style-name="P37">this is a list item indented with- tabs</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P37">this is a list item indented with- spaces</text:p><text:list text:style-name="L21">- <text:list-item>- <text:p text:style-name="P38">this is an example list item indented with- tabs</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P38">this is an example list item indented with- spaces</text:p>- </text:list-item>- </text:list>- </text:list-item>-</text:list>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="fancy-list-markers" />Fancy-list markers<text:bookmark-end text:name="fancy-list-markers" /></text:h>-<text:list text:style-name="L22">- <text:list-item>- <text:p text:style-name="P39">begins with 2</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P39">and now 3</text:p>- <text:p text:style-name="P39">with a continuation</text:p>- <text:list>- <text:list-item>- <text:p text:style-name="P39">sublist with roman numerals, starting with- 4</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P39">more items</text:p>- <text:list>- <text:list-item>- <text:p text:style-name="P39">a subsublist</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P39">a subsublist</text:p>- </text:list-item>- </text:list>- </text:list-item>- </text:list>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Nesting:</text:p>-<text:list text:style-name="L23">- <text:list-item>- <text:p text:style-name="P40">Upper Alpha</text:p>- <text:list>- <text:list-item>- <text:p text:style-name="P40">Upper Roman.</text:p>- <text:list>- <text:list-item>- <text:p text:style-name="P40">Decimal start with 6</text:p>- <text:list>- <text:list-item>- <text:p text:style-name="P40">Lower alpha with paren</text:p>- </text:list-item>- </text:list>- </text:list-item>- </text:list>- </text:list-item>- </text:list>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Autonumbering:</text:p>-<text:list text:style-name="L24">- <text:list-item>- <text:p text:style-name="P41">Autonumber.</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P41">More.</text:p>- <text:list>- <text:list-item>- <text:p text:style-name="P41">Nested.</text:p>- </text:list-item>- </text:list>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Should not be a list item:</text:p>-<text:p text:style-name="Text_20_body">M.A. 2007</text:p>-<text:p text:style-name="Text_20_body">B. Williams</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="definition-lists" />Definition-Lists<text:bookmark-end text:name="definition-lists" /></text:h>-<text:p text:style-name="First_20_paragraph">Tight using spaces:</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">orange-fruit</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">banana</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">yellow-fruit</text:p>-<text:p text:style-name="First_20_paragraph">Tight using tabs:</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">orange-fruit</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">banana</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">yellow-fruit</text:p>-<text:p text:style-name="First_20_paragraph">Loose:</text:p>-<text:p text:style-name="Definition_20_Term">apple</text:p>-<text:p text:style-name="Definition_20_Definition">red fruit</text:p>-<text:p text:style-name="Definition_20_Term">orange</text:p>-<text:p text:style-name="Definition_20_Definition">orange fruit</text:p>-<text:p text:style-name="Definition_20_Term">banana</text:p>-<text:p text:style-name="Definition_20_Definition">yellow fruit</text:p>-<text:p text:style-name="First_20_paragraph">Multiple blocks with-italics:</text:p>-<text:p text:style-name="Definition_20_Term"><text:span text:style-name="T1">apple</text:span></text:p>-<text:p text:style-name="Definition_20_Definition">red-fruit</text:p><text:p text:style-name="Definition_20_Definition">contains seeds,-crisp, pleasant to taste</text:p>-<text:p text:style-name="Definition_20_Term"><text:span text:style-name="T1">orange</text:span></text:p>-<text:p text:style-name="Definition_20_Definition">orange-fruit</text:p><text:p text:style-name="P42">{ orange code block }</text:p><text:p text:style-name="P43">orange-block quote</text:p>-<text:p text:style-name="First_20_paragraph">Multiple definitions,-tight:</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">computer</text:p>-<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">orange-fruit</text:p>-<text:p text:style-name="Definition_20_Definition_20_Tight">bank</text:p>-<text:p text:style-name="First_20_paragraph">Multiple definitions,-loose:</text:p>-<text:p text:style-name="Definition_20_Term">apple</text:p>-<text:p text:style-name="Definition_20_Definition">red fruit</text:p>-<text:p text:style-name="Definition_20_Definition">computer</text:p>-<text:p text:style-name="Definition_20_Term">orange</text:p>-<text:p text:style-name="Definition_20_Definition">orange fruit</text:p>-<text:p text:style-name="Definition_20_Definition">bank</text:p>-<text:p text:style-name="First_20_paragraph">Blank line after term, indented-marker, alternate markers:</text:p>-<text:p text:style-name="Definition_20_Term">apple</text:p>-<text:p text:style-name="Definition_20_Definition">red fruit</text:p>-<text:p text:style-name="Definition_20_Definition">computer</text:p>-<text:p text:style-name="Definition_20_Term">orange</text:p>-<text:p text:style-name="Definition_20_Definition">orange-fruit</text:p><text:list text:style-name="L25">- <text:list-item>- <text:p text:style-name="P44">sublist</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P44">sublist</text:p>- </text:list-item>-</text:list>-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="html-blocks" />HTML-Blocks<text:bookmark-end text:name="html-blocks" /></text:h>-<text:p text:style-name="First_20_paragraph">Simple block on one line:</text:p>-<text:p text:style-name="Text_20_body">foo</text:p>-<text:p text:style-name="Text_20_body">And nested without indentation:</text:p>-<text:p text:style-name="Text_20_body">foo</text:p>-<text:p text:style-name="Text_20_body">bar</text:p>-<text:p text:style-name="Text_20_body">Interpreted markdown in a table:</text:p>-<text:p text:style-name="Text_20_body">This is-<text:span text:style-name="T1">emphasized</text:span></text:p>-<text:p text:style-name="Text_20_body">And this is-<text:span text:style-name="T2">strong</text:span></text:p>-<text:p text:style-name="Text_20_body">Here’s a simple block:</text:p>-<text:p text:style-name="Text_20_body">foo</text:p>-<text:p text:style-name="Text_20_body">This should be a code block,-though:</text:p>-<text:p text:style-name="P45"><div></text:p>-<text:p text:style-name="P46"><text:s text:c="4" />foo</text:p>-<text:p text:style-name="P47"></div></text:p>-<text:p text:style-name="First_20_paragraph">As should this:</text:p>-<text:p text:style-name="P48"><div>foo</div></text:p>-<text:p text:style-name="First_20_paragraph">Now, nested:</text:p>-<text:p text:style-name="Text_20_body">foo</text:p>-<text:p text:style-name="Text_20_body">This should just be an HTML-comment:</text:p>-<text:p text:style-name="Text_20_body">Multiline:</text:p>-<text:p text:style-name="Text_20_body">Code block:</text:p>-<text:p text:style-name="P49"><!-- Comment --></text:p>-<text:p text:style-name="First_20_paragraph">Just plain comment, with trailing-spaces on the line:</text:p>-<text:p text:style-name="Text_20_body">Code:</text:p>-<text:p text:style-name="P50"><hr /></text:p>-<text:p text:style-name="First_20_paragraph">Hr’s:</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="inline-markup" />Inline-Markup<text:bookmark-end text:name="inline-markup" /></text:h>-<text:p text:style-name="First_20_paragraph">This is-<text:span text:style-name="T1">emphasized</text:span>, and so-<text:span text:style-name="T1">is this</text:span>.</text:p>-<text:p text:style-name="Text_20_body">This is-<text:span text:style-name="T2">strong</text:span>, and so-<text:span text:style-name="T2">is this</text:span>.</text:p>-<text:p text:style-name="Text_20_body">An-<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition"><text:span text:style-name="T1">emphasized-link</text:span></text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:span text:style-name="T3">This is-strong and em.</text:span></text:p>-<text:p text:style-name="Text_20_body">So is-<text:span text:style-name="T3">this</text:span> word.</text:p>-<text:p text:style-name="Text_20_body"><text:span text:style-name="T3">This is-strong and em.</text:span></text:p>-<text:p text:style-name="Text_20_body">So is-<text:span text:style-name="T3">this</text:span> word.</text:p>-<text:p text:style-name="Text_20_body">This is code:-<text:span text:style-name="Source_Text">></text:span>,-<text:span text:style-name="Source_Text">$</text:span>,-<text:span text:style-name="Source_Text">\</text:span>,-<text:span text:style-name="Source_Text">\$</text:span>,-<text:span text:style-name="Source_Text"><html></text:span>.</text:p>-<text:p text:style-name="Text_20_body"><text:span text:style-name="T4">This is-</text:span><text:span text:style-name="T5">strikeout</text:span><text:span text:style-name="T4">.</text:span></text:p>-<text:p text:style-name="Text_20_body">Superscripts:-a<text:span text:style-name="T6">bc</text:span>d-a<text:span text:style-name="T7">hello</text:span>-a<text:span text:style-name="T6">hello there</text:span>.</text:p>-<text:p text:style-name="Text_20_body">Subscripts:-H<text:span text:style-name="T8">2</text:span>O,-H<text:span text:style-name="T8">23</text:span>O,-H<text:span text:style-name="T8">many of them</text:span>O.</text:p>-<text:p text:style-name="Text_20_body">These should not be superscripts or-subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="smart-quotes-ellipses-dashes" />Smart-quotes, ellipses,-dashes<text:bookmark-end text:name="smart-quotes-ellipses-dashes" /></text:h>-<text:p text:style-name="First_20_paragraph">“Hello,” said the spider. “‘Shelob’-is my name.”</text:p>-<text:p text:style-name="Text_20_body">‘A’, ‘B’, and ‘C’ are letters.</text:p>-<text:p text:style-name="Text_20_body">‘Oak,’ ‘elm,’ and ‘beech’ are names of-trees. So is ‘pine.’</text:p>-<text:p text:style-name="Text_20_body">‘He said, “I want to go.”’ Were you alive-in the 70’s?</text:p>-<text:p text:style-name="Text_20_body">Here is some quoted-‘<text:span text:style-name="Source_Text">code</text:span>’ and a-“<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&bar=2" office:name=""><text:span text:style-name="Definition">quoted-link</text:span></text:a>”.</text:p>-<text:p text:style-name="Text_20_body">Some dashes: one—two — three—four —-five.</text:p>-<text:p text:style-name="Text_20_body">Dashes between numbers: 5–7, 255–66,-1987–1999.</text:p>-<text:p text:style-name="Text_20_body">Ellipses…and…and….</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="latex" />LaTeX<text:bookmark-end text:name="latex" /></text:h>-<text:list text:style-name="L26">- <text:list-item>- <text:p text:style-name="P51"></text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P51">2 + 2 = 4</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P51"><text:span text:style-name="T1">x</text:span> ∈ <text:span text:style-name="T1">y</text:span></text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P51"><text:span text:style-name="T1">α</text:span> ∧ <text:span text:style-name="T1">ω</text:span></text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P51">223</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P51"><text:span text:style-name="T1">p</text:span>-Tree</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P51">Here’s some display math:- $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P51">Here’s one that has a line break in it:- <text:span text:style-name="T1">α</text:span> + <text:span text:style-name="T1">ω</text:span> × <text:span text:style-name="T1">x</text:span><text:span text:style-name="T6">2</text:span>.</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">These shouldn’t be math:</text:p>-<text:list text:style-name="L27">- <text:list-item>- <text:p text:style-name="P52">To get the famous equation, write- <text:span text:style-name="Source_Text">$e = mc^2$</text:span>.</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P52">$22,000 is a- <text:span text:style-name="T1">lot</text:span> of money. So is $34,000. (It- worked if “lot” is emphasized.)</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P52">Shoes ($20) and socks ($5).</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P52">Escaped- <text:span text:style-name="Source_Text">$</text:span>: $73- <text:span text:style-name="T1">this should be emphasized</text:span>- 23$.</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">Here’s a LaTeX table:</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="special-characters" />Special-Characters<text:bookmark-end text:name="special-characters" /></text:h>-<text:p text:style-name="First_20_paragraph">Here is some unicode:</text:p>-<text:list text:style-name="L28">- <text:list-item>- <text:p text:style-name="P53">I hat: Î</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P53">o umlaut: ö</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P53">section: §</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P53">set membership: ∈</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P53">copyright: ©</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">AT&T has an ampersand in their-name.</text:p>-<text:p text:style-name="Text_20_body">AT&T is another way to write-it.</text:p>-<text:p text:style-name="Text_20_body">This & that.</text:p>-<text:p text:style-name="Text_20_body">4 < 5.</text:p>-<text:p text:style-name="Text_20_body">6 > 5.</text:p>-<text:p text:style-name="Text_20_body">Backslash: \</text:p>-<text:p text:style-name="Text_20_body">Backtick: `</text:p>-<text:p text:style-name="Text_20_body">Asterisk: *</text:p>-<text:p text:style-name="Text_20_body">Underscore: _</text:p>-<text:p text:style-name="Text_20_body">Left brace: {</text:p>-<text:p text:style-name="Text_20_body">Right brace: }</text:p>-<text:p text:style-name="Text_20_body">Left bracket: [</text:p>-<text:p text:style-name="Text_20_body">Right bracket: ]</text:p>-<text:p text:style-name="Text_20_body">Left paren: (</text:p>-<text:p text:style-name="Text_20_body">Right paren: )</text:p>-<text:p text:style-name="Text_20_body">Greater-than: ></text:p>-<text:p text:style-name="Text_20_body">Hash: #</text:p>-<text:p text:style-name="Text_20_body">Period: .</text:p>-<text:p text:style-name="Text_20_body">Bang: !</text:p>-<text:p text:style-name="Text_20_body">Plus: +</text:p>-<text:p text:style-name="Text_20_body">Minus: -</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="links" />Links<text:bookmark-end text:name="links" /></text:h>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="explicit" />Explicit<text:bookmark-end text:name="explicit" /></text:h>-<text:p text:style-name="First_20_paragraph">Just a-<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">URL</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title"><text:span text:style-name="Definition">URL-and title</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title preceded by two spaces"><text:span text:style-name="Definition">URL-and title</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title preceded by a tab"><text:span text:style-name="Definition">URL-and title</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title with "quotes" in it"><text:span text:style-name="Definition">URL-and title</text:span></text:a></text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title with single quotes"><text:span text:style-name="Definition">URL-and title</text:span></text:a></text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/with_underscore" office:name=""><text:span text:style-name="Definition">with_underscore</text:span></text:a></text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="mailto:nobody@nowhere.net" office:name=""><text:span text:style-name="Definition">Email-link</text:span></text:a></text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="" office:name=""><text:span text:style-name="Definition">Empty</text:span></text:a>.</text:p>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="reference" />Reference<text:bookmark-end text:name="reference" /></text:h>-<text:p text:style-name="First_20_paragraph">Foo-<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">bar</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">With-<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">embedded-[brackets]</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">b</text:span></text:a>-by itself should be a link.</text:p>-<text:p text:style-name="Text_20_body">Indented-<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">once</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Indented-<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">twice</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Indented-<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">thrice</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">This should [not][] be a link.</text:p>-<text:p text:style-name="P54">[not]: /url</text:p>-<text:p text:style-name="First_20_paragraph">Foo-<text:a xlink:type="simple" xlink:href="/url/" office:name="Title with "quotes" inside"><text:span text:style-name="Definition">bar</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Foo-<text:a xlink:type="simple" xlink:href="/url/" office:name="Title with "quote" inside"><text:span text:style-name="Definition">biz</text:span></text:a>.</text:p>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="with-ampersands" />With-ampersands<text:bookmark-end text:name="with-ampersands" /></text:h>-<text:p text:style-name="First_20_paragraph">Here’s a-<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&bar=2" office:name=""><text:span text:style-name="Definition">link-with an ampersand in the URL</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Here’s a link with an amersand in the-link text:-<text:a xlink:type="simple" xlink:href="http://att.com/" office:name="AT&T"><text:span text:style-name="Definition">AT&T</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Here’s an-<text:a xlink:type="simple" xlink:href="/script?foo=1&bar=2" office:name=""><text:span text:style-name="Definition">inline-link</text:span></text:a>.</text:p>-<text:p text:style-name="Text_20_body">Here’s an-<text:a xlink:type="simple" xlink:href="/script?foo=1&bar=2" office:name=""><text:span text:style-name="Definition">inline-link in pointy braces</text:span></text:a>.</text:p>-<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="autolinks" />Autolinks<text:bookmark-end text:name="autolinks" /></text:h>-<text:p text:style-name="First_20_paragraph">With an ampersand:-<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&bar=2" office:name=""><text:span text:style-name="Definition">http://example.com/?foo=1&bar=2</text:span></text:a></text:p>-<text:list text:style-name="L29">- <text:list-item>- <text:p text:style-name="P55">In a list?</text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P55"><text:a xlink:type="simple" xlink:href="http://example.com/" office:name=""><text:span text:style-name="Definition">http://example.com/</text:span></text:a></text:p>- </text:list-item>- <text:list-item>- <text:p text:style-name="P55">It should.</text:p>- </text:list-item>-</text:list>-<text:p text:style-name="First_20_paragraph">An e-mail address:-<text:a xlink:type="simple" xlink:href="mailto:nobody@nowhere.net" office:name=""><text:span text:style-name="Definition">nobody@nowhere.net</text:span></text:a></text:p>-<text:p text:style-name="P56">Blockquoted:-<text:a xlink:type="simple" xlink:href="http://example.com/" office:name=""><text:span text:style-name="Definition">http://example.com/</text:span></text:a></text:p>-<text:p text:style-name="First_20_paragraph">Auto-links should not occur here:-<text:span text:style-name="Source_Text"><http://example.com/></text:span></text:p>-<text:p text:style-name="P57">or here: <http://example.com/></text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="images" />Images<text:bookmark-end text:name="images" /></text:h>-<text:p text:style-name="First_20_paragraph">From “Voyage dans la Lune” by-Georges Melies (1902):</text:p>-<text:p text:style-name="FigureWithCaption"><draw:frame draw:name="img1"><draw:image xlink:href="lalune.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame></text:p>-<text:p text:style-name="FigureCaption">lalune</text:p>-<text:p text:style-name="Text_20_body">Here is a movie-<draw:frame draw:name="img2"><draw:image xlink:href="movie.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame>-icon.</text:p>-<text:p text:style-name="Horizontal_20_Line" />-<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="footnotes" />Footnotes<text:bookmark-end text:name="footnotes" /></text:h>-<text:p text:style-name="First_20_paragraph">Here is a footnote-reference,<text:note text:id="ftn0" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here-is the footnote. It can go anywhere after the footnote reference. It need not be-placed at the end of the document.</text:p></text:note-body></text:note> and-another.<text:note text:id="ftn1" text:note-class="footnote"><text:note-citation>2</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here’s-the long note. This one contains multiple-blocks.</text:p><text:p text:style-name="Footnote">Subsequent blocks are-indented to show that they belong to the footnote (as with list-items).</text:p><text:p text:style-name="P58"><text:s text:c="2" />{ <code> }</text:p><text:p text:style-name="Footnote">If-you want, you can indent every line, but you can also be lazy and just indent-the first line of each block.</text:p></text:note-body></text:note> This should-<text:span text:style-name="T1">not</text:span> be a footnote reference, because-it contains a space.[^my note] Here is an inline-note.<text:note text:id="ftn2" text:note-class="footnote"><text:note-citation>3</text:note-citation><text:note-body><text:p text:style-name="Footnote">This-is <text:span text:style-name="T1">easier</text:span> to type. Inline notes may-contain-<text:a xlink:type="simple" xlink:href="http://google.com" office:name=""><text:span text:style-name="Definition">links</text:span></text:a>-and <text:span text:style-name="Source_Text">]</text:span> verbatim characters,-as well as [bracketed text].</text:p></text:note-body></text:note></text:p>-<text:p text:style-name="P59">Notes can go in-quotes.<text:note text:id="ftn3" text:note-class="footnote"><text:note-citation>4</text:note-citation><text:note-body><text:p text:style-name="Footnote">In-quote.</text:p></text:note-body></text:note></text:p>-<text:list text:style-name="L30">- <text:list-item>- <text:p text:style-name="P60">And in list+<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.3">+ <office:font-face-decls>+ <style:font-face style:name="Courier New" style:font-family-generic="modern" style:font-pitch="fixed" svg:font-family="'Courier New'" />+ </office:font-face-decls>+ <office:automatic-styles>+ <style:style style:name="T1" style:family="text"><style:text-properties fo:font-style="italic" fo:font-weight="bold" style:font-style-asian="italic" style:font-style-complex="italic" style:font-weight-asian="bold" style:font-weight-complex="bold" /></style:style>+ <style:style style:name="T2" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-line-through-style="solid" /></style:style>+ <style:style style:name="T3" style:family="text"><style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic" style:text-position="super 58%" /></style:style>+ <style:style style:name="fr2" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" style:wrap="none" /></style:style>+ <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Formula"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" /></style:style>+ <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Quotations">+ <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />+ </style:style>+ <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Quotations">+ <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />+ </style:style>+ <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Quotations">+ <style:paragraph-properties fo:margin-left="0.5in" fo:margin-right="0in" fo:text-indent="0in" style:auto-text-indent="false" />+ </style:style>+ <text:list-style style:name="Pandoc_5f_Numbering_5f_1">+ <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="1" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ </text:list-style>+ <text:list-style style:name="Pandoc_5f_Numbering_5f_2">+ <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="i" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ </text:list-style>+ <text:list-style style:name="Pandoc_5f_Numbering_5f_5">+ <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="I" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ </text:list-style>+ <text:list-style style:name="Pandoc_5f_Numbering_5f_6">+ <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="a" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ </text:list-style>+ <text:list-style style:name="Pandoc_5f_Numbering_5f_4">+ <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+ <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-suffix=".">+ <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ </text:list-style>+ <text:list-style style:name="Pandoc_5f_Numbering_5f_3">+ <text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.0000in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="2" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.1972in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="3" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.3944in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="4" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.5916in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="5" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.7888in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="6" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="0.9860in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="7" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.1832in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="8" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.3804in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="9" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.5776in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ <text:list-level-style-number text:level="10" text:style-name="Numbering_20_Symbols" style:num-format="A" style:num-prefix="(" style:num-suffix=")">+ <style:list-level-properties text:space-before="1.7748in" text:min-label-width="0.1965in" text:min-label-distance="0.1in" />+ </text:list-level-style-number>+ </text:list-style>+ </office:automatic-styles>+<office:body>+<office:text>+<text:p text:style-name="Title">Pandoc Test Suite</text:p>+<text:p text:style-name="Author">John MacFarlane</text:p>+<text:p text:style-name="Author">Anonymous</text:p>+<text:p text:style-name="Date">July 17, 2006</text:p>+<text:p text:style-name="Text_20_body">This is a set of tests for pandoc. Most+of them are adapted from John Gruber’s markdown test suite.</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="headers" />Headers<text:bookmark-end text:name="headers" /></text:h>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2-with-an-embedded-link" />Level+2 with an+<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">embedded+link</text:span></text:a><text:bookmark-end text:name="level-2-with-an-embedded-link" /></text:h>+<text:h text:style-name="Heading_20_3" text:outline-level="3"><text:bookmark-start text:name="level-3-with-emphasis" />Level+3 with+<text:span text:style-name="Emphasis">emphasis</text:span><text:bookmark-end text:name="level-3-with-emphasis" /></text:h>+<text:h text:style-name="Heading_20_4" text:outline-level="4"><text:bookmark-start text:name="level-4" />Level+4<text:bookmark-end text:name="level-4" /></text:h>+<text:h text:style-name="Heading_20_5" text:outline-level="5"><text:bookmark-start text:name="level-5" />Level+5<text:bookmark-end text:name="level-5" /></text:h>+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="level-1" />Level+1<text:bookmark-end text:name="level-1" /></text:h>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2-with-emphasis" />Level+2 with+<text:span text:style-name="Emphasis">emphasis</text:span><text:bookmark-end text:name="level-2-with-emphasis" /></text:h>+<text:h text:style-name="Heading_20_3" text:outline-level="3"><text:bookmark-start text:name="level-3" />Level+3<text:bookmark-end text:name="level-3" /></text:h>+<text:p text:style-name="First_20_paragraph">with no blank line</text:p>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="level-2" />Level+2<text:bookmark-end text:name="level-2" /></text:h>+<text:p text:style-name="First_20_paragraph">with no blank line</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="paragraphs" />Paragraphs<text:bookmark-end text:name="paragraphs" /></text:h>+<text:p text:style-name="First_20_paragraph">Here’s a regular+paragraph.</text:p>+<text:p text:style-name="Text_20_body">In Markdown 1.0.0 and earlier. Version 8.+This line turns into a list item. Because a hard-wrapped line in the middle of a+paragraph looked like a list item.</text:p>+<text:p text:style-name="Text_20_body">Here’s one with a bullet. *+criminey.</text:p>+<text:p text:style-name="Text_20_body">There should be a hard line+break<text:line-break />here.</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="block-quotes" />Block+Quotes<text:bookmark-end text:name="block-quotes" /></text:h>+<text:p text:style-name="First_20_paragraph">E-mail style:</text:p>+<text:p text:style-name="Quotations">This is a block quote. It is pretty+short.</text:p>+<text:p text:style-name="Quotations">Code in a block quote:</text:p>+<text:p text:style-name="Preformatted_20_Text">sub status {</text:p>+<text:p text:style-name="Preformatted_20_Text"><text:s text:c="4" />print "working";</text:p>+<text:p text:style-name="Preformatted_20_Text">}</text:p>+<text:p text:style-name="Quotations">A list:</text:p>+<text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">item one</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">item two</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="Quotations">Nested block quotes:</text:p>+<text:p text:style-name="P1">nested</text:p>+<text:p text:style-name="P2">nested</text:p>+<text:p text:style-name="First_20_paragraph">This should not be a block quote: 2+> 1.</text:p>+<text:p text:style-name="Text_20_body">And a following paragraph.</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="code-blocks" />Code+Blocks<text:bookmark-end text:name="code-blocks" /></text:h>+<text:p text:style-name="First_20_paragraph">Code:</text:p>+<text:p text:style-name="Preformatted_20_Text">---- (should be four hyphens)</text:p>+<text:p text:style-name="Preformatted_20_Text"></text:p>+<text:p text:style-name="Preformatted_20_Text">sub status {</text:p>+<text:p text:style-name="Preformatted_20_Text"><text:s text:c="4" />print "working";</text:p>+<text:p text:style-name="Preformatted_20_Text">}</text:p>+<text:p text:style-name="Preformatted_20_Text"></text:p>+<text:p text:style-name="Preformatted_20_Text">this code block is indented by one tab</text:p>+<text:p text:style-name="First_20_paragraph">And:</text:p>+<text:p text:style-name="Preformatted_20_Text"><text:s text:c="4" />this code block is indented by two tabs</text:p>+<text:p text:style-name="Preformatted_20_Text"></text:p>+<text:p text:style-name="Preformatted_20_Text">These should not be escaped: <text:s text:c="1" />\$ \\ \> \[ \{</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="lists" />Lists<text:bookmark-end text:name="lists" /></text:h>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="unordered" />Unordered<text:bookmark-end text:name="unordered" /></text:h>+<text:p text:style-name="First_20_paragraph">Asterisks tight:</text:p>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">asterisk 1</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">asterisk 2</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">asterisk 3</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Asterisks loose:</text:p>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">asterisk 1</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">asterisk 2</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">asterisk 3</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Pluses tight:</text:p>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Plus 1</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Plus 2</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Plus 3</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Pluses loose:</text:p>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">Plus 1</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">Plus 2</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">Plus 3</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Minuses tight:</text:p>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Minus 1</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Minus 2</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Minus 3</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Minuses loose:</text:p>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">Minus 1</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">Minus 2</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">Minus 3</text:p>+ </text:list-item>+</text:list>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="ordered" />Ordered<text:bookmark-end text:name="ordered" /></text:h>+<text:p text:style-name="First_20_paragraph">Tight:</text:p>+<text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">First</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Second</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Third</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">and:</text:p>+<text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">One</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Two</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Three</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Loose using tabs:</text:p>+<text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number">First</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number">Second</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number">Third</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">and using spaces:</text:p>+<text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number">One</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number">Two</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number">Three</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Multiple paragraphs:</text:p>+<text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number">Item 1, graf one.</text:p>+ <text:p text:style-name="List_20_Number">Item 1. graf two. The quick brown+ fox jumped over the lazy dog’s back.</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number">Item 2.</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number">Item 3.</text:p>+ </text:list-item>+</text:list>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="nested" />Nested<text:bookmark-end text:name="nested" /></text:h>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Tab</text:p><text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Tab</text:p><text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Tab</text:p>+ </text:list-item>+ </text:list>+ </text:list-item>+ </text:list>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Here’s another:</text:p>+<text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">First</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Second:</text:p>+ <text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Fee</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Fie</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Foe</text:p>+ </text:list-item>+ </text:list>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Third</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Same thing but with+paragraphs:</text:p>+<text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number">First</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number">Second:</text:p>+ <text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Fee</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Fie</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Foe</text:p>+ </text:list-item>+ </text:list>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number">Third</text:p>+ </text:list-item>+</text:list>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="tabs-and-spaces" />Tabs+and spaces<text:bookmark-end text:name="tabs-and-spaces" /></text:h>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">this is a list item indented with+ tabs</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">this is a list item indented with+ spaces</text:p><text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">this is an example list item+ indented with tabs</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet">this is an example list item+ indented with spaces</text:p>+ </text:list-item>+ </text:list>+ </text:list-item>+</text:list>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="fancy-list-markers" />Fancy+list markers<text:bookmark-end text:name="fancy-list-markers" /></text:h>+<text:list text:style-name="Pandoc_5f_Numbering_5f_1" text:start-value="2">+ <text:list-item>+ <text:p text:style-name="List_20_Number">begins with 2</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number">and now 3</text:p>+ <text:p text:style-name="List_20_Number">with a continuation</text:p>+ <text:list text:style-name="Pandoc_5f_Numbering_5f_2" text:start-value="4">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">sublist with roman+ numerals, starting with 4</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">more items</text:p>+ <text:list text:style-name="Pandoc_5f_Numbering_5f_3">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">a+ subsublist</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">a+ subsublist</text:p>+ </text:list-item>+ </text:list>+ </text:list-item>+ </text:list>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Nesting:</text:p>+<text:list text:style-name="Pandoc_5f_Numbering_5f_4">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Upper Alpha</text:p>+ <text:list text:style-name="Pandoc_5f_Numbering_5f_5">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Upper Roman.</text:p>+ <text:list text:style-name="Pandoc_5f_Numbering_5f_1" text:start-value="6">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Decimal start with+ 6</text:p>+ <text:list text:style-name="Pandoc_5f_Numbering_5f_6" text:start-value="3">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Lower alpha+ with paren</text:p>+ </text:list-item>+ </text:list>+ </text:list-item>+ </text:list>+ </text:list-item>+ </text:list>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Autonumbering:</text:p>+<text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Autonumber.</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">More.</text:p>+ <text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">Nested.</text:p>+ </text:list-item>+ </text:list>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Should not be a list item:</text:p>+<text:p text:style-name="Text_20_body">M.A. 2007</text:p>+<text:p text:style-name="Text_20_body">B. Williams</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="definition-lists" />Definition+Lists<text:bookmark-end text:name="definition-lists" /></text:h>+<text:p text:style-name="First_20_paragraph">Tight using spaces:</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">orange+fruit</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">banana</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">yellow+fruit</text:p>+<text:p text:style-name="First_20_paragraph">Tight using tabs:</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">orange+fruit</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">banana</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">yellow+fruit</text:p>+<text:p text:style-name="First_20_paragraph">Loose:</text:p>+<text:p text:style-name="Definition_20_Term">apple</text:p>+<text:p text:style-name="Definition_20_Definition">red fruit</text:p>+<text:p text:style-name="Definition_20_Term">orange</text:p>+<text:p text:style-name="Definition_20_Definition">orange fruit</text:p>+<text:p text:style-name="Definition_20_Term">banana</text:p>+<text:p text:style-name="Definition_20_Definition">yellow fruit</text:p>+<text:p text:style-name="First_20_paragraph">Multiple blocks with+italics:</text:p>+<text:p text:style-name="Definition_20_Term"><text:span text:style-name="Emphasis">apple</text:span></text:p>+<text:p text:style-name="Definition_20_Definition">red+fruit</text:p><text:p text:style-name="Definition_20_Definition">contains seeds,+crisp, pleasant to taste</text:p>+<text:p text:style-name="Definition_20_Term"><text:span text:style-name="Emphasis">orange</text:span></text:p>+<text:p text:style-name="Definition_20_Definition">orange+fruit</text:p><text:p text:style-name="Preformatted_20_Text">{ orange code block }</text:p><text:p text:style-name="P3">orange+block quote</text:p>+<text:p text:style-name="First_20_paragraph">Multiple definitions,+tight:</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">apple</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">red fruit</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">computer</text:p>+<text:p text:style-name="Definition_20_Term_20_Tight">orange</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">orange+fruit</text:p>+<text:p text:style-name="Definition_20_Definition_20_Tight">bank</text:p>+<text:p text:style-name="First_20_paragraph">Multiple definitions,+loose:</text:p>+<text:p text:style-name="Definition_20_Term">apple</text:p>+<text:p text:style-name="Definition_20_Definition">red fruit</text:p>+<text:p text:style-name="Definition_20_Definition">computer</text:p>+<text:p text:style-name="Definition_20_Term">orange</text:p>+<text:p text:style-name="Definition_20_Definition">orange fruit</text:p>+<text:p text:style-name="Definition_20_Definition">bank</text:p>+<text:p text:style-name="First_20_paragraph">Blank line after term, indented+marker, alternate markers:</text:p>+<text:p text:style-name="Definition_20_Term">apple</text:p>+<text:p text:style-name="Definition_20_Definition">red fruit</text:p>+<text:p text:style-name="Definition_20_Definition">computer</text:p>+<text:p text:style-name="Definition_20_Term">orange</text:p>+<text:p text:style-name="Definition_20_Definition">orange+fruit</text:p><text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">sublist</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">sublist</text:p>+ </text:list-item>+</text:list>+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="html-blocks" />HTML+Blocks<text:bookmark-end text:name="html-blocks" /></text:h>+<text:p text:style-name="First_20_paragraph">Simple block on one line:</text:p>+<text:p text:style-name="Text_20_body">foo</text:p>+<text:p text:style-name="Text_20_body">And nested without indentation:</text:p>+<text:p text:style-name="Text_20_body">foo</text:p>+<text:p text:style-name="Text_20_body">bar</text:p>+<text:p text:style-name="Text_20_body">Interpreted markdown in a table:</text:p>+<text:p text:style-name="Text_20_body">This is+<text:span text:style-name="Emphasis">emphasized</text:span></text:p>+<text:p text:style-name="Text_20_body">And this is+<text:span text:style-name="Strong_20_Emphasis">strong</text:span></text:p>+<text:p text:style-name="Text_20_body">Here’s a simple block:</text:p>+<text:p text:style-name="Text_20_body">foo</text:p>+<text:p text:style-name="Text_20_body">This should be a code block,+though:</text:p>+<text:p text:style-name="Preformatted_20_Text"><div></text:p>+<text:p text:style-name="Preformatted_20_Text"><text:s text:c="4" />foo</text:p>+<text:p text:style-name="Preformatted_20_Text"></div></text:p>+<text:p text:style-name="First_20_paragraph">As should this:</text:p>+<text:p text:style-name="Preformatted_20_Text"><div>foo</div></text:p>+<text:p text:style-name="First_20_paragraph">Now, nested:</text:p>+<text:p text:style-name="Text_20_body">foo</text:p>+<text:p text:style-name="Text_20_body">This should just be an HTML+comment:</text:p>+<text:p text:style-name="Text_20_body">Multiline:</text:p>+<text:p text:style-name="Text_20_body">Code block:</text:p>+<text:p text:style-name="Preformatted_20_Text"><!-- Comment --></text:p>+<text:p text:style-name="First_20_paragraph">Just plain comment, with trailing+spaces on the line:</text:p>+<text:p text:style-name="Text_20_body">Code:</text:p>+<text:p text:style-name="Preformatted_20_Text"><hr /></text:p>+<text:p text:style-name="First_20_paragraph">Hr’s:</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="inline-markup" />Inline+Markup<text:bookmark-end text:name="inline-markup" /></text:h>+<text:p text:style-name="First_20_paragraph">This is+<text:span text:style-name="Emphasis">emphasized</text:span>, and so+<text:span text:style-name="Emphasis">is this</text:span>.</text:p>+<text:p text:style-name="Text_20_body">This is+<text:span text:style-name="Strong_20_Emphasis">strong</text:span>, and so+<text:span text:style-name="Strong_20_Emphasis">is this</text:span>.</text:p>+<text:p text:style-name="Text_20_body">An+<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition"><text:span text:style-name="Emphasis">emphasized+link</text:span></text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:span text:style-name="T1">This is+strong and em.</text:span></text:p>+<text:p text:style-name="Text_20_body">So is+<text:span text:style-name="T1">this</text:span> word.</text:p>+<text:p text:style-name="Text_20_body"><text:span text:style-name="T1">This is+strong and em.</text:span></text:p>+<text:p text:style-name="Text_20_body">So is+<text:span text:style-name="T1">this</text:span> word.</text:p>+<text:p text:style-name="Text_20_body">This is code:+<text:span text:style-name="Source_20_Text">></text:span>,+<text:span text:style-name="Source_20_Text">$</text:span>,+<text:span text:style-name="Source_20_Text">\</text:span>,+<text:span text:style-name="Source_20_Text">\$</text:span>,+<text:span text:style-name="Source_20_Text"><html></text:span>.</text:p>+<text:p text:style-name="Text_20_body"><text:span text:style-name="Strikeout">This+is+</text:span><text:span text:style-name="T2">strikeout</text:span><text:span text:style-name="Strikeout">.</text:span></text:p>+<text:p text:style-name="Text_20_body">Superscripts:+a<text:span text:style-name="Superscript">bc</text:span>d+a<text:span text:style-name="T3">hello</text:span>+a<text:span text:style-name="Superscript">hello there</text:span>.</text:p>+<text:p text:style-name="Text_20_body">Subscripts:+H<text:span text:style-name="Subscript">2</text:span>O,+H<text:span text:style-name="Subscript">23</text:span>O,+H<text:span text:style-name="Subscript">many of them</text:span>O.</text:p>+<text:p text:style-name="Text_20_body">These should not be superscripts or+subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="smart-quotes-ellipses-dashes" />Smart+quotes, ellipses,+dashes<text:bookmark-end text:name="smart-quotes-ellipses-dashes" /></text:h>+<text:p text:style-name="First_20_paragraph">“Hello,” said the spider. “‘Shelob’+is my name.”</text:p>+<text:p text:style-name="Text_20_body">‘A’, ‘B’, and ‘C’ are letters.</text:p>+<text:p text:style-name="Text_20_body">‘Oak,’ ‘elm,’ and ‘beech’ are names of+trees. So is ‘pine.’</text:p>+<text:p text:style-name="Text_20_body">‘He said, “I want to go.”’ Were you alive+in the 70’s?</text:p>+<text:p text:style-name="Text_20_body">Here is some quoted+‘<text:span text:style-name="Source_20_Text">code</text:span>’ and a+“<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&bar=2" office:name=""><text:span text:style-name="Definition">quoted+link</text:span></text:a>”.</text:p>+<text:p text:style-name="Text_20_body">Some dashes: one—two — three—four —+five.</text:p>+<text:p text:style-name="Text_20_body">Dashes between numbers: 5–7, 255–66,+1987–1999.</text:p>+<text:p text:style-name="Text_20_body">Ellipses…and…and….</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="latex" />LaTeX<text:bookmark-end text:name="latex" /></text:h>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight"></text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">2 + 2 = 4</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight"><text:span text:style-name="Emphasis">x</text:span> ∈ <text:span text:style-name="Emphasis">y</text:span></text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight"><text:span text:style-name="Emphasis">α</text:span> ∧ <text:span text:style-name="Emphasis">ω</text:span></text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">223</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight"><text:span text:style-name="Emphasis">p</text:span>-Tree</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Here’s some display math:+ $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Here’s one that has a line+ break in it:+ <text:span text:style-name="Emphasis">α</text:span> + <text:span text:style-name="Emphasis">ω</text:span> × <text:span text:style-name="Emphasis">x</text:span><text:span text:style-name="Superscript">2</text:span>.</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">These shouldn’t be math:</text:p>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">To get the famous+ equation, write+ <text:span text:style-name="Source_20_Text">$e = mc^2$</text:span>.</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">$22,000 is a+ <text:span text:style-name="Emphasis">lot</text:span> of money. So is+ $34,000. (It worked if “lot” is emphasized.)</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Shoes ($20) and socks+ ($5).</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">Escaped+ <text:span text:style-name="Source_20_Text">$</text:span>: $73+ <text:span text:style-name="Emphasis">this should be emphasized</text:span>+ 23$.</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">Here’s a LaTeX table:</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="special-characters" />Special+Characters<text:bookmark-end text:name="special-characters" /></text:h>+<text:p text:style-name="First_20_paragraph">Here is some unicode:</text:p>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">I hat: Î</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">o umlaut: ö</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">section: §</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">set membership: ∈</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">copyright: ©</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">AT&T has an ampersand in their+name.</text:p>+<text:p text:style-name="Text_20_body">AT&T is another way to write+it.</text:p>+<text:p text:style-name="Text_20_body">This & that.</text:p>+<text:p text:style-name="Text_20_body">4 < 5.</text:p>+<text:p text:style-name="Text_20_body">6 > 5.</text:p>+<text:p text:style-name="Text_20_body">Backslash: \</text:p>+<text:p text:style-name="Text_20_body">Backtick: `</text:p>+<text:p text:style-name="Text_20_body">Asterisk: *</text:p>+<text:p text:style-name="Text_20_body">Underscore: _</text:p>+<text:p text:style-name="Text_20_body">Left brace: {</text:p>+<text:p text:style-name="Text_20_body">Right brace: }</text:p>+<text:p text:style-name="Text_20_body">Left bracket: [</text:p>+<text:p text:style-name="Text_20_body">Right bracket: ]</text:p>+<text:p text:style-name="Text_20_body">Left paren: (</text:p>+<text:p text:style-name="Text_20_body">Right paren: )</text:p>+<text:p text:style-name="Text_20_body">Greater-than: ></text:p>+<text:p text:style-name="Text_20_body">Hash: #</text:p>+<text:p text:style-name="Text_20_body">Period: .</text:p>+<text:p text:style-name="Text_20_body">Bang: !</text:p>+<text:p text:style-name="Text_20_body">Plus: +</text:p>+<text:p text:style-name="Text_20_body">Minus: -</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="links" />Links<text:bookmark-end text:name="links" /></text:h>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="explicit" />Explicit<text:bookmark-end text:name="explicit" /></text:h>+<text:p text:style-name="First_20_paragraph">Just a+<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">URL</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title"><text:span text:style-name="Definition">URL+and title</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title preceded by two spaces"><text:span text:style-name="Definition">URL+and title</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title preceded by a tab"><text:span text:style-name="Definition">URL+and title</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title with "quotes" in it"><text:span text:style-name="Definition">URL+and title</text:span></text:a></text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name="title with single quotes"><text:span text:style-name="Definition">URL+and title</text:span></text:a></text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/with_underscore" office:name=""><text:span text:style-name="Definition">with_underscore</text:span></text:a></text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="mailto:nobody@nowhere.net" office:name=""><text:span text:style-name="Definition">Email+link</text:span></text:a></text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="" office:name=""><text:span text:style-name="Definition">Empty</text:span></text:a>.</text:p>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="reference" />Reference<text:bookmark-end text:name="reference" /></text:h>+<text:p text:style-name="First_20_paragraph">Foo+<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">bar</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">With+<text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">embedded+[brackets]</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body"><text:a xlink:type="simple" xlink:href="/url/" office:name=""><text:span text:style-name="Definition">b</text:span></text:a>+by itself should be a link.</text:p>+<text:p text:style-name="Text_20_body">Indented+<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">once</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Indented+<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">twice</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Indented+<text:a xlink:type="simple" xlink:href="/url" office:name=""><text:span text:style-name="Definition">thrice</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">This should [not][] be a link.</text:p>+<text:p text:style-name="Preformatted_20_Text">[not]: /url</text:p>+<text:p text:style-name="First_20_paragraph">Foo+<text:a xlink:type="simple" xlink:href="/url/" office:name="Title with "quotes" inside"><text:span text:style-name="Definition">bar</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Foo+<text:a xlink:type="simple" xlink:href="/url/" office:name="Title with "quote" inside"><text:span text:style-name="Definition">biz</text:span></text:a>.</text:p>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="with-ampersands" />With+ampersands<text:bookmark-end text:name="with-ampersands" /></text:h>+<text:p text:style-name="First_20_paragraph">Here’s a+<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&bar=2" office:name=""><text:span text:style-name="Definition">link+with an ampersand in the URL</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Here’s a link with an amersand in the+link text:+<text:a xlink:type="simple" xlink:href="http://att.com/" office:name="AT&T"><text:span text:style-name="Definition">AT&T</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Here’s an+<text:a xlink:type="simple" xlink:href="/script?foo=1&bar=2" office:name=""><text:span text:style-name="Definition">inline+link</text:span></text:a>.</text:p>+<text:p text:style-name="Text_20_body">Here’s an+<text:a xlink:type="simple" xlink:href="/script?foo=1&bar=2" office:name=""><text:span text:style-name="Definition">inline+link in pointy braces</text:span></text:a>.</text:p>+<text:h text:style-name="Heading_20_2" text:outline-level="2"><text:bookmark-start text:name="autolinks" />Autolinks<text:bookmark-end text:name="autolinks" /></text:h>+<text:p text:style-name="First_20_paragraph">With an ampersand:+<text:a xlink:type="simple" xlink:href="http://example.com/?foo=1&bar=2" office:name=""><text:span text:style-name="Definition">http://example.com/?foo=1&bar=2</text:span></text:a></text:p>+<text:list text:style-name="List_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">In a list?</text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight"><text:a xlink:type="simple" xlink:href="http://example.com/" office:name=""><text:span text:style-name="Definition">http://example.com/</text:span></text:a></text:p>+ </text:list-item>+ <text:list-item>+ <text:p text:style-name="List_20_Bullet_20_Tight">It should.</text:p>+ </text:list-item>+</text:list>+<text:p text:style-name="First_20_paragraph">An e-mail address:+<text:a xlink:type="simple" xlink:href="mailto:nobody@nowhere.net" office:name=""><text:span text:style-name="Definition">nobody@nowhere.net</text:span></text:a></text:p>+<text:p text:style-name="Quotations">Blockquoted:+<text:a xlink:type="simple" xlink:href="http://example.com/" office:name=""><text:span text:style-name="Definition">http://example.com/</text:span></text:a></text:p>+<text:p text:style-name="First_20_paragraph">Auto-links should not occur here:+<text:span text:style-name="Source_20_Text"><http://example.com/></text:span></text:p>+<text:p text:style-name="Preformatted_20_Text">or here: <http://example.com/></text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="images" />Images<text:bookmark-end text:name="images" /></text:h>+<text:p text:style-name="First_20_paragraph">From “Voyage dans la Lune” by+Georges Melies (1902):</text:p>+<text:p text:style-name="FigureWithCaption"><draw:frame draw:name="img1"><draw:image xlink:href="lalune.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame></text:p>+<text:p text:style-name="FigureCaption">lalune</text:p>+<text:p text:style-name="Text_20_body">Here is a movie+<draw:frame draw:name="img2"><draw:image xlink:href="movie.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" /></draw:frame>+icon.</text:p>+<text:p text:style-name="Horizontal_20_Line" />+<text:h text:style-name="Heading_20_1" text:outline-level="1"><text:bookmark-start text:name="footnotes" />Footnotes<text:bookmark-end text:name="footnotes" /></text:h>+<text:p text:style-name="First_20_paragraph">Here is a footnote+reference,<text:note text:id="ftn0" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here+is the footnote. It can go anywhere after the footnote reference. It need not be+placed at the end of the document.</text:p></text:note-body></text:note> and+another.<text:note text:id="ftn1" text:note-class="footnote"><text:note-citation>2</text:note-citation><text:note-body><text:p text:style-name="Footnote">Here’s+the long note. This one contains multiple+blocks.</text:p><text:p text:style-name="Footnote">Subsequent blocks are+indented to show that they belong to the footnote (as with list+items).</text:p><text:p text:style-name="Preformatted_20_Text"><text:s text:c="2" />{ <code> }</text:p><text:p text:style-name="Footnote">If+you want, you can indent every line, but you can also be lazy and just indent+the first line of each block.</text:p></text:note-body></text:note> This should+<text:span text:style-name="Emphasis">not</text:span> be a footnote reference,+because it contains a space.[^my note] Here is an inline+note.<text:note text:id="ftn2" text:note-class="footnote"><text:note-citation>3</text:note-citation><text:note-body><text:p text:style-name="Footnote">This+is <text:span text:style-name="Emphasis">easier</text:span> to type. Inline+notes may contain+<text:a xlink:type="simple" xlink:href="http://google.com" office:name=""><text:span text:style-name="Definition">links</text:span></text:a>+and <text:span text:style-name="Source_20_Text">]</text:span> verbatim+characters, as well as [bracketed+text].</text:p></text:note-body></text:note></text:p>+<text:p text:style-name="Quotations">Notes can go in+quotes.<text:note text:id="ftn3" text:note-class="footnote"><text:note-citation>4</text:note-citation><text:note-body><text:p text:style-name="Footnote">In+quote.</text:p></text:note-body></text:note></text:p>+<text:list text:style-name="Numbering_20_1">+ <text:list-item>+ <text:p text:style-name="List_20_Number_20_Tight">And in list items.<text:note text:id="ftn4" text:note-class="footnote"><text:note-citation>5</text:note-citation><text:note-body><text:p text:style-name="Footnote">In list.</text:p></text:note-body></text:note></text:p> </text:list-item>
@@ -21,52 +21,52 @@ <outline text="Level 3" _note="with no blank line"> </outline> </outline>- <outline text="Level 2" _note="with no blank line ------------------------------------------------------------------------">+ <outline text="Level 2" _note="with no blank line --------------------------------------------------------------------------------"> </outline> </outline>-<outline text="Paragraphs" _note="Here’s a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here’s one with a bullet. \* criminey. There should be a hard line break here. ------------------------------------------------------------------------">+<outline text="Paragraphs" _note="Here's a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item. Here's one with a bullet. \* criminey. There should be a hard line break\ here. --------------------------------------------------------------------------------"> </outline>-<outline text="Block Quotes" _note="E-mail style: > This is a block quote. It is pretty short. > Code in a block quote: > > sub status { > print "working"; > } > > A list: > > 1. item one > 2. item two > > Nested block quotes: > > > nested > > > nested This should not be a block quote: 2 &gt; 1. And a following paragraph. ------------------------------------------------------------------------">+<outline text="Block Quotes" _note="E-mail style: > This is a block quote. It is pretty short. > Code in a block quote: > > sub status { > print "working"; > } > > A list: > > 1. item one > 2. item two > > Nested block quotes: > > > nested > > > nested This should not be a block quote: 2 \> 1. And a following paragraph. --------------------------------------------------------------------------------"> </outline>-<outline text="Code Blocks" _note="Code: ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab And: this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ ------------------------------------------------------------------------">+<outline text="Code Blocks" _note="Code: ---- (should be four hyphens) sub status { print "working"; } this code block is indented by one tab And: this code block is indented by two tabs These should not be escaped: \$ \\ \> \[ \{ --------------------------------------------------------------------------------"> </outline> <outline text="Lists">- <outline text="Unordered" _note="Asterisks tight: - asterisk 1 - asterisk 2 - asterisk 3 Asterisks loose: - asterisk 1 - asterisk 2 - asterisk 3 Pluses tight: - Plus 1 - Plus 2 - Plus 3 Pluses loose: - Plus 1 - Plus 2 - Plus 3 Minuses tight: - Minus 1 - Minus 2 - Minus 3 Minuses loose: - Minus 1 - Minus 2 - Minus 3">+ <outline text="Unordered" _note="Asterisks tight: - asterisk 1 - asterisk 2 - asterisk 3 Asterisks loose: - asterisk 1 - asterisk 2 - asterisk 3 Pluses tight: - Plus 1 - Plus 2 - Plus 3 Pluses loose: - Plus 1 - Plus 2 - Plus 3 Minuses tight: - Minus 1 - Minus 2 - Minus 3 Minuses loose: - Minus 1 - Minus 2 - Minus 3"> </outline>- <outline text="Ordered" _note="Tight: 1. First 2. Second 3. Third and: 1. One 2. Two 3. Three Loose using tabs: 1. First 2. Second 3. Third and using spaces: 1. One 2. Two 3. Three Multiple paragraphs: 1. Item 1, graf one. Item 1. graf two. The quick brown fox jumped over the lazy dog’s back. 2. Item 2. 3. Item 3.">+ <outline text="Ordered" _note="Tight: 1. First 2. Second 3. Third and: 1. One 2. Two 3. Three Loose using tabs: 1. First 2. Second 3. Third and using spaces: 1. One 2. Two 3. Three Multiple paragraphs: 1. Item 1, graf one. Item 1. graf two. The quick brown fox jumped over the lazy dog's back. 2. Item 2. 3. Item 3."> </outline>- <outline text="Nested" _note="- Tab - Tab - Tab Here’s another: 1. First 2. Second: - Fee - Fie - Foe 3. Third Same thing but with paragraphs: 1. First 2. Second: - Fee - Fie - Foe 3. Third">+ <outline text="Nested" _note="- Tab - Tab - Tab Here's another: 1. First 2. Second: - Fee - Fie - Foe 3. Third Same thing but with paragraphs: 1. First 2. Second: - Fee - Fie - Foe 3. Third"> </outline>- <outline text="Tabs and spaces" _note="- this is a list item indented with tabs - this is a list item indented with spaces - this is an example list item indented with tabs - this is an example list item indented with spaces">+ <outline text="Tabs and spaces" _note="- this is a list item indented with tabs - this is a list item indented with spaces - this is an example list item indented with tabs - this is an example list item indented with spaces"> </outline>- <outline text="Fancy list markers" _note="1. begins with 2 2. and now 3 with a continuation 1. sublist with roman numerals, starting with 4 2. more items 1. a subsublist 2. a subsublist Nesting: 1. Upper Alpha 1. Upper Roman. 1. Decimal start with 6 1. Lower alpha with paren Autonumbering: 1. Autonumber. 2. More. 1. Nested. Should not be a list item: M.A. 2007 B. Williams ------------------------------------------------------------------------">+ <outline text="Fancy list markers" _note="(2) begins with 2 (3) and now 3 with a continuation iv. sublist with roman numerals, starting with 4 v. more items (A) a subsublist (B) a subsublist Nesting: A. Upper Alpha I. Upper Roman. (6) Decimal start with 6 c) Lower alpha with paren Autonumbering: 1. Autonumber. 2. More. 1. Nested. Should not be a list item: M.A. 2007 B. Williams --------------------------------------------------------------------------------"> </outline> </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 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: foo And nested without indentation: foo bar Interpreted markdown in a table: This is *emphasized* And this is **strong** Here’s a simple block: foo This should be a code block, though: <div> foo </div> As should this: <div>foo</div> Now, nested: foo This should just be an HTML comment: Multiline: Code block: <!-- Comment --> Just plain comment, with trailing spaces on the line: Code: <hr /> Hr’s: ------------------------------------------------------------------------">+<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₂O, H₂₃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 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>-<outline text="Smart quotes, ellipses, dashes" _note="“Hello,” said the spider. “‘Shelob’ is my name.” ‘A’, ‘B’, and ‘C’ are letters. ‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’ ‘He said, “I want to go.”’ Were you alive in the 70’s? Here is some quoted ‘`code`’ and a “[quoted link](http://example.com/?foo=1&bar=2)”. Some dashes: one—two — three—four — five. Dashes between numbers: 5–7, 255–66, 1987–1999. Ellipses…and…and…. ------------------------------------------------------------------------">+<outline text="Smart quotes, ellipses, dashes" _note=""Hello," said the spider. "'Shelob' is my name." 'A', 'B', and 'C' are letters. 'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.' 'He said, "I want to go."' Were you alive in the 70's? Here is some quoted '`code`' and a "[quoted link](http://example.com/?foo=1&bar=2)". Some dashes: one---two --- three---four --- five. Dashes between numbers: 5--7, 255--66, 1987--1999. Ellipses...and...and.... --------------------------------------------------------------------------------"> </outline>-<outline text="LaTeX" _note="- - 2 + 2 = 4 - *x* ∈ *y* - *α* ∧ *ω* - 223 - *p*-Tree - Here’s some display math: $$\frac{d}{dx}f(x)=\lim\_{h\to 0}\frac{f(x+h)-f(x)}{h}$$ - Here’s one that has a line break in it: *α* + *ω* × *x*². These shouldn’t be math: - To get the famous equation, write `$e = mc^2$`. - $22,000 is a *lot* of money. So is $34,000. (It worked if “lot” is emphasized.) - Shoes ($20) and socks ($5). - Escaped `$`: $73 *this should be emphasized* 23$. Here’s a LaTeX table: ------------------------------------------------------------------------">+<outline text="LaTeX" _note="- `\cite[22-23]{smith.1899}`{=tex} - $2+2=4$ - $x \in y$ - $\alpha \wedge \omega$ - $223$ - $p$-Tree - Here's some display math: $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$ - Here's one that has a line break in it: $\alpha + \omega \times x^2$. These shouldn't be math: - To get the famous equation, write `$e = mc^2$`. - \$22,000 is a *lot* of money. So is \$34,000. (It worked if "lot" is emphasized.) - Shoes (\$20) and socks (\$5). - Escaped `$`: \$73 *this should be emphasized* 23\$. Here's a LaTeX table: \begin{tabular}{|l|l|}\hline Animal & Number \\ \hline Dog & 2 \\ Cat & 1 \\ \hline \end{tabular} --------------------------------------------------------------------------------"> </outline>-<outline text="Special Characters" _note="Here is some unicode: - I hat: Î - o umlaut: ö - section: § - set membership: ∈ - copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 &lt; 5. 6 &gt; 5. Backslash: \\ Backtick: \` Asterisk: \* Underscore: \_ Left brace: { Right brace: } Left bracket: \[ Right bracket: \] Left paren: ( Right paren: ) Greater-than: &gt; Hash: \# Period: . Bang: ! Plus: + Minus: - ------------------------------------------------------------------------">+<outline text="Special Characters" _note="Here is some unicode: - I hat: Î - o umlaut: ö - section: § - set membership: ∈ - copyright: © AT&T has an ampersand in their name. AT&T is another way to write it. This & that. 4 \< 5. 6 \> 5. Backslash: \\ Backtick: \` Asterisk: \* Underscore: \_ Left brace: { Right brace: } Left bracket: \[ Right bracket: \] Left paren: ( Right paren: ) Greater-than: \> Hash: \# Period: . Bang: ! Plus: + Minus: - --------------------------------------------------------------------------------"> </outline> <outline text="Links">- <outline text="Explicit" _note="Just a [URL](/url/). [URL and title](/url/ "title"). [URL and title](/url/ "title preceded by two spaces"). [URL and title](/url/ "title preceded by a tab"). [URL and title](/url/ "title with "quotes" in it") [URL and title](/url/ "title with single quotes") [with\_underscore](/url/with_underscore) [Email link](mailto:nobody@nowhere.net) [Empty]().">+ <outline text="Explicit" _note="Just a [URL](/url/). [URL and title](/url/ "title"). [URL and title](/url/ "title preceded by two spaces"). [URL and title](/url/ "title preceded by a tab"). [URL and title](/url/ "title with "quotes" in it") [URL and title](/url/ "title with single quotes") [with_underscore](/url/with_underscore) [Email link](mailto:nobody@nowhere.net) [Empty]()."> </outline> <outline text="Reference" _note="Foo [bar](/url/). With [embedded \[brackets\]](/url/). [b](/url/) by itself should be a link. Indented [once](/url). Indented [twice](/url). Indented [thrice](/url). This should \[not\]\[\] be a link. [not]: /url Foo [bar](/url/ "Title with "quotes" inside"). Foo [biz](/url/ "Title with "quote" inside")."> </outline>- <outline text="With ampersands" _note="Here’s a [link with an ampersand in the URL](http://example.com/?foo=1&bar=2). Here’s a link with an amersand in the link text: [AT&T](http://att.com/ "AT&T"). Here’s an [inline link](/script?foo=1&bar=2). Here’s an [inline link in pointy braces](/script?foo=1&bar=2).">+ <outline text="With ampersands" _note="Here's a [link with an ampersand in the URL](http://example.com/?foo=1&bar=2). Here's a link with an amersand in the link text: [AT&T](http://att.com/ "AT&T"). Here's an [inline link](/script?foo=1&bar=2). Here's an [inline link in pointy braces](/script?foo=1&bar=2)."> </outline>- <outline text="Autolinks" _note="With an ampersand: <http://example.com/?foo=1&bar=2> - In a list? - <http://example.com/> - It should. An e-mail address: <nobody@nowhere.net> > Blockquoted: <http://example.com/> Auto-links should not occur here: `<http://example.com/>` or here: <http://example.com/> ------------------------------------------------------------------------">+ <outline text="Autolinks" _note="With an ampersand: <http://example.com/?foo=1&bar=2> - In a list? - <http://example.com/> - It should. An e-mail address: <nobody@nowhere.net> > Blockquoted: <http://example.com/> Auto-links should not occur here: `<http://example.com/>` or here: <http://example.com/> --------------------------------------------------------------------------------"> </outline> </outline>-<outline text="Images" _note="From “Voyage dans la Lune” by Georges Melies (1902):  Here is a movie  icon. ------------------------------------------------------------------------">+<outline text="Images" _note="From "Voyage dans la Lune" by Georges Melies (1902):  Here is a movie  icon. --------------------------------------------------------------------------------"> </outline>-<outline text="Footnotes" _note="Here is a footnote reference,[1] and another.[2] This should *not* be a footnote reference, because it contains a space.\[^my note\] Here is an inline note.[3] > Notes can go in quotes.[4] 1. And in list items.[5] This paragraph should not be part of the note, as it is not indented. [1] Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. [2] Here’s the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). { <code> } If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. [3] This is *easier* to type. Inline notes may contain [links](http://google.com) and `]` verbatim characters, as well as \[bracketed text\]. [4] In quote. [5] In list.">+<outline text="Footnotes" _note="Here is a footnote reference,[^1] and another.[^2] This should *not* be a footnote reference, because it contains a space.\[\^my note\] Here is an inline note.[^3] > Notes can go in quotes.[^4] 1. And in list items.[^5] This paragraph should not be part of the note, as it is not indented. [^1]: Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document. [^2]: Here's the long note. This one contains multiple blocks. Subsequent blocks are indented to show that they belong to the footnote (as with list items). { <code> } If you want, you can indent every line, but you can also be lazy and just indent the first line of each block. [^3]: This is *easier* to type. Inline notes may contain [links](http://google.com) and `]` verbatim characters, as well as \[bracketed text\]. [^4]: In quote. [^5]: In list."> </outline> </body> </opml>
@@ -75,7 +75,6 @@ #+begin_quote This is a block quote. It is pretty short.- #+end_quote #+begin_quote@@ -96,14 +95,11 @@ #+begin_quote nested- #+end_quote #+begin_quote nested- #+end_quote- #+end_quote This should not be a block quote: 2 > 1.@@ -345,7 +341,6 @@ #+begin_quote orange block quote- #+end_quote Multiple definitions, tight:@@ -568,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. @@ -604,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$.@@ -753,7 +748,6 @@ #+begin_quote Blockquoted: [[http://example.com/]]- #+end_quote Auto-links should not occur here: =<http://example.com/>=@@ -768,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]]@@ -787,7 +781,6 @@ #+begin_quote Notes can go in quotes.[fn:4]- #+end_quote 1. And in list items.[fn:5]
@@ -101,45 +101,45 @@ Asterisks tight: -- asterisk 1-- asterisk 2-- asterisk 3+- asterisk 1+- asterisk 2+- asterisk 3 Asterisks loose: -- asterisk 1+- asterisk 1 -- asterisk 2+- asterisk 2 -- asterisk 3+- asterisk 3 Pluses tight: -- Plus 1-- Plus 2-- Plus 3+- Plus 1+- Plus 2+- Plus 3 Pluses loose: -- Plus 1+- Plus 1 -- Plus 2+- Plus 2 -- Plus 3+- Plus 3 Minuses tight: -- Minus 1-- Minus 2-- Minus 3+- Minus 1+- Minus 2+- Minus 3 Minuses loose: -- Minus 1+- Minus 1 -- Minus 2+- Minus 2 -- Minus 3+- Minus 3 Ordered @@ -183,17 +183,17 @@ Nested -- Tab- - Tab- - Tab+- Tab+ - Tab+ - Tab Here’s another: 1. First 2. Second:- - Fee- - Fie- - Foe+ - Fee+ - Fie+ - Foe 3. Third Same thing but with paragraphs:@@ -202,21 +202,21 @@ 2. Second: - - Fee- - Fie- - Foe+ - Fee+ - Fie+ - Foe 3. Third Tabs and spaces -- this is a list item indented with tabs+- this is a list item indented with tabs -- this is a list item indented with spaces+- this is a list item indented with spaces - - this is an example list item indented with tabs+ - this is an example list item indented with tabs - - this is an example list item indented with spaces+ - this is an example list item indented with spaces Fancy list markers @@ -257,93 +257,93 @@ Tight using spaces: apple- red fruit+ red fruit orange- orange fruit+ orange fruit banana- yellow fruit+ yellow fruit Tight using tabs: apple- red fruit+ red fruit orange- orange fruit+ orange fruit banana- yellow fruit+ yellow fruit Loose: apple - red fruit+ red fruit orange - orange fruit+ orange fruit banana - yellow fruit+ yellow fruit Multiple blocks with italics: apple - red fruit+ red fruit - contains seeds, crisp, pleasant to taste+ contains seeds, crisp, pleasant to taste orange - orange fruit+ orange fruit - { orange code block }+ { orange code block } - orange block quote+ orange block quote Multiple definitions, tight: apple- red fruit- computer+ red fruit+ computer orange- orange fruit- bank+ orange fruit+ bank Multiple definitions, loose: apple - red fruit+ red fruit - computer+ computer orange - orange fruit+ orange fruit - bank+ bank Blank line after term, indented marker, alternate markers: apple - red fruit+ red fruit - computer+ computer orange - orange fruit+ orange fruit - 1. sublist- 2. sublist+ 1. sublist+ 2. sublist HTML Blocks @@ -448,23 +448,22 @@ LaTeX -- -- 2 + 2 = 4-- x ∈ y-- α ∧ ω-- 223-- p-Tree-- Here’s some display math:- $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$-- Here’s one that has a line break in it: α + ω × x².+- +- 2 + 2 = 4+- x ∈ y+- α ∧ ω+- 223+- p-Tree+- Here’s some display math:+ $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$+- Here’s one that has a line break in it: α + ω × x². These shouldn’t be math: -- To get the famous equation, write $e = mc^2$.-- $22,000 is a lot of money. So is $34,000. (It worked if “lot” is- emphasized.)-- Shoes ($20) and socks ($5).-- Escaped $: $73 this should be emphasized 23$.+- To get the famous equation, write $e = mc^2$.+- $22,000 is a lot of money. So is $34,000. (It worked if “lot” is emphasized.)+- Shoes ($20) and socks ($5).+- Escaped $: $73 this should be emphasized 23$. Here’s a LaTeX table: @@ -474,11 +473,11 @@ Here is some unicode: -- I hat: Î-- o umlaut: ö-- section: §-- set membership: ∈-- copyright: ©+- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: © AT&T has an ampersand in their name. @@ -582,9 +581,9 @@ With an ampersand: http://example.com/?foo=1&bar=2 -- In a list?-- http://example.com/-- It should.+- In a list?+- http://example.com/+- It should. An e-mail address: nobody@nowhere.net
@@ -133,45 +133,45 @@ Asterisks tight: -- asterisk 1-- asterisk 2-- asterisk 3+- asterisk 1+- asterisk 2+- asterisk 3 Asterisks loose: -- asterisk 1+- asterisk 1 -- asterisk 2+- asterisk 2 -- asterisk 3+- asterisk 3 Pluses tight: -- Plus 1-- Plus 2-- Plus 3+- Plus 1+- Plus 2+- Plus 3 Pluses loose: -- Plus 1+- Plus 1 -- Plus 2+- Plus 2 -- Plus 3+- Plus 3 Minuses tight: -- Minus 1-- Minus 2-- Minus 3+- Minus 1+- Minus 2+- Minus 3 Minuses loose: -- Minus 1+- Minus 1 -- Minus 2+- Minus 2 -- Minus 3+- Minus 3 Ordered -------@@ -217,20 +217,20 @@ Nested ------ -- Tab+- Tab - - Tab+ - Tab - - Tab+ - Tab Here’s another: 1. First 2. Second: - - Fee- - Fie- - Foe+ - Fee+ - Fie+ - Foe 3. Third @@ -240,22 +240,22 @@ 2. Second: - - Fee- - Fie- - Foe+ - Fee+ - Fie+ - Foe 3. Third Tabs and spaces --------------- -- this is a list item indented with tabs+- this is a list item indented with tabs -- this is a list item indented with spaces+- this is a list item indented with spaces - - this is an example list item indented with tabs+ - this is an example list item indented with tabs - - this is an example list item indented with spaces+ - this is an example list item indented with spaces Fancy list markers ------------------@@ -610,24 +610,24 @@ LaTeX ===== -- :raw-latex:`\cite[22-23]{smith.1899}`-- :math:`2+2=4`-- :math:`x \in y`-- :math:`\alpha \wedge \omega`-- :math:`223`-- :math:`p`-Tree-- Here’s some display math:+- :raw-latex:`\cite[22-23]{smith.1899}`+- :math:`2+2=4`+- :math:`x \in y`+- :math:`\alpha \wedge \omega`+- :math:`223`+- :math:`p`-Tree+- Here’s some display math: - .. math:: \frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}-- Here’s one that has a line break in it: :math:`\alpha + \omega \times x^2`.+ .. math:: \frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}+- Here’s one that has a line break in it: :math:`\alpha + \omega \times x^2`. These shouldn’t be math: -- To get the famous equation, write ``$e = mc^2$``.-- $22,000 is a *lot* of money. So is $34,000. (It worked if “lot” is- emphasized.)-- Shoes ($20) and socks ($5).-- Escaped ``$``: $73 *this should be emphasized* 23$.+- To get the famous equation, write ``$e = mc^2$``.+- $22,000 is a *lot* of money. So is $34,000. (It worked if “lot” is+ emphasized.)+- Shoes ($20) and socks ($5).+- Escaped ``$``: $73 *this should be emphasized* 23$. Here’s a LaTeX table: @@ -646,11 +646,11 @@ Here is some unicode: -- I hat: Î-- o umlaut: ö-- section: §-- set membership: ∈-- copyright: ©+- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: © AT&T has an ampersand in their name. @@ -762,9 +762,9 @@ With an ampersand: http://example.com/?foo=1&bar=2 -- In a list?-- http://example.com/-- It should.+- In a list?+- http://example.com/+- It should. An e-mail address: nobody@nowhere.net @@ -784,7 +784,7 @@ From “Voyage dans la Lune” by Georges Melies (1902): .. figure:: lalune.jpg- :alt: Voyage dans la Lune+ :alt: lalune lalune
@@ -149,7 +149,7 @@ {\pard \ql \f0 \sa0 \li360 \fi-360 2.\tx360\tab More.\par} {\pard \ql \f0 \sa0 \li720 \fi-360 a.\tx360\tab Nested.\sa180\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 Should not be a list item:\par}-{\pard \ql \f0 \sa180 \li0 \fi0 M.A.\u160?2007\par}+{\pard \ql \f0 \sa180 \li0 \fi0 M.A.\u160 ?2007\par} {\pard \ql \f0 \sa180 \li0 \fi0 B. Williams\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \outlinelevel0 \b \fs36 Definition Lists\par}@@ -245,8 +245,8 @@ {\pard \ql \f0 \sa180 \li0 \fi0 So is {\b {\i this}} word.\par} {\pard \ql \f0 \sa180 \li0 \fi0 This is code: {\f1 >}, {\f1 $}, {\f1 \\}, {\f1 \\$}, {\f1 <html>}.\par} {\pard \ql \f0 \sa180 \li0 \fi0 {\strike This is {\i strikeout}.}\par}-{\pard \ql \f0 \sa180 \li0 \fi0 Superscripts: a{\super bc}d a{\super {\i hello}} a{\super hello\u160?there}.\par}-{\pard \ql \f0 \sa180 \li0 \fi0 Subscripts: H{\sub 2}O, H{\sub 23}O, H{\sub many\u160?of\u160?them}O.\par}+{\pard \ql \f0 \sa180 \li0 \fi0 Superscripts: a{\super bc}d a{\super {\i hello}} a{\super hello\u160 ?there}.\par}+{\pard \ql \f0 \sa180 \li0 \fi0 Subscripts: H{\sub 2}O, H{\sub 23}O, H{\sub many\u160 ?of\u160 ?them}O.\par} {\pard \ql \f0 \sa180 \li0 \fi0 These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \outlinelevel0 \b \fs36 Smart quotes, ellipses, dashes\par}@@ -260,17 +260,17 @@ \u8221".\par} {\pard \ql \f0 \sa180 \li0 \fi0 Some dashes: one\u8212-two \u8212- three\u8212-four \u8212- five.\par} {\pard \ql \f0 \sa180 \li0 \fi0 Dashes between numbers: 5\u8211-7, 255\u8211-66, 1987\u8211-1999.\par}-{\pard \ql \f0 \sa180 \li0 \fi0 Ellipses\u8230?and\u8230?and\u8230?.\par}+{\pard \ql \f0 \sa180 \li0 \fi0 Ellipses\u8230 ?and\u8230 ?and\u8230 ?.\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \outlinelevel0 \b \fs36 LaTeX\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab \par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab 2\u8197?+\u8197?2\u8196?=\u8196?4\par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i x}\u8196?\u8712?\u8196?{\i y}\par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i \u945?}\u8197?\u8743?\u8197?{\i \u969?}\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab 2\u8197 ?+\u8197 ?2\u8196 ?=\u8196 ?4\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i x}\u8196 ?\u8712 ?\u8196 ?{\i y}\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i \u945 ?}\u8197 ?\u8743 ?\u8197 ?{\i \u969 ?}\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab 223\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\i p}-Tree\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Here\u8217's some display math: $$\\frac\{d\}\{dx\}f(x)=\\lim_\{h\\to 0\}\\frac\{f(x+h)-f(x)\}\{h\}$$\par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Here\u8217's one that has a line break in it: {\i \u945?}\u8197?+\u8197?{\i \u969?}\u8197?\u215?\u8197?{\i x}{\super 2}.\sa180\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab Here\u8217's one that has a line break in it: {\i \u945 ?}\u8197 ?+\u8197 ?{\i \u969 ?}\u8197 ?\u215 ?\u8197 ?{\i x}{\super 2}.\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 These shouldn\u8217't be math:\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab To get the famous equation, write {\f1 $e = mc^2$}.\par} {\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab $22,000 is a {\i lot} of money. So is $34,000. (It worked if \u8220"lot\u8221" is emphasized.)\par}@@ -280,11 +280,11 @@ {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \outlinelevel0 \b \fs36 Special Characters\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here is some unicode:\par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab I hat: \u206?\par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab o umlaut: \u246?\par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab section: \u167?\par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab set membership: \u8712?\par}-{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab copyright: \u169?\sa180\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab I hat: \u206 ?\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab o umlaut: \u246 ?\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab section: \u167 ?\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab set membership: \u8712 ?\par}+{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab copyright: \u169 ?\sa180\par} {\pard \ql \f0 \sa180 \li0 \fi0 AT&T has an ampersand in their name.\par} {\pard \ql \f0 \sa180 \li0 \fi0 AT&T is another way to write it.\par} {\pard \ql \f0 \sa180 \li0 \fi0 This & that.\par}@@ -421,7 +421,8 @@ {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \outlinelevel0 \b \fs36 Images\par} {\pard \ql \f0 \sa180 \li0 \fi0 From \u8220"Voyage dans la Lune\u8221" by Georges Melies (1902):\par}-{\pard \ql \f0 \sa180 \li0 \fi0 {\pict\jpegblip\picw250\pich250\picwgoal3000\pichgoal3000 ffd8ffe000104a46494600010101007800780000ffdb00430006040506050406060506070706080a100a0a09090a140e0f0c1017141818171416161a1d251f1a1b231c1616202c20232627292a29191f2d302d283025282928ffdb0043010707070a080a130a0a13281a161a2828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828ffc000110800fa00fa03011100021101031101ffc4001c0000000701010000000000000000000000010203040506070008ffc4003e100002010303020404040502050500030001020300041105122106311322415107617181143291a1234252b1c115f016336272d1082443e1f1265382ffc40017010101010100000000000000000000000000010204ffc4001b11010101010003010000000000000000000001110212213141ffda000c03010002110311003f00dadd18a10a704f6a95ccc57e37750782b0d8d9ea0cd32e7c5446e07e9f4ad723119a7b89e61e348f260719278aad613cbb640002938c76a182b264fc87bd13009c0c019c76e3d68a072e1cf6f4cd502d330c28269a61bb39c923923d4fad44c08dccb95cfd28b8280769ee08a263891e1808739e4f1d8d149392172cc714050dbb9fde8960ed8c60b79b1ed44103b05c331dbdb1dc5026ac1946d20ff8140aa631c773ec738a0346a003bf93e9cf02801895e7b9a01886796c923bd0090a06393c76a0142003ce3d86680d8dd9392303f5341ccc1b3cf7a2c812c37e4923d381429757013209fa511c18146c9247a0f6a007900c0c671c6280854e086c673eb45c27c038fd68aedff2fda836ef881f136f25d5e6b7d1262964aa02b03f98fbf153131935edcc97576f35c33349212cc4f39f7ab26186dfce5b200f73451f7600dcb8cf27e7400c0b291914046c9e0718fde81371b8e7273f4ef4007691919240e714097f31f376e7b5008caee27807b0f5a02c8e1b3c6d27d33cd0201d839523144d1a149ae084b78da47638211771fd050d582c3a0faab5119b6d12f8ab1c06788a0fd4e2ac356fd1fe08754ddccaba849696309e598c9e2103fed1dcfdeadc44fea5ff00a7f956366d375e492403ca935bedcf1eea4ff6ac68a55efc1beb3b552574f8e7009ff933a927ec715bc82b3a8f4d6bba5ca1352d22fe061cf9a0383f71dea5119cc6c0baed3eaac0f1fad40897dcc3d81f7a052366c1007df3400f21edefc5008c28f30c9c5170ee4fc37830086395250a7c66770c18e78da31c0c63de8609b41f7c515c5172a30c3b76344a3e377cb2339cf7a242aea89808cce368272b8c1a2e107c672a49f5c1a181c9c7ae7da8a2119e7b1f5068099ffa68258a132062d8f9e0f34059502b61bf2824e681bb297ced2a71efda80f19c47b9c77fdbe74057c13e539cf3c1a0eeeb9c73f33405ddb4f18249c1e28062b79ae242902024465b9214614649e7bd0362a7249eddc513456e5720f38f5a1a98e96e95d6baa6ebc2d1ad1e65521649bb469f563534d6d7d31f04347d2a2fc5f535db6a0e83718906c887cbbe5a9a8bef44dce9f731ca9a2e89169d6d6f2184b1455dc07b11dcfeb4d16f119c649a681285b03d3e5500f87820ff006a0e098191de80ac9b8904647b55d11da9681a56a31f87a869f6970b8ffe4883629a289aefc16e92d441682da5b098f21ed9f033f353914d19b751fc08d66cc16d12fe2bf45ec92ff0df1fdbfb559ec667aff4eeb1a04db359d3ae6d40eccebe53f46ec7f5ab82263da7dcf3eb5174e5181076918c7de869503232491ee4515c1803824f03b51287f30e0e7d803449494832c157278a2e8c71fcb9f9d144639236824d01e142efb1768cfb9c7ef40512a818de78ff00a682518e7cc30ab9e00a02cce9953247bd41e467191ed9a04205ee99da4e4e3d283a524b0427b5026c18a8e082067db8341ce0e39ed409b6502907391edda80f2dfdc496f0c124ac6184b144cf0a4e338fd2894f7a7342d4ba9b568f4fd261f12571966270a8bfd47d8511bae85f02b47b7fc34bac5d5c5dc88a0c90ab6c8d9bedce3ef4d1ad691a6dae976a96d616d15b409f9638d70054a1dbc68ea51d4329f4619a8022b78e04548515117b05000a035c5c4702a995c26e3819f534047bcb68a458cce866719540724d02e41c0f7a012a40f6141cbc8e7bd01719e38e6838af1c0a04ca8206d3cd037bdb082fad9e0bd8a39e0718649141047d0d5d18f759fc0cd3af164b8e9999acae4e4f81236e898f7c0f55fed574615aee83a96817ef67abda3db4ebdb7f66f983d88a061bb8db9e3d45165076db83c1f950a53780d8247c80a2398f182724f1c7ad080c608cfa7a51a0062adc7afbd0130173bb9c5070f071cb37e82826106e8f615e01c9e680d6b35bc534be3c1e3831b2aa962bb188f2b71df1de819ae4b1048c7f57bd01a58268e332642ae0704f7cf6207af6a01b99e17b7b6416e227407c494139909ed9f4c0a04a4e501e0f1eb40d263e53dce7fa682c9d0bd13abf58dd6db18bc2b157c4975270ab8ef8f563f21447a73a03a1f4de8eb031582b497328066b97fcd21ff038edfde88b7e32703bd64188e7e6283864b73400cd804b67ca3268317eacea6d56ff005233592f8b6303f953fa4af7c2fa93417fe98b763e0ea171297bab98558068f695ce0e08fdbd281e5c6a57ba5e9d14d716ef7774f2ec112601da4f27ec2827ada74bab559a20e148fcae36b0f91140283729c77a0e0a7777a01dac68395719e39a029607cb901b19c501480ab9279f4a086ea8d0b48d76c0586b7143224a76c61ce1831fe93e86b43cd1f12fe19ea7d2533dcdbeebcd20b612651e68f9ece3fcf6fa5067cbcf20ff009a051724905411e94032799060723da8406d6c67e7ea68d0e1770fe5cfb5026c37039ef9a02eca098c91e6e01e71c500b1d8a49c12786cf6a06a4e256008e3d050119958007920e2801154e32fb4120927b014017eb1c523ac5209a356215c291b87be28957ef853f0d66eaa99352d515e1d190f947669ce7b0ffa7e74a8f4be996569a5d9c56b6704705b46bb5238d42851f2ac875712bc70b3c30f892019540704d01ad2669a0491936330c95ce7140b2e4939a03638c7e8680ae485e33bbe540d60d3ada162c90a02c7270a39340a4f28b68da4645007a8f6a069a746f73235ddcefc391e12b2e1916824948742c99382473c73404791c617695279dc0640f9502c578c9efeb4095cb4cb0830ba21cf999c6401f4f5a05061d430c8079a02e03b3004311c7d281b5e3cd676c65489ee594e4aafe6c7ae07a9a0a075bbea3a8ea96f047d3935ebc404f04ad29411e08e011d98fed416fd212ee5b05b4d5ad6300c615807f1171eaa49eff5ad418c7c55f8466dd66d57a521f20cbcd66a7247a9283dbe5418a63862479877cf1f6c5008e400bdf1ce684016fe53dfbd1a73794600e08ce3d6800377c8c7d6800a9cf75fd4503d91492460f7ee3d28247a7b459f5fd592d22711c206f9e563858a31f99cfd050583518ba75247b1d134f9aed21396d4669769931dc01c003f7a329c4d17458ac5b55d36c12e040a3f1da75c1cb04ede2447f7f6a94567ad7a66db4fbbb29ba7d65b8b4bd8ccd09c8231eaa07b8ab04a7c2cf87b3f53ea8d77abc72c1a5dabe2452bb5a561fc83e5ee7e541e988218ed2dd22b7855228d76a46a00000ec00a510bd4dd511f4fe84da95cc31f880022da4902b1e7d3e99ac86fd03d631f565b4ee6d4dbbc649009cab2e48c83f514165b8b94b6895c44f279c280839e78ce28178ae6de46748a789e453865570483ec6812d42e85a421fc37918b00a883924d024c6e99b7a2a966c0009e17dc9f9fed40f81c77e28139218e4ff9815b9cf23340a01c907b9140201038ed402fcafd28386464e4fd33c50272bc60032609cf00fbd024f722dc66f24822ddf972f8feff00e280f69b24844919cac9ce7de83a447f30ded823007b50459d6ecacb528349b979127651b1dc795f1f3f7a0990148054823dc5015d491c0a0c3be337c2ff00c489b5ee9c87172016b9b541c49ff5a8f7f71eb560c1fc43e0a47e1aa94277310431f91fa551c1727f29ed409b641c86e31839a3454805739c1f6a026f1fd740f64665fc8c31cfde82db79bb40e9e8f49b62eb7d7e8b717ec832c91ff247fa1dc7df2281bcc9369d671493c422b7911654c1215f92bb8827bf068624ba635392df5eb4b9924558ee5bc19b71cee43c6dc7cf34c657be8db0b0b9d0f51d2afe668934dbf9628ddb8c2b8c0073f3a80da37546a7d25174fd95dc125c69f7313ee5655dfc313bd483cf07b1f6a68d5b48d5ec758b612e9d7293211c8fe653f35ee2a084eb9e8bb1eafb3582fe496278f3e1c919fcb9f97ad03ee8dd017a6741b6d3229dae161057c5750a48249ec3eb4139238568f6a9e7b103b5037934cb3793c610a2cd9277a8da73f5140ee38f6280c4b11c65b934023006d50050030e4647de80c846de3b500fcf9fbd0197273ed4007b91400e580c8e45074a82400e72682b36fd2162b7f25ddc09af2766ceeb872db79cf00f6a0b3229550140e07007a50092db860673de818df473c862686dad6470d9cce3b7b63e740fa1de6252ebb5bd81cd00bee2d800d003a6464004763ce683ce9f1cbe1f1d3a67ea1d1a30b68edffba814708c7f9c63d0fafceaca31e6dc71e1f07daa82608c83819f7a1a11ce149238fd68d0a579ec682cfd27a7c3a86bd10bc38b3b756b8b93c1fe1a8c91f7381f7a034f752ea5aa5c5eb292f732128037619c018f6ec282e5a2cb047abda74d5ce9b6da80f136de4a496219b3e48c92000323ea73467519d3da5bb757dbda410ac90c77c23058f99007ee7ec31416882ee47d23acb5185caf8bab4691b1efe57fff0038a9457ee75a82f6e7429350466b482f2742c0f74241c80c38c64541a9cfa1e89ac0177d33ab3d8de28f2b5bca429f91140e2c7a9b5ae9fb85b6ea9b46b9b3c796fe040768f76ec0fafb1f9505df4ebdb3d4edd6e74db98ee216fe68ce47d280648f75e2485a44da385ddc13f4a025ddbdbea16a633286566ce55f9c8f6c502ad750db2c514f30dec428247e6340bbf04100b73402afb943ed2b9e30683836defe9403bc1e06734020e06280cafe8683a375941d841c77c1a0151b467b50159f00e4127e5402872371040c5046eb5aadbe9b1c02e2f6dad25b89047099c677b7b0140fe3f1010afc803f3018e68160c3041ee2823f5dba92d34db89a1d9e2843b03b6d05bd013560c1748d57aa2797c6b35bab78e6959dc47231580ff336dcfb03c1a58364b5bbb7d7fa7b7427f1f673830c8664285bd1815238fad20f2c7c41e979ba43aa2e2c1cb1b663bede438f3a13c7dc76fb5515e9065b851f7a02950002a09c51a1b83cf14176e90d3645e9ad7752752aac23b3439c066665c827e944d29a6410aea725c4567135bd840d3c88a723728c29c9efe6c50d3ee9545b0bf8ef2e6e3c2fc2c6f72f2920e5f19039ee4938a9a875d03278377acf52ddf867f036ef71923932bfe51fbd3475cdc369df0db4fb389d4ea37970fa9cc0b00511795ce7d4f181eb4cd2451755fc45ac16d637381b14ca36b641dfce723e4053170d6cb52bbb362f6d3cb19241f2b9029862f09f143549ba7e7d2eef6caf2797c66ee17fdfd69862d1a069da7dfdac579d17adcda5ea9e1a992376c4723e39e3b024fd7e94c458ac3e25dee8d31d3bae74e7b79002bf8b8549471db38f5f4ed4c165e943a06a328d4ba605b4b22a1523c420c64fbaf38a82d36f0ce7cf7463790729b53017e940e0b0ceceed8ce0500e1b70daa08f5c9ed41d271cd0132476e7d7ff00aa069797d2411168ed9a41fcc858211f73c5075acb25ca6fb82aa31e58a36c81f561dcd033d42169e158ac64b98151b3981c2966cf639f4a064c7a8ac55e4865b7d493701e1c8e52403ea3cbfda827e390ca3f2c914aa81991bd281cdacc2747215c60e0ee5c67e940cb51b0b2bcbd824bfb08ee1a252d1caea1821cfa67b1fa504982b2283ce08f518a08abb82f6dd0369a5662081e14ce40c7ae1b04fda82275cb0bfd4f4536f7114589a5412461f3e4ce4e0e060f63f6ab2893d3b4b5b5b78e22ed22aae3cc3cc7e64fad3449a22a461500007602a0cd7e3b74c26b5d2ad79147baf34eccca40e4a7f30ff3f6aba3cd0543267eb5427b86f1f4c76ef45d0eca1ad5ef224d13e1cf4fd9b22192fa67bc955f8c8c617fba9fb510d7a6ed3fd43a735e5b54964be658c048fb6cdd9e7eb8a186bac97d174e6d22e23437b7ac26b95e77c68bf950fa7279e2b22dba45b59e97a669fa4ea36aeff89cea9a90451fc355ff0096ad9f4ce3f41570675d4fa8c77da8de5cde5be26bc653171ca47dc1f6c9fed5562b97f70276808da7c24f0c1c63804e33fa8a2928c0e0383c8f7ed41d92a41393f4a2548595c2c37493db4cd04e8a08f139566edfef3445b6e7aeaf65d2df48ea2b11776ae02a93e564c772adef409f4ee8ba9a21d73a36fa579ad9f325afe599171ed9c30a960d5ba0fe2843abb47a6f510fc26a4c36890f9558fcc6783506a1147b510024e30339ce680d2c6ae9861eb9a009178a0205443b989e39cd01d8075e3047ce80563057ca381ed4011c4531e503d85013c91b804a21279c903341131cda8c3abdc8650f6d20c4321232adec3dc504bab2c113c9293bb1963df3408dd4b75e1efb2856463dbc43b4631fad047e9177ad4fe32ea16b1db4b8fe1aa92571f5f5a0916bc8e0895af5c46c17cd8c9ff7da80f6d736f7f6915c59cab35bc837238ed8a072a31c1ef4062870718a06f7702dc5b3c522ee4752ae0fa8230683c75d6ba3b74ef535fe984929149e4278ca9e47edfdab42058003763ed409f88ffd6dfad06b1f12ae612fa0c76e0b471e9916d23f973eb4158d3efeff004a984da5debc1295d8e4018dbf3145d583a2ad96f356bbd7f5d90dc59587f1e79a6392f28fcaa3ee47159444ea3aa5ddfc7acf50dcdc344d7a4dbc317f52641200f6000fdeb41b5ef51d8eab672ffa9e971c97c11638268e431a46000012a3b9a351567db823b11f3ef40948e428048207a8340ab48ae83cb83ee0f3428a982719edf3e68c9cc97d3fe15ad8c9be138f2bf38e7b8f6ef40f7a5f55bdd3f56b46d3649127f1405f08e7249c76f5fa50689d48ba5f545cdcbdb462cba9206411b2b055bb07d4fb1c73528d4fa8f52d62cf47b6b8d2e65fc458c49f8a818795c151939f977a823ba0fe253750eb7fe937b04293f9f6c90be41dbdc7ff006283473c1efc1a06f69776d73bbf0f2aca32572bc80470450284a46dfca19f819f5a04e799614def26c0bdce09cfd85045dc75769d12dc3c3e2491db0dd3c85195235f7c91cfd066ae0cdba9be31f4ec61a386c1ef9d4ee473e45cfb1cf34c101d3ff1ac9d481d46c628ed24751881880833f988e7b0fa5328dfed2f2def2ce2b9b79925b791772ca87208f7a60182ee2b95cc0c48f53823fbd40ac658b30f4f4a086d4ee1d75bb6b78f4e965596366fc5211b23238008fde81f43692da5bc30d97831a0397dc09e3d714087506bf61a2c4cd77324726d2caaec141f9fd2ae0c435bf8c57173ad7876f7a2daca10489121244cdf319ce3dbf5a834fe81f881a6f57bcb6ba7c53c72c11873e28cee1db391dbef4199ff00ea4348116a5a66a8a8a04aad04847a90723f6ad7d18c312ddc02a3815423ba0f63fa541687bd9efe1b533b3c9e0a78473e899e318a09bd0ba6eef543e3b2bd8e9b10064bd9e4da001dc81401aeeb29a984d0ba7d5e1d06d4e6594f06523bc8e7f5c0ac8af752dfc17d7090d9218ec6d9447129ee71fcc4fb9cd6842ab10dc0014f3e5a2c1704b671dfdc734525226dc939e283a362c7f940344a380393df144733e2276e38f5efcd01b4bbbfc3dda4a9298a44395902e4a9c70682660d4265d62de40b1bdc1545054f95c8fe627df141af7c3af8808f3dd68dd5d2a45765884b8908d8c3b6c27b7a77a945d7a5fa474bd2ba8e4d5748b28624955d5d8b13b79ee9e983d8d40a753758c7a46b96f6114725dc92279a2810b3a64f94900763cfafa503fd3b59b79ed84da34713c0cd890f0a158fa1f981de826e1b548959fc4dc5cee24b6467e59ed4101ff19e9f676baa5d6a72c50adb4ad1ac790ccc076200f7ad41e7df881d79a87576a5f87b0f161d381db1c2a36e7e6d8ff3416bf87ff082c6f208ef7a82f22b9761bd6d619785f6dc477fa53705ab57f83bd297ceb1e9caf67708db9c4526723e849e3e94f212dd25d117fd29a8c09a76b534fa39cf8b6b71ced38e36fb73417f52e64548e34007e673e9f21ef590a1c918c90718dc281a69b68f67118d9da5058b798f6fa7fe280daadd1b2d36eae70710c4d263df0a4d583cc7a668fd4bf11b5837d7c93dcd9a3146959822a0e781f4cfa55161e9dd7fa67a4f55b9e9aea3e9f81fc09ca0ba118998fcdb2338c7b528d39f4cd2ba76e2d357d292df4eb391809963420ce1b1b576fa1e7359119f1eb4e17dd033ca172d6b2a4df303383fdeb5c8f2eef3bce4e0e335684cb0c9f354160d36f64b0baf16072b91b5f03391f43c51aab23a5debe91c4fad4d73689e6fc3a290573ff4f03e59f4a3280d67581ce916567f84b58ce0a1fccec3d58fa9a084de08c90464e4d1a8e419059b201f4a05630a176918efc50176293872c17bf14042aa0125b03db14046c60b60123fde6827fa0c68edd5365ff11346ba6292ee64194240c807e59a32b7fc51bfe8bd5ed5db424860beb62b89218422ce09c11c01dbbd0660ae110bf1bf2154838dbebfefeb41a8f4cdac7f117458f4d9ecd2df53b4cf81a822808c47255c0f7c8e7fb54a2ec2cfabba3b4b4b8d3af12eedad40926b0f070a13f9b633649f7a82eba6ea4357d321d4ecad512daf20df26e016507fa4fbfaf3e98f9d067dd2bd2faac9aa4d72d72d1e9510ca46a7631c7a320e18f1dfd7bd059afb7da816d23de4ba5de211346a1e4785f190548e4648c63b64e6b43ce9d5baafe3b539c5b452dbda46c638a167cb281c73ee4ff9340e3a3fa5f5aea4ba58f4bb57dbfcf2b02a8bf7f7a0de3a5fa0b50d2a2d92eb3e048c0a97c867dbedcf6a944e5cf4f6b76d1b3d8ea42795066266c87c81c65b9cfaf15048e83af3cd64abac08edaf01546c38dae4e0657ee6826e5b892de3702292e2545ddb55700fd0fbfca81c4b3bc718716eef9eeaa402280d14ab3c0b2c65c06fe571823ed40df56b217fa6dd5ab9216689a33f2c8c558307e83b8d77a37aaa7d22f2512c28768800c9954671b3d33ebef568d0ef7a7749eb0b5bbbb162d657b32b46d2e1564c8ed9c5644d1b0b9bbd261d2a440af6cb0e2e5b1e7dbc1238e0f7a0375b696daa7496a3a4dac8a92cf078685b271db04d391e40d5ec4586a1716de2a49e0c8c85d3b120f715ba1899173ff305413070abd89cfe9f5a2d3ee9c8639fa874eb6b804c52dc46b20c9f302c3bd11e84d47e1af4d5dc6521d3e3b662c19a58721ff5a9a321f89bd27a374b456d158dccd34d333332c9b4b2afbe47a7cb1f7aa33d2bc0d8c0f1c8f6a2c14b6d501b39cf63450897380c319e3de8065031c038f7ed40d8faf1ce41e4d004876a8dc3cc7e743025c956c818028c904579e7f0e15695c9c0541924f6c00283d0bf07f42d6b48820b8d62d20b2b58d656404959e52f83c8ff00fcfafbd4a35bb06f12391a48dd55cee2b2f3818ed8f6a8158a159890f02242079147623e631c502b0db436d1ecb7458d4738038fb0a087d6eeb508f48bb7d32d95750752b6c26c905b3ddb6f61eb574794f5cb6b9d0fa9678b512b25d24bbe52b8c1638278fbd582c57ff12afaed45b5bc0d0d8a8c08a2731ee3eec5793f40450466a1d59af446293c186cd53ca0c36eab93dc649e49fbd048e89f1675ed35e301e293919dcbf9867b37cbe94a35fe94ea4d33aba6824306dc48015750d86c6e247b0cf63591a40b8dc23fc30f14138dcac3000f9d03687547f12e8dd5af816b13148dddbcd29039c0f6f6f7a0eb5d62caf5636825db70c9bc4328f0dc0271c8a090627d3073ce681acf6505ccf14d35bc2f2c2731bb28254fb8a075144a83ca806792400334049ee6281e2496408656d880ff0031f61fa50446bd76058ea1b9e21025a3bb48afe71df9c7b71de9c8f196a0de23ca7b827d4f7add117e0cbfd4b5059392369663ff004e71c51aa97e8f555eadd258f2bf8a889cff00dc28cbd0bf123a926e96d163bdb74490bca2321c678209ff001591e71eafd7a7d7ef45cde2c20aae144638033fb9ad2e1b5e69d058da431ccf21d4a5c3b4631b62523807feaf5c7a50222f2d648c25f5aeec8c2cd19dae3d3e87e944d3eb7e90d425b49ef2292de38224f1505c3f8724a9eeaa7bd0d57a60406059436306868a7803839c7ad1a158039c13f4a33a716767f8cb9b6b55e1ae2458813e9938cd07a9f42d0b4de99b4b7d1f41b58ff19b03c93ba06607fa8b1f5f619a5b8266d74a65d42da6ba90cce996dcdc8c9fff006a5a2c2635083b05ef83eb5028076341db4b1ed9f7a04651fc41db18ed419d75b744dbea335fcb0db0335f2057901c05da73c8f9d5d18a75174a3f4c47335e35da4ce418a489374254f707d463d33565d1529b569a489a17944b06ec8057d71dcd037b4b6b8bfba31584124b27e62a8a4f1ea68357f83da7ea5a76bfe0912453ccabb49194653cb60f6ce3dfda983d196cd108c2401711f9768e306b2297d73fc6d02773a8b591922693c5004bb9d72542fa2f6efde8314ff867aeeec27500b77bb5670e36ca19b1dff2e7f2fd2837ce8bd5dd348b78b552219022870d9c46e792a4f6c608a0b846c8e03232b29ec41cd0199f1410fd4b24b1e8f712c0a5e4452d851e6c639dbf3238a0afa42ba77475e4ba8470896681da45180b18da76af3c9029c8f26dc1df2b9c606e273e86b743331924f27f4a82c12280e59b008e79f6a2d4d74188ff00e30d203a82ad7519c1ff00b860d11ba7c5e86c9fa3afae6f4091e043e021270b21e01c7dcd6479ab4dd3aeb56be4b7b184cf2b301b57d07bfd2b4bad0fe25e9f6960ba7c7a55ac50cd750335ccaade7723b83b8f6e38a2207a5ba4e7ea3d93780cb616ca53781f99fbff009a0b675a5be9765d43a75a6ad3b25adb4185429b831c70303dfdfd2831eb8954ca48f3827819c71ed406b2b1b9bf9a5fc1c4ce2253238047957dc9345d122b792eee522811a495ce1157b93ed444ff0049f476b1aaf51c761345269d25be269259570c833c6077249e062a68f53e8ef0da69509d4ae225b92a04af232ab16f98cf1f4a5a266d4dbca8af13a329ecca723f51502d14f0cb9f05d1c8ee01c91f6a0393b4edfe63c8a031608859b38f97340d84d04e5846eae50f9829ce3eb400fb24466041f5e3d2823f56d22db57b192d6e61468a41c823ff0035651916bbf04ada7badda5cad6d1b72c09dc33f2a6875d25f0865d06fe2bc6d4c4d3282026cca8cfafcfd29a34cd234a10c768f711a78f1bb392a3001208e3ec69a26a58d640c832091c90706a084ea1d3eeafdadf4f86da3166c0b4b397c18f046140f5ce4d04f4702436e91c28a9122e028ed8a0a9f5a5b6a09a1bc5a135bc72cce048b3c5bc15c638f9d59043fc2db997481aa69dae49e1cb6bb643239211939e467818f97bd305965ebce9a10bc8da9dbaa2679dd9ce3d8530572cfac87566ab05ae9f1490692b9696e1f833738555f96793504df5f25945d2576b7ec16dc46792381c7b7ad5e60f234980e42f6c9c56a82ec3eff00bd4124e49700f1c646e3cd169ce9575f83d52cee324347323f6e3861ff008a23d47d4ba6a75074fdcd8ef317e2e2ff0098bdd4706a60c3f4ae8cd5f44eb8fc3e97248a638cbc73bf90483d463b373e9574685abf42a6b5649fea72bbdeac4a8d3b018cfae31f7a6895b6b29b41d30d8e9f6bbed9213e1b7a994e724fcbb5064bd7835a9752d3af75d8116354778f660788cbd9483dbb0a0cd20b2b8d43528ad2088bdcccf854039cff00e2827a0d34e9da1de896f2182492efc0976f998aa827d3d334113a74aa9a9298628e74570478bc0c7cf1da83724bb8246d3e6416b0384da61b5501c9f5c3704f152c037561a95f5fce61d3ad6db4ab950f34b331dd9f4191db8fdcd406d67a675ab4b6d325d1af248272a43430315ddec7038f6ad4b3f448bf47eb71cb69abddebf21d5e26896203846c30c8603b9c6452d9835901405660376319ac84bf13180779d8bb82827d4fb0a06f777367a75acd7170f1430a9f331200cfceae061a0cf6dac692d7365266191db0578f5edf3a6075a6c9278b3433188a467860d96fbd40fe540471409aa0c1140750001ed8ed4058e15133c983960077edf6a06faade5c5b7822d2d926766cb967da2341dd8f0727d85033d27597d62e2ee3163756915bbf8799d71e2f19dcbf2a092b88dd9a311950a0e5b70ce47fe6ac18af53f5b69da9752dd69da9ca906876e24465d9e69881c6ff005c679c0aa2bfd267a347512c93dbb5d42d90d3c800b68c9ce0ec3cfa528db74ad034db5905ee8be1ac728dc153984f3f980f4fb56453be2de8f647a6aff53796596f0aed46798ec033ce149c0fb0ad71479c9bb9dc3bf3c55a0b95f65a825150b481a407b93c0fda8a29c06671dc93803bd131eafd0af6dffe18d2ee25982a4b04603b7a9c631fad03bbe586381bc5945b96385718c827db3eb5288eb8ba934eb15fc3c535f05427796dcccdec7150637d5bd55d5362b7975aa4d0d919018adec8637807bb60723000e4f7cd58203538aefa8aeb478a7b9beba924547b8774cf8608036a80704639cf1f9855d1a7f4c68b67a03de5e5d59dad8d988c62e1c0f107a1e7fdf7a082ea6d07a6e3e99375a7cb6b3db093c727701e2360f7f53dfb50653d4130d42ee18f48b3f0232a15218936963ebf5fbd06dbf0cfa74855b9d46e04b730c6144691e12307d33ea7de8348ba6b5478a279a004f98c479247b81f5a9438805ac0be2e02e73c9ef8fbd40c2346d43578eefc40da7da1dc8b8eefea4fcb9fef419beabf12a4bcebcb2d2fa7ee0dc58492084b30236bb6467dce383f6a0b87556a67a7f4d95a0bbb5468816f0a69c78b2e072572719ce78357079dfab3af2e7a92c963b88d94abbbf91cedc93edf418aa2c5f0dbe2a6a9a0c90d8de34773a6a8da1186d6403fa48fec682d9adeb7a9b4c9d572dacc9a6c9700456e5ca910e000ecbd8e580352fb1ae7476bd6dd49a325e5a9f3025245fe961dea097523cc0919a032af039a006936c81423104649c703ef40dcce64bc3035a87b6f0c378f9fe7cf2b8fdf340a4b6e25962915d94a67807839f7a043586922b5636ec44c061063f31f6ab079d7fe19b7eb2d4efeef55d5d74f992e9a0fc3a441dcb13927b838c9aa2d4bf042c618e178efee6e18104870172318edf5c1e6945bbe1a748ea7d2315edbea3a99bcb190030c401010e4e783ee0fa56455be3d6b90c1a6268d69e17f1486900ee98ec29ccc183119419e7e55ba11f089f523ef5058363a8059fb8e31e9421b491056c01819e28d3d0ff07eea3d53a1e3b6b8db235aca63c139c0eea68ca47a9fa6ef757b83ff00bf68ad428c2f248c7a8f9fcea518df516adac74e7544f63a2ea172f1800291e6cee19ec78cd5826344e85b6bad25ba8fade5b99dae0ee11efc71e858f7e7d054a2d7d39a75ae8f7b6b00b8917f1516624b78429da327cec493db1db1d8540cf4aea28f58d6aeae2f6dd64b498082d880488d149fcea7d4939ab04175e6850a8d32de3b78e380c8de32c4db4e18e430fef543cf86fd0d691b4fabdf6648b3b2db69ce7dd87be68342d2f4fb9b5b891af1a28a2dc05bc5036d001e0eef7352884b961a2ea9aa7555c885e08d45b5bc52b61b686c120fb939fb541276bd4b61d53624d942e2f6200bc32290633e99f4233416dd3ad3f0d611c0c77b632e71dc9ef41156dd27a45addcb3dbd9c513b1dd941821bdc7b558333b9f873757fd69a85e3f813e9c7723b5d93265d872473c11544a68ff08fa75e290b42ec4e4124e70738fa5048e89f0f745d2aeadd2decedda6525c975121183c77f7a945c754d0e0d563682ed43425369403bff00bcd58308ba7d5fe13f5a05889974a9d8b46aede4914f707d88ff001528ddf4fd7edb54d1a1d56c312dab2e64dbc9418e78f5c541296d70b716d1cd6f8789977230ecc280cb7519b816f212b205de4e0843ce300f6cfcb39a0545c42cee88e0b458ddec33ee680eac92266360debc7b5056fad2d354b9b189745744be121daf27e550548ce3d4d58324d07a725e98ea2b7ff5381f5169a7579d021fe13904ee43ddfbe49038ab46e76cf05cc714f6d309232a4a98ce54fd6b2196bb7f2e9b631b2c427b891b6851db3eff002007341e5bf887aa2ea3d4f77378be381e42fdb711ed5a1554395caf1cd07617dcd04fc85402101da791421b49920331381c60d1a69bf02f56f03a925b12c162b98c955f775e47df19a32d99b518268e4491668704a79d4aeec7b7bd4a30feb7e9144d76e265697c3e2693631674273803e556087d76f35fd49859e9925ccf611141106f2e182e3241f727f5a94681a268f79ad1b1b8b9dd66b1c2b1ce9bb06361c1e7bf3fe6a096b0d3ba57488e485b52b40909c386901607d47bf7a0ae758eb69ac4d15be81a748f0a9c35cc90b2eff4c03c1c638a0b77405c5d5d45f87be5fe359a88b81b401dc1c7d38fb50586fed18ea3015790091591e447c1518c8c7a0a0a5754d8c9d49a8d9f4ee9dba0b3b5224b9692327728f627e7c6682f9a7e996b6b3a8b6b748a348820c7720761412c064e3041ce282b5d4bd73d3bd3f33daea97ac2e540dd0a292dc8cd043c1f15ba2a7923b65bb910371b9a12141f9d02edf13ba2ade56857551e5e77244c54fd0e280746ebfe99bbbd655d56dcdc9ce08465565f4ee3bfca82d53eb3a6dac3e25c5f5ba646402e33fa77a0aff5b74ad8757e9ca972844aa37c520fcca7d3f5ab067bd369a8f467544d626c98e9f7118f0200e4465c903049c8c9e6ad1b24334b6fa6249716cab20037c309dd83db03b5640dddac3764a4f02cb1103863919fa7a1a06d6f600c37162911b7b252b87dc773f1927393f4a079f868edae1ae6328a8b1ed38e30050226e85d5dc1f879011b3c47c2f604719f9d01eff4f4b83e3c6b18bb452b1cac9b8a83de80b16e8208a3b7b58e1407cc061427cc0ff1560ce7a8f592d69a97504cad2dac01a2b53900c3e9e51ea58f727d0551e73bfb86b99a49a46dcf21c96340dc13804f20f6f9501c0e3b8a0963316fcc4607007f57bd084d64dec01200ce483468ff0040d525d1755b4d4206ff0095207c11dc67ff0019a18f56584f6daad9dade4211e39104a8ded9152b235cd8c530613229c8c1c8ef50472e81690ee00322b0c100f0debdbb7ca8111ace856371358cba85aa5cc407891ccf83f2ef4048b4ad2e59bf116769672c72f99dd1437239078e2824a4d3e1b94559234110e781839fa0a0561b38ad532a12319c86c6307e740a9732a3a00cac870cd8e0faf0681be8b6db965bb909df3c85806eeabced5a09523647e6e0fef419a6adf116daf7ac34be9dd1da686e7f1ca2e243b76320ce57df9ff1560cc3e3f470ff00c78255b842b35bc6c4af9b6e323d3e95467b6365f8dbcf062beb68c119595d8aaff6e282422e9899b4f6bb5d46cda2562a76316c1078f4a0859e1b9b762c0bf94f0e84feb4125a57505c58ea70dd5d0174a986d92b1c13f6f5a0de7a5be366877260b5d42dee2d2423124a487507ebdf15289dd3fac7a7bab6feded74d61733473acdb5a162142ff00313d81ed505fa58fc6d809380c1b9f5c502e0e05040ea367a85dea454de2ff00a610375b04c16c7a16ef8340b5f6930dce9375636acf6a278f04c5dd4f1dbf4a084e91d06f3a52dee62bbd4a2b882494ced3c8a448063b63b638fde803ab7ae749b2b3096d792c93c8c109b55dcd18ce3710473ffdd043dc758dc5869044565aa5dda4c3c2b7bc78c1f14e3963db03e7c0ab066bf1327d41ba76ca6bc48ecad24c456f6b0c87cf8e4bbfa138c0fa9aa3297c83dd4e28395811cf2680a5b93c7ed413cd1ff0f3c797b8031406645236b0508406f30e68ba49c051b97d0e0e7d28ad57e19f575c5be8f269515dac772877c11bc464dea7ba8c739ce78f9d3193bb8ebfea2bcbd6b5b6b8b58bb7f13c2f0ce31cf0deb4c0f2dbad6d743d2ee99efae752d6c02a86e0054524f6383c7ff94c0b6af274c75149a46a5a82c46f1e1479fc3190bd8156fbe7f4a960bf74e9d253f1167a3ac09e0856610e3041ec7f6c540f67b892cee7f8d18368232ef2af2508c7047cf340ead5bf130accc9b1186541e723d09ffc5033bbb1b82d74d6b37f1244daa1b38073df3f4a08eeb1d3b50d4fa6a5b4d32f12cef1902ee73e523d476fde8306eb0d3fabfa4ba92c278af67bb7281606472f90bdd58558253a6afb40ea1d62283a8b461a66a6f931cf6a7c2466f7cfb939e7b5515fbed3747b5eb8f06eb78d35080a2ec9719c76f98049a0b4ebdd37d1bad869acbf0b03c5c16b29444adf50ded41995f68564a263a66b31cd02be152505493f51c1a088bab69ad1bc179e320f07c37c8a0692b46c4995f0381db39a0b2fc34e971d57d4705bc8db6c50ef9dd97b81fcbf7381528f5ae97a1d8e996d1db69b0c7648855b10a81b80f43c739c54134147b9a036063279fb5046e957726a0f2cfe04915b06db1788305ffeac7a0a00d72f8d9c491c06337533050ac7185cf2df6a06da2da4293488f34973328c34aea428c9ec3eded40ee7d2ad249448f6b133820ee2833df3fde819ea96897461b05b87815f2ee919e5d47704fa039ab079b3e326b70eafd4ef6d6650d8e9ebf868b69c8247723efebf2aa280eb9193ebedc5002a124e015340018fb8fde82cf32b1603d0678cd02406dce3008e47ce81b499c331383c9c9f5a2e9c69377369f7d6f796a4acf148acb83fb511e91b3b3d0bab745b7d45acedd8e3732b71b1fd73f7a5a19eafd09a56a0a96b1c705b49c48510761ce4fcfbd4d0d752826b2b583476fc3daacb295b79d768de8a32b1e71f989e49f6a7d14dd1af5ba275a45b8b093c054492ea769092373765c1da4679fbd306e36ba9595fe9f0dcdbcc92c33e1579cf27d0d409ea178f68521b6b76926ee8a7853f7ff140bc768d78f6f73748d1cd103b543f0091cf6efc502f7319dac194371d8b6326829f0c501d7ae6fa568d5d4942c806d4db81839f53c8cd59456fae6e628749b5bab8b1865b08e4726588ec11e7f2e49071c93da9a31dd4341d675e9a5bad374f9858162d0b4ac70e18f0573df35a0c759f87bd53a404f174f965dfff00f479b1ef570576e34bd4b4cc0bdb3b9b7258a00e846e3f2a94376475cee4914af7ca9150685f09ba61efb52fc7dd69bf8eb7c158d1d0b47bb38f37efde968d6eeb4eb5e91d6ad25b660aee59974db6881690918e31ce39279e062a5a34bb57b88adedd1e379679065d80036679e6a07e8391bce7e940c659ef5afe1286de3b16f2b8903094b7b2fa7ce81eb380c4260ed193f2a0cd6fa5d4a4ea0fc7bdadcce923158a3039db83c038e3ef41a0e96b2ad8a35e009291b8a939d9f227e43bd590436bbd6fa269202c974b7123602c76e779624e00e29833bf897d493e896525dbcb2a6b5a9c3e1456b91b6d60cf989c7f31f7a60c02490961ebcf3eb541308e39e067b507007b96007a67fb50178f97eb4165ce18165c2927b773fad023202d9c8dbb7818ff003408300b87f2f1c107d0d0c15a4f2e339c90467f6a18bdfc2cea8ff4bd561b4b9ba686d6e64552c4f954e7d7e46a60f4688d240af1b2bc6cbf5047ca960617ba658de1b792f2d94a5ab33461b18524633fa1a81b5c8b5168967369d23c0e0a24622dc981d81c76aba29df0bb48d660d52fceb88d069f04aeb69130037127f37b9c0ed9a8350781240bbc06da72323b1f7a0eb8816e633192ebc8c9472a78fa50349b4c83c068e24f0ddbcc1c13b837be4d055b57e98b996d4db5b4a893dc1e6620b6ccf2c467efc504ce97a38d3f4d874bf09af6d46e2f25cb82724e791db15650a43f878b51fc34f3da8f132b6d6a98c80a39ff007e99aba249631b58b9047239ec3e55368aeeb7d2da6f52c0eb7f16e87f2c6e836ba90724ab7a67b55d115ac7c3e8aed2182def4c56a14096368959a423d77e3229a27b41e9d8343b01069c8a8dc9660aa3713df3c64d4a1c695d3d6b67a8cba94b9b8d4e61869e4e4a8c636a7f4afcaa09a485519caae19b966f7a0435196582c656b74df3e308beec7b50629375775b691ac5bdb6b16d6378779f019b00a31cf391c9c2f1daae0b35ef52f5374de88d77aa45a6cd25ddc0108694ee2188c28007603d6a0d16c92430a4b2ed3230dc401855cfa0a0a07c45d7b5db9d462e9ee960b14b2ee134ef8c850012147ec78ab0670b643a2efae753d72686e6e2da211db42176079c8e768f65e39f7aa332d6f58bbd635096f6fe6692695b24f603d801e82823cb900ee00e68006460051dfd680ed9f0c905b713d8d006d5f5419fa505a18f94e40501b1b81a04186d62402c87be3d6810b81290aea8467201231cd1749dbc437f9f1e201db3de8ba07dc0175c027f28a335b17c26f888d6b6d0e8fabf892a29c453b1e547f49f7a946d6424f08236491c833ee0835073294888894120700f0280813c40a6711bc8843e00fca7d3ef40e41dc081f9a811681c6f7565329185623b7e9de812b3bcf11ff0b74563bd50494cf120071b97e5fda80d7577046c9019d5669dbc340324eec67fb734103d5da96bf67a7cf0e916f6e2765f25ddc4c11107ab1c8c647cce2816d3ec7f0f6564cae6e67da375e6d52cc4af2e4fb13ed4145f899d47b3499f4bb6d46cda49b69b92921565c3648e3dd40c81cd5c0ae89f13ec246d3e379ed2d6da180b5d34849da1780b128e49271c9f4a60ba685d5fa36bc42d95c324ec7090cc9b1d87b81ed50588958977cacaaa3b9341c655f12348d1dcb8dc1946540f99a019e2134454eeda7bed3839cd052fe2136b536b5d3563a1ca53c49da4b9507198940ce7e5c9fbe281c6b7a974cf4ee4ea7242d76dc784a3c595b3e9b464e3f6ad0ac745ccbd4fadcbabea42da56959a382ce7460d6b1a93c01f97272093ebf6a82f1ad6af0e9da5cb3cecf6902216919f82aa3818c7a9f4c530649a9f5269ba7429d472239bc991a1b0d3c3152880f0f23039e7bf3de90635ab6a377aa5ebdcdecef2c9239e59f3827e5ed54302195fcc38cd01245395c1f5f4a05b606538e483c501b6939e3b5077860f3914165754c33e549000dbe87de813b820c27fa7baafb8a04a69c98e281e42618c795338033df1f3a06c03e4e029247007ad010093c35674da71f977640340081a190658e41c820f141b0fc33f8926c218b4ed609366a02249bb2d19ce3ea4528dbece68eead926b7916689c643a9e0d643387521fea2f693c2d6efc786ee46d9bfed3eff2a04669edf5295ff057a60bd865309246d3bbbedc1efef41d63a8dec9ab4fa7dd4510fc3c69234ca186e2d9c003b7a67bd034bad0a5bb96e25d575267889cc1b54446d9bd0a37bfbfbd02925945a72cba8dddc48b3f87b1e58f23c623f292bdb7fa7cf38a0a5750f54ebba56a9a67fc516b6d6fd3970ea9234677c8dc7f38f6e4640ce282d1ac4b16bfa72c1d2bad430cd1ba822061865f5007d3daac19cf547c189357d561bbd3eee683c62cd786e9b73337b8c7bd512bd39f06adedec2de0d5ae639da372e6485363107f97767b505cee755d03a5e58ac228659af123184b7b733322e38c91dbf5a943ab3d52e64b49ee755d2e64950e238e35f10c884e17cbe87dc540e6d7509a4f110e9f7566a471712850abf6ce463e6280bacea36fd33a4497f773cf32c698dcc4beee33938edc7ad05534aea683ae61d64c4d2a69b6b88d16d5ca5c303f3e386cf61db140e27b5e99e96b64bdd562b6b30aa36c6c37cac7dc9eec6b42c1a66a962fa70beb6b516d0cbe76322f86c78f6c66831bf8b5d5d2dfa35a5dce60b1933b6ce3c788769f2b331ec1b8fd2831b79649984b239773c1dc68129725c1c640e73400ec781d8fb1a03c4a85d0c8582640257bd01e51fc42236263c9c67be280429c6037eb405dbf5fd682c2a0bb976cf07d3fc5009279ef8ec4e68193a9902b28e7dc71fb501d95b098e0f6dd9e0d0049131019b047b8390281bb292484e47c8500c4f242c3076bf704704739a0be7c3febfbae9a5daf23cd017c7e19fb107bb67d0f6fd6837cd2757d1fab34f4f05e37dde630b1c3a91edf4f7159103d6eb7da65fdbdf59dadb5e2460ac876ed9e1c8c060f9efe9c8a0a75cfc42d5742d2ee5a7e9dbb494b6d6b9bc930cce4f940e3cd81ed4160e98f88315e689fff0022b57664199cc5196f0c7a164ef8f98cd0589baffa68590985eb15c0db1985839f6c2919340b69d03f5285bdd6f4bf021424db4329cb153fccc3d09c76a090d3340d2f479a7bab3b38e2924e5e451cfd280d7dafe936f6c5e4bd89813b02a36589ce318a0358dc35cc4e17f9bf234cdbb78fa0c607a7340e6cec20b1596610c6934b8323226379edda81da8dcb9ec40a042f50b5bb21645473b58b11dbd7bfca8304f8add5d67a9ea8ba5d8ea72c1a4d8a952f10f2c920e368cf71e99fad5833dd0754d6ed66bdb2e9a91a5babb2a310465a57c1ddc1038e7bd5171d3748b8d46ee1ff005298dc6a764c27d4eeaee7fe1c01795881c9e7804fe940dbe287c4b6d75a1b1d1c986d62277c91bf131f4c0f6fad0663737135d3b497124924871f98e7803007d2811dc5b83903dc0a0333f03be7de8122df2c9a05a11e5f51f7a05ce7071804fca8033e5da0734020b0183bb23e5416269577ed0e5323078ceeefdff6a03dbcd62914c2f629a47c622689800879e4fbd046f9d8a2a03e31385c0e73da8b83ca590947dcaead8208e73da8849b3e19ce704f7c5015586d006431f5cf61f3a04ee586ff002481c8fe6191408f0011eb8e30682774dea9bbb5784492ca6385832e1ca95e3d2834be9df8c312e2db5eb4375080337000f1303d18763591a469baef4d755989ec6f6dae5a23e20b599406dd8e080ddbed41272f4dd8caf1c86d163910f9595882a3d718a035edd695d3b6a926b57d0ac65b10b4e06eedd863bf141077fd7af2782bd3fa26a1a8891d57c630948c0279393dcd04cf5875258f4de9f0cb7b7b6d66d2b81ba752d85f5214724fed41036bd79d2fe319d7a8f4b9c81e58de2f04827b9ce09a07a3acecf54b790685ace8697606009e52c377b7f2e682b097d7d36acf0f55df5edbdc0977412468cb6ce3be10af3c63b9c8a0b0751f505be9690dd5d752436f62a3fe4c6448f3b7b0c64e38f615734651f107e3045ac42b67a7693018633b965bc1bc838ee173807bf7cd33065baaeb1a95f2c11dfcd2bc51fe48880aa3e8a062a8b059f595df4ae9a74de9e9ec499d43c97b1427c6e47e525bb63e4282ad3ea3712893c599dbc4259c1627713c927de81043950df97db1406da8411c92063be280230839627078e79a0390a71b5bb5003a8c1232338e4507025573e9fbd02a0e41dc0e680c3691cf714053bb34160895dc16f291d98d02322aa39f3e14707ffaa06f202a5bb0c7201f4a343aca51090497efdfbfce89840c8db8e46573923ff14410b00490d9f5c1a0425dd8ce4673e873cd0265e4dbe7041ed814009b8cbb8e5863bd07163b7716e0607b6698060b96b7b9478dc8643918247ee39a60b7e97f133a8b4e0c63d4ee597380923970a3ef4c0e13e25dfcfab457ba95bdbddb212016501867b9cfbfda982f907c74b282da34874a9048aa479c83838edc62982b7ac7c42d235cd67f15ac5b40c366418a2cb0c1c81e6f5e31db14c160d035de8cd4a3f18ea96562cc37359dfe9cac887fef039fd6b39446f56ea5d13a9dca4579a922496b1975b8d22dfc3566cf9557230703be715ac1431d4d2275325d7fae6b4f6f182a93ef1e32a9f41938f6a60afeb1a95c5fea53dccf772cf2c8c489240031f627e7565c0d67bbf160487c1801073bc0c31f91f953420f2bc8c7c52cc540032738a809905c0f4fa501940208e73df34028e703938a0577ae013f4a001300db4f03b71407461ce0502dca8c9c7dcf6a003fafcbdcd0070bc1e0fd734070db467b8a04cb9c9e68274b93bcb1daa40200ed4099765249ec476cf340849b8b264823bf34689ee009cb671df1409bc8e8b8e770e3ec68984d9c953cf97be2860b248caaebc107dc67f7a184c31232db88fd451031ce50e76039f5c8045026efb8f93279e0fd680b239504f0483d88ef409ee25bb90c79c0e050151c6e21b39ce783eb40adbcc2cefa17bdb61322387781c950e3dbdf9c8a066f28790b22e013db3dbef54726081e63c6460d34191b1bb0720f634060e7600412c781502409c8e3d7b500ed71dbef8ed40243f181c0a02e5d4e0fad006f644e4819e3b501f7e3049e7b501bc43b4e391da80558003392d40a23305e320d02e64cf998e1bf5a032b0c927b8e68049c8c8e71c6280377043118f4e680bbff00de0504ddbb3128371c1c64668024e59f3cd02521254e4fad1a2107e48fe6a6809ddb9e78a029e1463d05027ffc744a6c3857c7b1a205ff00e637fbf4a02b12b1794e39f4a02024e7249ed409924720906800005173fd7404989698ee39e4f7a04cf723d07a501fff0097ed406ffe36a018ff00281e99a037f4d0731f3bfd28007e53400ff99a810248c0cf140bc60123233cff008a0557f9beb4056eff007a07109243e79a03778b27bfbd02b128c27039a054001b818a06609de793da815006070283ffd9}\par}+{\pard \ql \f0 \sa0 \li0 \fi0 {\pict\jpegblip\picw250\pich250\picwgoal3000\pichgoal3000 ffd8ffe000104a46494600010101007800780000ffdb00430006040506050406060506070706080a100a0a09090a140e0f0c1017141818171416161a1d251f1a1b231c1616202c20232627292a29191f2d302d283025282928ffdb0043010707070a080a130a0a13281a161a2828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828ffc000110800fa00fa03011100021101031101ffc4001c0000000701010000000000000000000000010203040506070008ffc4003e100002010303020404040502050500030001020300041105122106311322415107617181143291a1234252b1c115f016336272d1082443e1f1265382ffc40017010101010100000000000000000000000000010204ffc4001b11010101010003010000000000000000000001110212213141ffda000c03010002110311003f00dadd18a10a704f6a95ccc57e37750782b0d8d9ea0cd32e7c5446e07e9f4ad723119a7b89e61e348f260719278aad613cbb640002938c76a182b264fc87bd13009c0c019c76e3d68a072e1cf6f4cd502d330c28269a61bb39c923923d4fad44c08dccb95cfd28b8280769ee08a263891e1808739e4f1d8d149392172cc714050dbb9fde8960ed8c60b79b1ed44103b05c331dbdb1dc5026ac1946d20ff8140aa631c773ec738a0346a003bf93e9cf02801895e7b9a01886796c923bd0090a06393c76a0142003ce3d86680d8dd9392303f5341ccc1b3cf7a2c812c37e4923d381429757013209fa511c18146c9247a0f6a007900c0c671c6280854e086c673eb45c27c038fd68aedff2fda836ef881f136f25d5e6b7d1262964aa02b03f98fbf153131935edcc97576f35c33349212cc4f39f7ab26186dfce5b200f73451f7600dcb8cf27e7400c0b291914046c9e0718fde81371b8e7273f4ef4007691919240e714097f31f376e7b5008caee27807b0f5a02c8e1b3c6d27d33cd0201d839523144d1a149ae084b78da47638211771fd050d582c3a0faab5119b6d12f8ab1c06788a0fd4e2ac356fd1fe08754ddccaba849696309e598c9e2103fed1dcfdeadc44fea5ff00a7f956366d375e492403ca935bedcf1eea4ff6ac68a55efc1beb3b552574f8e7009ff933a927ec715bc82b3a8f4d6bba5ca1352d22fe061cf9a0383f71dea5119cc6c0baed3eaac0f1fad40897dcc3d81f7a052366c1007df3400f21edefc5008c28f30c9c5170ee4fc37830086395250a7c66770c18e78da31c0c63de8609b41f7c515c5172a30c3b76344a3e377cb2339cf7a242aea89808cce368272b8c1a2e107c672a49f5c1a181c9c7ae7da8a2119e7b1f5068099ffa68258a132062d8f9e0f34059502b61bf2824e681bb297ced2a71efda80f19c47b9c77fdbe74057c13e539cf3c1a0eeeb9c73f33405ddb4f18249c1e28062b79ae242902024465b9214614649e7bd0362a7249eddc513456e5720f38f5a1a98e96e95d6baa6ebc2d1ad1e65521649bb469f563534d6d7d31f04347d2a2fc5f535db6a0e83718906c887cbbe5a9a8bef44dce9f731ca9a2e89169d6d6f2184b1455dc07b11dcfeb4d16f119c649a681285b03d3e5500f87820ff006a0e098191de80ac9b8904647b55d11da9681a56a31f87a869f6970b8ffe4883629a289aefc16e92d441682da5b098f21ed9f033f353914d19b751fc08d66cc16d12fe2bf45ec92ff0df1fdbfb559ec667aff4eeb1a04db359d3ae6d40eccebe53f46ec7f5ab82263da7dcf3eb5174e5181076918c7de869503232491ee4515c1803824f03b51287f30e0e7d803449494832c157278a2e8c71fcb9f9d144639236824d01e142efb1768cfb9c7ef40512a818de78ff00a682518e7cc30ab9e00a02cce9953247bd41e467191ed9a04205ee99da4e4e3d283a524b0427b5026c18a8e082067db8341ce0e39ed409b6502907391edda80f2dfdc496f0c124ac6184b144cf0a4e338fd2894f7a7342d4ba9b568f4fd261f12571966270a8bfd47d8511bae85f02b47b7fc34bac5d5c5dc88a0c90ab6c8d9bedce3ef4d1ad691a6dae976a96d616d15b409f9638d70054a1dbc68ea51d4329f4619a8022b78e04548515117b05000a035c5c4702a995c26e3819f534047bcb68a458cce866719540724d02e41c0f7a012a40f6141cbc8e7bd01719e38e6838af1c0a04ca8206d3cd037bdb082fad9e0bd8a39e0718649141047d0d5d18f759fc0cd3af164b8e9999acae4e4f81236e898f7c0f55fed574615aee83a96817ef67abda3db4ebdb7f66f983d88a061bb8db9e3d45165076db83c1f950a53780d8247c80a2398f182724f1c7ad080c608cfa7a51a0062adc7afbd0130173bb9c5070f071cb37e82826106e8f615e01c9e680d6b35bc534be3c1e3831b2aa962bb188f2b71df1de819ae4b1048c7f57bd01a58268e332642ae0704f7cf6207af6a01b99e17b7b6416e227407c494139909ed9f4c0a04a4e501e0f1eb40d263e53dce7fa682c9d0bd13abf58dd6db18bc2b157c4975270ab8ef8f563f21447a73a03a1f4de8eb031582b497328066b97fcd21ff038edfde88b7e32703bd64188e7e6283864b73400cd804b67ca3268317eacea6d56ff005233592f8b6303f953fa4af7c2fa93417fe98b763e0ea171297bab98558068f695ce0e08fdbd281e5c6a57ba5e9d14d716ef7774f2ec112601da4f27ec2827ada74bab559a20e148fcae36b0f91140283729c77a0e0a7777a01dac68395719e39a029607cb901b19c501480ab9279f4a086ea8d0b48d76c0586b7143224a76c61ce1831fe93e86b43cd1f12fe19ea7d2533dcdbeebcd20b612651e68f9ece3fcf6fa5067cbcf20ff009a051724905411e94032799060723da8406d6c67e7ea68d0e1770fe5cfb5026c37039ef9a02eca098c91e6e01e71c500b1d8a49c12786cf6a06a4e256008e3d050119958007920e2801154e32fb4120927b014017eb1c523ac5209a356215c291b87be28957ef853f0d66eaa99352d515e1d190f947669ce7b0ffa7e74a8f4be996569a5d9c56b6704705b46bb5238d42851f2ac875712bc70b3c30f892019540704d01ad2669a0491936330c95ce7140b2e4939a03638c7e8680ae485e33bbe540d60d3ada162c90a02c7270a39340a4f28b68da4645007a8f6a069a746f73235ddcefc391e12b2e1916824948742c99382473c73404791c617695279dc0640f9502c578c9efeb4095cb4cb0830ba21cf999c6401f4f5a05061d430c8079a02e03b3004311c7d281b5e3cd676c65489ee594e4aafe6c7ae07a9a0a075bbea3a8ea96f047d3935ebc404f04ad29411e08e011d98fed416fd212ee5b05b4d5ad6300c615807f1171eaa49eff5ad418c7c55f8466dd66d57a521f20cbcd66a7247a9283dbe5418a63862479877cf1f6c5008e400bdf1ce684016fe53dfbd1a73794600e08ce3d6800377c8c7d6800a9cf75fd4503d91492460f7ee3d28247a7b459f5fd592d22711c206f9e563858a31f99cfd050583518ba75247b1d134f9aed21396d4669769931dc01c003f7a329c4d17458ac5b55d36c12e040a3f1da75c1cb04ede2447f7f6a94567ad7a66db4fbbb29ba7d65b8b4bd8ccd09c8231eaa07b8ab04a7c2cf87b3f53ea8d77abc72c1a5dabe2452bb5a561fc83e5ee7e541e988218ed2dd22b7855228d76a46a00000ec00a510bd4dd511f4fe84da95cc31f880022da4902b1e7d3e99ac86fd03d631f565b4ee6d4dbbc649009cab2e48c83f514165b8b94b6895c44f279c280839e78ce28178ae6de46748a789e453865570483ec6812d42e85a421fc37918b00a883924d024c6e99b7a2a966c0009e17dc9f9fed40f81c77e28139218e4ff9815b9cf23340a01c907b9140201038ed402fcafd28386464e4fd33c50272bc60032609cf00fbd024f722dc66f24822ddf972f8feff00e280f69b24844919cac9ce7de83a447f30ded823007b50459d6ecacb528349b979127651b1dc795f1f3f7a0990148054823dc5015d491c0a0c3be337c2ff00c489b5ee9c87172016b9b541c49ff5a8f7f71eb560c1fc43e0a47e1aa94277310431f91fa551c1727f29ed409b641c86e31839a3454805739c1f6a026f1fd740f64665fc8c31cfde82db79bb40e9e8f49b62eb7d7e8b717ec832c91ff247fa1dc7df2281bcc9369d671493c422b7911654c1215f92bb8827bf068624ba635392df5eb4b9924558ee5bc19b71cee43c6dc7cf34c657be8db0b0b9d0f51d2afe668934dbf9628ddb8c2b8c0073f3a80da37546a7d25174fd95dc125c69f7313ee5655dfc313bd483cf07b1f6a68d5b48d5ec758b612e9d7293211c8fe653f35ee2a084eb9e8bb1eafb3582fe496278f3e1c919fcb9f97ad03ee8dd017a6741b6d3229dae161057c5750a48249ec3eb4139238568f6a9e7b103b5037934cb3793c610a2cd9277a8da73f5140ee38f6280c4b11c65b934023006d50050030e4647de80c846de3b500fcf9fbd0197273ed4007b91400e580c8e45074a82400e72682b36fd2162b7f25ddc09af2766ceeb872db79cf00f6a0b3229550140e07007a50092db860673de818df473c862686dad6470d9cce3b7b63e740fa1de6252ebb5bd81cd00bee2d800d003a6464004763ce683ce9f1cbe1f1d3a67ea1d1a30b68edffba814708c7f9c63d0fafceaca31e6dc71e1f07daa82608c83819f7a1a11ce149238fd68d0a579ec682cfd27a7c3a86bd10bc38b3b756b8b93c1fe1a8c91f7381f7a034f752ea5aa5c5eb292f732128037619c018f6ec282e5a2cb047abda74d5ce9b6da80f136de4a496219b3e48c92000323ea73467519d3da5bb757dbda410ac90c77c23058f99007ee7ec31416882ee47d23acb5185caf8bab4691b1efe57fff0038a9457ee75a82f6e7429350466b482f2742c0f74241c80c38c64541a9cfa1e89ac0177d33ab3d8de28f2b5bca429f91140e2c7a9b5ae9fb85b6ea9b46b9b3c796fe040768f76ec0fafb1f9505df4ebdb3d4edd6e74db98ee216fe68ce47d280648f75e2485a44da385ddc13f4a025ddbdbea16a633286566ce55f9c8f6c502ad750db2c514f30dec428247e6340bbf04100b73402afb943ed2b9e30683836defe9403bc1e06734020e06280cafe8683a375941d841c77c1a0151b467b50159f00e4127e5402872371040c5046eb5aadbe9b1c02e2f6dad25b89047099c677b7b0140fe3f1010afc803f3018e68160c3041ee2823f5dba92d34db89a1d9e2843b03b6d05bd013560c1748d57aa2797c6b35bab78e6959dc47231580ff336dcfb03c1a58364b5bbb7d7fa7b7427f1f673830c8664285bd1815238fad20f2c7c41e979ba43aa2e2c1cb1b663bede438f3a13c7dc76fb5515e9065b851f7a02950002a09c51a1b83cf14176e90d3645e9ad7752752aac23b3439c066665c827e944d29a6410aea725c4567135bd840d3c88a723728c29c9efe6c50d3ee9545b0bf8ef2e6e3c2fc2c6f72f2920e5f19039ee4938a9a875d03278377acf52ddf867f036ef71923932bfe51fbd3475cdc369df0db4fb389d4ea37970fa9cc0b00511795ce7d4f181eb4cd2451755fc45ac16d637381b14ca36b641dfce723e4053170d6cb52bbb362f6d3cb19241f2b9029862f09f143549ba7e7d2eef6caf2797c66ee17fdfd69862d1a069da7dfdac579d17adcda5ea9e1a992376c4723e39e3b024fd7e94c458ac3e25dee8d31d3bae74e7b79002bf8b8549471db38f5f4ed4c165e943a06a328d4ba605b4b22a1523c420c64fbaf38a82d36f0ce7cf7463790729b53017e940e0b0ceceed8ce0500e1b70daa08f5c9ed41d271cd0132476e7d7ff00aa069797d2411168ed9a41fcc858211f73c5075acb25ca6fb82aa31e58a36c81f561dcd033d42169e158ac64b98151b3981c2966cf639f4a064c7a8ac55e4865b7d493701e1c8e52403ea3cbfda827e390ca3f2c914aa81991bd281cdacc2747215c60e0ee5c67e940cb51b0b2bcbd824bfb08ee1a252d1caea1821cfa67b1fa504982b2283ce08f518a08abb82f6dd0369a5662081e14ce40c7ae1b04fda82275cb0bfd4f4536f7114589a5412461f3e4ce4e0e060f63f6ab2893d3b4b5b5b78e22ed22aae3cc3cc7e64fad3449a22a461500007602a0cd7e3b74c26b5d2ad79147baf34eccca40e4a7f30ff3f6aba3cd0543267eb5427b86f1f4c76ef45d0eca1ad5ef224d13e1cf4fd9b22192fa67bc955f8c8c617fba9fb510d7a6ed3fd43a735e5b54964be658c048fb6cdd9e7eb8a186bac97d174e6d22e23437b7ac26b95e77c68bf950fa7279e2b22dba45b59e97a669fa4ea36aeff89cea9a90451fc355ff0096ad9f4ce3f41570675d4fa8c77da8de5cde5be26bc653171ca47dc1f6c9fed5562b97f70276808da7c24f0c1c63804e33fa8a2928c0e0383c8f7ed41d92a41393f4a2548595c2c37493db4cd04e8a08f139566edfef3445b6e7aeaf65d2df48ea2b11776ae02a93e564c772adef409f4ee8ba9a21d73a36fa579ad9f325afe599171ed9c30a960d5ba0fe2843abb47a6f510fc26a4c36890f9558fcc6783506a1147b510024e30339ce680d2c6ae9861eb9a009178a0205443b989e39cd01d8075e3047ce80563057ca381ed4011c4531e503d85013c91b804a21279c903341131cda8c3abdc8650f6d20c4321232adec3dc504bab2c113c9293bb1963df3408dd4b75e1efb2856463dbc43b4631fad047e9177ad4fe32ea16b1db4b8fe1aa92571f5f5a0916bc8e0895af5c46c17cd8c9ff7da80f6d736f7f6915c59cab35bc837238ed8a072a31c1ef4062870718a06f7702dc5b3c522ee4752ae0fa8230683c75d6ba3b74ef535fe984929149e4278ca9e47edfdab42058003763ed409f88ffd6dfad06b1f12ae612fa0c76e0b471e9916d23f973eb4158d3efeff004a984da5debc1295d8e4018dbf3145d583a2ad96f356bbd7f5d90dc59587f1e79a6392f28fcaa3ee47159444ea3aa5ddfc7acf50dcdc344d7a4dbc317f52641200f6000fdeb41b5ef51d8eab672ffa9e971c97c11638268e431a46000012a3b9a351567db823b11f3ef40948e428048207a8340ab48ae83cb83ee0f3428a982719edf3e68c9cc97d3fe15ad8c9be138f2bf38e7b8f6ef40f7a5f55bdd3f56b46d3649127f1405f08e7249c76f5fa50689d48ba5f545cdcbdb462cba9206411b2b055bb07d4fb1c73528d4fa8f52d62cf47b6b8d2e65fc458c49f8a818795c151939f977a823ba0fe253750eb7fe937b04293f9f6c90be41dbdc7ff006283473c1efc1a06f69776d73bbf0f2aca32572bc80470450284a46dfca19f819f5a04e799614def26c0bdce09cfd85045dc75769d12dc3c3e2491db0dd3c85195235f7c91cfd066ae0cdba9be31f4ec61a386c1ef9d4ee473e45cfb1cf34c101d3ff1ac9d481d46c628ed24751881880833f988e7b0fa5328dfed2f2def2ce2b9b79925b791772ca87208f7a60182ee2b95cc0c48f53823fbd40ac658b30f4f4a086d4ee1d75bb6b78f4e965596366fc5211b23238008fde81f43692da5bc30d97831a0397dc09e3d714087506bf61a2c4cd77324726d2caaec141f9fd2ae0c435bf8c57173ad7876f7a2daca10489121244cdf319ce3dbf5a834fe81f881a6f57bcb6ba7c53c72c11873e28cee1db391dbef4199ff00ea4348116a5a66a8a8a04aad04847a90723f6ad7d18c312ddc02a3815423ba0f63fa541687bd9efe1b533b3c9e0a78473e899e318a09bd0ba6eef543e3b2bd8e9b10064bd9e4da001dc81401aeeb29a984d0ba7d5e1d06d4e6594f06523bc8e7f5c0ac8af752dfc17d7090d9218ec6d9447129ee71fcc4fb9cd6842ab10dc0014f3e5a2c1704b671dfdc734525226dc939e283a362c7f940344a380393df144733e2276e38f5efcd01b4bbbfc3dda4a9298a44395902e4a9c70682660d4265d62de40b1bdc1545054f95c8fe627df141af7c3af8808f3dd68dd5d2a45765884b8908d8c3b6c27b7a77a945d7a5fa474bd2ba8e4d5748b28624955d5d8b13b79ee9e983d8d40a753758c7a46b96f6114725dc92279a2810b3a64f94900763cfafa503fd3b59b79ed84da34713c0cd890f0a158fa1f981de826e1b548959fc4dc5cee24b6467e59ed4101ff19e9f676baa5d6a72c50adb4ad1ac790ccc076200f7ad41e7df881d79a87576a5f87b0f161d381db1c2a36e7e6d8ff3416bf87ff082c6f208ef7a82f22b9761bd6d619785f6dc477fa53705ab57f83bd297ceb1e9caf67708db9c4526723e849e3e94f212dd25d117fd29a8c09a76b534fa39cf8b6b71ced38e36fb73417f52e64548e34007e673e9f21ef590a1c918c90718dc281a69b68f67118d9da5058b798f6fa7fe280daadd1b2d36eae70710c4d263df0a4d583cc7a668fd4bf11b5837d7c93dcd9a3146959822a0e781f4cfa55161e9dd7fa67a4f55b9e9aea3e9f81fc09ca0ba118998fcdb2338c7b528d39f4cd2ba76e2d357d292df4eb391809963420ce1b1b576fa1e7359119f1eb4e17dd033ca172d6b2a4df303383fdeb5c8f2eef3bce4e0e335684cb0c9f354160d36f64b0baf16072b91b5f03391f43c51aab23a5debe91c4fad4d73689e6fc3a290573ff4f03e59f4a3280d67581ce916567f84b58ce0a1fccec3d58fa9a084de08c90464e4d1a8e419059b201f4a05630a176918efc50176293872c17bf14042aa0125b03db14046c60b60123fde6827fa0c68edd5365ff11346ba6292ee64194240c807e59a32b7fc51bfe8bd5ed5db424860beb62b89218422ce09c11c01dbbd0660ae110bf1bf2154838dbebfefeb41a8f4cdac7f117458f4d9ecd2df53b4cf81a822808c47255c0f7c8e7fb54a2ec2cfabba3b4b4b8d3af12eedad40926b0f070a13f9b633649f7a82eba6ea4357d321d4ecad512daf20df26e016507fa4fbfaf3e98f9d067dd2bd2faac9aa4d72d72d1e9510ca46a7631c7a320e18f1dfd7bd059afb7da816d23de4ba5de211346a1e4785f190548e4648c63b64e6b43ce9d5baafe3b539c5b452dbda46c638a167cb281c73ee4ff9340e3a3fa5f5aea4ba58f4bb57dbfcf2b02a8bf7f7a0de3a5fa0b50d2a2d92eb3e048c0a97c867dbedcf6a944e5cf4f6b76d1b3d8ea42795066266c87c81c65b9cfaf15048e83af3cd64abac08edaf01546c38dae4e0657ee6826e5b892de3702292e2545ddb55700fd0fbfca81c4b3bc718716eef9eeaa402280d14ab3c0b2c65c06fe571823ed40df56b217fa6dd5ab9216689a33f2c8c558307e83b8d77a37aaa7d22f2512c28768800c9954671b3d33ebef568d0ef7a7749eb0b5bbbb162d657b32b46d2e1564c8ed9c5644d1b0b9bbd261d2a440af6cb0e2e5b1e7dbc1238e0f7a0375b696daa7496a3a4dac8a92cf078685b271db04d391e40d5ec4586a1716de2a49e0c8c85d3b120f715ba1899173ff305413070abd89cfe9f5a2d3ee9c8639fa874eb6b804c52dc46b20c9f302c3bd11e84d47e1af4d5dc6521d3e3b662c19a58721ff5a9a321f89bd27a374b456d158dccd34d333332c9b4b2afbe47a7cb1f7aa33d2bc0d8c0f1c8f6a2c14b6d501b39cf63450897380c319e3de8065031c038f7ed40d8faf1ce41e4d004876a8dc3cc7e743025c956c818028c904579e7f0e15695c9c0541924f6c00283d0bf07f42d6b48820b8d62d20b2b58d656404959e52f83c8ff00fcfafbd4a35bb06f12391a48dd55cee2b2f3818ed8f6a8158a159890f02242079147623e631c502b0db436d1ecb7458d4738038fb0a087d6eeb508f48bb7d32d95750752b6c26c905b3ddb6f61eb574794f5cb6b9d0fa9678b512b25d24bbe52b8c1638278fbd582c57ff12afaed45b5bc0d0d8a8c08a2731ee3eec5793f40450466a1d59af446293c186cd53ca0c36eab93dc649e49fbd048e89f1675ed35e301e293919dcbf9867b37cbe94a35fe94ea4d33aba6824306dc48015750d86c6e247b0cf63591a40b8dc23fc30f14138dcac3000f9d03687547f12e8dd5af816b13148dddbcd29039c0f6f6f7a0eb5d62caf5636825db70c9bc4328f0dc0271c8a090627d3073ce681acf6505ccf14d35bc2f2c2731bb28254fb8a075144a83ca806792400334049ee6281e2496408656d880ff0031f61fa50446bd76058ea1b9e21025a3bb48afe71df9c7b71de9c8f196a0de23ca7b827d4f7add117e0cbfd4b5059392369663ff004e71c51aa97e8f555eadd258f2bf8a889cff00dc28cbd0bf123a926e96d163bdb74490bca2321c678209ff001591e71eafd7a7d7ef45cde2c20aae144638033fb9ad2e1b5e69d058da431ccf21d4a5c3b4631b62523807feaf5c7a50222f2d648c25f5aeec8c2cd19dae3d3e87e944d3eb7e90d425b49ef2292de38224f1505c3f8724a9eeaa7bd0d57a60406059436306868a7803839c7ad1a158039c13f4a33a716767f8cb9b6b55e1ae2458813e9938cd07a9f42d0b4de99b4b7d1f41b58ff19b03c93ba06607fa8b1f5f619a5b8266d74a65d42da6ba90cce996dcdc8c9fff006a5a2c2635083b05ef83eb5028076341db4b1ed9f7a04651fc41db18ed419d75b744dbea335fcb0db0335f2057901c05da73c8f9d5d18a75174a3f4c47335e35da4ce418a489374254f707d463d33565d1529b569a489a17944b06ec8057d71dcd037b4b6b8bfba31584124b27e62a8a4f1ea68357f83da7ea5a76bfe0912453ccabb49194653cb60f6ce3dfda983d196cd108c2401711f9768e306b2297d73fc6d02773a8b591922693c5004bb9d72542fa2f6efde8314ff867aeeec27500b77bb5670e36ca19b1dff2e7f2fd2837ce8bd5dd348b78b552219022870d9c46e792a4f6c608a0b846c8e03232b29ec41cd0199f1410fd4b24b1e8f712c0a5e4452d851e6c639dbf3238a0afa42ba77475e4ba8470896681da45180b18da76af3c9029c8f26dc1df2b9c606e273e86b743331924f27f4a82c12280e59b008e79f6a2d4d74188ff00e30d203a82ad7519c1ff00b860d11ba7c5e86c9fa3afae6f4091e043e021270b21e01c7dcd6479ab4dd3aeb56be4b7b184cf2b301b57d07bfd2b4bad0fe25e9f6960ba7c7a55ac50cd750335ccaade7723b83b8f6e38a2207a5ba4e7ea3d93780cb616ca53781f99fbff009a0b675a5be9765d43a75a6ad3b25adb4185429b831c70303dfdfd2831eb8954ca48f3827819c71ed406b2b1b9bf9a5fc1c4ce2253238047957dc9345d122b792eee522811a495ce1157b93ed444ff0049f476b1aaf51c761345269d25be269259570c833c6077249e062a68f53e8ef0da69509d4ae225b92a04af232ab16f98cf1f4a5a266d4dbca8af13a329ecca723f51502d14f0cb9f05d1c8ee01c91f6a0393b4edfe63c8a031608859b38f97340d84d04e5846eae50f9829ce3eb400fb24466041f5e3d2823f56d22db57b192d6e61468a41c823ff0035651916bbf04ada7badda5cad6d1b72c09dc33f2a6875d25f0865d06fe2bc6d4c4d3282026cca8cfafcfd29a34cd234a10c768f711a78f1bb392a3001208e3ec69a26a58d640c832091c90706a084ea1d3eeafdadf4f86da3166c0b4b397c18f046140f5ce4d04f4702436e91c28a9122e028ed8a0a9f5a5b6a09a1bc5a135bc72cce048b3c5bc15c638f9d59043fc2db997481aa69dae49e1cb6bb643239211939e467818f97bd305965ebce9a10bc8da9dbaa2679dd9ce3d8530572cfac87566ab05ae9f1490692b9696e1f833738555f96793504df5f25945d2576b7ec16dc46792381c7b7ad5e60f234980e42f6c9c56a82ec3eff00bd4124e49700f1c646e3cd169ce9575f83d52cee324347323f6e3861ff008a23d47d4ba6a75074fdcd8ef317e2e2ff0098bdd4706a60c3f4ae8cd5f44eb8fc3e97248a638cbc73bf90483d463b373e9574685abf42a6b5649fea72bbdeac4a8d3b018cfae31f7a6895b6b29b41d30d8e9f6bbed9213e1b7a994e724fcbb5064bd7835a9752d3af75d8116354778f660788cbd9483dbb0a0cd20b2b8d43528ad2088bdcccf854039cff00e2827a0d34e9da1de896f2182492efc0976f998aa827d3d334113a74aa9a9298628e74570478bc0c7cf1da83724bb8246d3e6416b0384da61b5501c9f5c3704f152c037561a95f5fce61d3ad6db4ab950f34b331dd9f4191db8fdcd406d67a675ab4b6d325d1af248272a43430315ddec7038f6ad4b3f448bf47eb71cb69abddebf21d5e26896203846c30c8603b9c6452d9835901405660376319ac84bf13180779d8bb82827d4fb0a06f777367a75acd7170f1430a9f331200cfceae061a0cf6dac692d7365266191db0578f5edf3a6075a6c9278b3433188a467860d96fbd40fe540471409aa0c1140750001ed8ed4058e15133c983960077edf6a06faade5c5b7822d2d926766cb967da2341dd8f0727d85033d27597d62e2ee3163756915bbf8799d71e2f19dcbf2a092b88dd9a311950a0e5b70ce47fe6ac18af53f5b69da9752dd69da9ca906876e24465d9e69881c6ff005c679c0aa2bfd267a347512c93dbb5d42d90d3c800b68c9ce0ec3cfa528db74ad034db5905ee8be1ac728dc153984f3f980f4fb56453be2de8f647a6aff53796596f0aed46798ec033ce149c0fb0ad71479c9bb9dc3bf3c55a0b95f65a825150b481a407b93c0fda8a29c06671dc93803bd131eafd0af6dffe18d2ee25982a4b04603b7a9c631fad03bbe586381bc5945b96385718c827db3eb5288eb8ba934eb15fc3c535f05427796dcccdec7150637d5bd55d5362b7975aa4d0d919018adec8637807bb60723000e4f7cd58203538aefa8aeb478a7b9beba924547b8774cf8608036a80704639cf1f9855d1a7f4c68b67a03de5e5d59dad8d988c62e1c0f107a1e7fdf7a082ea6d07a6e3e99375a7cb6b3db093c727701e2360f7f53dfb50653d4130d42ee18f48b3f0232a15218936963ebf5fbd06dbf0cfa74855b9d46e04b730c6144691e12307d33ea7de8348ba6b5478a279a004f98c479247b81f5a9438805ac0be2e02e73c9ef8fbd40c2346d43578eefc40da7da1dc8b8eefea4fcb9fef419beabf12a4bcebcb2d2fa7ee0dc58492084b30236bb6467dce383f6a0b87556a67a7f4d95a0bbb5468816f0a69c78b2e072572719ce78357079dfab3af2e7a92c963b88d94abbbf91cedc93edf418aa2c5f0dbe2a6a9a0c90d8de34773a6a8da1186d6403fa48fec682d9adeb7a9b4c9d572dacc9a6c9700456e5ca910e000ecbd8e580352fb1ae7476bd6dd49a325e5a9f3025245fe961dea097523cc0919a032af039a006936c81423104649c703ef40dcce64bc3035a87b6f0c378f9fe7cf2b8fdf340a4b6e25962915d94a67807839f7a043586922b5636ec44c061063f31f6ab079d7fe19b7eb2d4efeef55d5d74f992e9a0fc3a441dcb13927b838c9aa2d4bf042c618e178efee6e18104870172318edf5c1e6945bbe1a748ea7d2315edbea3a99bcb190030c401010e4e783ee0fa56455be3d6b90c1a6268d69e17f1486900ee98ec29ccc183119419e7e55ba11f089f523ef5058363a8059fb8e31e9421b491056c01819e28d3d0ff07eea3d53a1e3b6b8db235aca63c139c0eea68ca47a9fa6ef757b83ff00bf68ad428c2f248c7a8f9fcea518df516adac74e7544f63a2ea172f1800291e6cee19ec78cd5826344e85b6bad25ba8fade5b99dae0ee11efc71e858f7e7d054a2d7d39a75ae8f7b6b00b8917f1516624b78429da327cec493db1db1d8540cf4aea28f58d6aeae2f6dd64b498082d880488d149fcea7d4939ab04175e6850a8d32de3b78e380c8de32c4db4e18e430fef543cf86fd0d691b4fabdf6648b3b2db69ce7dd87be68342d2f4fb9b5b891af1a28a2dc05bc5036d001e0eef7352884b961a2ea9aa7555c885e08d45b5bc52b61b686c120fb939fb541276bd4b61d53624d942e2f6200bc32290633e99f4233416dd3ad3f0d611c0c77b632e71dc9ef41156dd27a45addcb3dbd9c513b1dd941821bdc7b558333b9f873757fd69a85e3f813e9c7723b5d93265d872473c11544a68ff08fa75e290b42ec4e4124e70738fa5048e89f0f745d2aeadd2decedda6525c975121183c77f7a945c754d0e0d563682ed43425369403bff00bcd58308ba7d5fe13f5a05889974a9d8b46aede4914f707d88ff001528ddf4fd7edb54d1a1d56c312dab2e64dbc9418e78f5c541296d70b716d1cd6f8789977230ecc280cb7519b816f212b205de4e0843ce300f6cfcb39a0545c42cee88e0b458ddec33ee680eac92266360debc7b5056fad2d354b9b189745744be121daf27e550548ce3d4d58324d07a725e98ea2b7ff5381f5169a7579d021fe13904ee43ddfbe49038ab46e76cf05cc714f6d309232a4a98ce54fd6b2196bb7f2e9b631b2c427b891b6851db3eff002007341e5bf887aa2ea3d4f77378be381e42fdb711ed5a1554395caf1cd07617dcd04fc85402101da791421b49920331381c60d1a69bf02f56f03a925b12c162b98c955f775e47df19a32d99b518268e4491668704a79d4aeec7b7bd4a30feb7e9144d76e265697c3e2693631674273803e556087d76f35fd49859e9925ccf611141106f2e182e3241f727f5a94681a268f79ad1b1b8b9dd66b1c2b1ce9bb06361c1e7bf3fe6a096b0d3ba57488e485b52b40909c386901607d47bf7a0ae758eb69ac4d15be81a748f0a9c35cc90b2eff4c03c1c638a0b77405c5d5d45f87be5fe359a88b81b401dc1c7d38fb50586fed18ea3015790091591e447c1518c8c7a0a0a5754d8c9d49a8d9f4ee9dba0b3b5224b9692327728f627e7c6682f9a7e996b6b3a8b6b748a348820c7720761412c064e3041ce282b5d4bd73d3bd3f33daea97ac2e540dd0a292dc8cd043c1f15ba2a7923b65bb910371b9a12141f9d02edf13ba2ade56857551e5e77244c54fd0e280746ebfe99bbbd655d56dcdc9ce08465565f4ee3bfca82d53eb3a6dac3e25c5f5ba646402e33fa77a0aff5b74ad8757e9ca972844aa37c520fcca7d3f5ab067bd369a8f467544d626c98e9f7118f0200e4465c903049c8c9e6ad1b24334b6fa6249716cab20037c309dd83db03b5640dddac3764a4f02cb1103863919fa7a1a06d6f600c37162911b7b252b87dc773f1927393f4a079f868edae1ae6328a8b1ed38e30050226e85d5dc1f879011b3c47c2f604719f9d01eff4f4b83e3c6b18bb452b1cac9b8a83de80b16e8208a3b7b58e1407cc061427cc0ff1560ce7a8f592d69a97504cad2dac01a2b53900c3e9e51ea58f727d0551e73bfb86b99a49a46dcf21c96340dc13804f20f6f9501c0e3b8a0963316fcc4607007f57bd084d64dec01200ce483468ff0040d525d1755b4d4206ff0095207c11dc67ff0019a18f56584f6daad9dade4211e39104a8ded9152b235cd8c530613229c8c1c8ef50472e81690ee00322b0c100f0debdbb7ca8111ace856371358cba85aa5cc407891ccf83f2ef4048b4ad2e59bf116769672c72f99dd1437239078e2824a4d3e1b94559234110e781839fa0a0561b38ad532a12319c86c6307e740a9732a3a00cac870cd8e0faf0681be8b6db965bb909df3c85806eeabced5a09523647e6e0fef419a6adf116daf7ac34be9dd1da686e7f1ca2e243b76320ce57df9ff1560cc3e3f470ff00c78255b842b35bc6c4af9b6e323d3e95467b6365f8dbcf062beb68c119595d8aaff6e282422e9899b4f6bb5d46cda2562a76316c1078f4a0859e1b9b762c0bf94f0e84feb4125a57505c58ea70dd5d0174a986d92b1c13f6f5a0de7a5be366877260b5d42dee2d2423124a487507ebdf15289dd3fac7a7bab6feded74d61733473acdb5a162142ff00313d81ed505fa58fc6d809380c1b9f5c502e0e05040ea367a85dea454de2ff00a610375b04c16c7a16ef8340b5f6930dce9375636acf6a278f04c5dd4f1dbf4a084e91d06f3a52dee62bbd4a2b882494ced3c8a448063b63b638fde803ab7ae749b2b3096d792c93c8c109b55dcd18ce3710473ffdd043dc758dc5869044565aa5dda4c3c2b7bc78c1f14e3963db03e7c0ab066bf1327d41ba76ca6bc48ecad24c456f6b0c87cf8e4bbfa138c0fa9aa3297c83dd4e28395811cf2680a5b93c7ed413cd1ff0f3c797b8031406645236b0508406f30e68ba49c051b97d0e0e7d28ad57e19f575c5be8f269515dac772877c11bc464dea7ba8c739ce78f9d3193bb8ebfea2bcbd6b5b6b8b58bb7f13c2f0ce31cf0deb4c0f2dbad6d743d2ee99efae752d6c02a86e0054524f6383c7ff94c0b6af274c75149a46a5a82c46f1e1479fc3190bd8156fbe7f4a960bf74e9d253f1167a3ac09e0856610e3041ec7f6c540f67b892cee7f8d18368232ef2af2508c7047cf340ead5bf130accc9b1186541e723d09ffc5033bbb1b82d74d6b37f1244daa1b38073df3f4a08eeb1d3b50d4fa6a5b4d32f12cef1902ee73e523d476fde8306eb0d3fabfa4ba92c278af67bb7281606472f90bdd58558253a6afb40ea1d62283a8b461a66a6f931cf6a7c2466f7cfb939e7b5515fbed3747b5eb8f06eb78d35080a2ec9719c76f98049a0b4ebdd37d1bad869acbf0b03c5c16b29444adf50ded41995f68564a263a66b31cd02be152505493f51c1a088bab69ad1bc179e320f07c37c8a0692b46c4995f0381db39a0b2fc34e971d57d4705bc8db6c50ef9dd97b81fcbf7381528f5ae97a1d8e996d1db69b0c7648855b10a81b80f43c739c54134147b9a036063279fb5046e957726a0f2cfe04915b06db1788305ffeac7a0a00d72f8d9c491c06337533050ac7185cf2df6a06da2da4293488f34973328c34aea428c9ec3eded40ee7d2ad249448f6b133820ee2833df3fde819ea96897461b05b87815f2ee919e5d47704fa039ab079b3e326b70eafd4ef6d6650d8e9ebf868b69c8247723efebf2aa280eb9193ebedc5002a124e015340018fb8fde82cf32b1603d0678cd02406dce3008e47ce81b499c331383c9c9f5a2e9c69377369f7d6f796a4acf148acb83fb511e91b3b3d0bab745b7d45acedd8e3732b71b1fd73f7a5a19eafd09a56a0a96b1c705b49c48510761ce4fcfbd4d0d752826b2b583476fc3daacb295b79d768de8a32b1e71f989e49f6a7d14dd1af5ba275a45b8b093c054492ea769092373765c1da4679fbd306e36ba9595fe9f0dcdbcc92c33e1579cf27d0d409ea178f68521b6b76926ee8a7853f7ff140bc768d78f6f73748d1cd103b543f0091cf6efc502f7319dac194371d8b6326829f0c501d7ae6fa568d5d4942c806d4db81839f53c8cd59456fae6e628749b5bab8b1865b08e4726588ec11e7f2e49071c93da9a31dd4341d675e9a5bad374f9858162d0b4ac70e18f0573df35a0c759f87bd53a404f174f965dfff00f479b1ef570576e34bd4b4cc0bdb3b9b7258a00e846e3f2a94376475cee4914af7ca9150685f09ba61efb52fc7dd69bf8eb7c158d1d0b47bb38f37efde968d6eeb4eb5e91d6ad25b660aee59974db6881690918e31ce39279e062a5a34bb57b88adedd1e379679065d80036679e6a07e8391bce7e940c659ef5afe1286de3b16f2b8903094b7b2fa7ce81eb380c4260ed193f2a0cd6fa5d4a4ea0fc7bdadcce923158a3039db83c038e3ef41a0e96b2ad8a35e009291b8a939d9f227e43bd590436bbd6fa269202c974b7123602c76e779624e00e29833bf897d493e896525dbcb2a6b5a9c3e1456b91b6d60cf989c7f31f7a60c02490961ebcf3eb541308e39e067b507007b96007a67fb50178f97eb4165ce18165c2927b773fad023202d9c8dbb7818ff003408300b87f2f1c107d0d0c15a4f2e339c90467f6a18bdfc2cea8ff4bd561b4b9ba686d6e64552c4f954e7d7e46a60f4688d240af1b2bc6cbf5047ca960617ba658de1b792f2d94a5ab33461b18524633fa1a81b5c8b5168967369d23c0e0a24622dc981d81c76aba29df0bb48d660d52fceb88d069f04aeb69130037127f37b9c0ed9a8350781240bbc06da72323b1f7a0eb8816e633192ebc8c9472a78fa50349b4c83c068e24f0ddbcc1c13b837be4d055b57e98b996d4db5b4a893dc1e6620b6ccf2c467efc504ce97a38d3f4d874bf09af6d46e2f25cb82724e791db15650a43f878b51fc34f3da8f132b6d6a98c80a39ff007e99aba249631b58b9047239ec3e55368aeeb7d2da6f52c0eb7f16e87f2c6e836ba90724ab7a67b55d115ac7c3e8aed2182def4c56a14096368959a423d77e3229a27b41e9d8343b01069c8a8dc9660aa3713df3c64d4a1c695d3d6b67a8cba94b9b8d4e61869e4e4a8c636a7f4afcaa09a485519caae19b966f7a0435196582c656b74df3e308beec7b50629375775b691ac5bdb6b16d6378779f019b00a31cf391c9c2f1daae0b35ef52f5374de88d77aa45a6cd25ddc0108694ee2188c28007603d6a0d16c92430a4b2ed3230dc401855cfa0a0a07c45d7b5db9d462e9ee960b14b2ee134ef8c850012147ec78ab0670b643a2efae753d72686e6e2da211db42176079c8e768f65e39f7aa332d6f58bbd635096f6fe6692695b24f603d801e82823cb900ee00e68006460051dfd680ed9f0c905b713d8d006d5f5419fa505a18f94e40501b1b81a04186d62402c87be3d6810b81290aea8467201231cd1749dbc437f9f1e201db3de8ba07dc0175c027f28a335b17c26f888d6b6d0e8fabf892a29c453b1e547f49f7a946d6424f08236491c833ee0835073294888894120700f0280813c40a6711bc8843e00fca7d3ef40e41dc081f9a811681c6f7565329185623b7e9de812b3bcf11ff0b74563bd50494cf120071b97e5fda80d7577046c9019d5669dbc340324eec67fb734103d5da96bf67a7cf0e916f6e2765f25ddc4c11107ab1c8c647cce2816d3ec7f0f6564cae6e67da375e6d52cc4af2e4fb13ed4145f899d47b3499f4bb6d46cda49b69b92921565c3648e3dd40c81cd5c0ae89f13ec246d3e379ed2d6da180b5d34849da1780b128e49271c9f4a60ba685d5fa36bc42d95c324ec7090cc9b1d87b81ed50588958977cacaaa3b9341c655f12348d1dcb8dc1946540f99a019e2134454eeda7bed3839cd052fe2136b536b5d3563a1ca53c49da4b9507198940ce7e5c9fbe281c6b7a974cf4ee4ea7242d76dc784a3c595b3e9b464e3f6ad0ac745ccbd4fadcbabea42da56959a382ce7460d6b1a93c01f97272093ebf6a82f1ad6af0e9da5cb3cecf6902216919f82aa3818c7a9f4c530649a9f5269ba7429d472239bc991a1b0d3c3152880f0f23039e7bf3de90635ab6a377aa5ebdcdecef2c9239e59f3827e5ed54302195fcc38cd01245395c1f5f4a05b606538e483c501b6939e3b5077860f3914165754c33e549000dbe87de813b820c27fa7baafb8a04a69c98e281e42618c795338033df1f3a06c03e4e029247007ad010093c35674da71f977640340081a190658e41c820f141b0fc33f8926c218b4ed609366a02249bb2d19ce3ea4528dbece68eead926b7916689c643a9e0d643387521fea2f693c2d6efc786ee46d9bfed3eff2a04669edf5295ff057a60bd865309246d3bbbedc1efef41d63a8dec9ab4fa7dd4510fc3c69234ca186e2d9c003b7a67bd034bad0a5bb96e25d575267889cc1b54446d9bd0a37bfbfbd02925945a72cba8dddc48b3f87b1e58f23c623f292bdb7fa7cf38a0a5750f54ebba56a9a67fc516b6d6fd3970ea9234677c8dc7f38f6e4640ce282d1ac4b16bfa72c1d2bad430cd1ba822061865f5007d3daac19cf547c189357d561bbd3eee683c62cd786e9b73337b8c7bd512bd39f06adedec2de0d5ae639da372e6485363107f97767b505cee755d03a5e58ac228659af123184b7b733322e38c91dbf5a943ab3d52e64b49ee755d2e64950e238e35f10c884e17cbe87dc540e6d7509a4f110e9f7566a471712850abf6ce463e6280bacea36fd33a4497f773cf32c698dcc4beee33938edc7ad05534aea683ae61d64c4d2a69b6b88d16d5ca5c303f3e386cf61db140e27b5e99e96b64bdd562b6b30aa36c6c37cac7dc9eec6b42c1a66a962fa70beb6b516d0cbe76322f86c78f6c66831bf8b5d5d2dfa35a5dce60b1933b6ce3c788769f2b331ec1b8fd2831b79649984b239773c1dc68129725c1c640e73400ec781d8fb1a03c4a85d0c8582640257bd01e51fc42236263c9c67be280429c6037eb405dbf5fd682c2a0bb976cf07d3fc5009279ef8ec4e68193a9902b28e7dc71fb501d95b098e0f6dd9e0d0049131019b047b8390281bb292484e47c8500c4f242c3076bf704704739a0be7c3febfbae9a5daf23cd017c7e19fb107bb67d0f6fd6837cd2757d1fab34f4f05e37dde630b1c3a91edf4f7159103d6eb7da65fdbdf59dadb5e2460ac876ed9e1c8c060f9efe9c8a0a75cfc42d5742d2ee5a7e9dbb494b6d6b9bc930cce4f940e3cd81ed4160e98f88315e689fff0022b57664199cc5196f0c7a164ef8f98cd0589baffa68590985eb15c0db1985839f6c2919340b69d03f5285bdd6f4bf021424db4329cb153fccc3d09c76a090d3340d2f479a7bab3b38e2924e5e451cfd280d7dafe936f6c5e4bd89813b02a36589ce318a0358dc35cc4e17f9bf234cdbb78fa0c607a7340e6cec20b1596610c6934b8323226379edda81da8dcb9ec40a042f50b5bb21645473b58b11dbd7bfca8304f8add5d67a9ea8ba5d8ea72c1a4d8a952f10f2c920e368cf71e99fad5833dd0754d6ed66bdb2e9a91a5babb2a310465a57c1ddc1038e7bd5171d3748b8d46ee1ff005298dc6a764c27d4eeaee7fe1c01795881c9e7804fe940dbe287c4b6d75a1b1d1c986d62277c91bf131f4c0f6fad0663737135d3b497124924871f98e7803007d2811dc5b83903dc0a0333f03be7de8122df2c9a05a11e5f51f7a05ce7071804fca8033e5da0734020b0183bb23e5416269577ed0e5323078ceeefdff6a03dbcd62914c2f629a47c622689800879e4fbd046f9d8a2a03e31385c0e73da8b83ca590947dcaead8208e73da8849b3e19ce704f7c5015586d006431f5cf61f3a04ee586ff002481c8fe6191408f0011eb8e30682774dea9bbb5784492ca6385832e1ca95e3d2834be9df8c312e2db5eb4375080337000f1303d18763591a469baef4d755989ec6f6dae5a23e20b599406dd8e080ddbed41272f4dd8caf1c86d163910f9595882a3d718a035edd695d3b6a926b57d0ac65b10b4e06eedd863bf141077fd7af2782bd3fa26a1a8891d57c630948c0279393dcd04cf5875258f4de9f0cb7b7b6d66d2b81ba752d85f5214724fed41036bd79d2fe319d7a8f4b9c81e58de2f04827b9ce09a07a3acecf54b790685ace8697606009e52c377b7f2e682b097d7d36acf0f55df5edbdc0977412468cb6ce3be10af3c63b9c8a0b0751f505be9690dd5d752436f62a3fe4c6448f3b7b0c64e38f615734651f107e3045ac42b67a7693018633b965bc1bc838ee173807bf7cd33065baaeb1a95f2c11dfcd2bc51fe48880aa3e8a062a8b059f595df4ae9a74de9e9ec499d43c97b1427c6e47e525bb63e4282ad3ea3712893c599dbc4259c1627713c927de81043950df97db1406da8411c92063be280230839627078e79a0390a71b5bb5003a8c1232338e4507025573e9fbd02a0e41dc0e680c3691cf714053bb34160895dc16f291d98d02322aa39f3e14707ffaa06f202a5bb0c7201f4a343aca51090497efdfbfce89840c8db8e46573923ff14410b00490d9f5c1a0425dd8ce4673e873cd0265e4dbe7041ed814009b8cbb8e5863bd07163b7716e0607b6698060b96b7b9478dc8643918247ee39a60b7e97f133a8b4e0c63d4ee597380923970a3ef4c0e13e25dfcfab457ba95bdbddb212016501867b9cfbfda982f907c74b282da34874a9048aa479c83838edc62982b7ac7c42d235cd67f15ac5b40c366418a2cb0c1c81e6f5e31db14c160d035de8cd4a3f18ea96562cc37359dfe9cac887fef039fd6b39446f56ea5d13a9dca4579a922496b1975b8d22dfc3566cf9557230703be715ac1431d4d2275325d7fae6b4f6f182a93ef1e32a9f41938f6a60afeb1a95c5fea53dccf772cf2c8c489240031f627e7565c0d67bbf160487c1801073bc0c31f91f953420f2bc8c7c52cc540032738a809905c0f4fa501940208e73df34028e703938a0577ae013f4a001300db4f03b71407461ce0502dca8c9c7dcf6a003fafcbdcd0070bc1e0fd734070db467b8a04cb9c9e68274b93bcb1daa40200ed4099765249ec476cf340849b8b264823bf34689ee009cb671df1409bc8e8b8e770e3ec68984d9c953cf97be2860b248caaebc107dc67f7a184c31232db88fd451031ce50e76039f5c8045026efb8f93279e0fd680b239504f0483d88ef409ee25bb90c79c0e050151c6e21b39ce783eb40adbcc2cefa17bdb61322387781c950e3dbdf9c8a066f28790b22e013db3dbef54726081e63c6460d34191b1bb0720f634060e7600412c781502409c8e3d7b500ed71dbef8ed40243f181c0a02e5d4e0fad006f644e4819e3b501f7e3049e7b501bc43b4e391da80558003392d40a23305e320d02e64cf998e1bf5a032b0c927b8e68049c8c8e71c6280377043118f4e680bbff00de0504ddbb3128371c1c64668024e59f3cd02521254e4fad1a2107e48fe6a6809ddb9e78a029e1463d05027ffc744a6c3857c7b1a205ff00e637fbf4a02b12b1794e39f4a02024e7249ed409924720906800005173fd7404989698ee39e4f7a04cf723d07a501fff0097ed406ffe36a018ff00281e99a037f4d0731f3bfd28007e53400ff99a810248c0cf140bc60123233cff008a0557f9beb4056eff007a07109243e79a03778b27bfbd02b128c27039a054001b818a06609de793da815006070283ffd9}\par}+{\pard \ql \f0 \sa0 \li0 \fi0 lalune\par} {\pard \ql \f0 \sa180 \li0 \fi0 Here is a movie {\pict\jpegblip\picw20\pich22\picwgoal400\pichgoal440 ffd8ffe000104a46494600010101004800480000fffe0050546869732061727420697320696e20746865207075626c696320646f6d61696e2e204b6576696e204875676865732c206b6576696e68406569742e636f6d2c2053657074656d6265722031393935ffdb00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101ffdb00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101ffc00011080016001403012200021101031101ffc4001a000100020301000000000000000000000000080905060a07ffc400231000010501000300010500000000000000060304050708020001090a11153976b7ffc400160101010100000000000000000000000000060800ffc400261101000102050109000000000000000000010200030405061121b33134365154717475b4ffda000c03010002110311003f00a90cf388f366a62aa720ed6ae07f96901f3831d973452b8cf36fe3570fc908e46d466433e5dd954f2e96992d9e498c7753faa44916e016ca91cc7d88b38fe60a5b97737defcbcc539c98d336a57f4fc2ca9a486bf07ab575ad9a3af4df221d8215e36df86c4504ff0024574551b3d687ee0575757b3ad64e311ee62bd94158d37e24198c43973099f1fc0c41614d950246513a081abf76cfe7061f6863281e6352fd1670949c148dd6dfb0d25f5b3689b1d5c965b0eacbf4e0932ad28e22ab9ae945633f4744bd3c8cee0a7fdf085b9000f449c5f7afa30b83e0b6fd7b0c8429c9467ff9715347c891e25fa24a205861aa715e6a09bd0488237dc2723414d9891381524e8ca7c0894664f835653631ab55ee7e3de433e4ff001b30949124e4c10c8b6ad0a479b3f9c937b2cf5bc0095ad600a0a41a0e9faee174a1c605e161c6c7a313539650b0113190f1a8368e60d5b24f30ff008ea7f0bf867fa6595feeb6978f1fe0f9c26177f4d63a51a9235184750e7d18811339cd000000c75f000e00380380ae390c350def826ed42ad051fa6f501c50f9b699c3b69cbeb76476d202bf3ac985b6e0e968be66572893e6a744540bd9722e5c87956848629bc2559306bd113e8653d3b6aff651dfad7a3ac8b02958cba02a93ccf525757039bae6cff090e1d90688e8aa233ee86a4c4a3e0586d6b2340522e47dcb7d0046d8a5acb05a123ee25d2b230b2ada6e2e2f9ede3c05202520ec2487b0d56562529d8b3393bca76adca4ec1bca508abb001babc007915d84fe3dd14e207e3c62f8379da2a3b861fb6629d28dba53b6ea388ebfed866bf6dfb553455e91ed547ae92e9445253a4fdf3efb4f8ebdfbe7d3c78f1ee0bb9e13e358e942a4ed49e22cff00eeb35fdd7ebfffd9} icon.\par} {\pard \qc \f0 \sa180 \li0 \fi0 \emdash\emdash\emdash\emdash\emdash\par} {\pard \ql \f0 \sa180 \li0 \fi0 \outlinelevel0 \b \fs36 Footnotes\par}
@@ -810,8 +810,9 @@ <p><figure> <head>lalune</head> <graphic url="lalune.jpg" />- <figDesc>fig:Voyage dans la Lune</figDesc>+ <figDesc>Voyage dans la Lune</figDesc> </figure></p>+ <p>lalune</p> <p>Here is a movie <figure> <head>movie</head> <graphic url="movie.jpg" />
@@ -1,4 +1,6 @@-\input texinfo+\input texinfo @c -*-texinfo-*-+@settitle Pandoc Test Suite+ @documentencoding UTF-8 @macro textstrikeout{text}@@ -48,23 +50,20 @@ @node Headers @chapter Headers-@anchor{#headers} @menu-* Level 2 with an embedded link::+* Level 2 with an @uref{/url,embedded link}:: @end menu -@node Level 2 with an embedded link+@node Level 2 with an @uref{/url,embedded link} @section Level 2 with an @uref{/url,embedded link}-@anchor{#level-2-with-an-embedded-link} @menu-* Level 3 with emphasis::+* Level 3 with @emph{emphasis}:: @end menu -@node Level 3 with emphasis+@node Level 3 with @emph{emphasis} @subsection Level 3 with @emph{emphasis}-@anchor{#level-3-with-emphasis} @menu * Level 4::@@ -72,21 +71,18 @@ @node Level 4 @subsubsection Level 4-@anchor{#level-4} Level 5 @node Level 1 @chapter Level 1-@anchor{#level-1} @menu-* Level 2 with emphasis::+* Level 2 with @emph{emphasis}:: * Level 2:: @end menu -@node Level 2 with emphasis+@node Level 2 with @emph{emphasis} @section Level 2 with @emph{emphasis}-@anchor{#level-2-with-emphasis} @menu * Level 3::@@ -94,12 +90,10 @@ @node Level 3 @subsection Level 3-@anchor{#level-3} with no blank line @node Level 2 @section Level 2-@anchor{#level-2} with no blank line @iftex@@ -111,7 +105,6 @@ @node Paragraphs @chapter Paragraphs-@anchor{#paragraphs} Here's a regular paragraph. In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.@@ -132,7 +125,6 @@ @node Block Quotes @chapter Block Quotes-@anchor{#block-quotes} E-mail style: @quotation@@ -178,7 +170,6 @@ @node Code Blocks @chapter Code Blocks-@anchor{#code-blocks} Code: @verbatim@@ -208,7 +199,6 @@ @node Lists @chapter Lists-@anchor{#lists} @menu * Unordered::@@ -220,7 +210,6 @@ @node Unordered @section Unordered-@anchor{#unordered} Asterisks tight: @itemize@@ -298,7 +287,6 @@ @node Ordered @section Ordered-@anchor{#ordered} Tight: @enumerate @@ -367,7 +355,6 @@ @node Nested @section Nested-@anchor{#nested} @itemize @item Tab@@ -428,7 +415,6 @@ @node Tabs and spaces @section Tabs and spaces-@anchor{#tabs-and-spaces} @itemize @item this is a list item indented with tabs@@ -449,7 +435,6 @@ @node Fancy list markers @section Fancy list markers-@anchor{#fancy-list-markers} @enumerate 2 @item begins with 2@@ -526,7 +511,6 @@ @node Definition Lists @chapter Definition Lists-@anchor{#definition-lists} Tight using spaces: @table @asis@@ -648,7 +632,6 @@ @node HTML Blocks @chapter HTML Blocks-@anchor{#html-blocks} Simple block on one line: foo@@ -709,7 +692,6 @@ @node Inline Markup @chapter Inline Markup-@anchor{#inline-markup} This is @emph{emphasized}, and so @emph{is this}. This is @strong{strong}, and so @strong{is this}.@@ -744,7 +726,6 @@ @node Smart quotes ellipses dashes @chapter Smart quotes, ellipses, dashes-@anchor{#smart-quotes-ellipses-dashes} ``Hello,'' said the spider. ```Shelob' is my name.'' `A', `B', and `C' are letters.@@ -771,7 +752,6 @@ @node LaTeX @chapter LaTeX-@anchor{#latex} @itemize @item @tex@@ -826,7 +806,6 @@ @node Special Characters @chapter Special Characters-@anchor{#special-characters} Here is some unicode: @itemize@@ -893,7 +872,6 @@ @node Links @chapter Links-@anchor{#links} @menu * Explicit::@@ -904,7 +882,6 @@ @node Explicit @section Explicit-@anchor{#explicit} Just a @uref{/url/,URL}. @uref{/url/,URL and title}.@@ -925,7 +902,6 @@ @node Reference @section Reference-@anchor{#reference} Foo @uref{/url/,bar}. With @uref{/url/,embedded [brackets]}.@@ -950,7 +926,6 @@ @node With ampersands @section With ampersands-@anchor{#with-ampersands} Here's a @uref{http://example.com/?foo=1&bar=2,link with an ampersand in the URL}. @@ -962,7 +937,6 @@ @node Autolinks @section Autolinks-@anchor{#autolinks} With an ampersand: @url{http://example.com/?foo=1&bar=2} @itemize@@ -974,7 +948,7 @@ It should. @end itemize -An e-mail address: @uref{mailto:nobody@@nowhere.net,nobody@@nowhere.net}+An e-mail address: @uref{mailto:nobody@@nowhere.net,nobody@@nowherenet} @quotation Blockquoted: @url{http://example.com/}@@ -994,14 +968,12 @@ @node Images @chapter Images-@anchor{#images} From ``Voyage dans la Lune'' by Georges Melies (1902): @float @image{lalune,,,lalune,jpg} @caption{lalune} @end float- Here is a movie @image{movie,,,movie,jpg} icon. @iftex@@ -1013,7 +985,6 @@ @node Footnotes @chapter Footnotes-@anchor{#footnotes} Here is a footnote reference,@footnote{Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.} and another.@footnote{Here's the long note. This one contains multiple blocks.
@@ -677,8 +677,17 @@ From "Voyage dans la Lune" by Georges Melies (1902): -!lalune.jpg(Voyage dans la Lune)!+<figure>++<figcaption>+ lalune++</figcaption>++!lalune.jpg(Voyage dans la Lune)!++</figure> Here is a movie !movie.jpg(movie)! icon.
@@ -0,0 +1,872 @@+#let horizontalrule = line(start: (25%,0%), end: (75%,0%))++#show terms.item: it => block(breakable: false)[+ #text(weight: "bold")[#it.term]+ #block(inset: (left: 1.5em, top: -0.4em))[#it.description]+]++#set table(+ inset: 6pt,+ stroke: none+)++#show figure.where(+ kind: table+): set figure.caption(position: top)++#show figure.where(+ kind: image+): set figure.caption(position: bottom)++#let content-to-string(content) = {+ if content.has("text") {+ content.text+ } else if content.has("children") {+ content.children.map(content-to-string).join("")+ } else if content.has("body") {+ content-to-string(content.body)+ } else if content == [ ] {+ " "+ }+}+#let conf(+ title: none,+ subtitle: none,+ authors: (),+ keywords: (),+ date: none,+ abstract-title: none,+ abstract: none,+ thanks: none,+ cols: 1,+ margin: (x: 1.25in, y: 1.25in),+ paper: "us-letter",+ lang: "en",+ region: "US",+ font: none,+ fontsize: 11pt,+ mathfont: none,+ codefont: none,+ linestretch: 1,+ sectionnumbering: none,+ linkcolor: none,+ citecolor: none,+ filecolor: none,+ pagenumbering: "1",+ doc,+) = {+ set document(+ title: title,+ 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,+ leading: linestretch * 0.65em+ )+ set text(lang: lang,+ region: region,+ size: fontsize)++ set text(font: font) if font != none+ show math.equation: set text(font: mathfont) if mathfont != none+ show raw: set text(font: codefont) if codefont != none++ set heading(numbering: sectionnumbering)++ show link: set text(fill: rgb(content-to-string(linkcolor))) if linkcolor != none+ show ref: set text(fill: rgb(content-to-string(citecolor))) if citecolor != none+ show link: this => {+ if filecolor != none and type(this.dest) == label {+ text(this, fill: rgb(content-to-string(filecolor)))+ } else {+ text(this)+ }+ }++ if title != none {+ place(top, float: true, scope: "parent", clearance: 4mm, block(below: 1em, width: 100%)[+ #if title != none {+ align(center, block[+ #text(weight: "bold", size: 1.5em, hyphenate: false)[#title #if thanks != none {+ footnote(thanks, numbering: "*")+ counter(footnote).update(n => n - 1)+ }]+ #(+ if subtitle != none {+ parbreak()+ text(weight: "bold", size: 1.25em, hyphenate: false)[#subtitle]+ }+ )])+ }++ #if authors != none and authors != [] {+ let count = authors.len()+ let ncols = calc.min(count, 3)+ grid(+ columns: (1fr,) * ncols,+ row-gutter: 1.5em,+ ..authors.map(author => align(center)[+ #author.name \+ #author.affiliation \+ #author.email+ ])+ )+ }++ #if date != none {+ align(center)[#block(inset: 1em)[+ #date+ ]]+ }++ #if abstract != none {+ block(inset: 2em)[+ #text(weight: "semibold")[#abstract-title] #h(1em) #abstract+ ]+ }+ ])+ }+ doc+}+#show: doc => conf(+ title: [Pandoc Test Suite],+ authors: (+ ( name: [John MacFarlane],+ affiliation: "",+ email: "" ),+ ( name: [Anonymous],+ affiliation: "",+ email: "" ),+ ),+ date: [July 17, 2006],+ abstract-title: [Abstract],+ pagenumbering: "1",+ cols: 1,+ doc,+)+++This is a set of tests for pandoc. Most of them are adapted from John Gruber's+markdown test suite.++#horizontalrule++= Headers+<headers>+== Level 2 with an #link("/url")[embedded link]+<level-2-with-an-embedded-link>+=== Level 3 with #emph[emphasis]+<level-3-with-emphasis>+==== Level 4+<level-4>+===== Level 5+<level-5>+= Level 1+<level-1>+== Level 2 with #emph[emphasis]+<level-2-with-emphasis>+=== Level 3+<level-3>+with no blank line++== Level 2+<level-2>+with no blank line++#horizontalrule++= Paragraphs+<paragraphs>+Here's a regular paragraph.++In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.+Because a hard-wrapped line in the middle of a paragraph looked like a list+item.++Here's one with a bullet. \* criminey.++There should be a hard line break \ here.++#horizontalrule++= Block Quotes+<block-quotes>+E-mail style:++#quote(block: true)[+This is a block quote. It is pretty short.+]++#quote(block: true)[+Code in a block quote:++```+sub status {+ print "working";+}+```++A list:+++ item one++ item two++Nested block quotes:++#quote(block: true)[+nested+]++#quote(block: true)[+nested+]+]++This should not be a block quote: 2 \> 1.++And a following paragraph.++#horizontalrule++= Code Blocks+<code-blocks>+Code:++```+---- (should be four hyphens)++sub status {+ print "working";+}++this code block is indented by one tab+```++And:++```+ this code block is indented by two tabs++These should not be escaped: \$ \\ \> \[ \{+```++#horizontalrule++= Lists+<lists>+== Unordered+<unordered>+Asterisks tight:++- asterisk 1+- asterisk 2+- asterisk 3++Asterisks loose:++- asterisk 1++- asterisk 2++- asterisk 3++Pluses tight:++- Plus 1+- Plus 2+- Plus 3++Pluses loose:++- Plus 1++- Plus 2++- Plus 3++Minuses tight:++- Minus 1+- Minus 2+- Minus 3++Minuses loose:++- Minus 1++- Minus 2++- Minus 3++== Ordered+<ordered>+Tight:+++ First++ Second++ Third++and:+++ One++ Two++ Three++Loose using tabs:+++ First+++ Second+++ Third++and using spaces:+++ One+++ Two+++ Three++Multiple paragraphs:+++ Item 1, graf one.++ Item 1. graf two. The quick brown fox jumped over the lazy dog's back.+++ Item 2.+++ Item 3.++== Nested+<nested>+- Tab+ - Tab+ - Tab++Here's another:+++ First++ Second:+ - Fee+ - Fie+ - Foe++ Third++Same thing but with paragraphs:+++ First+++ Second:++ - Fee+ - Fie+ - Foe+++ Third++== Tabs and spaces+<tabs-and-spaces>+- this is a list item indented with tabs++- this is a list item indented with spaces++ - this is an example list item indented with tabs++ - this is an example list item indented with spaces++== Fancy list markers+<fancy-list-markers>+#block[+#set enum(numbering: "(1)", start: 2)++ begins with 2+++ and now 3++ with a continuation++ #block[+ #set enum(numbering: "i.", start: 4)+ + sublist with roman numerals, starting with 4+ + more items+ #block[+ #set enum(numbering: "(A)", start: 1)+ + a subsublist+ + a subsublist+ ]+ ]+]++Nesting:++#block[+#set enum(numbering: "A.", start: 1)++ Upper Alpha+ #block[+ #set enum(numbering: "I.", start: 1)+ + Upper Roman.+ #block[+ #set enum(numbering: "(1)", start: 6)+ + Decimal start with 6+ #block[+ #set enum(numbering: "a)", start: 3)+ + Lower alpha with paren+ ]+ ]+ ]+]++Autonumbering:+++ Autonumber.++ More.+ + Nested.++Should not be a list item:++M.A.~2007++B. Williams++#horizontalrule++= Definition Lists+<definition-lists>+Tight using spaces:++/ apple: #block[+red fruit+]++/ orange: #block[+orange fruit+]++/ banana: #block[+yellow fruit+]++Tight using tabs:++/ apple: #block[+red fruit+]++/ orange: #block[+orange fruit+]++/ banana: #block[+yellow fruit+]++Loose:++/ apple: #block[+red fruit+]++/ orange: #block[+orange fruit+]++/ banana: #block[+yellow fruit+]++Multiple blocks with italics:++/ #emph[apple]: #block[+red fruit++contains seeds, crisp, pleasant to taste+]++/ #emph[orange]: #block[+orange fruit++```+{ orange code block }+```++#quote(block: true)[+orange block quote+]+]++Multiple definitions, tight:++/ apple: #block[+red fruit++computer+]++/ orange: #block[+orange fruit++bank+]++Multiple definitions, loose:++/ apple: #block[+red fruit++computer+]++/ orange: #block[+orange fruit++bank+]++Blank line after term, indented marker, alternate markers:++/ apple: #block[+red fruit++computer+]++/ orange: #block[+orange fruit+++ sublist++ sublist+]++= HTML Blocks+<html-blocks>+Simple block on one line:++#block[+foo+]+And nested without indentation:++#block[+#block[+#block[+foo++]+]+#block[+bar+]+]+Interpreted markdown in a table:++This is #emph[emphasized]+And this is #strong[strong]+Here's a simple block:++#block[+foo++]+This should be a code block, though:++```+<div>+ foo+</div>+```++As should this:++```+<div>foo</div>+```++Now, nested:++#block[+#block[+#block[+foo+]+]+]+This should just be an HTML comment:++Multiline:++Code block:++```+<!-- Comment -->+```++Just plain comment, with trailing spaces on the line:++Code:++```+<hr />+```++Hr's:++#horizontalrule++= Inline Markup+<inline-markup>+This is #emph[emphasized], and so #emph[is this].++This is #strong[strong], and so #strong[is this].++An #emph[#link("/url")[emphasized link]].++#strong[#emph[This is strong and em.]]++So is #strong[#emph[this]] word.++#strong[#emph[This is strong and em.]]++So is #strong[#emph[this]] word.++This is code: `>`, `$`, `\`, `\$`, `<html>`.++#strike[This is #emph[strikeout].]++Superscripts: a#super[bc]d a#super[#emph[hello]] a#super[hello~there].++Subscripts: H#sub[2]O, H#sub[23]O, H#sub[many~of~them]O.++These should not be superscripts or subscripts, because of the unescaped spaces:+a^b c^d, a\~b c\~d.++#horizontalrule++= Smart quotes, ellipses, dashes+<smart-quotes-ellipses-dashes>+"Hello," said the spider. "'Shelob' is my name."++'A', 'B', and 'C' are letters.++'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'++'He said, "I want to go."' Were you alive in the 70's?++Here is some quoted '`code`' and a+"#link("http://example.com/?foo=1&bar=2")[quoted link]".++Some dashes: one---two --- three---four --- five.++Dashes between numbers: 5--7, 255--66, 1987--1999.++Ellipses…and…and….++#horizontalrule++= LaTeX+<latex>+-+- $2 + 2 = 4$+- $x in y$+- $alpha and omega$+- $223$+- $p$-Tree+- Here's some display math:+ $ frac(d, d x) f\(x\)= lim_(h arrow.r 0) frac(f\(x + h\)- f\(x\), h) $+- Here's one that has a line break in it: $alpha + omega times x^2$.++These shouldn't be math:++- To get the famous equation, write `$e = mc^2$`.+- \$22,000 is a #emph[lot] of money. So is \$34,000. (It worked if "lot" is+ emphasized.)+- Shoes (\$20) and socks (\$5).+- Escaped `$`: \$73 #emph[this should be emphasized] 23\$.++Here's a LaTeX table:++#horizontalrule++= Special Characters+<special-characters>+Here is some unicode:++- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: ©++AT&T has an ampersand in their name.++AT&T is another way to write it.++This & that.++4 \< 5.++6 \> 5.++Backslash: \\++Backtick: \`++Asterisk: \*++Underscore: \_++Left brace: {++Right brace: }++Left bracket: \[++Right bracket: \]++Left paren: (++Right paren: )++Greater-than: \>++Hash: \#++Period: .++Bang: !++Plus: +++Minus: -++#horizontalrule++= Links+<links>+== Explicit+<explicit>+Just a #link("/url/")[URL].++#link("/url/")[URL and title].++#link("/url/")[URL and title].++#link("/url/")[URL and title].++#link("/url/")[URL and title]++#link("/url/")[URL and title]++#link("/url/with_underscore")[with\_underscore]++#link("mailto:nobody@nowhere.net")[Email link]++#link("")[Empty].++== Reference+<reference>+Foo #link("/url/")[bar].++With #link("/url/")[embedded \[brackets\]].++#link("/url/")[b] by itself should be a link.++Indented #link("/url")[once].++Indented #link("/url")[twice].++Indented #link("/url")[thrice].++This should \[not\]\[\] be a link.++```+[not]: /url+```++Foo #link("/url/")[bar].++Foo #link("/url/")[biz].++== With ampersands+<with-ampersands>+Here's a+#link("http://example.com/?foo=1&bar=2")[link with an ampersand in the URL].++Here's a link with an amersand in the link text: #link("http://att.com/")[AT&T].++Here's an #link("/script?foo=1&bar=2")[inline link].++Here's an #link("/script?foo=1&bar=2")[inline link in pointy braces].++== Autolinks+<autolinks>+With an ampersand: #link("http://example.com/?foo=1&bar=2")++- In a list?+- #link("http://example.com/")+- It should.++An e-mail address: #link("mailto:nobody@nowhere.net")[nobody\@nowhere.net]++#quote(block: true)[+Blockquoted: #link("http://example.com/")+]++Auto-links should not occur here: `<http://example.com/>`++```+or here: <http://example.com/>+```++#horizontalrule++= Images+<images>+From "Voyage dans la Lune" by Georges Melies (1902):++#figure(image("lalune.jpg", alt: "lalune"),+ caption: [+ lalune+ ]+)++Here is a movie #box(image("movie.jpg", alt: "movie")) icon.++#horizontalrule++= Footnotes+<footnotes>+Here is a footnote reference,#footnote[Here is the footnote. It can go anywhere+after the footnote reference. It need not be placed at the end of the document.]+and another.#footnote[Here's the long note. This one contains multiple blocks.++Subsequent blocks are indented to show that they belong to the footnote (as with+list items).++```+ { <code> }+```++If you want, you can indent every line, but you can also be lazy and just indent+the first line of each block.] This should #emph[not] be a footnote reference,+because it contains a space.\[^my note\] Here is an inline note.#footnote[This+is #emph[easier] to type. Inline notes may contain+#link("http://google.com")[links] and `]` verbatim characters, as well as+\[bracketed text\].]++#quote(block: true)[+Notes can go in quotes.#footnote[In quote.]+]+++ And in list items.#footnote[In list.]++This paragraph should not be part of the note, as it is not indented.
@@ -0,0 +1,669 @@+ Pandoc Test Suite by John MacFarlane, Anonymous+++ Type |gO| to see the table of contents.+++This is a set of tests for pandoc. Most of them are adapted from John Gruber's+markdown test suite.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Headers *headers*++--------------------------------------------------------------------------------+Level 2 with an embedded link /url *level-2-with-an-embedded-link*++LEVEL 3 WITH EMPHASIS *level-3-with-emphasis*++Level 4 *level-4*++Level 5 *level-5*++================================================================================+Level 1 *level-1*++--------------------------------------------------------------------------------+Level 2 with emphasis *level-2-with-emphasis*++LEVEL 3 *level-3*++with no blank line++--------------------------------------------------------------------------------+Level 2 *level-2*++with no blank line++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Paragraphs *paragraphs*++Here's a regular paragraph.++In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.+Because a hard-wrapped line in the middle of a paragraph looked like a list+item.++Here's one with a bullet. * criminey.++There should be a hard line break+here.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Block Quotes *block-quotes*++E-mail style:++ This is a block quote. It is pretty short.++ Code in a block quote:++ >+ sub status {+ print "working";+ }+<+ A list:++ 1. item one+ 2. item two++ Nested block quotes:++ nested++ nested++This should not be a block quote: 2 > 1.++And a following paragraph.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Code Blocks *code-blocks*++Code:++>+ ---- (should be four hyphens)++ sub status {+ print "working";+ }++ this code block is indented by one tab+<+And:++>+ this code block is indented by two tabs++ These should not be escaped: \$ \\ \> \[ \{+<+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Lists *lists*++--------------------------------------------------------------------------------+Unordered *unordered*++Asterisks tight:++- asterisk 1+- asterisk 2+- asterisk 3++Asterisks loose:++- asterisk 1++- asterisk 2++- asterisk 3++Pluses tight:++- Plus 1+- Plus 2+- Plus 3++Pluses loose:++- Plus 1++- Plus 2++- Plus 3++Minuses tight:++- Minus 1+- Minus 2+- Minus 3++Minuses loose:++- Minus 1++- Minus 2++- Minus 3++--------------------------------------------------------------------------------+Ordered *ordered*++Tight:++1. First+2. Second+3. Third++and:++1. One+2. Two+3. Three++Loose using tabs:++1. First++2. Second++3. Third++and using spaces:++1. One++2. Two++3. Three++Multiple paragraphs:++1. Item 1, graf one.++ Item 1. graf two. The quick brown fox jumped over the lazy dog's back.++2. Item 2.++3. Item 3.++--------------------------------------------------------------------------------+Nested *nested*++- Tab+ - Tab+ - Tab++Here's another:++1. First+2. Second:+ - Fee+ - Fie+ - Foe+3. Third++Same thing but with paragraphs:++1. First++2. Second:++ - Fee+ - Fie+ - Foe++3. Third++--------------------------------------------------------------------------------+Tabs and spaces *tabs-and-spaces*++- this is a list item indented with tabs++- this is a list item indented with spaces++ - this is an example list item indented with tabs++ - this is an example list item indented with spaces++--------------------------------------------------------------------------------+Fancy list markers *fancy-list-markers*++(2) begins with 2++(3) and now 3++ with a continuation++ iv. sublist with roman numerals, starting with 4+ v. more items+ (A) a subsublist+ (B) a subsublist++Nesting:++A. Upper Alpha+ I. Upper Roman.+ (6) Decimal start with 6+ c) Lower alpha with paren++Autonumbering:++1. Autonumber.+2. More.+ 1. Nested.++Should not be a list item:++M.A. 2007++B. Williams++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Definition Lists *definition-lists*++Tight using spaces:++apple+ red fruit+orange+ orange fruit+banana+ yellow fruit++Tight using tabs:++apple+ red fruit+orange+ orange fruit+banana+ yellow fruit++Loose:++apple+ red fruit++orange+ orange fruit++banana+ yellow fruit++Multiple blocks with italics:++apple+ red fruit++ contains seeds, crisp, pleasant to taste++orange+ orange fruit++ >+ { orange code block }+<+ orange block quote++Multiple definitions, tight:++apple+ red fruit+ computer+orange+ orange fruit+ bank++Multiple definitions, loose:++apple+ red fruit++ computer++orange+ orange fruit++ bank++Blank line after term, indented marker, alternate markers:++apple+ red fruit++ computer++orange+ orange fruit++ 1. sublist+ 2. sublist++================================================================================+HTML Blocks *html-blocks*++Simple block on one line:++foo+And nested without indentation:++foo++bar+Interpreted markdown in a table:++This is emphasized+And this is strong+Here's a simple block:++foo++This should be a code block, though:++>+ <div>+ foo+ </div>+<+As should this:++>+ <div>foo</div>+<+Now, nested:++foo+This should just be an HTML comment:++Multiline:++Code block:++>+ <!-- Comment -->+<+Just plain comment, with trailing spaces on the line:++Code:++>+ <hr />+<+Hr's:++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Inline Markup *inline-markup*++This is emphasized, and so is this.++This is strong, and so is this.++An emphasized link /url.++This is strong and em.++So is this word.++This is strong and em.++So is this word.++This is code: `>`, `$`, `\`, `\$`, `<html>`.++This is strikeout.++Superscripts: abcd ahello ahello there.++Subscripts: H2O, H23O, Hmany of themO.++These should not be superscripts or subscripts, because of the unescaped spaces:+a^b c^d, a~b c~d.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Smart quotes, ellipses, dashes *smart-quotes-ellipses-dashes*++"Hello," said the spider. "'Shelob' is my name."++'A', 'B', and 'C' are letters.++'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'++'He said, "I want to go."' Were you alive in the 70's?++Here is some quoted '`code`' and a "quoted link+http://example.com/?foo=1&bar=2".++Some dashes: one---two --- three---four --- five.++Dashes between numbers: 5--7, 255--66, 1987--1999.++Ellipses...and...and....++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+LaTeX *latex*++- +- `$2+2=4$`+- `$x \in y$`+- `$\alpha \wedge \omega$`+- `$223$`+- `$p$`-Tree+- Here's some display math:+ `$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$`+- Here's one that has a line break in it: `$\alpha + \omega \times x^2$`.++These shouldn't be math:++- To get the famous equation, write `$e = mc^2$`.+- $22,000 is a lot of money. So is $34,000. (It worked if "lot" is emphasized.)+- Shoes ($20) and socks ($5).+- Escaped `$`: $73 this should be emphasized 23$.++Here's a LaTeX table:++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Special Characters *special-characters*++Here is some unicode:++- I hat: Î+- o umlaut: ö+- section: §+- set membership: ∈+- copyright: ©++AT&T has an ampersand in their name.++AT&T is another way to write it.++This & that.++4 < 5.++6 > 5.++Backslash: \++Backtick: `++Asterisk: *++Underscore: _++Left brace: {++Right brace: }++Left bracket: [++Right bracket: ]++Left paren: (++Right paren: )++Greater-than: >++Hash: #++Period: .++Bang: !++Plus: +++Minus: -++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Links *links*++--------------------------------------------------------------------------------+Explicit *explicit*++Just a URL /url/.++URL and title /url/.++URL and title /url/.++URL and title /url/.++URL and title /url/++URL and title /url/++with_underscore /url/with_underscore++Email link nobody@nowhere.net++Empty .++--------------------------------------------------------------------------------+Reference *reference*++Foo bar /url/.++With embedded [brackets] /url/.++b /url/ by itself should be a link.++Indented once /url.++Indented twice /url.++Indented thrice /url.++This should [not][] be a link.++>+ [not]: /url+<+Foo bar /url/.++Foo biz /url/.++--------------------------------------------------------------------------------+With ampersands *with-ampersands*++Here's a link with an ampersand in the URL http://example.com/?foo=1&bar=2.++Here's a link with an amersand in the link text: AT&T http://att.com/.++Here's an inline link /script?foo=1&bar=2.++Here's an inline link in pointy braces /script?foo=1&bar=2.++--------------------------------------------------------------------------------+Autolinks *autolinks*++With an ampersand: http://example.com/?foo=1&bar=2++- In a list?+- http://example.com/+- It should.++An e-mail address: nobody@nowhere.net++ Blockquoted: http://example.com/++Auto-links should not occur here: `<http://example.com/>`++>+ or here: <http://example.com/>+<+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Images *images*++From "Voyage dans la Lune" by Georges Melies (1902):++Here is a movie icon.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++================================================================================+Footnotes *footnotes*++Here is a footnote reference, |footnote1| and another. |footnote2| This should+not be a footnote reference, because it contains a space.[^my note] Here is an+inline note. |footnote3|++ Notes can go in quotes. |footnote4|++1. And in list items. |footnote5|++This paragraph should not be part of the note, as it is not indented.++ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *++ *footnote1*+Here is the footnote. It can go anywhere after the footnote reference. It need+not be placed at the end of the document.++ *footnote2*+Here's the long note. This one contains multiple blocks.++Subsequent blocks are indented to show that they belong to the footnote (as with+list items).++>+ { <code> }+<+If you want, you can indent every line, but you can also be lazy and just indent+the first line of each block.++ *footnote3*+This is easier to type. Inline notes may contain links http://google.com and `]`+verbatim characters, as well as [bracketed text].++ *footnote4*+In quote.++ *footnote5*+In list.++ vim:tw=80:sw=4:ts=4:ft=help:norl:et:
@@ -623,8 +623,9 @@ From “Voyage dans la Lune” by Georges Melies (1902): -[[image:lalune.jpg||alt="lalune" title="fig:Voyage dans la Lune"]]-+(((+[[image:lalune.jpg||alt="lalune" title="Voyage dans la Lune"]]+))) Here is a movie [[image:movie.jpg||alt="movie"]] icon.
@@ -593,7 +593,9 @@ From “Voyage dans la Lune” by Georges Melies (1902): -{{lalune.jpg|Voyage dans la Lune lalune}}+{{lalune.jpg|Voyage dans la Lune}}+lalune+ Here is a movie {{movie.jpg|movie}} icon.
@@ -4,13 +4,13 @@ style=, color=, contrastcolor=]+\setupurl[style=] % make chapter, section bookmarks visible when opening document \placebookmarks[chapter, section, subsection, subsubsection, subsubsubsection, subsubsubsubsection][chapter, section] \setupinteractionscreen[option={bookmark,title}] \setuppagenumbering[location={footer,middle}]-\setupbackend[export=yes] \setupstructure[state=start,method=auto] % use microtypography
@@ -1,21 +1,31 @@ % Options for packages loaded elsewhere \PassOptionsToPackage{unicode}{hyperref} \PassOptionsToPackage{hyphens}{url}-% \documentclass[+ ngerman,+ british,+ nswissgerman,+ spanish,+ french,+ english, ]{article}+\usepackage{xcolor} \usepackage{amsmath,amssymb}-\usepackage{lmodern}+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering \usepackage{iftex} \ifPDFTeX \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage{textcomp} % provide euro and other symbols \else % if luatex or xetex- \usepackage{unicode-math}+ \usepackage{unicode-math} % this also loads fontspec \defaultfontfeatures{Scale=MatchLowercase} \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1} \fi+\usepackage{lmodern}+\ifPDFTeX\else+ % xetex/luatex font selection+\fi % Use upquote if available, for straight quotes in verbatim environments \IfFileExists{upquote.sty}{\usepackage{upquote}}{} \IfFileExists{microtype.sty}{% use microtype if available@@ -32,28 +42,17 @@ }{% if KOMA class \KOMAoptions{parskip=half}} \makeatother-\usepackage{xcolor}-\setlength{\emergencystretch}{3em} % prevent overfull lines-\providecommand{\tightlist}{%- \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}-\setcounter{secnumdepth}{-\maxdimen} % remove section numbering \ifLuaTeX-\usepackage[bidi=basic]{babel}+\usepackage[bidi=basic,shorthands=off]{babel} \else-\usepackage[bidi=default]{babel}+\usepackage[bidi=default,shorthands=off]{babel} \fi-\babelprovide[main,import]{english}-\babelprovide[import]{ngerman}-\babelprovide[import]{british}-\babelprovide[import]{nswissgerman}-\babelprovide[import]{spanish}-\babelprovide[import]{french}-% get rid of language-specific shorthands (see #6817):-\let\LanguageShortHands\languageshorthands-\def\languageshorthands#1{} \ifLuaTeX- \usepackage{selnolig} % disable illegal ligatures+ \usepackage{selnolig} % disable illegal ligatures \fi+\setlength{\emergencystretch}{3em} % prevent overfull lines+\providecommand{\tightlist}{%+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} \ifPDFTeX \TeXXeTstate=1 \newcommand{\RL}[1]{\beginR #1\endR}@@ -61,9 +60,19 @@ \newenvironment{RTL}{\beginR}{\endR} \newenvironment{LTR}{\beginL}{\endL} \fi-\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}}+\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} % disable monospaced font for URLs+\urlstyle{same}+% fallback for those not using the hyperref driver hyperxmp:+\makeatletter+\@ifundefined{xmpquote}{\newcommand{\xmpquote}[1]{#1}}{}+\makeatother \hypersetup{ pdflang={en}, hidelinks,@@ -74,8 +83,7 @@ \begin{document} -\hypertarget{empty-divs-and-spans}{%-\section{Empty Divs and Spans}\label{empty-divs-and-spans}}+\section{Empty Divs and Spans}\label{empty-divs-and-spans} Some text and @@ -85,8 +93,7 @@ Next paragraph with a {span} and a word-thatincludesa{span}right? -\hypertarget{directionality}{%-\section{Directionality}\label{directionality}}+\section{Directionality}\label{directionality} Some text and @@ -103,8 +110,7 @@ Next paragraph with a \RL{rtl span} and a word-that-includesa\LR{ltrspan}right? -\hypertarget{languages}{%-\section{Languages}\label{languages}}+\section{Languages}\label{languages} Some text and @@ -122,8 +128,7 @@ Some \foreignlanguage{spanish}{Spanish text}. -\hypertarget{combined}{%-\section{Combined}\label{combined}}+\section{Combined}\label{combined} Some text and
@@ -0,0 +1,381 @@+Pandoc+ Meta { unMeta = fromList [] }+ [ Header 2 ( "sheet-1" , [] , [] ) [ Str "Main" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Strong [ Str "Person" ] ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Strong [ Str "Age" ] ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Strong [ Str "Location" ] ] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Anton" , Space , Str "Antich" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "23.0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Switzerland" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "James" , Space , Str "Bond" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "35.0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Moscow" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain+ [ Str "Just"+ , Space+ , Str "a"+ , Space+ , Str "random"+ , Space+ , Str "cell"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ , Header 2 ( "sheet-2" , [] , [] ) [ Str "Secondary" ]+ , Table+ ( "" , [] , [] )+ (Caption Nothing [])+ [ ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ , ( AlignDefault , ColWidthDefault )+ ]+ (TableHead+ ( "" , [] , [] )+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain+ [ Str "Sum"+ , Space+ , Str "of"+ , Space+ , Str "Age"+ ]+ ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Column" , Space , Str "Labels" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ ]+ ])+ [ TableBody+ ( "" , [] , [] )+ (RowHeadColumns 0)+ []+ [ Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Row" , Space , Str "Labels" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Moscow" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Switzerland" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "(blank)" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Grand" , Space , Str "Total" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Anton" , Space , Str "Antich" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "23.0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "23.0" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "James" , Space , Str "Bond" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "35.0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "35.0" ] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "(blank)" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ ]+ , Row+ ( "" , [] , [] )+ [ Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "Grand" , Space , Str "Total" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "35.0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "23.0" ] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [] ]+ , Cell+ ( "" , [] , [] )+ AlignDefault+ (RowSpan 1)+ (ColSpan 1)+ [ Plain [ Str "58.0" ] ]+ ]+ ]+ ]+ (TableFoot ( "" , [] , [] ) [])+ ]
binary file changed (absent → 13604 bytes)
@@ -1,181 +0,0 @@-<!doctype html>-<html lang="en">-<head>- <meta charset="utf-8">- <title>Try pandoc!</title>- <meta name="viewport" content="width=device-width, initial-scale=1.0">- <meta http-equiv="X-UA-Compatible" content="IE=edge">- <!--[if lt IE 9]>- <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>- <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>- <![endif]-->- <style>- body { margin: auto; font-family: sans-serif; font-size: 10pt; color: #555; }- #command { min-width: 26em; background-color: #555; color: #eee; border-radius: 9pt; margin: 6pt; padding: 6pt; }- h1 { margin-bottom: 1em; font-size: 166%; margin: 0; padding: 6pt; }- h1 a { text-decoration: none; color: inherit; }- label { font-weight: 600; }- textarea { height: auto; font-family: monospace; font-size: 10pt; margin-top: 15px; min-height: 65vh; width: 44vw; }- div.alert { margin: 1em; }- pre#results { width: 100%; margin-top: 15px; min-height: 65vh; width: 44vw; }- footer { color: #555; text-align: center; margin: 1em; }- p.version { color: #555; }- .container { margin: 12px; }- .row { display: flex; flex-wrap: nowrap; justify-content: space-between; }- #frompane { flex: 1; padding: 1em; }- #topane { flex: 1; padding: 1em; }- #command { font-family: monospace; padding: 1em; }- button#convert { vertical-align: bottom; }- pre#command { margin-top: 1em; background-color: transparent; border: none; }- </style>-</head>-<body>-<div class="container">- <div class="row">- <div id="title">- <h1>Try <a href="https://pandoc.org">pandoc</a>!</h1>- </div>- <div id="command">- <pre id="command"></pre>- </div>- </div>- <div class="row">- <div id="frompane">- <button id="convert">Convert</button>- - <label for="from">- from- </label>- <select id="from">- <option value="bibtex">BibTeX</option>- <option value="biblatex">BibLaTeX</option>- <option value="commonmark">CommonMark</option>- <option value="commonmark_x">CommonMark (extended)</option>- <option value="creole">Creole</option>- <option value="csljson">CSL JSON</option>- <option value="csv">CSV</option>- <option value="docbook">DocBook</option>- <option value="dokuwiki">DokuWiki</option>- <option value="docx">Docx (Word)</option>- <option value="epub">EPUB</option>- <option value="fb2">FB2</option>- <option value="haddock">Haddock markup</option>- <option value="html">HTML</option>- <option value="jats">JATS</option>- <option value="jira">Jira</option>- <option value="ipynb">Jupyter Notebook (ipynb)</option>- <option value="latex">LaTeX</option>- <option value="man">Man</option>- <option value="markdown" selected>Markdown (pandoc)</option>- <option value="gfm">Markdown (GitHub-flavored)</option>- <option value="markdown_phpextra">Markdown (PHP Markdown Extra)</option>- <option value="markdown_strict">Markdown (strict)</option>- <option value="mediawiki">MediaWiki</option>- <option value="markdown_mmd">MultiMarkdown</option>- <option value="muse">Muse</option>- <option value="native">Native (Pandoc AST)</option>- <option value="odt">ODT</option>- <option value="opml">OPML</option>- <option value="org">Org Mode</option>- <option value="ris">RIS</option>- <option value="rst">reStructuredText</option>- <option value="t2t">Txt2Tags</option>- <option value="textile">Textile</option>- <option value="tikiwiki">TikiWiki</option>- <option value="twiki">TWiki</option>- <option value="vimwiki">Vimwiki</option>- </select><br/>- <label for="loadfile">Load from file</label>- <input id="loadfile" type="file" />- <br/>- <textarea id="text" rows="15"></textarea>- <br/>- <label for="examples">- Examples- </label>- <select id="examples">- <option value="" selected disabled>Select an example</option>- <option value="https://pandoc.org/try/?text=%40BOOK%7BWurm2011-ho%2C%0A++title+++++%3D+%22%7BSubstanz+und+Qualität+%3A+Ein+Beitrag+zur+Interpretation+der%0A+++++++++++++++plotinischen+Traktate+VI%2C1%2C+2+und+3%7D%22%2C%0A++author++++%3D+%22Wurm%2C+Klaus%22%2C%0A++publisher+%3D+%22De+Gruyter%22%2C%0A++series++++%3D+%22Quellen+und+Studien+zur+Philosophie%22%2C%0A++edition+++%3D+%22Reprint+2011%22%2C%0A++year++++++%3D++2011%2C%0A++address+++%3D+%22Berlin%22%2C%0A++keywords++%3D+%22%21%21%21+Plotinus+translation%22%2C%0A++language++%3D+%22de%22%0A%7D%0A&from=bibtex&to=csljson&standalone=false">BibTeX to CSL JSON</option>- <option value="https://pandoc.org/try/?text=---%0Areferences%3A%0A-+author%3A%0A++-+family%3A+Salam%0A++++given%3A+Abdus%0A++container-title%3A+%22Elementary+particle+theory%3A+Relativistic+groups+and%0A++++analyticity.+Proceedings+of+the+eighth+Nobel+symposium%22%0A++editor%3A%0A++-+family%3A+Svartholm%0A++++given%3A+Nils%0A++event-date%3A+1968-05-19%2F1968-05-25%0A++event-place%3A+Aspenäsgarden%2C+Lerum%0A++id%3A+salam%0A++issued%3A+1968%0A++page%3A+367-377%0A++publisher%3A+Almquist+%26+Wiksell%0A++publisher-place%3A+Stockholm%0A++title%3A+Weak+and+electromagnetic+interactions%0A++type%3A+paper-conference%0A---%0A%0A%40salam+%5Bp.+370%5D+says+some+interesting+things.%0A&from=markdown&to=man&standalone=false&citeproc=true">Markdown to man with citation</option>- <option value="https://pandoc.org/try/?text=%3D%3D+Definition+%3D%3D%0AAlthough+seemingly+different%2C+the+various+approaches+to+defining+tensors+describe+the+same+geometric+concept+using+different+language+and+at+different+levels+of+abstraction.%0A%0A%3D%3D%3D+As+multidimensional+arrays+%3D%3D%3D%0AA+tensor+may+be+represented+as+an+array+%28potentially+multidimensional%29.+Just+as+a+%5B%5BVector+space%7Cvector%5D%5D+in+an+%7B%7Bmvar%7Cn%7D%7D-%5B%5Bdimension+%28vector+space%29%7Cdimensional%5D%5D+space+is+represented+by+a+one-dimensional+array+with+%7B%7Bmvar%7Cn%7D%7D+components+with+respect+to+a+given+%5B%5BBasis+%28linear+algebra%29%23Ordered+bases+and+coordinates%7Cbasis%5D%5D%2C+any+tensor+with+respect+to+a+basis+is+represented+by+a+multidimensional+array.++For+example%2C+a+%5B%5Blinear+operator%5D%5D+is+represented+in+a+basis+as+a+two-dimensional+square+%7B%7Bmath%7C%27%27n%27%27+×+%27%27n%27%27%7D%7D+array.++The+numbers+in+the+multidimensional+array+are+known+as+the+%27%27scalar+components%27%27+of+the+tensor+or+simply+its+%27%27components%27%27.++They+are+denoted+by+indices+giving+their+position+in+the+array%2C+as+%5B%5Bsubscript+and+superscript%7Csubscripts+and+superscripts%5D%5D%2C+following+the+symbolic+name+of+the+tensor.++For+example%2C+the+components+of+an+order+%7B%7Bmath%7C2%7D%7D+tensor+%7B%7Bmvar%7CT%7D%7D+could+be+denoted+%7B%7Bmath%7C%27%27T%27%27%3Csub%3E%27%27ij%27%27%3C%2Fsub%3E%7D%7D%E2%80%AF%2C+where+%7B%7Bmvar%7Ci%7D%7D+and+%7B%7Bmvar%7Cj%7D%7D+are+indices+running+from+%7B%7Bmath%7C1%7D%7D+to+%7B%7Bmvar%7Cn%7D%7D%2C+or+also+by+%7B%7Bmath%7C%27%27T%27%27%26thinsp%3B%7B%7Bsu%7Cb%3D%27%27j%27%27%7Cp%3D%27%27i%27%27%7D%7D%7D%7D.++Whether+an+index+is+displayed+as+a+superscript+or+subscript+depends+on+the+transformation+properties+of+the+tensor%2C+described+below.+Thus+while+%7B%7Bmath%7C%27%27T%27%27%3Csub%3E%27%27ij%27%27%3C%2Fsub%3E%7D%7D+and+%7B%7Bmath%7C%27%27T%27%27%26thinsp%3B%7B%7Bsu%7Cb%3D%27%27j%27%27%7Cp%3D%27%27i%27%27%7D%7D%7D%7D+can+both+be+expressed+as+%27%27n%27%27+by+%27%27n%27%27+matrices%2C+and+are+numerically+related+via+%5B%5BRaising+and+lowering+indices%7Cindex+juggling%5D%5D%2C+the+difference+in+their+transformation+laws+indicates+it+would+be+improper+to+add+them+together.+The+total+number+of+indices+required+to+identify+each+component+uniquely+is+equal+to+the+%5B%5BArray+data+structure%23Dimension%7Cdimension%5D%5D+of+the+array%2C+and+is+called+the+%27%27order%27%27%2C+%27%27degree%27%27+or+%27%27rank%27%27+of+the+tensor.++However%2C+the+term+%22rank%22+generally+has+%5B%5Btensor+rank%7Canother+meaning%5D%5D+in+the+context+of+matrices+and+tensors.%0A%0AJust+as+the+components+of+a+vector+change+when+we+change+the+%5B%5Bbasis+%28linear+algebra%29%7Cbasis%5D%5D+of+the+vector+space%2C+the+components+of+a+tensor+also+change+under+such+a+transformation.++Each+type+of+tensor+comes+equipped+with+a+%27%27transformation+law%27%27+that+details+how+the+components+of+the+tensor+respond+to+a+%5B%5Bchange+of+basis%5D%5D.++The+components+of+a+vector+can+respond+in+two+distinct+ways+to+a+%5B%5Bchange+of+basis%5D%5D+%28see+%5B%5Bcovariance+and+contravariance+of+vectors%5D%5D%29%2C+where+the+new+%5B%5Bbasis+vectors%5D%5D+%3Cmath%3E%5Cmathbf%7B%5Chat%7Be%7D%7D_i%3C%2Fmath%3E+are+expressed+in+terms+of+the+old+basis+vectors+%3Cmath%3E%5Cmathbf%7Be%7D_j%3C%2Fmath%3E+as%2C%0A%3A%3Cmath%3E%5Cmathbf%7B%5Chat%7Be%7D%7D_i+%3D+%5Csum_%7Bj%3D1%7D%5En+%5Cmathbf%7Be%7D_j+R%5Ej_i+%3D+%5Cmathbf%7Be%7D_j+R%5Ej_i+.%3C%2Fmath%3E%0A%0AHere+%27%27R%27%27%3Csup%3E%27%27+j%27%27%3C%2Fsup%3E%3Csub%3E%27%27i%27%27%3C%2Fsub%3E+are+the+entries+of+the+change+of+basis+matrix%2C+and+in+the+rightmost+expression+the+%5B%5Bsummation%5D%5D+sign+was+suppressed%3A+this+is+the+%5B%5BEinstein+summation+convention%5D%5D%2C+which+will+be+used+throughout+this+article.%3Cref+group%3D%22Note%22%3EThe+Einstein+summation+convention%2C+in+brief%2C+requires+the+sum+to+be+taken+over+all+values+of+the+index+whenever+the+same+symbol+appears+as+a+subscript+and+superscript+in+the+same+term.++For+example%2C+under+this+convention+%3Cmath%3EB_i+C%5Ei+%3D+B_1+C%5E1+%2B+B_2+C%5E2+%2B+%5Ccdots+B_n+C%5En%3C%2Fmath%3E%3C%2Fref%3E++The+components+%27%27v%27%27%3Csup%3E%27%27i%27%27%3C%2Fsup%3E+of+a+column+vector+%27%27%27v%27%27%27+transform+with+the+%5B%5Bmatrix+inverse%7Cinverse%5D%5D+of+the+matrix+%27%27R%27%27%2C%0A%3A%3Cmath%3E%5Chat%7Bv%7D%5Ei+%3D+%5Cleft%28R%5E%7B-1%7D%5Cright%29%5Ei_j+v%5Ej%2C%3C%2Fmath%3E%0A%0Awhere+the+hat+denotes+the+components+in+the+new+basis.++This+is+called+a+%27%27contravariant%27%27+transformation+law%2C+because+the+vector+components+transform+by+the+%27%27inverse%27%27+of+the+change+of+basis.++In+contrast%2C+the+components%2C+%27%27w%27%27%3Csub%3E%27%27i%27%27%3C%2Fsub%3E%2C+of+a+covector+%28or+row+vector%29%2C+%27%27%27w%27%27%27%2C+transform+with+the+matrix+%27%27R%27%27+itself%2C%0A%3A%3Cmath%3E%5Chat%7Bw%7D_i+%3D+w_j+R%5Ej_i+.%3C%2Fmath%3E&from=mediawiki&to=docx&standalone=false">MediaWiki to docx with equations</option>- </select>-- </div>- <div id="topane">- <label for="to">- to- </label>- <select id="to">- <option value="asciidoc">AsciiDoc (original)</option>- <option value="asciidoctor">AsciiDoc (asciidoctor-flavored)</option>- <option value="beamer">LaTeX Beamer</option>- <option value="bibtex">BibTeX</option>- <option value="biblatex">BibLaTeX</option>- <option value="commonmark">CommonMark</option>- <option value="context">ConTeXt</option>- <option value="csljson">CSL JSON</option>- <option value="docbook4">DocBook v4</option>- <option value="docbook5">DocBook v5</option>- <option value="docx">Docx (Word)</option>- <option value="dokuwiki">DokuWiki</option>- <option value="dzslides">DZSlides</option>- <option value="epub2">EPUB v2</option>- <option value="epub3">EPUB v3</option>- <option value="haddock">Haddock markup</option>- <option value="html4">HTML 4</option>- <option value="html5" selected>HTML 5</option>- <option value="icml">ICML</option>- <option value="jats">JATS</option>- <option value="jira">Jira</option>- <option value="json">JSON</option>- <option value="ipynb">Jupyter Notebook (ipynb)</option>- <option value="latex">LaTeX</option>- <option value="man">Man</option>- <option value="ms">Ms</option>- <option value="markdown">Markdown (pandoc)</option>- <option value="gfm">Markdown (GitHub-flavored)</option>- <option value="markdown_phpextra">Markdown (PHP Markdown Extra)</option>- <option value="markdown_strict">Markdown (strict)</option>- <option value="mediawiki">MediaWiki</option>- <option value="markdown_mmd">MultiMarkdown</option>- <option value="muse">Muse</option>- <option value="native">Native (Pandoc AST)</option>- <option value="odt">ODT</option>- <option value="opendocument">OpenDocument</option>- <option value="opml">OPML</option>- <option value="org">Org Mode</option>- <option value="plain">Plain text</option>- <option value="pptx">Powerpoint</option>- <option value="revealjs">reveal.js</option>- <option value="rst">reStructuredText</option>- <option value="rtf">RTF</option>- <option value="S5">S5</option>- <option value="slideous">Slideous</option>- <option value="slidy">Slidy</option>- <option value="tei">TEI</option>- <option value="texinfo">Texinfo</option>- <option value="textile">Textile</option>- <option value="zimwiki">ZimWiki</option>- </select>- <input type="checkbox" id="standalone" name="standalone">- <label for="standalone">Standalone- <a href="https://pandoc.org/MANUAL.html#option--standalone" target="_blank">(?)</a>- </label>- <input type="checkbox" id="citeproc" name="citeproc">- <label for="citeproc">Citeproc- <a href="https://pandoc.org/MANUAL.html#option--citeproc" target="_blank">(?)</a>- </label>- <br/>- <a id="permalink" title="link to this conversion" href="">permalink</a></br/>- <pre id="results"></pre>- </div>- </div>-</div>-<footer>- <p class="version">pandoc version <span id="version"></span></p>-</footer>--<script src="trypandoc.js?202208191048"></script>--</body>-</html>
@@ -1,166 +0,0 @@-"use strict";--var params = {- text: '"hello *world*"',- to: 'html5',- from: 'markdown',- standalone: false,- citeproc: false };--function permalink() {- let input = document.getElementById("text").value;- let from = document.getElementById("from").value;- let to = document.getElementById("to").value;- let standalone = document.getElementById("standalone").checked ? true : false;- let citeproc = document.getElementById("citeproc").checked ? true : false;- let href = window.location.href;- const URLparams = new URLSearchParams(Object.entries({text: input, from: from, to: to, standalone: standalone, citeproc: citeproc}));- return href.replace(/([?].*)?$/,"?" + URLparams);-}--const binaryFormats = {- docx: { extension: "docx",- mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" },- odt: { extension: "odt",- mime: "application/vnd.oasis.opendocument.text" },- pptx: { extension: "pptx",- mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation" },- epub: { extension: "epub",- mime: "application/epub+zip" },- epub2: { extension: "epub",- mime: "application/epub+zip" },- epub3: { extension: "epub",- mime: "application/epub+zip" }-};--const binaryMimeTypes = {- ["application/epub+zip"]: true,- ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"]: true,- ["application/vnd.openxmlformats-officedocument.presentationml.presentation"]: true,- ["application/vnd.oasis.opendocument.text"]: true-};--function paramsFromURL() {- if (window.location.search.length > 0) {- const uparams = new URLSearchParams(window.location.search);- params.text = uparams.get("text") || "";- params.from = uparams.get("from") || "markdown";- params.to = uparams.get("to") || "html5";- params.standalone = uparams.get("standalone") === "true";- params.citeproc = uparams.get("citeproc") === "true";- }-}--function handleErrors(response) {- if (response.status == 503) {- throw Error("Conversion timed out.")-// } else if (!response.ok) {-// throw Error(response.statusText);- }- return response;-}--function convert() {- document.getElementById("results").textContent = "";- let text = document.getElementById("text").value;- let from = document.getElementById("from").value;- let to = document.getElementById("to").value;- let standalone = document.getElementById("standalone").checked;- let citeproc = document.getElementById("citeproc").checked;- params = { text: text, from: from, to: to, standalone: standalone,- citeproc: citeproc };-- if (text && text != "") {- let commandString = "pandoc"- + " --from " + from + " --to " + to- + (standalone ? " --standalone" : "")- + (citeproc ? " --citeproc" : "") ;- document.getElementById("command").textContent = commandString;- fetch("/cgi-bin/pandoc-server.cgi", {- method: "POST",- headers: {"Content-Type": "application/json"},- body: JSON.stringify({ from: params.from,- to: params.to,- text: params.text,- standalone: params.standalone,- citeproc: params.citeproc })- })- .then(handleErrors)- .then(response => response.text())- .then(restext => {- let binary = binaryFormats[to];- if (binary) {- document.getElementById("results").innerHTML =- '<a download="trypandoc.' + binary.extension +- '" href="data:' + binary.mime + ';base64,' + restext +- '">click to download trypandoc.' + binary.extension + '</a>';- } else {- document.getElementById("results").textContent = restext;- }- document.getElementById("permalink").href = permalink();- })- .catch(error => {- document.getElementById("results").textContent = error- }- );- };-}--(function() {- paramsFromURL();- document.getElementById("text").value = params.text;- document.getElementById("from").value = params.from;- document.getElementById("to").value = params.to;- document.getElementById("standalone").checked = params.standalone;- document.getElementById("citeproc").checked = params.citeproc;-- document.getElementById("convert").onclick = convert;- document.getElementById("from").onchange = convert;- document.getElementById("to").onchange = convert;- document.getElementById("standalone").onchange = convert;- document.getElementById("citeproc").onchange = convert;-- document.getElementById("examples").onchange =- (e => window.location.href = e.target.value );-- const fileInput = document.getElementById('loadfile');-- // Listen for the change event so we can capture the file- fileInput.addEventListener('change', (e) => {- // Get a reference to the file- const file = e.target.files[0];- const mimetype = file.type;- let binary = binaryMimeTypes[mimetype];-- // Encode the file using the FileReader API- const reader = new FileReader();- let inputtext = document.getElementById("text");- reader.onloadend = () => {- // Use a regex to remove data url part- if (binary) {- const base64String = reader.result- .replace('data:', '')- .replace(/^.+,/, '');- inputtext.value = base64String;- } else {- inputtext.value = reader.result;- }- };- if (binary) {- reader.readAsDataURL(file);- } else {- reader.readAsText(file);- }- });-- fetch("/cgi-bin/pandoc-server.cgi/version")- .then(handleErrors)- .then(response => response.text())- .then(restext =>- document.getElementById("version").textContent = restext- );-- convert();--})();-
@@ -0,0 +1,113 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.XML.Light+ Copyright : Copyright (C) 2021-2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++xml-light, which we used in pandoc's the XML-based readers, has+some limitations: in particular, it produces nodes with String+instead of Text, and the parser falls over on processing instructions+(see #7091).++This module exports much of the API of xml-light, but using Text instead+of String. In addition, the xml-light parsers are replaced by xml-conduit's+well-tested parser. (The xml-conduit types are mapped to types+isomorphic to xml-light's, to avoid the need for massive code modifications+elsewhere.) Bridge functions to map xml-light types to this module's+types are also provided (since libraries like texmath still use xml-light).++Another advantage of the xml-conduit parser is that it gives us+detailed information on xml parse errors.++In the future we may want to move to using xml-conduit or another+xml library in the code base, but this change gives us+better performance and accuracy without much change in the+code that used xml-light.+-}+module Text.Pandoc.XML.Light+ ( module Text.Pandoc.XML.Light.Types+ , module Text.Pandoc.XML.Light.Proc+ , module Text.Pandoc.XML.Light.Output+ -- * Replacement for xml-light's Text.XML.Input+ , parseXMLElement+ , parseXMLContents+ -- * Versions that allow passing in a custom entity table+ , parseXMLElementWithEntities+ , parseXMLContentsWithEntities+ ) where++import qualified Control.Exception as E+import qualified Text.XML as Conduit+import Text.XML.Unresolved (InvalidEventStream(..))+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Map as M+import Data.Maybe (mapMaybe)+import Text.Pandoc.XML.Light.Types+import Text.Pandoc.XML.Light.Proc+import Text.Pandoc.XML.Light.Output+import qualified Data.XML.Types as XML++-- Drop in replacement for parseXMLDoc in xml-light.+parseXMLElement :: TL.Text -> Either T.Text Element+parseXMLElement = parseXMLElementWithEntities mempty++-- Drop in replacement for parseXMLDoc in xml-light.+parseXMLElementWithEntities :: M.Map T.Text T.Text+ -> TL.Text -> Either T.Text Element+parseXMLElementWithEntities entityMap t =+ elementToElement . Conduit.documentRoot <$>+ either (Left . T.pack . E.displayException) Right+ (Conduit.parseText Conduit.def{ Conduit.psRetainNamespaces = True+ , Conduit.psDecodeEntities = decodeEnts } t)+ where+ decodeEnts ref = case M.lookup ref entityMap of+ Nothing -> XML.ContentEntity ref+ Just t' -> XML.ContentText t'++parseXMLContents :: TL.Text -> Either T.Text [Content]+parseXMLContents = parseXMLContentsWithEntities mempty++parseXMLContentsWithEntities :: M.Map T.Text T.Text+ -> TL.Text -> Either T.Text [Content]+parseXMLContentsWithEntities entityMap t =+ case Conduit.parseText Conduit.def{ Conduit.psRetainNamespaces = True+ , Conduit.psDecodeEntities = decodeEnts+ } t of+ Left e ->+ case E.fromException e of+ Just (ContentAfterRoot _) ->+ elContent <$> parseXMLElementWithEntities entityMap+ ("<wrapper>" <> t <> "</wrapper>")+ _ -> Left . T.pack . E.displayException $ e+ Right x -> Right [Elem . elementToElement . Conduit.documentRoot $ x]+ where+ decodeEnts ref = case M.lookup ref entityMap of+ Nothing -> XML.ContentEntity ref+ Just t' -> XML.ContentText t'++elementToElement :: Conduit.Element -> Element+elementToElement (Conduit.Element name attribMap nodes) =+ Element (nameToQname name) attrs (mapMaybe nodeToContent nodes) Nothing+ where+ attrs = map (\(n,v) -> Attr (nameToQname n) v) $+ M.toList attribMap+ nameToQname (Conduit.Name localName mbns mbpref) =+ case mbpref of+ Nothing ->+ case T.stripPrefix "xmlns:" localName of+ Just rest -> QName rest mbns (Just "xmlns")+ Nothing -> QName localName mbns mbpref+ _ -> QName localName mbns mbpref++nodeToContent :: Conduit.Node -> Maybe Content+nodeToContent (Conduit.NodeElement el) =+ Just (Elem (elementToElement el))+nodeToContent (Conduit.NodeContent t) =+ Just (Text (CData CDataText t Nothing))+nodeToContent _ = Nothing
@@ -0,0 +1,234 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{- |+ Module : Text.Pandoc.XML.Light.Output+ Copyright : Copyright (C) 2007 Galois, Inc., 2021-2024 John MacFarlane+ License : GNU GPL, version 2 or above+++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++ This code is based on code from xml-light, released under the BSD3 license.+ We use a text Builder instead of ShowS.+-}+module Text.Pandoc.XML.Light.Output+ ( -- * Replacement for xml-light's Text.XML.Output+ ppTopElement+ , ppElement+ , ppContent+ , ppcElement+ , ppcContent+ , showTopElement+ , showElement+ , showContent+ , useShortEmptyTags+ , defaultConfigPP+ , ConfigPP(..)+ ) where++import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import Data.Text.Lazy.Builder (Builder, singleton, fromText, toLazyText)+import Text.Pandoc.XML.Light.Types++--+-- duplicates functions from Text.XML.Output+--++-- | The XML 1.0 header+xmlHeader :: Text+xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+++--------------------------------------------------------------------------------+data ConfigPP = ConfigPP+ { shortEmptyTag :: QName -> Bool+ , prettify :: Bool+ }++-- | Default pretty orinting configuration.+-- * Always use abbreviate empty tags.+defaultConfigPP :: ConfigPP+defaultConfigPP = ConfigPP { shortEmptyTag = const True+ , prettify = False+ }++-- | The predicate specifies for which empty tags we should use XML's+-- abbreviated notation <TAG />. This is useful if we are working with+-- some XML-ish standards (such as certain versions of HTML) where some+-- empty tags should always be displayed in the <TAG></TAG> form.+useShortEmptyTags :: (QName -> Bool) -> ConfigPP -> ConfigPP+useShortEmptyTags p c = c { shortEmptyTag = p }+++-- | Specify if we should use extra white-space to make document more readable.+-- WARNING: This adds additional white-space to text elements,+-- and so it may change the meaning of the document.+useExtraWhiteSpace :: Bool -> ConfigPP -> ConfigPP+useExtraWhiteSpace p c = c { prettify = p }++-- | A configuration that tries to make things pretty+-- (possibly at the cost of changing the semantics a bit+-- through adding white space.)+prettyConfigPP :: ConfigPP+prettyConfigPP = useExtraWhiteSpace True defaultConfigPP+++--------------------------------------------------------------------------------+++-- | Pretty printing renders XML documents faithfully,+-- with the exception that whitespace may be added\/removed+-- in non-verbatim character data.+ppTopElement :: Element -> Text+ppTopElement = ppcTopElement prettyConfigPP++-- | Pretty printing elements+ppElement :: Element -> Text+ppElement = ppcElement prettyConfigPP++-- | Pretty printing content+ppContent :: Content -> Text+ppContent = ppcContent prettyConfigPP++-- | Pretty printing renders XML documents faithfully,+-- with the exception that whitespace may be added\/removed+-- in non-verbatim character data.+ppcTopElement :: ConfigPP -> Element -> Text+ppcTopElement c e = T.unlines [xmlHeader,ppcElement c e]++-- | Pretty printing elements+ppcElement :: ConfigPP -> Element -> Text+ppcElement c = TL.toStrict . toLazyText . ppElementS c mempty++-- | Pretty printing content+ppcContent :: ConfigPP -> Content -> Text+ppcContent c = TL.toStrict . toLazyText . ppContentS c mempty++ppcCData :: ConfigPP -> CData -> Text+ppcCData c = TL.toStrict . toLazyText . ppCDataS c mempty++type Indent = Builder++-- | Pretty printing content using ShowT+ppContentS :: ConfigPP -> Indent -> Content -> Builder+ppContentS c i x = case x of+ Elem e -> ppElementS c i e+ Text t -> ppCDataS c i t+ CRef r -> showCRefS r++ppElementS :: ConfigPP -> Indent -> Element -> Builder+ppElementS c i e = i <> tagStart (elName e) (elAttribs e) <>+ (case elContent e of+ [] | "?" `T.isPrefixOf` qName name -> fromText " ?>"+ | shortEmptyTag c name -> fromText " />"+ [Text t] -> singleton '>' <> ppCDataS c mempty t <> tagEnd name+ cs -> singleton '>' <> nl <>+ mconcat (map ((<> nl) . ppContentS c (sp <> i)) cs) <>+ i <> tagEnd name+ where (nl,sp) = if prettify c then ("\n"," ") else ("","")+ )+ where name = elName e++ppCDataS :: ConfigPP -> Indent -> CData -> Builder+ppCDataS c i t = i <> if cdVerbatim t /= CDataText || not (prettify c)+ then showCDataS t+ else foldr cons mempty (T.unpack (showCData t))+ where cons :: Char -> Builder -> Builder+ cons '\n' ys = singleton '\n' <> i <> ys+ cons y ys = singleton y <> ys++++--------------------------------------------------------------------------------++-- | Adds the <?xml?> header.+showTopElement :: Element -> Text+showTopElement c = xmlHeader <> showElement c++showContent :: Content -> Text+showContent = ppcContent defaultConfigPP++showElement :: Element -> Text+showElement = ppcElement defaultConfigPP++showCData :: CData -> Text+showCData = ppcCData defaultConfigPP++-- Note: crefs should not contain '&', ';', etc.+showCRefS :: Text -> Builder+showCRefS r = singleton '&' <> fromText r <> singleton ';'++-- | Convert a text element to characters.+showCDataS :: CData -> Builder+showCDataS cd =+ case cdVerbatim cd of+ CDataText -> escStr (cdData cd)+ CDataVerbatim -> fromText "<![CDATA[" <> escCData (cdData cd) <>+ fromText "]]>"+ CDataRaw -> fromText (cdData cd)++--------------------------------------------------------------------------------+escCData :: Text -> Builder+escCData t+ | "]]>" `T.isPrefixOf` t =+ fromText "]]]]><![CDATA[>" <> fromText (T.drop 3 t)+escCData t+ = case T.uncons t of+ Nothing -> mempty+ Just (c,t') -> singleton c <> escCData t'++escChar :: Char -> Builder+escChar c = case c of+ '<' -> fromText "<"+ '>' -> fromText ">"+ '&' -> fromText "&"+ '"' -> fromText """+ -- we use ' instead of ' because IE apparently has difficulties+ -- rendering ' in xhtml.+ -- Reported by Rohan Drape <rohan.drape@gmail.com>.+ '\'' -> fromText "'"+ _ -> singleton c++ {- original xml-light version:+ -- NOTE: We escape '\r' explicitly because otherwise they get lost+ -- when parsed back in because of then end-of-line normalization rules.+ _ | isPrint c || c == '\n' -> singleton c+ | otherwise -> showText "&#" . showsT oc . singleton ';'+ where oc = ord c+ -}++escStr :: Text -> Builder+escStr cs = if T.any needsEscape cs+ then mconcat (map escChar (T.unpack cs))+ else fromText cs+ where+ needsEscape '<' = True+ needsEscape '>' = True+ needsEscape '&' = True+ needsEscape '"' = True+ needsEscape '\'' = True+ needsEscape _ = False++tagEnd :: QName -> Builder+tagEnd qn = fromText "</" <> showQName qn <> singleton '>'++tagStart :: QName -> [Attr] -> Builder+tagStart qn as = singleton '<' <> showQName qn <> as_str+ where as_str = if null as+ then mempty+ else mconcat (map showAttr as)++showAttr :: Attr -> Builder+showAttr (Attr qn v) = singleton ' ' <> showQName qn <>+ singleton '=' <>+ singleton '"' <> escStr v <> singleton '"'++showQName :: QName -> Builder+showQName q =+ case qPrefix q of+ Nothing -> fromText (qName q)+ Just p -> fromText p <> singleton ':' <> fromText (qName q)
@@ -0,0 +1,137 @@+{-# LANGUAGE FlexibleInstances #-}+{- |+ Module : Text.Pandoc.XML.Light.Proc+ Copyright : Copyright (C) 2007 Galois, Inc., 2021-2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++ This code is taken from xml-light, released under the BSD3 license.+-}+module Text.Pandoc.XML.Light.Proc+ (+ -- * Replacement for xml-light's Text.XML.Proc+ strContent+ , onlyElems+ , elChildren+ , onlyText+ , findChildren+ , filterChildren+ , filterChildrenName+ , findChild+ , filterChild+ , filterChildName+ , findElement+ , filterElement+ , filterElementName+ , findElements+ , filterElements+ , filterElementsName+ , findAttr+ , lookupAttr+ , lookupAttrBy+ , findAttrBy+ ) where++import Data.Text (Text)+import Data.Maybe (listToMaybe)+import Data.List(find)+import Text.Pandoc.XML.Light.Types++--+-- copied from xml-light Text.XML.Proc+--++-- | Get the text value of an XML element. This function+-- ignores non-text elements, and concatenates all text elements.+strContent :: Element -> Text+strContent = mconcat . map cdData . onlyText . elContent++-- | Select only the elements from a list of XML content.+onlyElems :: [Content] -> [Element]+onlyElems xs = [ x | Elem x <- xs ]++-- | Select only the elements from a parent.+elChildren :: Element -> [Element]+elChildren e = [ x | Elem x <- elContent e ]++-- | Select only the text from a list of XML content.+onlyText :: [Content] -> [CData]+onlyText xs = [ x | Text x <- xs ]++-- | Find all immediate children with the given name.+findChildren :: QName -> Element -> [Element]+findChildren q e = filterChildren ((q ==) . elName) e++-- | Filter all immediate children wrt a given predicate.+filterChildren :: (Element -> Bool) -> Element -> [Element]+filterChildren p e = filter p (onlyElems (elContent e))+++-- | Filter all immediate children wrt a given predicate over their names.+filterChildrenName :: (QName -> Bool) -> Element -> [Element]+filterChildrenName p e = filter (p.elName) (onlyElems (elContent e))+++-- | Find an immediate child with the given name.+findChild :: QName -> Element -> Maybe Element+findChild q e = listToMaybe (findChildren q e)++-- | Find an immediate child with the given name.+filterChild :: (Element -> Bool) -> Element -> Maybe Element+filterChild p e = listToMaybe (filterChildren p e)++-- | Find an immediate child with name matching a predicate.+filterChildName :: (QName -> Bool) -> Element -> Maybe Element+filterChildName p e = listToMaybe (filterChildrenName p e)++-- | Find the left-most occurrence of an element matching given name.+findElement :: QName -> Element -> Maybe Element+findElement q e = listToMaybe (findElements q e)++-- | Filter the left-most occurrence of an element wrt. given predicate.+filterElement :: (Element -> Bool) -> Element -> Maybe Element+filterElement p e = listToMaybe (filterElements p e)++-- | Filter the left-most occurrence of an element wrt. given predicate.+filterElementName :: (QName -> Bool) -> Element -> Maybe Element+filterElementName p e = listToMaybe (filterElementsName p e)++-- | Find all non-nested occurrences of an element.+-- (i.e., once we have found an element, we do not search+-- for more occurrences among the element's children).+findElements :: QName -> Element -> [Element]+findElements qn e = filterElementsName (qn==) e++-- | Find all non-nested occurrences of an element wrt. given predicate.+-- (i.e., once we have found an element, we do not search+-- for more occurrences among the element's children).+filterElements :: (Element -> Bool) -> Element -> [Element]+filterElements p e+ | p e = [e]+ | otherwise = concatMap (filterElements p) $ onlyElems $ elContent e++-- | Find all non-nested occurrences of an element wrt a predicate over element names.+-- (i.e., once we have found an element, we do not search+-- for more occurrences among the element's children).+filterElementsName :: (QName -> Bool) -> Element -> [Element]+filterElementsName p e = filterElements (p.elName) e++-- | Lookup the value of an attribute.+findAttr :: QName -> Element -> Maybe Text+findAttr x e = lookupAttr x (elAttribs e)++-- | Lookup attribute name from list.+lookupAttr :: QName -> [Attr] -> Maybe Text+lookupAttr x = lookupAttrBy (x ==)++-- | Lookup the first attribute whose name satisfies the given predicate.+lookupAttrBy :: (QName -> Bool) -> [Attr] -> Maybe Text+lookupAttrBy p as = attrVal `fmap` find (p . attrKey) as++-- | Lookup the value of the first attribute whose name+-- satisfies the given predicate.+findAttrBy :: (QName -> Bool) -> Element -> Maybe Text+findAttrBy p e = lookupAttrBy p (elAttribs e)
@@ -0,0 +1,191 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE DeriveDataTypeable #-}+{- |+ Module : Text.Pandoc.XML.Light.Types+ Copyright : Copyright (C) 2007 Galois, Inc., 2021-2024 John MacFarlane+ License : GNU GPL, version 2 or above++ Maintainer : John MacFarlane <jgm@berkeley.edu>+ Stability : alpha+ Portability : portable++ This code is taken from xml-light, released under the BSD3 license.+ It has been modified to use Text instead of String, and the fromXL*+ functions have been added.+-}+module Text.Pandoc.XML.Light.Types+ ( -- * Basic types, duplicating those from xml-light but with Text+ -- instead of String+ Line+ , Content(..)+ , Element(..)+ , Attr(..)+ , CData(..)+ , CDataKind(..)+ , QName(..)+ , Node(..)+ , unode+ , unqual+ , add_attr+ , add_attrs+ -- * Conversion functions from xml-light types+ , fromXLQName+ , fromXLCData+ , fromXLElement+ , fromXLAttr+ , fromXLContent+ ) where++import Data.Text (Text)+import qualified Data.Text as T+import Data.Data (Data)+import Data.Typeable (Typeable)+import qualified Text.XML.Light as XL++--+-- type definitions lightly modified from xml-light+--++-- | A line is an Integer+type Line = Integer++-- | XML content+data Content = Elem Element+ | Text CData+ | CRef Text+ deriving (Show, Typeable, Data, Ord, Eq)++-- | XML elements+data Element = Element {+ elName :: QName,+ elAttribs :: [Attr],+ elContent :: [Content],+ elLine :: Maybe Line+ } deriving (Show, Typeable, Data, Ord, Eq)++-- | XML attributes+data Attr = Attr {+ attrKey :: QName,+ attrVal :: Text+ } deriving (Eq, Ord, Show, Typeable, Data)++-- | XML CData+data CData = CData {+ cdVerbatim :: CDataKind,+ cdData :: Text,+ cdLine :: Maybe Line+ } deriving (Show, Typeable, Data, Ord, Eq)++data CDataKind+ = CDataText -- ^ Ordinary character data; pretty printer escapes &, < etc.+ | CDataVerbatim -- ^ Unescaped character data; pretty printer embeds it in <![CDATA[..+ | CDataRaw -- ^ As-is character data; pretty printer passes it along without any escaping or CDATA wrap-up.+ deriving ( Eq, Ord, Show, Typeable, Data )++-- | XML qualified names+data QName = QName {+ qName :: Text,+ qURI :: Maybe Text,+ qPrefix :: Maybe Text+ } deriving (Show, Typeable, Data)+++instance Eq QName where+ q1 == q2 = compare q1 q2 == EQ++instance Ord QName where+ compare q1 q2 =+ case compare (qName q1) (qName q2) of+ EQ -> case (qURI q1, qURI q2) of+ (Nothing,Nothing) -> compare (qPrefix q1) (qPrefix q2)+ (u1,u2) -> compare u1 u2+ x -> x++class Node t where+ node :: QName -> t -> Element++instance Node ([Attr],[Content]) where+ node n (attrs,cont) = Element { elName = n+ , elAttribs = attrs+ , elContent = cont+ , elLine = Nothing+ }++instance Node [Attr] where node n as = node n (as,[]::[Content])+instance Node Attr where node n a = node n [a]+instance Node () where node n () = node n ([]::[Attr])++instance Node [Content] where node n cs = node n ([]::[Attr],cs)+instance Node Content where node n c = node n [c]+instance Node ([Attr],Content) where node n (as,c) = node n (as,[c])+instance Node (Attr,Content) where node n (a,c) = node n ([a],[c])++instance Node ([Attr],[Element]) where+ node n (as,cs) = node n (as,map Elem cs)++instance Node ([Attr],Element) where node n (as,c) = node n (as,[c])+instance Node (Attr,Element) where node n (a,c) = node n ([a],c)+instance Node [Element] where node n es = node n ([]::[Attr],es)+instance Node Element where node n e = node n [e]++instance Node ([Attr],[CData]) where+ node n (as,cs) = node n (as,map Text cs)++instance Node ([Attr],CData) where node n (as,c) = node n (as,[c])+instance Node (Attr,CData) where node n (a,c) = node n ([a],c)+instance Node [CData] where node n es = node n ([]::[Attr],es)+instance Node CData where node n e = node n [e]++instance Node ([Attr],Text) where+ node n (as,t) = node n (as, CData { cdVerbatim = CDataText+ , cdData = t+ , cdLine = Nothing })++instance Node (Attr,Text ) where node n (a,t) = node n ([a],t)+instance Node Text where node n t = node n ([]::[Attr],t)++-- | Create node with unqualified name+unode :: Node t => Text -> t -> Element+unode = node . unqual++unqual :: Text -> QName+unqual x = QName x Nothing Nothing++-- | Add an attribute to an element.+add_attr :: Attr -> Element -> Element+add_attr a e = add_attrs [a] e++-- | Add some attributes to an element.+add_attrs :: [Attr] -> Element -> Element+add_attrs as e = e { elAttribs = as ++ elAttribs e }++--+-- conversion from xml-light+--++fromXLQName :: XL.QName -> QName+fromXLQName qn = QName { qName = T.pack $ XL.qName qn+ , qURI = T.pack <$> XL.qURI qn+ , qPrefix = T.pack <$> XL.qPrefix qn }++fromXLCData :: XL.CData -> CData+fromXLCData cd = CData { cdVerbatim = case XL.cdVerbatim cd of+ XL.CDataText -> CDataText+ XL.CDataVerbatim -> CDataVerbatim+ XL.CDataRaw -> CDataRaw+ , cdData = T.pack $ XL.cdData cd+ , cdLine = XL.cdLine cd }++fromXLElement :: XL.Element -> Element+fromXLElement el = Element { elName = fromXLQName $ XL.elName el+ , elAttribs = map fromXLAttr $ XL.elAttribs el+ , elContent = map fromXLContent $ XL.elContent el+ , elLine = XL.elLine el }++fromXLAttr :: XL.Attr -> Attr+fromXLAttr (XL.Attr qn s) = Attr (fromXLQName qn) (T.pack s)++fromXLContent :: XL.Content -> Content+fromXLContent (XL.Elem el) = Elem $ fromXLElement el+fromXLContent (XL.Text cd) = Text $ fromXLCData cd+fromXLContent (XL.CRef s) = CRef (T.pack s)